Source

rez_group.js

//-----------------------------------------------------------------------------
// Group
//
// Group represents a group of assets that is dynamically generated by the
// include_tag and exclude_tag attributes.
//-----------------------------------------------------------------------------

/**
 * @class RezGroup
 * @extends RezBasicObject
 * @category Elements
 * @description Represents a dynamically generated group of assets in the Rez game engine.
 * Groups filter assets based on type, include_tags, and exclude_tags attributes.
 * Provides methods for getting random assets from the filtered collection.
 */
class RezGroup extends RezBasicObject {
  /**
   * @function constructor
   * @memberof RezGroup
   * @param {string} id - unique identifier for this group
   * @param {object} attributes - group attributes including type, include_tags, exclude_tags
   * @description Creates a new asset group instance
   */
  constructor(id, attributes) {
    super("group", id, attributes);
  }

  /**
   * @function elementInitializer
   * @memberof RezGroup
   * @description Initializes the group by filtering assets during game startup
   */
  elementInitializer() {
    this.filterAssets();
  }

  /**
   * @function filterAssets
   * @memberof RezGroup
   * @description Filters all game assets based on type, include_tags, and exclude_tags
   * to build the group's asset collection. The filtered assets are shuffled and stored.
   */
  filterAssets() {
    // Start with all assets
    let assets = this.game.getAll("asset");

    // Does the asset have the right type
    const selectedType = this.getAttributeValue("type");
    assets = assets.filter((asset) => asset.type === selectedType);

    // Assets without tags can't be in a group
    assets = assets.filter((asset) => asset.hasAttribute("tags") && asset.getAttributeValue("tags").size > 0);

    // If there is an include filter, filter those without the relevant tags
    const includeTags = this.getAttributeValue("include_tags", new Set());
    if(includeTags.size > 0) {
      assets = assets.filter((asset) => {
        const tags = asset.getAttributeValue("tags");
        return tags.hasSubset(includeTags);
      });
    }

    // If there is an exclude filter, filter those with the relevant tags
    const excludeTags = this.getAttributeValue("exclude_tags", new Set());
    if(excludeTags.size > 0) {
      assets = assets.filter((asset) => {
        const tags = asset.getAttributeValue("tags");
        return tags.intersection(excludeTags).size === 0;
      });
    }

    if(assets.size === 0) {
      console.log("Attempt to create group that matches 0 assets!");
    }

    assets = assets.map((asset) => asset.id).fyShuffle();

    this.setAttribute("assets", assets);
  }

  /**
   * @function randomAssetId
   * @memberof RezGroup
   * @returns {string} ID of a random asset from this group
   * @description Gets a random asset ID from this group, consuming it from the collection.
   * If the group is empty, it will re-filter assets first.
   * @throws {Error} if no matching assets are found
   */
  randomAssetId() {
    if(this.assets.size === 0) {
      this.filterAssets();
    }

    const assetId = this.assets.shift();
    if(typeof(assetId) === "undefined") {
      throw new Error(`Attempt to get random asset from Group |${this.id}| with no matching assets!`);
    }

    return assetId;
  }
}

// this.properties_to_archive = ["assets"];

window.Rez.RezGroup = RezGroup;