diff --git a/src/core/tags.js b/src/core/tags.js index 031f814e63d..d9220d3ca81 100644 --- a/src/core/tags.js +++ b/src/core/tags.js @@ -7,6 +7,40 @@ import { EventHandler } from './event-handler.js'; * @augments EventHandler */ class Tags extends EventHandler { + /** + * Fired for each individual tag that is added. + * + * @event + * @example + * tags.on('add', (tag, parent) => { + * console.log(`${tag} added to ${parent.name}`); + * }); + */ + static EVENT_ADD = 'add'; + + /** + * Fired for each individual tag that is removed. + * + * @event + * @example + * tags.on('remove', (tag, parent) => { + * console.log(`${tag} removed from ${parent.name}`); + * }); + */ + static EVENT_REMOVE = 'remove'; + + /** + * Fired when tags have been added or removed. It will fire once on bulk changes, while `add` + * and `remove` will fire on each tag operation. + * + * @event + * @example + * tags.on('change', (parent) => { + * console.log(`Tags changed on ${parent.name}`); + * }); + */ + static EVENT_CHANGE = 'change'; + /** @private */ _index = {}; @@ -24,26 +58,6 @@ class Tags extends EventHandler { this._parent = parent; } - /** - * @event Tags#add - * @param {string} tag - Name of a tag added to a set. - * @param {object} parent - Parent object who tags belong to. - */ - - /** - * @event Tags#remove - * @param {string} tag - Name of a tag removed from a set. - * @param {object} parent - Parent object who tags belong to. - */ - - /** - * Fires when tags have been added or removed. It will fire once on bulk changes, while - * `add`/`remove` will fire on each tag operation. - * - * @event Tags#change - * @param {object} [parent] - Parent object who tags belong to. - */ - /** * Add a tag, duplicates are ignored. Can be array or comma separated arguments for multiple tags. * diff --git a/src/framework/asset/asset-registry.js b/src/framework/asset/asset-registry.js index 0c04e09d903..ba945901112 100644 --- a/src/framework/asset/asset-registry.js +++ b/src/framework/asset/asset-registry.js @@ -34,182 +34,171 @@ import { Asset } from './asset.js'; */ class AssetRegistry extends EventHandler { /** - * @type {Set} - * @private - */ - _assets = new Set(); - - /** - * @type {Map} - * @private - */ - _idToAsset = new Map(); - - /** - * @type {Map} - * @private - */ - _urlToAsset = new Map(); - - /** - * @type {Map>} - * @private - */ - _nameToAsset = new Map(); - - /** - * Index for looking up by tags. + * Fired when an asset completes loading. This event is available in three forms. They are as + * follows: * - * @private - */ - _tags = new TagsCache('_id'); - - /** - * A URL prefix that will be added to all asset loading requests. + * 1. `load` - Fired when any asset finishes loading. + * 2. `load:[id]` - Fired when a specific asset has finished loading, where `[id]` is the + * unique id of the asset. + * 3. `load:url:[url]` - Fired when an asset finishes loading whose URL matches `[url]`, where + * `[url]` is the URL of the asset. * - * @type {string|null} + * @event + * @example + * app.assets.on('load', (asset) => { + * console.log(`Asset loaded: ${asset.name}`); + * }); + * @example + * const id = 123456; + * const asset = app.assets.get(id); + * app.assets.on('load:' + id, (asset) => { + * console.log(`Asset loaded: ${asset.name}`); + * }); + * app.assets.load(asset); + * @example + * const id = 123456; + * const asset = app.assets.get(id); + * app.assets.on('load:url:' + asset.file.url, (asset) => { + * console.log(`Asset loaded: ${asset.name}`); + * }); + * app.assets.load(asset); */ - prefix = null; + static EVENT_LOAD = 'load'; /** - * Create an instance of an AssetRegistry. + * Fired when an asset is added to the registry. This event is available in three forms. They + * are as follows: * - * @param {import('../handlers/loader.js').ResourceLoader} loader - The ResourceLoader used to - * load the asset files. - */ - constructor(loader) { - super(); - - this._loader = loader; - } - - /** - * Fired when an asset completes loading. + * 1. `add` - Fired when any asset is added to the registry. + * 2. `add:[id]` - Fired when an asset is added to the registry, where `[id]` is the unique id + * of the asset. + * 3. `add:url:[url]` - Fired when an asset is added to the registry and matches the URL + * `[url]`, where `[url]` is the URL of the asset. * - * @event AssetRegistry#load - * @param {Asset} asset - The asset that has just loaded. + * @event + * @example + * app.assets.on('add', (asset) => { + * console.log(`Asset added: ${asset.name}`); + * }); + * @example + * const id = 123456; + * app.assets.on('add:' + id, (asset) => { + * console.log(`Asset added: ${asset.name}`); + * }); * @example - * app.assets.on("load", function (asset) { - * console.log("asset loaded: " + asset.name); + * const id = 123456; + * const asset = app.assets.get(id); + * app.assets.on('add:url:' + asset.file.url, (asset) => { + * console.log(`Asset added: ${asset.name}`); * }); */ + static EVENT_ADD = 'add'; /** - * Fired when an asset completes loading. + * Fired when an asset is removed from the registry. This event is available in three forms. + * They are as follows: * - * @event AssetRegistry#load:[id] - * @param {Asset} asset - The asset that has just loaded. + * 1. `remove` - Fired when any asset is removed from the registry. + * 2. `remove:[id]` - Fired when an asset is removed from the registry, where `[id]` is the + * unique id of the asset. + * 3. `remove:url:[url]` - Fired when an asset is removed from the registry and matches the + * URL `[url]`, where `[url]` is the URL of the asset. + * + * @event + * @param {Asset} asset - The asset that was removed. + * @example + * app.assets.on('remove', (asset) => { + * console.log(`Asset removed: ${asset.name}`); + * }); + * @example + * const id = 123456; + * app.assets.on('remove:' + id, (asset) => { + * console.log(`Asset removed: ${asset.name}`); + * }); * @example * const id = 123456; * const asset = app.assets.get(id); - * app.assets.on("load:" + id, function (asset) { - * console.log("asset loaded: " + asset.name); + * app.assets.on('remove:url:' + asset.file.url, (asset) => { + * console.log(`Asset removed: ${asset.name}`); * }); - * app.assets.load(asset); */ + static EVENT_REMOVE = 'remove'; /** - * Fired when an asset completes loading. + * Fired when an error occurs during asset loading. This event is available in two forms. They + * are as follows: + * + * 1. `error` - Fired when any asset reports an error in loading. + * 2. `error:[id]` - Fired when an asset reports an error in loading, where `[id]` is the + * unique id of the asset. * - * @event AssetRegistry#load:url:[url] - * @param {Asset} asset - The asset that has just loaded. + * @event * @example * const id = 123456; * const asset = app.assets.get(id); - * app.assets.on("load:url:" + asset.file.url, function (asset) { - * console.log("asset loaded: " + asset.name); + * app.assets.on('error', (err, asset) => { + * console.error(err); * }); * app.assets.load(asset); - */ - - /** - * Fired when an asset is added to the registry. - * - * @event AssetRegistry#add - * @param {Asset} asset - The asset that was added. * @example - * app.assets.on("add", function (asset) { - * console.log("New asset added: " + asset.name); + * const id = 123456; + * const asset = app.assets.get(id); + * app.assets.on('error:' + id, (err, asset) => { + * console.error(err); * }); + * app.assets.load(asset); */ + static EVENT_ERROR = 'error'; /** - * Fired when an asset is added to the registry. - * - * @event AssetRegistry#add:[id] - * @param {Asset} asset - The asset that was added. - * @example - * const id = 123456; - * app.assets.on("add:" + id, function (asset) { - * console.log("Asset 123456 loaded"); - * }); + * @type {Set} + * @private */ + _assets = new Set(); /** - * Fired when an asset is added to the registry. - * - * @event AssetRegistry#add:url:[url] - * @param {Asset} asset - The asset that was added. + * @type {Map} + * @private */ + _idToAsset = new Map(); /** - * Fired when an asset is removed from the registry. - * - * @event AssetRegistry#remove - * @param {Asset} asset - The asset that was removed. - * @example - * app.assets.on("remove", function (asset) { - * console.log("Asset removed: " + asset.name); - * }); + * @type {Map} + * @private */ + _urlToAsset = new Map(); /** - * Fired when an asset is removed from the registry. - * - * @event AssetRegistry#remove:[id] - * @param {Asset} asset - The asset that was removed. - * @example - * const id = 123456; - * app.assets.on("remove:" + id, function (asset) { - * console.log("Asset removed: " + asset.name); - * }); + * @type {Map>} + * @private */ + _nameToAsset = new Map(); /** - * Fired when an asset is removed from the registry. + * Index for looking up by tags. * - * @event AssetRegistry#remove:url:[url] - * @param {Asset} asset - The asset that was removed. + * @private */ + _tags = new TagsCache('_id'); /** - * Fired when an error occurs during asset loading. + * A URL prefix that will be added to all asset loading requests. * - * @event AssetRegistry#error - * @param {string} err - The error message. - * @param {Asset} asset - The asset that generated the error. - * @example - * const id = 123456; - * const asset = app.assets.get(id); - * app.assets.on("error", function (err, asset) { - * console.error(err); - * }); - * app.assets.load(asset); + * @type {string|null} */ + prefix = null; /** - * Fired when an error occurs during asset loading. + * Create an instance of an AssetRegistry. * - * @event AssetRegistry#error:[id] - * @param {Asset} asset - The asset that generated the error. - * @example - * const id = 123456; - * const asset = app.assets.get(id); - * app.assets.on("error:" + id, function (err, asset) { - * console.error(err); - * }); - * app.assets.load(asset); + * @param {import('../handlers/loader.js').ResourceLoader} loader - The ResourceLoader used to + * load the asset files. */ + constructor(loader) { + super(); + + this._loader = loader; + } /** * Create a filtered list of assets from the registry. diff --git a/src/framework/asset/asset.js b/src/framework/asset/asset.js index e39defdf138..d1f66be7fad 100644 --- a/src/framework/asset/asset.js +++ b/src/framework/asset/asset.js @@ -47,6 +47,85 @@ const VARIANT_DEFAULT_PRIORITY = ['pvr', 'dxt', 'etc2', 'etc1', 'basis']; * @augments EventHandler */ class Asset extends EventHandler { + /** + * Fired when the asset has completed loading. + * + * @event + * @example + * asset.on('load', (asset) => { + * console.log(`Asset loaded: ${asset.name}`); + * }); + */ + static EVENT_LOAD = 'load'; + + /** + * Fired just before the asset unloads the resource. This allows for the opportunity to prepare + * for an asset that will be unloaded. E.g. Changing the texture of a model to a default before + * the one it was using is unloaded. + * + * @event + * @example + * asset.on('unload', (asset) => { + * console.log(`Asset about to unload: ${asset.name}`); + * }); + */ + static EVENT_UNLOAD = 'unload'; + + /** + * Fired when the asset is removed from the asset registry. + * + * @event + * @example + * asset.on('remove', (asset) => { + * console.log(`Asset removed: ${asset.name}`); + * }); + */ + static EVENT_REMOVE = 'remove'; + + /** + * Fired if the asset encounters an error while loading. + * + * @event + * @example + * asset.on('error', (err, asset) => { + * console.error(`Error loading asset ${asset.name}: ${err}`); + * }); + */ + static EVENT_ERROR = 'error'; + + /** + * Fired when one of the asset properties `file`, `data`, `resource` or `resources` is changed. + * + * @event + * @example + * asset.on('change', (asset, property, newValue, oldValue) => { + * console.log(`Asset ${asset.name} has property ${property} changed from ${oldValue} to ${newValue}`); + * }); + */ + static EVENT_CHANGE = 'change'; + + /** + * Fired when we add a new localized asset id to the asset. + * + * @event + * @example + * asset.on('add:localized', (locale, assetId) => { + * console.log(`Asset ${asset.name} has added localized asset ${assetId} for locale ${locale}`); + * }); + */ + static EVENT_ADDLOCALIZED = 'add:localized'; + + /** + * Fired when we remove a localized asset id from the asset. + * + * @event + * @example + * asset.on('remove:localized', (locale, assetId) => { + * console.log(`Asset ${asset.name} has removed localized asset ${assetId} for locale ${locale}`); + * }); + */ + static EVENT_REMOVELOCALIZED = 'remove:localized'; + /** * Create a new Asset record. Generally, Assets are created in the loading process and you * won't need to create them by hand. @@ -146,63 +225,6 @@ class Asset extends EventHandler { if (file) this.file = file; } - /** - * Fired when the asset has completed loading. - * - * @event Asset#load - * @param {Asset} asset - The asset that was loaded. - */ - - /** - * Fired just before the asset unloads the resource. This allows for the opportunity to prepare - * for an asset that will be unloaded. E.g. Changing the texture of a model to a default before - * the one it was using is unloaded. - * - * @event Asset#unload - * @param {Asset} asset - The asset that is due to be unloaded. - */ - - /** - * Fired when the asset is removed from the asset registry. - * - * @event Asset#remove - * @param {Asset} asset - The asset that was removed. - */ - - /** - * Fired if the asset encounters an error while loading. - * - * @event Asset#error - * @param {string} err - The error message. - * @param {Asset} asset - The asset that generated the error. - */ - - /** - * Fired when one of the asset properties `file`, `data`, `resource` or `resources` is changed. - * - * @event Asset#change - * @param {Asset} asset - The asset that was loaded. - * @param {string} property - The name of the property that changed. - * @param {*} value - The new property value. - * @param {*} oldValue - The old property value. - */ - - /** - * Fired when we add a new localized asset id to the asset. - * - * @event Asset#add:localized - * @param {string} locale - The locale. - * @param {number} assetId - The asset id we added. - */ - - /** - * Fired when we remove a localized asset id from the asset. - * - * @event Asset#remove:localized - * @param {string} locale - The locale. - * @param {number} assetId - The asset id we removed. - */ - /** * The asset id. * diff --git a/src/framework/components/button/component.js b/src/framework/components/button/component.js index abab69e5f1e..29639ea326a 100644 --- a/src/framework/components/button/component.js +++ b/src/framework/components/button/component.js @@ -65,6 +65,203 @@ STATES_TO_SPRITE_FRAME_NAMES[VisualState.INACTIVE] = 'inactiveSpriteFrame'; * @category User Interface */ class ButtonComponent extends Component { + /** + * Fired when the mouse is pressed while the cursor is on the component. The handler is passed + * a {@link ElementMouseEvent}. + * + * @event + * @example + * entity.button.on('mousedown', (event) => { + * console.log(`Mouse down on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEDOWN = 'mousedown'; + + /** + * Fired when the mouse is released while the cursor is on the component. The handler is passed + * a {@link ElementMouseEvent}. + * + * @event + * @example + * entity.button.on('mouseup', (event) => { + * console.log(`Mouse up on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEUP = 'mouseup'; + + /** + * Fired when the mouse cursor enters the component. The handler is passed a + * {@link ElementMouseEvent}. + * + * @event + * @example + * entity.button.on('mouseenter', (event) => { + * console.log(`Mouse entered entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEENTER = 'mouseenter'; + + /** + * Fired when the mouse cursor leaves the component. The handler is passed a + * {@link ElementMouseEvent}. + * + * @event + * @example + * entity.button.on('mouseleave', (event) => { + * console.log(`Mouse left entity ${entity.name}`); + * }); + */ + static EVENT_MOUSELEAVE = 'mouseleave'; + + /** + * Fired when the mouse is pressed and released on the component or when a touch starts and ends on + * the component. The handler is passed a {@link ElementMouseEvent} or {@link ElementTouchEvent}. + * + * @event + * @example + * entity.button.on('click', (event) => { + * console.log(`Clicked entity ${entity.name}`); + * }); + */ + static EVENT_CLICK = 'click'; + + /** + * Fired when a touch starts on the component. The handler is passed a {@link ElementTouchEvent}. + * + * @event + * @example + * entity.button.on('touchstart', (event) => { + * console.log(`Touch started on entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHSTART = 'touchstart'; + + /** + * Fired when a touch ends on the component. The handler is passed a {@link ElementTouchEvent}. + * + * @event + * @example + * entity.button.on('touchend', (event) => { + * console.log(`Touch ended on entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHEND = 'touchend'; + + /** + * Fired when a touch is canceled on the component. The handler is passed a + * {@link ElementTouchEvent}. + * + * @event + * @example + * entity.button.on('touchcancel', (event) => { + * console.log(`Touch canceled on entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHCANCEL = 'touchcancel'; + + /** + * Fired when a touch leaves the component. The handler is passed a {@link ElementTouchEvent}. + * + * @event + * @example + * entity.button.on('touchleave', (event) => { + * console.log(`Touch left entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHLEAVE = 'touchleave'; + + /** + * Fired when a xr select starts on the component. The handler is passed a + * {@link ElementSelectEvent}. + * + * @event + * @example + * entity.button.on('selectstart', (event) => { + * console.log(`Select started on entity ${entity.name}`); + * }); + */ + static EVENT_SELECTSTART = 'selectstart'; + + /** + * Fired when a xr select ends on the component. The handler is passed a + * {@link ElementSelectEvent}. + * + * @event + * @example + * entity.button.on('selectend', (event) => { + * console.log(`Select ended on entity ${entity.name}`); + * }); + */ + static EVENT_SELECTEND = 'selectend'; + + /** + * Fired when a xr select now hovering over the component. The handler is passed a + * {@link ElementSelectEvent}. + * + * @event + * @example + * entity.button.on('selectenter', (event) => { + * console.log(`Select entered entity ${entity.name}`); + * }); + */ + static EVENT_SELECTENTER = 'selectenter'; + + /** + * Fired when a xr select not hovering over the component. The handler is passed a + * {@link ElementSelectEvent}. + * + * @event + * @example + * entity.button.on('selectleave', (event) => { + * console.log(`Select left entity ${entity.name}`); + * }); + */ + static EVENT_SELECTLEAVE = 'selectleave'; + + /** + * Fired when the button changes state to be hovered. + * + * @event + * @example + * entity.button.on('hoverstart', () => { + * console.log(`Entity ${entity.name} hovered`); + * }); + */ + static EVENT_HOVERSTART = 'hoverstart'; + + /** + * Fired when the button changes state to be not hovered. + * + * @event + * @example + * entity.button.on('hoverend', () => { + * console.log(`Entity ${entity.name} unhovered`); + * }); + */ + static EVENT_HOVEREND = 'hoverend'; + + /** + * Fired when the button changes state to be pressed. + * + * @event + * @example + * entity.button.on('pressedstart', () => { + * console.log(`Entity ${entity.name} pressed`); + * }); + */ + static EVENT_PRESSEDSTART = 'pressedstart'; + + /** + * Fired when the button changes state to be not pressed. + * + * @event + * @example + * entity.button.on('pressedend', () => { + * console.log(`Entity ${entity.name} unpressed`); + * }); + */ + static EVENT_PRESSEDEND = 'pressedend'; + /** * Create a new ButtonComponent instance. * @@ -548,120 +745,4 @@ function toColor3(color4) { return new Color(color4.r, color4.g, color4.b); } -/** - * Fired when the mouse is pressed while the cursor is on the component. - * - * @event ButtonComponent#mousedown - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - -/** - * Fired when the mouse is released while the cursor is on the component. - * - * @event ButtonComponent#mouseup - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - -/** - * Fired when the mouse cursor enters the component. - * - * @event ButtonComponent#mouseenter - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - -/** - * Fired when the mouse cursor leaves the component. - * - * @event ButtonComponent#mouseleave - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - -/** - * Fired when the mouse is pressed and released on the component or when a touch starts and ends on - * the component. - * - * @event ButtonComponent#click - * @param {import('../../input/element-input.js').ElementMouseEvent|import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - -/** - * Fired when a touch starts on the component. - * - * @event ButtonComponent#touchstart - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - -/** - * Fired when a touch ends on the component. - * - * @event ButtonComponent#touchend - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - -/** - * Fired when a touch is canceled on the component. - * - * @event ButtonComponent#touchcancel - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - -/** - * Fired when a touch leaves the component. - * - * @event ButtonComponent#touchleave - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - -/** - * Fired when a xr select starts on the component. - * - * @event ButtonComponent#selectstart - * @param {import('../../input/element-input.js').ElementSelectEvent} event - The event. - */ - -/** - * Fired when a xr select ends on the component. - * - * @event ButtonComponent#selectend - * @param {import('../../input/element-input.js').ElementSelectEvent} event - The event. - */ - -/** - * Fired when a xr select now hovering over the component. - * - * @event ButtonComponent#selectenter - * @param {import('../../input/element-input.js').ElementSelectEvent} event - The event. - */ - -/** - * Fired when a xr select not hovering over the component. - * - * @event ButtonComponent#selectleave - * @param {import('../../input/element-input.js').ElementSelectEvent} event - The event. - */ - -/** - * Fired when the button changes state to be hovered. - * - * @event ButtonComponent#hoverstart - */ - -/** - * Fired when the button changes state to be not hovered. - * - * @event ButtonComponent#hoverend - */ - -/** - * Fired when the button changes state to be pressed. - * - * @event ButtonComponent#pressedstart - */ - -/** - * Fired when the button changes state to be not pressed. - * - * @event ButtonComponent#pressedend - */ - export { ButtonComponent }; diff --git a/src/framework/components/collision/component.js b/src/framework/components/collision/component.js index 99c53a509b6..150956df6a9 100644 --- a/src/framework/components/collision/component.js +++ b/src/framework/components/collision/component.js @@ -59,6 +59,67 @@ const _quat = new Quat(); * @category Physics */ class CollisionComponent extends Component { + /** + * Fired when a contact occurs between two rigid bodies. The handler is passed a + * {@link ContactResult} object which contains details of the contact between the two rigid + * bodies. + * + * @event + * @example + * entity.collision.on('contact', (result) => { + * console.log(`Contact between ${entity.name} and ${result.other.name}`); + * }); + */ + static EVENT_CONTACT = 'contact'; + + /** + * Fired when two rigid bodies start touching. The handler is passed the {@link ContactResult} + * object which contains details of the contact between the two rigid bodies. + * + * @event + * @example + * entity.collision.on('collisionstart', (result) => { + * console.log(`${entity.name} started touching ${result.other.name}`); + * }); + */ + static EVENT_COLLISIONSTART = 'collisionstart'; + + /** + * Fired two rigid-bodies stop touching. The handler is passed an {@link Entity} that + * represents the other rigid body involved in the collision. + * + * @event + * @example + * entity.collision.on('collisionend', (other) => { + * console.log(`${entity.name} stopped touching ${other.name}`); + * }); + */ + static EVENT_COLLISIONEND = 'collisionend'; + + /** + * Fired when a rigid body enters a trigger volume. The handler is passed an {@link Entity} + * representing the rigid body that entered this collision volume. + * + * @event + * @example + * entity.collision.on('triggerenter', (other) => { + * console.log(`${other.name} entered trigger volume ${entity.name}`); + * }); + */ + static EVENT_TRIGGERENTER = 'triggerenter'; + + /** + * Fired when a rigid body exits a trigger volume. The handler is passed an {@link Entity} + * representing the rigid body that exited this collision volume. + * + * @event + * @example + * entity.collision.on('triggerleave', (other) => { + * console.log(`${other.name} exited trigger volume ${entity.name}`); + * }); + */ + static EVENT_TRIGGERLEAVE = 'triggerleave'; + /** * Create a new CollisionComponent. * @@ -89,41 +150,6 @@ class CollisionComponent extends Component { this.on('set_render', this.onSetRender, this); } - /** - * The 'contact' event is fired when a contact occurs between two rigid bodies. - * - * @event CollisionComponent#contact - * @param {ContactResult} result - Details of the contact between the two rigid bodies. - */ - - /** - * Fired when two rigid bodies start touching. - * - * @event CollisionComponent#collisionstart - * @param {ContactResult} result - Details of the contact between the two Entities. - */ - - /** - * Fired two rigid-bodies stop touching. - * - * @event CollisionComponent#collisionend - * @param {import('../../entity.js').Entity} other - The {@link Entity} that stopped touching this collision volume. - */ - - /** - * Fired when a rigid body enters a trigger volume. - * - * @event CollisionComponent#triggerenter - * @param {import('../../entity.js').Entity} other - The {@link Entity} that entered this collision volume. - */ - - /** - * Fired when a rigid body exits a trigger volume. - * - * @event CollisionComponent#triggerleave - * @param {import('../../entity.js').Entity} other - The {@link Entity} that exited this collision volume. - */ - /** * @param {string} name - Property name. * @param {*} oldValue - Previous value of the property. diff --git a/src/framework/components/element/component.js b/src/framework/components/element/component.js index 86f82191dd6..787113da63c 100644 --- a/src/framework/components/element/component.js +++ b/src/framework/components/element/component.js @@ -173,6 +173,139 @@ const matD = new Mat4(); * @category User Interface */ class ElementComponent extends Component { + /** + * Fired when the mouse is pressed while the cursor is on the component. Only fired when + * useInput is true. The handler is passed an {@link ElementMouseEvent}. + * + * @event + * @example + * entity.element.on('mousedown', (event) => { + * console.log(`Mouse down event on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEDOWN = 'mousedown'; + + /** + * Fired when the mouse is released while the cursor is on the component. Only fired when + * useInput is true. The handler is passed an {@link ElementMouseEvent}. + * + * @event + * @example + * entity.element.on('mouseup', (event) => { + * console.log(`Mouse up event on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEUP = 'mouseup'; + + /** + * Fired when the mouse cursor enters the component. Only fired when useInput is true. The + * handler is passed an {@link ElementMouseEvent}. + * + * @event + * @example + * entity.element.on('mouseenter', (event) => { + * console.log(`Mouse enter event on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEENTER = 'mouseenter'; + + /** + * Fired when the mouse cursor leaves the component. Only fired when useInput is true. The + * handler is passed an {@link ElementMouseEvent}. + * + * @event + * @example + * entity.element.on('mouseleave', (event) => { + * console.log(`Mouse leave event on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSELEAVE = 'mouseleave'; + + /** + * Fired when the mouse cursor is moved on the component. Only fired when useInput is true. The + * handler is passed an {@link ElementMouseEvent}. + * + * @event + * @example + * entity.element.on('mousemove', (event) => { + * console.log(`Mouse move event on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEMOVE = 'mousemove'; + + /** + * Fired when the mouse wheel is scrolled on the component. Only fired when useInput is true. + * The handler is passed an {@link ElementMouseEvent}. + * + * @event + * @example + * entity.element.on('mousewheel', (event) => { + * console.log(`Mouse wheel event on entity ${entity.name}`); + * }); + */ + static EVENT_MOUSEWHEEL = 'mousewheel'; + + /** + * Fired when the mouse is pressed and released on the component or when a touch starts and + * ends on the component. Only fired when useInput is true. The handler is passed an + * {@link ElementMouseEvent} or {@link ElementTouchEvent}. + * + * @event + * @example + * entity.element.on('click', (event) => { + * console.log(`Click event on entity ${entity.name}`); + * }); + */ + static EVENT_CLICK = 'click'; + + /** + * Fired when a touch starts on the component. Only fired when useInput is true. The handler is + * passed an {@link ElementTouchEvent}. + * + * @event + * @example + * entity.element.on('touchstart', (event) => { + * console.log(`Touch start event on entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHSTART = 'touchstart'; + + /** + * Fired when a touch ends on the component. Only fired when useInput is true. The handler is + * passed an {@link ElementTouchEvent}. + * + * @event + * @example + * entity.element.on('touchend', (event) => { + * console.log(`Touch end event on entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHEND = 'touchend'; + + /** + * Fired when a touch moves after it started touching the component. Only fired when useInput + * is true. The handler is passed an {@link ElementTouchEvent}. + * + * @event + * @example + * entity.element.on('touchmove', (event) => { + * console.log(`Touch move event on entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHMOVE = 'touchmove'; + + /** + * Fired when a touch is canceled on the component. Only fired when useInput is true. The + * handler is passed an {@link ElementTouchEvent}. + * + * @event + * @example + * entity.element.on('touchcancel', (event) => { + * console.log(`Touch cancel event on entity ${entity.name}`); + * }); + */ + static EVENT_TOUCHCANCEL = 'touchcancel'; + /** * Create a new ElementComponent instance. * @@ -268,87 +401,6 @@ class ElementComponent extends Component { this._maskedBy = null; // the entity that is masking this element } - /** - * Fired when the mouse is pressed while the cursor is on the component. Only fired when - * useInput is true. - * - * @event ElementComponent#mousedown - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - - /** - * Fired when the mouse is released while the cursor is on the component. Only fired when - * useInput is true. - * - * @event ElementComponent#mouseup - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - - /** - * Fired when the mouse cursor enters the component. Only fired when useInput is true. - * - * @event ElementComponent#mouseenter - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - - /** - * Fired when the mouse cursor leaves the component. Only fired when useInput is true. - * - * @event ElementComponent#mouseleave - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - - /** - * Fired when the mouse cursor is moved on the component. Only fired when useInput is true. - * - * @event ElementComponent#mousemove - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - - /** - * Fired when the mouse wheel is scrolled on the component. Only fired when useInput is true. - * - * @event ElementComponent#mousewheel - * @param {import('../../input/element-input.js').ElementMouseEvent} event - The event. - */ - - /** - * Fired when the mouse is pressed and released on the component or when a touch starts and - * ends on the component. Only fired when useInput is true. - * - * @event ElementComponent#click - * @param {import('../../input/element-input.js').ElementMouseEvent|import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - - /** - * Fired when a touch starts on the component. Only fired when useInput is true. - * - * @event ElementComponent#touchstart - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - - /** - * Fired when a touch ends on the component. Only fired when useInput is true. - * - * @event ElementComponent#touchend - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - - /** - * Fired when a touch moves after it started touching the component. Only fired when useInput - * is true. - * - * @event ElementComponent#touchmove - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - - /** - * Fired when a touch is canceled on the component. Only fired when useInput is true. - * - * @event ElementComponent#touchcancel - * @param {import('../../input/element-input.js').ElementTouchEvent} event - The event. - */ - /** * @type {number} * @private diff --git a/src/framework/components/element/element-drag-helper.js b/src/framework/components/element/element-drag-helper.js index 0aa22d98ad7..6363f9e6708 100644 --- a/src/framework/components/element/element-drag-helper.js +++ b/src/framework/components/element/element-drag-helper.js @@ -29,6 +29,40 @@ const OPPOSITE_AXIS = { * @category User Interface */ class ElementDragHelper extends EventHandler { + /** + * Fired when a new drag operation starts. + * + * @event + * @example + * elementDragHelper.on('drag:start', () => { + * console.log('Drag started'); + * }); + */ + static EVENT_DRAGSTART = 'drag:start'; + + /** + * Fired when the current new drag operation ends. + * + * @event + * @example + * elementDragHelper.on('drag:end', () => { + * console.log('Drag ended'); + * }); + */ + static EVENT_DRAGEND = 'drag:end'; + + /** + * Fired whenever the position of the dragged element changes. The handler is passed the + * current {@link Vec3} position of the dragged element. + * + * @event + * @example + * elementDragHelper.on('drag:move', (position) => { + * console.log(`Dragged element position is ${position}`); + * }); + */ + static EVENT_DRAGMOVE = 'drag:move'; + /** * Create a new ElementDragHelper instance. * @@ -60,25 +94,6 @@ class ElementDragHelper extends EventHandler { this._toggleLifecycleListeners('on'); } - /** - * Fired when a new drag operation starts. - * - * @event ElementDragHelper#drag:start - */ - - /** - * Fired when the current new drag operation ends. - * - * @event ElementDragHelper#drag:end - */ - - /** - * Fired whenever the position of the dragged element changes. - * - * @event ElementDragHelper#drag:move - * @param {Vec3} value - The current position. - */ - /** * @param {'on'|'off'} onOrOff - Either 'on' or 'off'. * @private diff --git a/src/framework/components/rigid-body/component.js b/src/framework/components/rigid-body/component.js index c102b4be653..ccddddc089a 100644 --- a/src/framework/components/rigid-body/component.js +++ b/src/framework/components/rigid-body/component.js @@ -55,6 +55,66 @@ const _vec3 = new Vec3(); * @category Physics */ class RigidBodyComponent extends Component { + /** + * Fired when a contact occurs between two rigid bodies. The handler is passed a + * {@link ContactResult} object containing details of the contact between the two rigid bodies. + * + * @event + * @example + * entity.rigidbody.on('contact', (result) => { + * console.log(`Contact between ${entity.name} and ${result.other.name}`); + * }); + */ + static EVENT_CONTACT = 'contact'; + + /** + * Fired when two rigid bodies start touching. The handler is passed a {@link ContactResult} + * object containing details of the contact between the two rigid bodies. + * + * @event + * @example + * entity.rigidbody.on('collisionstart', (result) => { + * console.log(`Collision started between ${entity.name} and ${result.other.name}`); + * }); + */ + static EVENT_COLLISIONSTART = 'collisionstart'; + + /** + * Fired when two rigid bodies stop touching. The handler is passed a {@link ContactResult} + * object containing details of the contact between the two rigid bodies. + * + * @event + * @example + * entity.rigidbody.on('collisionend', (result) => { + * console.log(`Collision ended between ${entity.name} and ${result.other.name}`); + * }); + */ + static EVENT_COLLISIONEND = 'collisionend'; + + /** + * Fired when a rigid body enters a trigger volume. The handler is passed an {@link Entity} + * representing the trigger volume that this rigid body entered. + * + * @event + * @example + * entity.rigidbody.on('triggerenter', (trigger) => { + * console.log(`Entity ${entity.name} entered trigger volume ${trigger.name}`); + * }); + */ + static EVENT_TRIGGERENTER = 'triggerenter'; + + /** + * Fired when a rigid body exits a trigger volume. The handler is passed an {@link Entity} + * representing the trigger volume that this rigid body exited. + * + * @event + * @example + * entity.rigidbody.on('triggerleave', (trigger) => { + * console.log(`Entity ${entity.name} exited trigger volume ${trigger.name}`); + * }); + */ + static EVENT_TRIGGERLEAVE = 'triggerleave'; + /** @private */ _angularDamping = 0; @@ -111,41 +171,6 @@ class RigidBodyComponent extends Component { super(system, entity); } - /** - * Fired when a contact occurs between two rigid bodies. - * - * @event RigidBodyComponent#contact - * @param {ContactResult} result - Details of the contact between the two rigid bodies. - */ - - /** - * Fired when two rigid bodies start touching. - * - * @event RigidBodyComponent#collisionstart - * @param {ContactResult} result - Details of the contact between the two rigid bodies. - */ - - /** - * Fired when two rigid bodies stop touching. - * - * @event RigidBodyComponent#collisionend - * @param {import('../../entity.js').Entity} other - The {@link Entity} that stopped touching this rigid body. - */ - - /** - * Fired when a rigid body enters a trigger volume. - * - * @event RigidBodyComponent#triggerenter - * @param {import('../../entity.js').Entity} other - The {@link Entity} with trigger volume that this rigid body entered. - */ - - /** - * Fired when a rigid body exits a trigger volume. - * - * @event RigidBodyComponent#triggerleave - * @param {import('../../entity.js').Entity} other - The {@link Entity} with trigger volume that this rigid body exited. - */ - /** @ignore */ static onLibraryLoaded() { // Lazily create shared variable diff --git a/src/framework/components/rigid-body/system.js b/src/framework/components/rigid-body/system.js index 7a2b1186181..220784aa674 100644 --- a/src/framework/components/rigid-body/system.js +++ b/src/framework/components/rigid-body/system.js @@ -257,6 +257,18 @@ const _schema = ['enabled']; * @category Physics */ class RigidBodyComponentSystem extends ComponentSystem { + /** + * Fired when a contact occurs between two rigid bodies. The handler is passed a + * {@link SingleContactResult} object containing details of the contact between the two bodies. + * + * @event + * @example + * app.systems.rigidbody.on('contact', (result) => { + * console.log(`Contact between ${result.a.name} and ${result.b.name}`); + * }); + */ + static EVENT_CONTACT = 'contact'; + /** * @type {number} * @ignore @@ -334,13 +346,6 @@ class RigidBodyComponentSystem extends ComponentSystem { this.on('beforeremove', this.onBeforeRemove, this); } - /** - * Fired when a contact occurs between two rigid bodies. - * - * @event RigidBodyComponentSystem#contact - * @param {SingleContactResult} result - Details of the contact between the two bodies. - */ - /** * Called once Ammo has been loaded. Responsible for creating the physics world. * diff --git a/src/framework/components/script/component.js b/src/framework/components/script/component.js index 91e57c1f70e..60b5475a139 100644 --- a/src/framework/components/script/component.js +++ b/src/framework/components/script/component.js @@ -19,187 +19,173 @@ import { Entity } from '../../entity.js'; */ class ScriptComponent extends Component { /** - * Create a new ScriptComponent instance. + * Fired when a {@link ScriptType} instance is created and attached to the script component. + * This event is available in two forms. They are as follows: * - * @param {import('./system.js').ScriptComponentSystem} system - The ComponentSystem that - * created this Component. - * @param {Entity} entity - The Entity that this Component is attached to. - */ - constructor(system, entity) { - super(system, entity); - - /** - * Holds all script instances for this component. - * - * @type {import('../../script/script-type.js').ScriptType[]} - * @private - */ - this._scripts = []; - // holds all script instances with an update method - this._updateList = new SortedLoopArray({ sortBy: '__executionOrder' }); - // holds all script instances with a postUpdate method - this._postUpdateList = new SortedLoopArray({ sortBy: '__executionOrder' }); - - this._scriptsIndex = {}; - this._destroyedScripts = []; - this._destroyed = false; - this._scriptsData = null; - this._oldState = true; - - // override default 'enabled' property of base pc.Component - // because this is faster - this._enabled = true; - - // whether this component is currently being enabled - this._beingEnabled = false; - // if true then we are currently looping through - // script instances. This is used to prevent a scripts array - // from being modified while a loop is being executed - this._isLoopingThroughScripts = false; - - // the order that this component will be updated - // by the script system. This is set by the system itself. - this._executionOrder = -1; - - this.on('set_enabled', this._onSetEnabled, this); - } - - /** - * Fired when Component becomes enabled. Note: this event does not take in account entity or - * any of its parent enabled state. + * 1. `create` - Fired when a script instance is created. The name of the script type and the + * script type instance are passed as arguments. + * 2. `create:[name]` - Fired when a script instance is created that has the specified script + * type name. The script instance is passed as an argument to the handler. * - * @event ScriptComponent#enable + * @event * @example - * entity.script.on('enable', function () { - * // component is enabled + * entity.script.on('create', (name, scriptInstance) => { + * console.log(`Instance of script '${name}' created`); * }); - */ - - /** - * Fired when Component becomes disabled. Note: this event does not take in account entity or - * any of its parent enabled state. - * - * @event ScriptComponent#disable * @example - * entity.script.on('disable', function () { - * // component is disabled + * entity.script.on('create:player', (scriptInstance) => { + * console.log(`Instance of script 'player' created`); * }); */ + static EVENT_CREATE = 'create'; /** - * Fired when Component changes state to enabled or disabled. Note: this event does not take in - * account entity or any of its parent enabled state. + * Fired when a {@link ScriptType} instance is destroyed and removed from the script component. + * This event is available in two forms. They are as follows: * - * @event ScriptComponent#state - * @param {boolean} enabled - True if now enabled, False if disabled. + * 1. `destroy` - Fired when a script instance is destroyed. The name of the script type and + * the script type instance are passed as arguments. + * 2. `destroy:[name]` - Fired when a script instance is destroyed that has the specified + * script type name. The script instance is passed as an argument. + * + * @event * @example - * entity.script.on('state', function (enabled) { - * // component changed state + * entity.script.on('destroy', (name, scriptInstance) => { + * console.log(`Instance of script '${name}' destroyed`); * }); - */ - - /** - * Fired when Component is removed from entity. - * - * @event ScriptComponent#remove * @example - * entity.script.on('remove', function () { - * // entity has no more script component + * entity.script.on('destroy:player', (scriptInstance) => { + * console.log(`Instance of script 'player' destroyed`); * }); */ + static EVENT_DESTROY = 'destroy'; /** - * Fired when a script instance is created and attached to component. + * Fired when the script component becomes enabled. This event does not take into account the + * enabled state of the entity or any of its ancestors. * - * @event ScriptComponent#create - * @param {string} name - The name of the Script Type. - * @param {import('../../script/script-type.js').ScriptType} scriptInstance - The instance of - * the {@link ScriptType} that has been created. + * @event * @example - * entity.script.on('create', function (name, scriptInstance) { - * // new script instance added to component + * entity.script.on('enable', () => { + * console.log(`Script component of entity '${entity.name}' has been enabled`); * }); */ + static EVENT_ENABLE = 'enable'; /** - * Fired when a script instance is created and attached to component. + * Fired when the script component becomes disabled. This event does not take into account the + * enabled state of the entity or any of its ancestors. * - * @event ScriptComponent#create:[name] - * @param {import('../../script/script-type.js').ScriptType} scriptInstance - The instance of - * the {@link ScriptType} that has been created. + * @event * @example - * entity.script.on('create:playerController', function (scriptInstance) { - * // new script instance 'playerController' is added to component + * entity.script.on('disable', () => { + * console.log(`Script component of entity '${entity.name}' has been disabled`); * }); */ + static EVENT_DISABLE = 'disable'; /** - * Fired when a script instance is destroyed and removed from component. + * Fired when the script component has been removed from its entity. * - * @event ScriptComponent#destroy - * @param {string} name - The name of the Script Type. - * @param {import('../../script/script-type.js').ScriptType} scriptInstance - The instance of - * the {@link ScriptType} that has been destroyed. + * @event * @example - * entity.script.on('destroy', function (name, scriptInstance) { - * // script instance has been destroyed and removed from component + * entity.script.on('remove', () => { + * console.log(`Script component removed from entity '${entity.name}'`); * }); */ + static EVENT_REMOVE = 'remove'; /** - * Fired when a script instance is destroyed and removed from component. + * Fired when the script component changes state to enabled or disabled. The handler is passed + * the new boolean enabled state of the script component. This event does not take into account + * the enabled state of the entity or any of its ancestors. * - * @event ScriptComponent#destroy:[name] - * @param {import('../../script/script-type.js').ScriptType} scriptInstance - The instance of - * the {@link ScriptType} that has been destroyed. + * @event * @example - * entity.script.on('destroy:playerController', function (scriptInstance) { - * // script instance 'playerController' has been destroyed and removed from component + * entity.script.on('state', (enabled) => { + * console.log(`Script component of entity '${entity.name}' changed state to '${enabled}'`); * }); */ + static EVENT_STATE = 'state'; /** - * Fired when a script instance is moved in component. + * Fired when the index of a {@link ScriptType} instance is changed in the script component. + * This event is available in two forms. They are as follows: * - * @event ScriptComponent#move - * @param {string} name - The name of the Script Type. - * @param {import('../../script/script-type.js').ScriptType} scriptInstance - The instance of - * the {@link ScriptType} that has been moved. - * @param {number} ind - New position index. - * @param {number} indOld - Old position index. + * 1. `move` - Fired when a script instance is moved. The name of the script type, the script + * type instance, the new index and the old index are passed as arguments. + * 2. `move:[name]` - Fired when a specifically named script instance is moved. The script + * instance, the new index and the old index are passed as arguments. + * + * @event * @example - * entity.script.on('move', function (name, scriptInstance, ind, indOld) { - * // script instance has been moved in component + * entity.script.on('move', (name, scriptInstance, newIndex, oldIndex) => { + * console.log(`Script '${name}' moved from index '${oldIndex}' to '${newIndex}'`); + * }); + * @example + * entity.script.on('move:player', (scriptInstance, newIndex, oldIndex) => { + * console.log(`Script 'player' moved from index '${oldIndex}' to '${newIndex}'`); * }); */ + static EVENT_MOVE = 'move'; /** - * Fired when a script instance is moved in component. + * Fired when a {@link ScriptType} instance had an exception. The handler is passed the script + * instance, the exception and the method name that the exception originated from. * - * @event ScriptComponent#move:[name] - * @param {import('../../script/script-type.js').ScriptType} scriptInstance - The instance of - * the {@link ScriptType} that has been moved. - * @param {number} ind - New position index. - * @param {number} indOld - Old position index. + * @event * @example - * entity.script.on('move:playerController', function (scriptInstance, ind, indOld) { - * // script instance 'playerController' has been moved in component + * entity.script.on('error', (scriptInstance, exception, methodName) => { + * console.log(`Script error: ${exception} in method '${methodName}'`); * }); */ + static EVENT_ERROR = 'error'; /** - * Fired when a script instance had an exception. + * Create a new ScriptComponent instance. * - * @event ScriptComponent#error - * @param {import('../../script/script-type.js').ScriptType} scriptInstance - The instance of - * the {@link ScriptType} that raised the exception. - * @param {Error} err - Native JS Error object with details of an error. - * @param {string} method - The method of the script instance that the exception originated from. - * @example - * entity.script.on('error', function (scriptInstance, err, method) { - * // script instance caught an exception - * }); + * @param {import('./system.js').ScriptComponentSystem} system - The ComponentSystem that + * created this Component. + * @param {Entity} entity - The Entity that this Component is attached to. */ + constructor(system, entity) { + super(system, entity); + + /** + * Holds all script instances for this component. + * + * @type {import('../../script/script-type.js').ScriptType[]} + * @private + */ + this._scripts = []; + // holds all script instances with an update method + this._updateList = new SortedLoopArray({ sortBy: '__executionOrder' }); + // holds all script instances with a postUpdate method + this._postUpdateList = new SortedLoopArray({ sortBy: '__executionOrder' }); + + this._scriptsIndex = {}; + this._destroyedScripts = []; + this._destroyed = false; + this._scriptsData = null; + this._oldState = true; + + // override default 'enabled' property of base pc.Component + // because this is faster + this._enabled = true; + + // whether this component is currently being enabled + this._beingEnabled = false; + // if true then we are currently looping through + // script instances. This is used to prevent a scripts array + // from being modified while a loop is being executed + this._isLoopingThroughScripts = false; + + // the order that this component will be updated + // by the script system. This is set by the system itself. + this._executionOrder = -1; + + this.on('set_enabled', this._onSetEnabled, this); + } /** * An array of all script instances attached to an entity. This array is read-only and should diff --git a/src/framework/components/scroll-view/component.js b/src/framework/components/scroll-view/component.js index c3c618b476f..5d870762057 100644 --- a/src/framework/components/scroll-view/component.js +++ b/src/framework/components/scroll-view/component.js @@ -58,6 +58,19 @@ const _tempScrollValue = new Vec2(); * @category User Interface */ class ScrollViewComponent extends Component { + /** + * Fired whenever the scroll position changes. The handler is passed a {@link Vec2} containing + * the horizontal and vertical scroll values in the range 0..1. + * + * @event + * @example + * entity.scrollview.on('set:scroll', (scroll) => { + * console.log(`Horizontal scroll position: ${scroll.x}`); + * console.log(`Vertical scroll position: ${scroll.y}`); + * }); + */ + static EVENT_SETSCROLL = 'set:scroll'; + /** * Create a new ScrollViewComponent. * @@ -106,13 +119,6 @@ class ScrollViewComponent extends Component { this._toggleElementListeners('on'); } - /** - * Fired whenever the scroll position changes. - * - * @event ScrollViewComponent#set:scroll - * @param {Vec2} scrollPosition - Horizontal and vertical scroll values in the range 0...1. - */ - /** * @param {string} onOrOff - 'on' or 'off'. * @param {import('./system.js').ScrollViewComponentSystem} system - The ComponentSystem that diff --git a/src/framework/components/scrollbar/component.js b/src/framework/components/scrollbar/component.js index d702d3465b1..d77c11fc7ff 100644 --- a/src/framework/components/scrollbar/component.js +++ b/src/framework/components/scrollbar/component.js @@ -28,6 +28,18 @@ import { EntityReference } from '../../utils/entity-reference.js'; * @category User Interface */ class ScrollbarComponent extends Component { + /** + * Fired whenever the scroll value changes. The handler is passed a number representing the + * current scroll value. + * + * @event + * @example + * entity.scrollbar.on('set:value', (value) => { + * console.log(`Scroll value is now ${value}`); + * }); + */ + static EVENT_SETVALUE = 'set:value'; + /** * Create a new ScrollbarComponent. * @@ -50,13 +62,6 @@ class ScrollbarComponent extends Component { this._toggleLifecycleListeners('on'); } - /** - * Fired whenever the scroll value changes. - * - * @event ScrollbarComponent#set:value - * @param {number} value - The current scroll value. - */ - /** * @param {string} onOrOff - 'on' or 'off'. * @private diff --git a/src/framework/components/sound/component.js b/src/framework/components/sound/component.js index 5989d9da73e..f2f98cc2068 100644 --- a/src/framework/components/sound/component.js +++ b/src/framework/components/sound/component.js @@ -13,6 +13,66 @@ import { SoundSlot } from './slot.js'; * @category Sound */ class SoundComponent extends Component { + /** + * Fired when a sound instance starts playing. The handler is passed the {@link SoundSlot} and + * the {@link SoundInstance} that started playing. + * + * @event + * @example + * entity.sound.on('play', (slot, instance) => { + * console.log(`Sound ${slot.name} started playing`); + * }); + */ + static EVENT_PLAY = 'play'; + + /** + * Fired when a sound instance is paused. The handler is passed the {@link SoundSlot} and the + * {@link SoundInstance} that was paused. + * + * @event + * @example + * entity.sound.on('pause', (slot, instance) => { + * console.log(`Sound ${slot.name} paused`); + * }); + */ + static EVENT_PAUSE = 'pause'; + + /** + * Fired when a sound instance is resumed. The handler is passed the {@link SoundSlot} and the + * {@link SoundInstance} that was resumed. + * + * @event + * @example + * entity.sound.on('resume', (slot, instance) => { + * console.log(`Sound ${slot.name} resumed`); + * }); + */ + static EVENT_RESUME = 'resume'; + + /** + * Fired when a sound instance is stopped. The handler is passed the {@link SoundSlot} and the + * {@link SoundInstance} that was stopped. + * + * @event + * @example + * entity.sound.on('stop', (slot, instance) => { + * console.log(`Sound ${slot.name} stopped`); + * }); + */ + static EVENT_STOP = 'stop'; + + /** + * Fired when a sound instance stops playing because it reached its end. The handler is passed + * the {@link SoundSlot} and the {@link SoundInstance} that ended. + * + * @event + * @example + * entity.sound.on('end', (slot, instance) => { + * console.log(`Sound ${slot.name} ended`); + * }); + */ + static EVENT_END = 'end'; + /** * Create a new Sound Component. * @@ -49,51 +109,6 @@ class SoundComponent extends Component { this._playingBeforeDisable = {}; } - /** - * Fired when a sound instance starts playing. - * - * @event SoundComponent#play - * @param {SoundSlot} slot - The slot whose instance started playing. - * @param {import('../../../platform/sound/instance.js').SoundInstance} instance - The instance - * that started playing. - */ - - /** - * Fired when a sound instance is paused. - * - * @event SoundComponent#pause - * @param {SoundSlot} slot - The slot whose instance was paused. - * @param {import('../../../platform/sound/instance.js').SoundInstance} instance - The instance - * that was paused created to play the sound. - */ - - /** - * Fired when a sound instance is resumed. - * - * @event SoundComponent#resume - * @param {SoundSlot} slot - The slot whose instance was resumed. - * @param {import('../../../platform/sound/instance.js').SoundInstance} instance - The instance - * that was resumed. - */ - - /** - * Fired when a sound instance is stopped. - * - * @event SoundComponent#stop - * @param {SoundSlot} slot - The slot whose instance was stopped. - * @param {import('../../../platform/sound/instance.js').SoundInstance} instance - The instance - * that was stopped. - */ - - /** - * Fired when a sound instance stops playing because it reached its ending. - * - * @event SoundComponent#end - * @param {SoundSlot} slot - The slot whose instance ended. - * @param {import('../../../platform/sound/instance.js').SoundInstance} instance - The instance - * that ended. - */ - /** * Update the specified property on all sound instances. * diff --git a/src/framework/components/sound/slot.js b/src/framework/components/sound/slot.js index f2af18a0ff6..8266fd59a40 100644 --- a/src/framework/components/sound/slot.js +++ b/src/framework/components/sound/slot.js @@ -35,6 +35,66 @@ const instanceOptions = { * @category Sound */ class SoundSlot extends EventHandler { + /** + * Fired when a {@link SoundInstance} starts playing on a slot. The handler is passed the sound + * instance that started playing. + * + * @event + * @example + * slot.on('play', (instance) => { + * console.log('Sound instance started playing'); + * }); + */ + static EVENT_PLAY = 'play'; + + /** + * Fired when a {@link SoundInstance} is paused on a slot. The handler is passed the sound + * instance that is paused. + * + * @event + * @example + * slot.on('pause', (instance) => { + * console.log('Sound instance paused'); + * }); + */ + static EVENT_PAUSE = 'pause'; + + /** + * Fired when a {@link SoundInstance} is resumed on a slot. The handler is passed the sound + * instance that is resumed. + * + * @event + * @example + * slot.on('resume', (instance) => { + * console.log('Sound instance resumed'); + * }); + */ + static EVENT_RESUME = 'resume'; + + /** + * Fired when a {@link SoundInstance} is stopped on a slot. The handler is passed the sound + * instance that is stopped. + * + * @event + * @example + * slot.on('stop', (instance) => { + * console.log('Sound instance stopped'); + * }); + */ + static EVENT_STOP = 'stop'; + + /** + * Fired when the sound {@link Asset} assigned to the slot is loaded. The handler is passed the + * loaded {@link Sound} resource. + * + * @event + * @example + * slot.on('load', (sound) => { + * console.log('Sound resource loaded'); + * }); + */ + static EVENT_LOAD = 'load'; + /** * The name of the slot. * @@ -102,42 +162,6 @@ class SoundSlot extends EventHandler { this._onInstanceEndHandler = this._onInstanceEnd.bind(this); } - /** - * Fired when a sound instance starts playing. - * - * @event SoundSlot#play - * @param {SoundInstance} instance - The instance that started playing. - */ - - /** - * Fired when a sound instance is paused. - * - * @event SoundSlot#pause - * @param {SoundInstance} instance - The instance that was paused created to play the sound. - */ - - /** - * Fired when a sound instance is resumed. - * - * @event SoundSlot#resume - * @param {SoundInstance} instance - The instance that was resumed. - */ - - /** - * Fired when a sound instance is stopped. - * - * @event SoundSlot#stop - * @param {SoundInstance} instance - The instance that was stopped. - */ - - /** - * Fired when the asset assigned to the slot is loaded. - * - * @event SoundSlot#load - * @param {import('../../../platform/sound/sound.js').Sound} sound - The sound resource that - * was loaded. - */ - /** * Plays a sound. If {@link SoundSlot#overlap} is true the new sound instance will be played * independently of any other instances already playing. Otherwise existing sound instances diff --git a/src/framework/components/sprite/component.js b/src/framework/components/sprite/component.js index c6d531c512b..d70fba56d9a 100644 --- a/src/framework/components/sprite/component.js +++ b/src/framework/components/sprite/component.js @@ -34,6 +34,78 @@ const PARAM_ATLAS_RECT = 'atlasRect'; * @category Graphics */ class SpriteComponent extends Component { + /** + * Fired when an animation clip starts playing. The handler is passed the + * {@link SpriteAnimationClip} that started playing. + * + * @event + * @example + * entity.sprite.on('play', (clip) => { + * console.log(`Animation clip ${clip.name} started playing.`); + * }); + */ + static EVENT_PLAY = 'play'; + + /** + * Fired when an animation clip is paused. The handler is passed the + * {@link SpriteAnimationClip} that was paused. + * + * @event + * @example + * entity.sprite.on('pause', (clip) => { + * console.log(`Animation clip ${clip.name} paused.`); + * }); + */ + static EVENT_PAUSE = 'pause'; + + /** + * Fired when an animation clip is resumed. The handler is passed the + * {@link SpriteAnimationClip} that was resumed. + * + * @event + * @example + * entity.sprite.on('resume', (clip) => { + * console.log(`Animation clip ${clip.name} resumed.`); + * }); + */ + static EVENT_RESUME = 'resume'; + + /** + * Fired when an animation clip is stopped. The handler is passed the + * {@link SpriteAnimationClip} that was stopped. + * + * @event + * @example + * entity.sprite.on('stop', (clip) => { + * console.log(`Animation clip ${clip.name} stopped.`); + * }); + */ + static EVENT_STOP = 'stop'; + + /** + * Fired when an animation clip stops playing because it reached its end. The handler is passed + * the {@link SpriteAnimationClip} that ended. + * + * @event + * @example + * entity.sprite.on('end', (clip) => { + * console.log(`Animation clip ${clip.name} ended.`); + * }); + */ + static EVENT_END = 'end'; + + /** + * Fired when an animation clip reached the end of its current loop. The handler is passed the + * {@link SpriteAnimationClip} that looped. + * + * @event + * @example + * entity.sprite.on('loop', (clip) => { + * console.log(`Animation clip ${clip.name} looped.`); + * }); + */ + static EVENT_LOOP = 'loop'; + /** * Create a new SpriteComponent instance. * @@ -109,48 +181,6 @@ class SpriteComponent extends Component { this._currentClip = this._defaultClip; } - /** - * Fired when an animation clip starts playing. - * - * @event SpriteComponent#play - * @param {SpriteAnimationClip} clip - The clip that started playing. - */ - - /** - * Fired when an animation clip is paused. - * - * @event SpriteComponent#pause - * @param {SpriteAnimationClip} clip - The clip that was paused. - */ - - /** - * Fired when an animation clip is resumed. - * - * @event SpriteComponent#resume - * @param {SpriteAnimationClip} clip - The clip that was resumed. - */ - - /** - * Fired when an animation clip is stopped. - * - * @event SpriteComponent#stop - * @param {SpriteAnimationClip} clip - The clip that was stopped. - */ - - /** - * Fired when an animation clip stops playing because it reached its ending. - * - * @event SpriteComponent#end - * @param {SpriteAnimationClip} clip - The clip that ended. - */ - - /** - * Fired when an animation clip reached the end of its current loop. - * - * @event SpriteComponent#loop - * @param {SpriteAnimationClip} clip - The clip. - */ - /** * The type of the SpriteComponent. Can be: * diff --git a/src/framework/components/sprite/sprite-animation-clip.js b/src/framework/components/sprite/sprite-animation-clip.js index 5a1ebbb53ec..e0fa22d3708 100644 --- a/src/framework/components/sprite/sprite-animation-clip.js +++ b/src/framework/components/sprite/sprite-animation-clip.js @@ -13,6 +13,72 @@ import { SPRITE_RENDERMODE_SIMPLE } from '../../../scene/constants.js'; * @category Graphics */ class SpriteAnimationClip extends EventHandler { + /** + * Fired when the clip starts playing. + * + * @event + * @example + * clip.on('play', () => { + * console.log('Clip started playing'); + * }); + */ + static EVENT_PLAY = 'play'; + + /** + * Fired when the clip is paused. + * + * @event + * @example + * clip.on('pause', () => { + * console.log('Clip paused'); + * }); + */ + static EVENT_PAUSE = 'pause'; + + /** + * Fired when the clip is resumed. + * + * @event + * @example + * clip.on('resume', () => { + * console.log('Clip resumed'); + * }); + */ + static EVENT_RESUME = 'resume'; + + /** + * Fired when the clip is stopped. + * + * @event + * @example + * clip.on('stop', () => { + * console.log('Clip stopped'); + * }); + */ + static EVENT_STOP = 'stop'; + + /** + * Fired when the clip stops playing because it reached its end. + * + * @event + * @example + * clip.on('end', () => { + * console.log('Clip ended'); + * }); + */ + static EVENT_END = 'end'; + + /** + * Fired when the clip reached the end of its current loop. + * + * @event + * @example + * clip.on('loop', () => { + * console.log('Clip looped'); + * }); + */ + static EVENT_LOOP = 'loop'; + /** * Create a new SpriteAnimationClip instance. * @@ -44,42 +110,6 @@ class SpriteAnimationClip extends EventHandler { this._time = 0; } - /** - * Fired when the clip starts playing. - * - * @event SpriteAnimationClip#play - */ - - /** - * Fired when the clip is paused. - * - * @event SpriteAnimationClip#pause - */ - - /** - * Fired when the clip is resumed. - * - * @event SpriteAnimationClip#resume - */ - - /** - * Fired when the clip is stopped. - * - * @event SpriteAnimationClip#stop - */ - - /** - * Fired when the clip stops playing because it reached its ending. - * - * @event SpriteAnimationClip#end - */ - - /** - * Fired when the clip reached the end of its current loop. - * - * @event SpriteAnimationClip#loop - */ - /** * The total duration of the animation in seconds. * diff --git a/src/framework/components/zone/component.js b/src/framework/components/zone/component.js index 35416e34451..582dbce48c9 100644 --- a/src/framework/components/zone/component.js +++ b/src/framework/components/zone/component.js @@ -14,68 +14,67 @@ import { Component } from '../component.js'; */ class ZoneComponent extends Component { /** - * Create a new ZoneComponent instance. + * Fired when the zone component is enabled. This event does not take into account the enabled + * state of the entity or any of its ancestors. * - * @param {import('./system.js').ZoneComponentSystem} system - The ComponentSystem that - * created this Component. - * @param {import('../../entity.js').Entity} entity - The Entity that this Component is - * attached to. + * @event + * @example + * entity.zone.on('enable', () => { + * console.log(`Zone component of entity '${entity.name}' has been enabled`); + * }); */ - constructor(system, entity) { - super(system, entity); - - this._oldState = true; - this._size = new Vec3(); - this.on('set_enabled', this._onSetEnabled, this); - } + static EVENT_ENABLE = 'enable'; /** - * Fired when Component becomes enabled. Note: this event does not take in account entity or - * any of its parent enabled state. + * Fired when the zone component is disabled. This event does not take into account the enabled + * state of the entity or any of its ancestors. * - * @event ZoneComponent#enable + * @event * @example - * entity.zone.on('enable', function () { - * // component is enabled + * entity.zone.on('disable', () => { + * console.log(`Zone component of entity '${entity.name}' has been disabled`); * }); - * @ignore */ + static EVENT_DISABLE = 'disable'; /** - * Fired when Component becomes disabled. Note: this event does not take in account entity or - * any of its parent enabled state. + * Fired when the enabled state of the zone component changes. This event does not take into + * account the enabled state of the entity or any of its ancestors. * - * @event ZoneComponent#disable + * @event * @example - * entity.zone.on('disable', function () { - * // component is disabled + * entity.zone.on('state', (enabled) => { + * console.log(`Zone component of entity '${entity.name}' has been ${enabled ? 'enabled' : 'disabled'}`); * }); - * @ignore */ + static EVENT_STATE = 'state'; /** - * Fired when Component changes state to enabled or disabled. Note: this event does not take in - * account entity or any of its parent enabled state. + * Fired when a zone component is removed from an entity. * - * @event ZoneComponent#state - * @param {boolean} enabled - True if now enabled, False if disabled. + * @event * @example - * entity.zone.on('state', function (enabled) { - * // component changed state + * entity.zone.on('remove', () => { + * console.log(`Zone component removed from entity '${entity.name}'`); * }); - * @ignore */ + static EVENT_REMOVE = 'remove'; /** - * Fired when a zone is removed from an entity. + * Create a new ZoneComponent instance. * - * @event ZoneComponent#remove - * @example - * entity.zone.on('remove', function () { - * // zone has been removed from an entity - * }); - * @ignore + * @param {import('./system.js').ZoneComponentSystem} system - The ComponentSystem that + * created this Component. + * @param {import('../../entity.js').Entity} entity - The Entity that this Component is + * attached to. */ + constructor(system, entity) { + super(system, entity); + + this._oldState = true; + this._size = new Vec3(); + this.on('set_enabled', this._onSetEnabled, this); + } /** * The size of the axis-aligned box of this ZoneComponent. diff --git a/src/framework/entity.js b/src/framework/entity.js index e2948d60d5d..408903b25ea 100644 --- a/src/framework/entity.js +++ b/src/framework/entity.js @@ -27,6 +27,17 @@ const _enableList = []; * @augments GraphNode */ class Entity extends GraphNode { + /** + * Fired after the entity is destroyed. + * + * @event + * @example + * entity.on('destroy', (e) => { + * console.log(`Entity ${e.name} has been destroyed`); + * }); + */ + static EVENT_DESTROY = 'destroy'; + /** * Gets the {@link AnimComponent} attached to this entity. * @@ -677,15 +688,4 @@ function resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, oldEntity, n } } -/** - * Fired after the entity is destroyed. - * - * @event Entity#destroy - * @param {Entity} entity - The entity that was destroyed. - * @example - * entity.on("destroy", function (e) { - * console.log('entity ' + e.name + ' has been destroyed'); - * }); - */ - export { Entity }; diff --git a/src/framework/script/script-type.js b/src/framework/script/script-type.js index 29dd24a972f..62ea7fad1f3 100644 --- a/src/framework/script/script-type.js +++ b/src/framework/script/script-type.js @@ -33,6 +33,101 @@ const funcNameRegex = new RegExp('^\\s*function(?:\\s|\\s*\\/\\*.*\\*\\/\\s*)+([ * @augments EventHandler */ class ScriptType extends EventHandler { + /** + * Fired when a script instance becomes enabled. + * + * @event + * @example + * PlayerController.prototype.initialize = function () { + * this.on('enable', () => { + * // Script Instance is now enabled + * }); + * }; + */ + static EVENT_ENABLE = 'enable'; + + /** + * Fired when a script instance becomes disabled. + * + * @event + * @example + * PlayerController.prototype.initialize = function () { + * this.on('disable', () => { + * // Script Instance is now disabled + * }); + * }; + */ + static EVENT_DISABLE = 'disable'; + + /** + * Fired when a script instance changes state to enabled or disabled. The handler is passed a + * boolean parameter that states whether the script instance is now enabled or disabled. + * + * @event + * @example + * PlayerController.prototype.initialize = function () { + * this.on('state', (enabled) => { + * console.log(`Script Instance is now ${enabled ? 'enabled' : 'disabled'}`); + * }); + * }; + */ + static EVENT_STATE = 'state'; + + /** + * Fired when a script instance is destroyed and removed from component. + * + * @event + * @example + * PlayerController.prototype.initialize = function () { + * this.on('destroy', () => { + * // no longer part of the entity + * // this is a good place to clean up allocated resources used by the script + * }); + * }; + */ + static EVENT_DESTROY = 'destroy'; + + /** + * Fired when script attributes have changed. This event is available in two forms. They are as follows: + * + * 1. `attr` - Fired for any attribute change. The handler is passed the name of the attribute + * that changed, the value of the attribute before the change and the value of the attribute + * after the change. + * 2. `attr:[name]` - Fired for a specific attribute change. The handler is passed the value of + * the attribute before the change and the value of the attribute after the change. + * + * @event + * @example + * PlayerController.prototype.initialize = function () { + * this.on('attr', (name, newValue, oldValue) => { + * console.log(`Attribute '${name}' changed from '${oldValue}' to '${newValue}'`); + * }); + * }; + * @example + * PlayerController.prototype.initialize = function () { + * this.on('attr:speed', (newValue, oldValue) => { + * console.log(`Attribute 'speed' changed from '${oldValue}' to '${newValue}'`); + * }); + * }; + */ + static EVENT_ATTR = 'attr'; + + /** + * Fired when a script instance had an exception. The script instance will be automatically + * disabled. The handler is passed an {@link Error} object containing the details of the + * exception and the name of the method that threw the exception. + * + * @event + * @example + * PlayerController.prototype.initialize = function () { + * this.on('error', (err, method) => { + * // caught an exception + * console.log(err.stack); + * }); + * }; + */ + static EVENT_ERROR = 'error'; + /** * The {@link AppBase} that the instance of this type belongs to. * @@ -94,101 +189,6 @@ class ScriptType extends EventHandler { this.initScriptType(args); } - /** - * Fired when a script instance becomes enabled. - * - * @event ScriptType#enable - * @example - * PlayerController.prototype.initialize = function () { - * this.on('enable', function () { - * // Script Instance is now enabled - * }); - * }; - */ - - /** - * Fired when a script instance becomes disabled. - * - * @event ScriptType#disable - * @example - * PlayerController.prototype.initialize = function () { - * this.on('disable', function () { - * // Script Instance is now disabled - * }); - * }; - */ - - /** - * Fired when a script instance changes state to enabled or disabled. - * - * @event ScriptType#state - * @param {boolean} enabled - True if now enabled, False if disabled. - * @example - * PlayerController.prototype.initialize = function () { - * this.on('state', function (enabled) { - * console.log('Script Instance is now ' + (enabled ? 'enabled' : 'disabled')); - * }); - * }; - */ - - /** - * Fired when a script instance is destroyed and removed from component. - * - * @event ScriptType#destroy - * @example - * PlayerController.prototype.initialize = function () { - * this.on('destroy', function () { - * // no more part of an entity - * // good place to cleanup entity from destroyed script - * }); - * }; - */ - - /** - * Fired when any script attribute has been changed. - * - * @event ScriptType#attr - * @param {string} name - Name of attribute. - * @param {object} value - New value. - * @param {object} valueOld - Old value. - * @example - * PlayerController.prototype.initialize = function () { - * this.on('attr', function (name, value, valueOld) { - * console.log(name + ' been changed from ' + valueOld + ' to ' + value); - * }); - * }; - */ - - /** - * Fired when a specific script attribute has been changed. - * - * @event ScriptType#attr:[name] - * @param {object} value - New value. - * @param {object} valueOld - Old value. - * @example - * PlayerController.prototype.initialize = function () { - * this.on('attr:speed', function (value, valueOld) { - * console.log('speed been changed from ' + valueOld + ' to ' + value); - * }); - * }; - */ - - /** - * Fired when a script instance had an exception. The script instance will be automatically - * disabled. - * - * @event ScriptType#error - * @param {Error} err - Native JavaScript Error object with details of error. - * @param {string} method - The method of the script instance that the exception originated from. - * @example - * PlayerController.prototype.initialize = function () { - * this.on('error', function (err, method) { - * // caught an exception - * console.log(err.stack); - * }); - * }; - */ - /** * True if the instance of this type is in running state. False when script is not running, * because the Entity or any of its parents are disabled or the {@link ScriptComponent} is diff --git a/src/framework/xr/xr-anchor.js b/src/framework/xr/xr-anchor.js index fc1c109b9ee..abd8afca39b 100644 --- a/src/framework/xr/xr-anchor.js +++ b/src/framework/xr/xr-anchor.js @@ -29,6 +29,55 @@ import { Quat } from '../../core/math/quat.js'; * @category XR */ class XrAnchor extends EventHandler { + /** + * Fired when an anchor is destroyed. + * + * @event + * @example + * // once anchor is destroyed + * anchor.once('destroy', () => { + * // destroy its related entity + * entity.destroy(); + * }); + */ + static EVENT_DESTROY = 'destroy'; + + /** + * Fired when an anchor's position and/or rotation is changed. + * + * @event + * @example + * anchor.on('change', () => { + * // anchor has been updated + * entity.setPosition(anchor.getPosition()); + * entity.setRotation(anchor.getRotation()); + * }); + */ + static EVENT_CHANGE = 'change'; + + /** + * Fired when an anchor has has been persisted. The handler is passed the UUID string that can + * be used to restore this anchor. + * + * @event + * @example + * anchor.on('persist', (uuid) => { + * // anchor has been persisted + * }); + */ + static EVENT_PERSIST = 'persist'; + + /** + * Fired when an anchor has been forgotten. + * + * @event + * @example + * anchor.on('forget', () => { + * // anchor has been forgotten + * }); + */ + static EVENT_FORGET = 'forget'; + /** * @type {Vec3} * @private @@ -67,51 +116,6 @@ class XrAnchor extends EventHandler { this._uuid = uuid; } - /** - * Fired when an {@link XrAnchor} is destroyed. - * - * @event XrAnchor#destroy - * @example - * // once anchor is destroyed - * anchor.once('destroy', function () { - * // destroy its related entity - * entity.destroy(); - * }); - */ - - /** - * Fired when an {@link XrAnchor}'s position and/or rotation is changed. - * - * @event XrAnchor#change - * @example - * anchor.on('change', function () { - * // anchor has been updated - * entity.setPosition(anchor.getPosition()); - * entity.setRotation(anchor.getRotation()); - * }); - */ - - /** - * Fired when an {@link XrAnchor}'s has been persisted. - * - * @event XrAnchor#persist - * @param {string} uuid - Unique string that can be used to restore this anchor. - * @example - * anchor.on('persist', function (uuid) { - * // anchor has been persisted - * }); - */ - - /** - * Fired when an {@link XrAnchor}'s has been forgotten. - * - * @event XrAnchor#forget - * @example - * anchor.on('forget', function () { - * // anchor has been forgotten - * }); - */ - /** * Destroy an anchor. */ diff --git a/src/framework/xr/xr-anchors.js b/src/framework/xr/xr-anchors.js index 77c5264d97c..8ca63d91aae 100644 --- a/src/framework/xr/xr-anchors.js +++ b/src/framework/xr/xr-anchors.js @@ -26,6 +26,63 @@ import { XrAnchor } from './xr-anchor.js'; * @category XR */ class XrAnchors extends EventHandler { + /** + * Fired when anchors become available. + * + * @event + * @example + * app.xr.anchors.on('available', () => { + * console.log('Anchors are available'); + * }); + */ + static EVENT_AVAILABLE = 'available'; + + /** + * Fired when anchors become unavailable. + * + * @event + * @example + * app.xr.anchors.on('unavailable', () => { + * console.log('Anchors are unavailable'); + * }); + */ + static EVENT_UNAVAILABLE = 'unavailable'; + + /** + * Fired when an anchor failed to be created. The handler is passed an Error object. + * + * @event + * @example + * app.xr.anchors.on('error', (err) => { + * console.error(err.message); + * }); + */ + static EVENT_ERROR = 'error'; + + /** + * Fired when a new {@link XrAnchor} is added. The handler is passed the {@link XrAnchor} that + * was added. + * + * @event + * @example + * app.xr.anchors.on('add', (anchor) => { + * console.log('Anchor added'); + * }); + */ + static EVENT_ADD = 'add'; + + /** + * Fired when an {@link XrAnchor} is destroyed. The handler is passed the {@link XrAnchor} that + * was destroyed. + * + * @event + * @example + * app.xr.anchors.on('destroy', (anchor) => { + * console.log('Anchor destroyed'); + * }); + */ + static EVENT_DESTROY = 'destroy'; + /** * @type {import('./xr-manager.js').XrManager} * @ignore @@ -104,47 +161,6 @@ class XrAnchors extends EventHandler { } } - /** - * Fired when anchors becomes available. - * - * @event XrAnchors#available - */ - - /** - * Fired when anchors becomes unavailable. - * - * @event XrAnchors#unavailable - */ - - /** - * Fired when anchor failed to be created. - * - * @event XrAnchors#error - * @param {Error} error - Error object related to a failure of anchors. - */ - - /** - * Fired when a new {@link XrAnchor} is added. - * - * @event XrAnchors#add - * @param {XrAnchor} anchor - Anchor that has been added. - * @example - * app.xr.anchors.on('add', function (anchor) { - * // new anchor is added - * }); - */ - - /** - * Fired when an {@link XrAnchor} is destroyed. - * - * @event XrAnchors#destroy - * @param {XrAnchor} anchor - Anchor that has been destroyed. - * @example - * app.xr.anchors.on('destroy', function (anchor) { - * // anchor that is destroyed - * }); - */ - /** @private */ _onSessionStart() { const available = this.manager.session.enabledFeatures.indexOf('anchors') !== -1; diff --git a/src/framework/xr/xr-depth-sensing.js b/src/framework/xr/xr-depth-sensing.js index c385a79fa32..fd21bf8564d 100644 --- a/src/framework/xr/xr-depth-sensing.js +++ b/src/framework/xr/xr-depth-sensing.js @@ -8,6 +8,24 @@ import { Mat4 } from '../../core/math/mat4.js'; * @ignore */ class XrDepthSensing extends EventHandler { + /** + * @event + * @deprecated + */ + static EVENT_AVAILABLE = 'available'; + + /** + * @event + * @deprecated + */ + static EVENT_UNAVAILABLE = 'unavailable'; + + /** + * @event + * @deprecated + */ + static EVENT_RESIZE = 'resize'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -54,26 +72,6 @@ class XrDepthSensing extends EventHandler { } } - /** - * @event XrDepthSensing#available - * @deprecated - * @ignore - */ - - /** - * @event XrDepthSensing#unavailable - * @deprecated - * @ignore - */ - - /** - * @event XrDepthSensing#resize - * @param {number} width - * @param {number} height - * @deprecated - * @ignore - */ - /** @private */ _onSessionStart() { if (this._views.availableDepth) @@ -102,7 +100,6 @@ class XrDepthSensing extends EventHandler { * @param {number} u - u * @param {number} v - v * @deprecated - * @ignore * @returns {number|null} number */ getDepth(u, v) { @@ -111,7 +108,6 @@ class XrDepthSensing extends EventHandler { /** * @deprecated - * @ignore */ update() { if (this._manager.session && this.supported && this._views.availableDepth && this._views.list.length && !this._available) { @@ -123,7 +119,6 @@ class XrDepthSensing extends EventHandler { /** * @type {boolean} * @deprecated - * @ignore */ get supported() { return this._views.supportedDepth; @@ -132,7 +127,6 @@ class XrDepthSensing extends EventHandler { /** * @type {boolean} * @deprecated - * @ignore */ get available() { return this._views.availableDepth; @@ -141,7 +135,6 @@ class XrDepthSensing extends EventHandler { /** * @type {string} * @deprecated - * @ignore */ get usage() { return this._views.depthUsage; @@ -150,7 +143,6 @@ class XrDepthSensing extends EventHandler { /** * @type {string} * @deprecated - * @ignore */ get dataFormat() { return this._views.depthFormat; @@ -159,7 +151,6 @@ class XrDepthSensing extends EventHandler { /** * @type {number} * @deprecated - * @ignore */ get width() { return this._views.list[0]?.textureDepth?.width ?? 0; @@ -168,7 +159,6 @@ class XrDepthSensing extends EventHandler { /** * @type {number} * @deprecated - * @ignore */ get height() { return this._views.list[0]?.textureDepth?.height ?? 0; @@ -177,7 +167,6 @@ class XrDepthSensing extends EventHandler { /** * @type {import('../../platform/graphics/texture.js').Texture|null} * @deprecated - * @ignore */ get texture() { return this._views.list[0]?.textureDepth; @@ -186,7 +175,6 @@ class XrDepthSensing extends EventHandler { /** * @type {Mat4} * @deprecated - * @ignore */ get uvMatrix() { return this._views.list[0]?.depthUvMatrix ?? this._uvMatrix; @@ -195,7 +183,6 @@ class XrDepthSensing extends EventHandler { /** * @type {number} * @deprecated - * @ignore */ get rawValueToMeters() { return this._views.list[0]?.depthValueToMeters ?? 0; diff --git a/src/framework/xr/xr-hand.js b/src/framework/xr/xr-hand.js index c7bee527be3..5b8d0a28736 100644 --- a/src/framework/xr/xr-hand.js +++ b/src/framework/xr/xr-hand.js @@ -34,6 +34,28 @@ if (platform.browser && window.XRHand) { * @category XR */ class XrHand extends EventHandler { + /** + * Fired when tracking becomes available. + * + * @event + * @example + * hand.on('tracking', () => { + * console.log('Hand tracking is available'); + * }); + */ + static EVENT_TRACKING = 'tracking'; + + /** + * Fired when tracking is lost. + * + * @event + * @example + * hand.on('trackinglost', () => { + * console.log('Hand tracking is lost'); + * }); + */ + static EVENT_TRACKINGLOST = 'trackinglost'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -125,18 +147,6 @@ class XrHand extends EventHandler { } } - /** - * Fired when tracking becomes available. - * - * @event XrHand#tracking - */ - - /** - * Fired when tracking is lost. - * - * @event XrHand#trackinglost - */ - /** * @param {*} frame - XRFrame from requestAnimationFrame callback. * @ignore diff --git a/src/framework/xr/xr-hit-test-source.js b/src/framework/xr/xr-hit-test-source.js index c65b8398b67..d52f8e01e93 100644 --- a/src/framework/xr/xr-hit-test-source.js +++ b/src/framework/xr/xr-hit-test-source.js @@ -22,6 +22,32 @@ const poolQuat = []; * @category XR */ class XrHitTestSource extends EventHandler { + /** + * Fired when {@link XrHitTestSource} is removed. + * + * @event + * @example + * hitTestSource.once('remove', () => { + * // hit test source has been removed + * }); + */ + static EVENT_REMOVE = 'remove'; + + /** + * Fired when the hit test source receives new results. It provides transform information that + * tries to match real world picked geometry. The handler is passed the {@link Vec3} position, + * the {@link Quat} rotation, the {@link XrInputSource} (if it is a transient hit test source) + * and the {@link XRHitTestResult} object that is created by WebXR API. + * + * @event + * @example + * hitTestSource.on('result', (position, rotation) => { + * target.setPosition(position); + * target.setRotation(rotation); + * }); + */ + static EVENT_RESULT = 'result'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -64,33 +90,6 @@ class XrHitTestSource extends EventHandler { this._inputSource = inputSource; } - /** - * Fired when {@link XrHitTestSource} is removed. - * - * @event XrHitTestSource#remove - * @example - * hitTestSource.once('remove', function () { - * // hit test source has been removed - * }); - */ - - /** - * Fired when hit test source receives new results. It provides transform information that - * tries to match real world picked geometry. - * - * @event XrHitTestSource#result - * @param {Vec3} position - Position of hit test. - * @param {Quat} rotation - Rotation of hit test. - * @param {import('./xr-input-source.js').XrInputSource|null} inputSource - If is transient hit - * test source, then it will provide related input source. - * @param {XRHitTestResult} XRHitTestResult - object that is created by WebXR API. - * @example - * hitTestSource.on('result', function (position, rotation) { - * target.setPosition(position); - * target.setRotation(rotation); - * }); - */ - /** * Stop and remove hit test source. */ diff --git a/src/framework/xr/xr-hit-test.js b/src/framework/xr/xr-hit-test.js index c2f1636935b..e853202091f 100644 --- a/src/framework/xr/xr-hit-test.js +++ b/src/framework/xr/xr-hit-test.js @@ -21,6 +21,56 @@ import { XrHitTestSource } from './xr-hit-test-source.js'; * @category XR */ class XrHitTest extends EventHandler { + /** + * Fired when new {@link XrHitTestSource} is added to the list. The handler is passed the + * {@link XrHitTestSource} object that has been added. + * + * @event + * @example + * app.xr.hitTest.on('add', (hitTestSource) => { + * // new hit test source is added + * }); + */ + static EVENT_ADD = 'add'; + + /** + * Fired when {@link XrHitTestSource} is removed to the list. The handler is passed the + * {@link XrHitTestSource} object that has been removed. + * + * @event + * @example + * app.xr.hitTest.on('remove', (hitTestSource) => { + * // hit test source is removed + * }); + */ + static EVENT_REMOVE = 'remove'; + + /** + * Fired when hit test source receives new results. It provides transform information that + * tries to match real world picked geometry. The handler is passed the {@link XrHitTestSource} + * that produced the hit result, the {@link Vec3} position, the {@link Quat} rotation and the + * {@link XrInputSource} (if it is a transient hit test source). + * + * @event + * @example + * app.xr.hitTest.on('result', (hitTestSource, position, rotation, inputSource) => { + * target.setPosition(position); + * target.setRotation(rotation); + * }); + */ + static EVENT_RESULT = 'result'; + + /** + * Fired when failed create hit test source. The handler is passed the Error object. + * + * @event + * @example + * app.xr.hitTest.on('error', (err) => { + * console.error(err.message); + * }); + */ + static EVENT_ERROR = 'error'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -63,52 +113,6 @@ class XrHitTest extends EventHandler { } } - /** - * Fired when new {@link XrHitTestSource} is added to the list. - * - * @event XrHitTest#add - * @param {XrHitTestSource} hitTestSource - Hit test source that has been added. - * @example - * app.xr.hitTest.on('add', function (hitTestSource) { - * // new hit test source is added - * }); - */ - - /** - * Fired when {@link XrHitTestSource} is removed to the list. - * - * @event XrHitTest#remove - * @param {XrHitTestSource} hitTestSource - Hit test source that has been removed. - * @example - * app.xr.hitTest.on('remove', function (hitTestSource) { - * // hit test source is removed - * }); - */ - - /** - * Fired when hit test source receives new results. It provides transform information that - * tries to match real world picked geometry. - * - * @event XrHitTest#result - * @param {XrHitTestSource} hitTestSource - Hit test source that produced the hit result. - * @param {import('../../core/math/vec3.js').Vec3} position - Position of hit test. - * @param {import('../../core/math/quat.js').Quat} rotation - Rotation of hit test. - * @param {import('./xr-input-source.js').XrInputSource|null} inputSource - If is transient hit - * test source, then it will provide related input source. - * @example - * app.xr.hitTest.on('result', function (hitTestSource, position, rotation, inputSource) { - * target.setPosition(position); - * target.setRotation(rotation); - * }); - */ - - /** - * Fired when failed create hit test source. - * - * @event XrHitTest#error - * @param {Error} error - Error object related to failure of creating hit test source. - */ - /** @private */ _onSessionStart() { if (this.manager.type !== XRTYPE_AR) diff --git a/src/framework/xr/xr-image-tracking.js b/src/framework/xr/xr-image-tracking.js index d938a38f1e7..055b6e3d439 100644 --- a/src/framework/xr/xr-image-tracking.js +++ b/src/framework/xr/xr-image-tracking.js @@ -11,6 +11,18 @@ import { XrTrackedImage } from './xr-tracked-image.js'; * @category XR */ class XrImageTracking extends EventHandler { + /** + * Fired when the XR session is started, but image tracking failed to process the provided + * images. The handler is passed the Error object. + * + * @event + * @example + * app.xr.imageTracking.on('error', (err) => { + * console.error(err.message); + * }); + */ + static EVENT_ERROR = 'error'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -53,14 +65,6 @@ class XrImageTracking extends EventHandler { } } - /** - * Fired when the XR session is started, but image tracking failed to process the provided - * images. - * - * @event XrImageTracking#error - * @param {Error} error - Error object related to a failure of image tracking. - */ - /** * Add an image for image tracking. A width can also be provided to help the underlying system * estimate the appropriate transformation. Modifying the tracked images list is only possible diff --git a/src/framework/xr/xr-input-source.js b/src/framework/xr/xr-input-source.js index 46f1a31985f..fae6c3468c4 100644 --- a/src/framework/xr/xr-input-source.js +++ b/src/framework/xr/xr-input-source.js @@ -22,6 +22,136 @@ let ids = 0; * @category XR */ class XrInputSource extends EventHandler { + /** + * Fired when {@link XrInputSource} is removed. + * + * @event + * @example + * inputSource.once('remove', () => { + * // input source is not available anymore + * }); + */ + static EVENT_REMOVE = 'remove'; + + /** + * Fired when input source has triggered primary action. This could be pressing a trigger + * button, or touching a screen. The handler is passed an {@link XRInputSourceEvent} object + * from the WebXR API. + * + * @event + * @example + * const ray = new pc.Ray(); + * inputSource.on('select', (evt) => { + * ray.set(inputSource.getOrigin(), inputSource.getDirection()); + * if (obj.intersectsRay(ray)) { + * // selected an object with input source + * } + * }); + */ + static EVENT_SELECT = 'select'; + + /** + * Fired when input source has started to trigger primary action. The handler is passed an + * {@link XRInputSourceEvent} object from the WebXR API. + * + * @event + * @example + * inputSource.on('selectstart', (evt) => { + * console.log('Select started'); + * }); + */ + static EVENT_SELECTSTART = 'selectstart'; + + /** + * Fired when input source has ended triggering primary action. The handler is passed an + * {@link XRInputSourceEvent} object from the WebXR API. + * + * @event + * @example + * inputSource.on('selectend', (evt) => { + * console.log('Select ended'); + * }); + */ + static EVENT_SELECTEND = 'selectend'; + + /** + * Fired when input source has triggered squeeze action. This is associated with "grabbing" + * action on the controllers. The handler is passed an {@link XRInputSourceEvent} object from + * the WebXR API. + * + * @event + * @example + * inputSource.on('squeeze', (evt) => { + * console.log('Squeeze'); + * }); + */ + static EVENT_SQUEEZE = 'squeeze'; + + /** + * Fired when input source has started to trigger squeeze action. The handler is passed an + * {@link XRInputSourceEvent} object from the WebXR API. + * + * @event + * @example + * inputSource.on('squeezestart', (evt) => { + * if (obj.containsPoint(inputSource.getPosition())) { + * // grabbed an object + * } + * }); + */ + static EVENT_SQUEEZESTART = 'squeezestart'; + + /** + * Fired when input source has ended triggering squeeze action. The handler is passed an + * {@link XRInputSourceEvent} object from the WebXR API. + * + * @event + * @example + * inputSource.on('squeezeend', (evt) => { + * console.log('Squeeze ended'); + * }); + */ + static EVENT_SQUEEZEEND = 'squeezeend'; + + /** + * Fired when new {@link XrHitTestSource} is added to the input source. The handler is passed + * the {@link XrHitTestSource} object that has been added. + * + * @event + * @example + * inputSource.on('hittest:add', (hitTestSource) => { + * // new hit test source is added + * }); + */ + static EVENT_HITTESTADD = 'hittest:add'; + + /** + * Fired when {@link XrHitTestSource} is removed to the the input source. The handler is passed + * the {@link XrHitTestSource} object that has been removed. + * + * @event + * @example + * inputSource.on('remove', (hitTestSource) => { + * // hit test source is removed + * }); + */ + static EVENT_HITTESTREMOVE = 'hittest:remove'; + + /** + * Fired when hit test source receives new results. It provides transform information that + * tries to match real world picked geometry. The handler is passed the {@link XrHitTestSource} + * object that produced the hit result, the {@link Vec3} position and the {@link Quat} + * rotation. + * + * @event + * @example + * inputSource.on('hittest:result', (hitTestSource, position, rotation) => { + * target.setPosition(position); + * target.setRotation(rotation); + * }); + */ + static EVENT_HITTESTRESULT = 'hittest:result'; + /** * @type {number} * @private @@ -186,114 +316,6 @@ class XrInputSource extends EventHandler { this._hand = new XrHand(this); } - /** - * Fired when {@link XrInputSource} is removed. - * - * @event XrInputSource#remove - * @example - * inputSource.once('remove', function () { - * // input source is not available anymore - * }); - */ - - /** - * Fired when input source has triggered primary action. This could be pressing a trigger - * button, or touching a screen. - * - * @event XrInputSource#select - * @param {object} evt - XRInputSourceEvent event data from WebXR API. - * @example - * const ray = new pc.Ray(); - * inputSource.on('select', function (evt) { - * ray.set(inputSource.getOrigin(), inputSource.getDirection()); - * if (obj.intersectsRay(ray)) { - * // selected an object with input source - * } - * }); - */ - - /** - * Fired when input source has started to trigger primary action. - * - * @event XrInputSource#selectstart - * @param {object} evt - XRInputSourceEvent event data from WebXR API. - */ - - /** - * Fired when input source has ended triggering primary action. - * - * @event XrInputSource#selectend - * @param {object} evt - XRInputSourceEvent event data from WebXR API. - */ - - /** - * Fired when input source has triggered squeeze action. This is associated with "grabbing" - * action on the controllers. - * - * @event XrInputSource#squeeze - * @param {object} evt - XRInputSourceEvent event data from WebXR API. - */ - - /** - * Fired when input source has started to trigger squeeze action. - * - * @event XrInputSource#squeezestart - * @param {object} evt - XRInputSourceEvent event data from WebXR API. - * @example - * inputSource.on('squeezestart', function (evt) { - * if (obj.containsPoint(inputSource.getPosition())) { - * // grabbed an object - * } - * }); - */ - - /** - * Fired when input source has ended triggering squeeze action. - * - * @event XrInputSource#squeezeend - * @param {object} evt - XRInputSourceEvent event data from WebXR API. - */ - - /** - * Fired when new {@link XrHitTestSource} is added to the input source. - * - * @event XrInputSource#hittest:add - * @param {import('./xr-hit-test-source.js').XrHitTestSource} hitTestSource - Hit test source - * that has been added. - * @example - * inputSource.on('hittest:add', function (hitTestSource) { - * // new hit test source is added - * }); - */ - - /** - * Fired when {@link XrHitTestSource} is removed to the the input source. - * - * @event XrInputSource#hittest:remove - * @param {import('./xr-hit-test-source.js').XrHitTestSource} hitTestSource - Hit test source - * that has been removed. - * @example - * inputSource.on('remove', function (hitTestSource) { - * // hit test source is removed - * }); - */ - - /** - * Fired when hit test source receives new results. It provides transform information that - * tries to match real world picked geometry. - * - * @event XrInputSource#hittest:result - * @param {import('./xr-hit-test-source.js').XrHitTestSource} hitTestSource - Hit test source - * that produced the hit result. - * @param {Vec3} position - Position of hit test. - * @param {Quat} rotation - Rotation of hit test. - * @example - * inputSource.on('hittest:result', function (hitTestSource, position, rotation) { - * target.setPosition(position); - * target.setRotation(rotation); - * }); - */ - /** * Unique number associated with instance of input source. Same physical devices when * reconnected will not share this ID. diff --git a/src/framework/xr/xr-input.js b/src/framework/xr/xr-input.js index edd2bfb003f..4b23eadc622 100644 --- a/src/framework/xr/xr-input.js +++ b/src/framework/xr/xr-input.js @@ -10,134 +10,156 @@ import { XrInputSource } from './xr-input-source.js'; */ class XrInput extends EventHandler { /** - * @type {import('./xr-manager.js').XrManager} - * @private - */ - manager; - - /** - * @type {XrInputSource[]} - * @private - */ - _inputSources = []; - - /** - * @type {Function} - * @private - */ - _onInputSourcesChangeEvt; - - /** - * @type {boolean} - * @ignore - */ - velocitiesSupported = false; - - /** - * Create a new XrInput instance. - * - * @param {import('./xr-manager.js').XrManager} manager - WebXR Manager. - * @hideconstructor - */ - constructor(manager) { - super(); - - this.manager = manager; - this.velocitiesSupported = !!(platform.browser && window.XRPose?.prototype?.hasOwnProperty('linearVelocity')); - - this._onInputSourcesChangeEvt = (evt) => { - this._onInputSourcesChange(evt); - }; - - this.manager.on('start', this._onSessionStart, this); - this.manager.on('end', this._onSessionEnd, this); - } - - /** - * Fired when new {@link XrInputSource} is added to the list. + * Fired when a new {@link XrInputSource} is added to the list. The handler is passed the + * {@link XrInputSource} that has been added. * - * @event XrInput#add - * @param {XrInputSource} inputSource - Input source that has been added. + * @event * @example - * app.xr.input.on('add', function (inputSource) { + * app.xr.input.on('add', (inputSource) => { * // new input source is added * }); */ + static EVENT_ADD = 'add'; /** - * Fired when {@link XrInputSource} is removed to the list. + * Fired when an {@link XrInputSource} is removed to the list. The handler is passed the + * {@link XrInputSource} that has been removed. * - * @event XrInput#remove - * @param {XrInputSource} inputSource - Input source that has been removed. + * @event * @example - * app.xr.input.on('remove', function (inputSource) { + * app.xr.input.on('remove', (inputSource) => { * // input source is removed * }); */ + static EVENT_REMOVE = 'remove'; /** * Fired when {@link XrInputSource} has triggered primary action. This could be pressing a - * trigger button, or touching a screen. + * trigger button, or touching a screen. The handler is passed the {@link XrInputSource} that + * triggered the select event and the XRInputSourceEvent event from the WebXR API. * - * @event XrInput#select - * @param {XrInputSource} inputSource - Input source that triggered select event. - * @param {object} evt - XRInputSourceEvent event data from WebXR API. + * @event * @example * const ray = new pc.Ray(); - * app.xr.input.on('select', function (inputSource, evt) { + * app.xr.input.on('select', (inputSource, evt) => { * ray.set(inputSource.getOrigin(), inputSource.getDirection()); * if (obj.intersectsRay(ray)) { * // selected an object with input source * } * }); */ + static EVENT_SELECT = 'select'; /** - * Fired when {@link XrInputSource} has started to trigger primary action. + * Fired when {@link XrInputSource} has started to trigger primary action. The handler is + * passed the {@link XrInputSource} that triggered the selectstart event and the + * XRInputSourceEvent event from the WebXR API. * - * @event XrInput#selectstart - * @param {XrInputSource} inputSource - Input source that triggered selectstart event. - * @param {object} evt - XRInputSourceEvent event data from WebXR API. + * @event + * @example + * app.xr.input.on('selectstart', (inputSource, evt) => { + * console.log('Select started'); + * }); */ + static EVENT_SELECTSTART = 'selectstart'; /** - * Fired when {@link XrInputSource} has ended triggerring primary action. + * Fired when {@link XrInputSource} has ended triggering primary action. The handler is passed + * the {@link XrInputSource} that triggered the selectend event and the XRInputSourceEvent + * event from the WebXR API. * - * @event XrInput#selectend - * @param {XrInputSource} inputSource - Input source that triggered selectend event. - * @param {object} evt - XRInputSourceEvent event data from WebXR API. + * @event + * @example + * app.xr.input.on('selectend', (inputSource, evt) => { + * console.log('Select ended'); + * }); */ + static EVENT_SELECTEND = 'selectend'; /** * Fired when {@link XrInputSource} has triggered squeeze action. This is associated with - * "grabbing" action on the controllers. + * "grabbing" action on the controllers. The handler is passed the {@link XrInputSource} that + * triggered the squeeze event and the XRInputSourceEvent event from the WebXR API. * - * @event XrInput#squeeze - * @param {XrInputSource} inputSource - Input source that triggered squeeze event. - * @param {object} evt - XRInputSourceEvent event data from WebXR API. + * @event + * @example + * app.xr.input.on('squeeze', (inputSource, evt) => { + * console.log('Squeeze'); + * }); */ + static EVENT_SQUEEZE = 'squeeze'; /** - * Fired when {@link XrInputSource} has started to trigger sqeeze action. + * Fired when {@link XrInputSource} has started to trigger sqeeze action. The handler is + * passed the {@link XrInputSource} that triggered the squeezestart event and the + * XRInputSourceEvent event from the WebXR API. * - * @event XrInput#squeezestart - * @param {XrInputSource} inputSource - Input source that triggered squeezestart event. - * @param {object} evt - XRInputSourceEvent event data from WebXR API. + * @event * @example - * app.xr.input.on('squeezestart', function (inputSource, evt) { + * app.xr.input.on('squeezestart', (inputSource, evt) => { * if (obj.containsPoint(inputSource.getPosition())) { * // grabbed an object * } * }); */ + static EVENT_SQUEEZESTART = 'squeezestart'; + + /** + * Fired when {@link XrInputSource} has ended triggering sqeeze action. The handler is passed + * the {@link XrInputSource} that triggered the squeezeend event and the XRInputSourceEvent + * event from the WebXR API. + * + * @event + * @example + * app.xr.input.on('squeezeend', (inputSource, evt) => { + * console.log('Squeeze ended'); + * }); + */ + static EVENT_SQUEEZEEND = 'squeezeend'; + + /** + * @type {import('./xr-manager.js').XrManager} + * @private + */ + manager; + + /** + * @type {XrInputSource[]} + * @private + */ + _inputSources = []; + + /** + * @type {Function} + * @private + */ + _onInputSourcesChangeEvt; + + /** + * @type {boolean} + * @ignore + */ + velocitiesSupported = false; /** - * Fired when {@link XrInputSource} has ended triggerring sqeeze action. + * Create a new XrInput instance. * - * @event XrInput#squeezeend - * @param {XrInputSource} inputSource - Input source that triggered squeezeend event. - * @param {object} evt - XRInputSourceEvent event data from WebXR API. + * @param {import('./xr-manager.js').XrManager} manager - WebXR Manager. + * @hideconstructor */ + constructor(manager) { + super(); + + this.manager = manager; + this.velocitiesSupported = !!(platform.browser && window.XRPose?.prototype?.hasOwnProperty('linearVelocity')); + + this._onInputSourcesChangeEvt = (evt) => { + this._onInputSourcesChange(evt); + }; + + this.manager.on('start', this._onSessionStart, this); + this.manager.on('end', this._onSessionEnd, this); + } /** @private */ _onSessionStart() { diff --git a/src/framework/xr/xr-light-estimation.js b/src/framework/xr/xr-light-estimation.js index cab5b80158e..7a483aa330e 100644 --- a/src/framework/xr/xr-light-estimation.js +++ b/src/framework/xr/xr-light-estimation.js @@ -22,6 +22,29 @@ const mat4B = new Mat4(); * @category XR */ class XrLightEstimation extends EventHandler { + /** + * Fired when light estimation data becomes available. + * + * @event + * @example + * app.xr.lightEstimation.on('available', () => { + * console.log('Light estimation is available'); + * }); + */ + static EVENT_AVAILABLE = 'available'; + + /** + * Fired when light estimation has failed to start. The handler is passed the Error object + * related to failure of light estimation start. + * + * @event + * @example + * app.xr.lightEstimation.on('error', (error) => { + * console.error(error.message); + * }); + */ + static EVENT_ERROR = 'error'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -91,23 +114,6 @@ class XrLightEstimation extends EventHandler { this._manager.on('end', this._onSessionEnd, this); } - /** - * Fired when light estimation data becomes available. - * - * @event XrLightEstimation#available - */ - - /** - * Fired when light estimation has failed to start. - * - * @event XrLightEstimation#error - * @param {Error} error - Error object related to failure of light estimation start. - * @example - * app.xr.lightEstimation.on('error', function (ex) { - * // has failed to start - * }); - */ - /** @private */ _onSessionStart() { const supported = !!this._manager.session.requestLightProbe; diff --git a/src/framework/xr/xr-manager.js b/src/framework/xr/xr-manager.js index d136d4da246..0c03445280e 100644 --- a/src/framework/xr/xr-manager.js +++ b/src/framework/xr/xr-manager.js @@ -40,6 +40,75 @@ import { XrViews } from './xr-views.js'; * @category XR */ class XrManager extends EventHandler { + /** + * Fired when availability of the XR type is changed. This event is available in two + * forms. They are as follows: + * + * 1. `available` - Fired when availability of any XR type is changed. The handler is passed + * the session type that has changed availability and a boolean representing the availability. + * 2. `available:[type]` - Fired when availability of specific XR type is changed. The handler + * is passed a boolean representing the availability. + * + * @event + * @example + * app.xr.on('available', (type, available) => { + * console.log(`XR type ${type} is now ${available ? 'available' : 'unavailable'}`); + * }); + * @example + * app.xr.on(`available:${pc.XRTYPE_VR}`, (available) => { + * console.log(`XR type VR is now ${available ? 'available' : 'unavailable'}`); + * }); + */ + static EVENT_AVAILABLE = 'available'; + + /** + * Fired when XR session is started. + * + * @event + * @example + * app.xr.on('start', () => { + * // XR session has started + * }); + */ + static EVENT_START = 'start'; + + /** + * Fired when XR session is ended. + * + * @event + * @example + * app.xr.on('end', () => { + * // XR session has ended + * }); + */ + static EVENT_END = 'end'; + + /** + * Fired when XR session is updated, providing relevant XRFrame object. The handler is passed + * [XRFrame](https://developer.mozilla.org/en-US/docs/Web/API/XRFrame) object that can be used + * for interfacing directly with WebXR APIs. + * + * @event + * @example + * app.xr.on('update', (frame) => { + * console.log('XR frame updated'); + * }); + */ + static EVENT_UPDATE = 'update'; + + /** + * Fired when XR session is failed to start or failed to check for session type support. The handler + * is passed the [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) + * object related to failure of session start or check of session type support. + * + * @event + * @example + * app.xr.on('error', (error) => { + * console.error(error.message); + * }); + */ + static EVENT_ERROR = 'error'; + /** * @type {import('../app-base.js').AppBase} * @ignore @@ -258,73 +327,6 @@ class XrManager extends EventHandler { } } - /** - * Fired when availability of specific XR type is changed. - * - * @event XrManager#available - * @param {string} type - The session type that has changed availability. - * @param {boolean} available - True if specified session type is now available. - * @example - * app.xr.on('available', function (type, available) { - * console.log('"' + type + '" XR session is now ' + (available ? 'available' : 'unavailable')); - * }); - */ - - /** - * Fired when availability of specific XR type is changed. - * - * @event XrManager#available:[type] - * @param {boolean} available - True if specified session type is now available. - * @example - * app.xr.on('available:' + pc.XRTYPE_VR, function (available) { - * console.log('Immersive VR session is now ' + (available ? 'available' : 'unavailable')); - * }); - */ - - /** - * Fired when XR session is started. - * - * @event XrManager#start - * @example - * app.xr.on('start', function () { - * // XR session has started - * }); - */ - - /** - * Fired when XR session is ended. - * - * @event XrManager#end - * @example - * app.xr.on('end', function () { - * // XR session has ended - * }); - */ - - /** - * Fired when XR session is updated, providing relevant XRFrame object. - * - * @event XrManager#update - * @param {object} frame - [XRFrame](https://developer.mozilla.org/en-US/docs/Web/API/XRFrame) - * object that can be used for interfacing directly with WebXR APIs. - * @example - * app.xr.on('update', function (frame) { - * - * }); - */ - - /** - * Fired when XR session is failed to start or failed to check for session type support. - * - * @event XrManager#error - * @param {Error} error - Error object related to failure of session start or check of session - * type support. - * @example - * app.xr.on('error', function (ex) { - * // XR session has failed to start, or failed to check for session type support - * }); - */ - /** * Destroys the XrManager instance. * diff --git a/src/framework/xr/xr-mesh-detection.js b/src/framework/xr/xr-mesh-detection.js index e17d91f182e..e4d3dcd9d48 100644 --- a/src/framework/xr/xr-mesh-detection.js +++ b/src/framework/xr/xr-mesh-detection.js @@ -22,6 +22,52 @@ import { XrMesh } from "./xr-mesh.js"; * @category XR */ class XrMeshDetection extends EventHandler { + /** + * Fired when mesh detection becomes available. + * + * @event + * @example + * app.xr.meshDetection.on('available', () => { + * console.log('Mesh detection is available'); + * }); + */ + static EVENT_AVAILABLE = 'available'; + + /** + * Fired when mesh detection becomes unavailable. + * + * @event + * @example + * app.xr.meshDetection.on('unavailable', () => { + * console.log('Mesh detection is unavailable'); + * }); + */ + static EVENT_UNAVAILABLE = 'unavailable'; + + /** + * Fired when new {@link XrMesh} is added to the list. The handler is passed the {@link XrMesh} + * instance that has been added. + * + * @event + * @example + * app.xr.meshDetection.on('add', (mesh) => { + * // a new XrMesh has been added + * }); + */ + static EVENT_ADD = 'add'; + + /** + * Fired when a {@link XrMesh} is removed from the list. The handler is passed the + * {@link XrMesh} instance that has been removed. + * + * @event + * @example + * app.xr.meshDetection.on('remove', (mesh) => { + * // XrMesh has been removed + * }); + */ + static EVENT_REMOVE = 'remove'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -69,40 +115,6 @@ class XrMeshDetection extends EventHandler { } } - /** - * Fired when mesh detection becomes available. - * - * @event XrMeshDetection#available - */ - - /** - * Fired when mesh detection becomes unavailable. - * - * @event XrMeshDetection#unavailable - */ - - /** - * Fired when new {@link XrMesh} is added to the list. - * - * @event XrMeshDetection#add - * @param {XrMesh} mesh - Mesh that has been added. - * @example - * app.xr.meshDetection.on('add', (mesh) => { - * // a new XrMesh has been added - * }); - */ - - /** - * Fired when a {@link XrMesh} is removed from the list. - * - * @event XrMeshDetection#remove - * @param {XrMesh} mesh - Mesh that has been removed. - * @example - * app.xr.meshDetection.on('remove', (mesh) => { - * // XrMesh has been removed - * }); - */ - /** * @param {XRFrame} frame - XRFrame from requestAnimationFrame callback. * @ignore diff --git a/src/framework/xr/xr-mesh.js b/src/framework/xr/xr-mesh.js index 35728114b71..8959a3d402f 100644 --- a/src/framework/xr/xr-mesh.js +++ b/src/framework/xr/xr-mesh.js @@ -10,6 +10,29 @@ import { Quat } from "../../core/math/quat.js"; * @category XR */ class XrMesh extends EventHandler { + /** + * Fired when an {@link XrMesh} is removed. + * + * @event + * @example + * mesh.once('remove', () => { + * // mesh is no longer available + * }); + */ + static EVENT_REMOVE = 'remove'; + + /** + * Fired when {@link XrMesh} attributes such as vertices, indices and/or label have been + * changed. Position and rotation can change at any time without triggering a `change` event. + * + * @event + * @example + * mesh.on('change', () => { + * // mesh attributes have been changed + * }); + */ + static EVENT_CHANGE = 'change'; + /** * @type {import('./xr-mesh-detection.js').XrMeshDetection} * @private @@ -56,27 +79,6 @@ class XrMesh extends EventHandler { this._lastChanged = this._xrMesh.lastChangedTime; } - /** - * Fired when {@link XrMesh} is removed. - * - * @event XrMesh#remove - * @example - * mesh.once('remove', function () { - * // mesh is no longer available - * }); - */ - - /** - * Fired when {@link XrMesh} attributes such as vertices, indices and/or label have been changed. - * Position and rotation can change at any time without triggering a `change` event. - * - * @event XrMesh#change - * @example - * mesh.on('change', function () { - * // mesh attributes have been changed - * }); - */ - /** * @type {XRMesh} * @ignore diff --git a/src/framework/xr/xr-plane-detection.js b/src/framework/xr/xr-plane-detection.js index 356b7a483c3..3a9b9fdd868 100644 --- a/src/framework/xr/xr-plane-detection.js +++ b/src/framework/xr/xr-plane-detection.js @@ -14,7 +14,7 @@ import { XrPlane } from './xr-plane.js'; * ``` * * ```javascript - * app.xr.planeDetection.on('add', function (plane) { + * app.xr.planeDetection.on('add', (plane) => { * // new plane been added * }); * ``` @@ -22,6 +22,52 @@ import { XrPlane } from './xr-plane.js'; * @category XR */ class XrPlaneDetection extends EventHandler { + /** + * Fired when plane detection becomes available. + * + * @event + * @example + * app.xr.planeDetection.on('available', () => { + * console.log('Plane detection is available'); + * }); + */ + static EVENT_AVAILABLE = 'available'; + + /** + * Fired when plane detection becomes unavailable. + * + * @event + * @example + * app.xr.planeDetection.on('unavailable', () => { + * console.log('Plane detection is unavailable'); + * }); + */ + static EVENT_UNAVAILABLE = 'unavailable'; + + /** + * Fired when new {@link XrPlane} is added to the list. The handler is passed the + * {@link XrPlane} instance that has been added. + * + * @event + * @example + * app.xr.planeDetection.on('add', (plane) => { + * // new plane is added + * }); + */ + static EVENT_ADD = 'add'; + + /** + * Fired when a {@link XrPlane} is removed from the list. The handler is passed the + * {@link XrPlane} instance that has been removed. + * + * @event + * @example + * app.xr.planeDetection.on('remove', (plane) => { + * // new plane is removed + * }); + */ + static EVENT_REMOVE = 'remove'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -69,40 +115,6 @@ class XrPlaneDetection extends EventHandler { } } - /** - * Fired when plane detection becomes available. - * - * @event XrPlaneDetection#available - */ - - /** - * Fired when plane detection becomes unavailable. - * - * @event XrPlaneDetection#unavailable - */ - - /** - * Fired when new {@link XrPlane} is added to the list. - * - * @event XrPlaneDetection#add - * @param {XrPlane} plane - Plane that has been added. - * @example - * app.xr.planeDetection.on('add', function (plane) { - * // new plane is added - * }); - */ - - /** - * Fired when a {@link XrPlane} is removed from the list. - * - * @event XrPlaneDetection#remove - * @param {XrPlane} plane - Plane that has been removed. - * @example - * app.xr.planeDetection.on('remove', function (plane) { - * // new plane is removed - * }); - */ - /** @private */ _onSessionStart() { const available = this._supported && this._manager.session.enabledFeatures.indexOf('plane-detection') !== -1; diff --git a/src/framework/xr/xr-plane.js b/src/framework/xr/xr-plane.js index 537336bbc40..8181e99f378 100644 --- a/src/framework/xr/xr-plane.js +++ b/src/framework/xr/xr-plane.js @@ -11,6 +11,29 @@ let ids = 0; * @category XR */ class XrPlane extends EventHandler { + /** + * Fired when an {@link XrPlane} is removed. + * + * @event + * @example + * plane.once('remove', () => { + * // plane is not available anymore + * }); + */ + static EVENT_REMOVE = 'remove'; + + /** + * Fired when {@link XrPlane} attributes such as: orientation and/or points have been changed. + * Position and rotation can change at any time without triggering a `change` event. + * + * @event + * @example + * plane.on('change', () -> { + * // plane has been changed + * }); + */ + static EVENT_CHANGE = 'change'; + /** * @type {number} * @private @@ -71,27 +94,6 @@ class XrPlane extends EventHandler { this._orientation = xrPlane.orientation; } - /** - * Fired when {@link XrPlane} is removed. - * - * @event XrPlane#remove - * @example - * plane.once('remove', function () { - * // plane is not available anymore - * }); - */ - - /** - * Fired when {@link XrPlane} attributes such as: orientation and/or points have been changed. - * Position and rotation can change at any time without triggering a `change` event. - * - * @event XrPlane#change - * @example - * plane.on('change', function () { - * // plane has been changed - * }); - */ - /** @ignore */ destroy() { if (!this._xrPlane) return; diff --git a/src/framework/xr/xr-tracked-image.js b/src/framework/xr/xr-tracked-image.js index 435e9d0ba03..c4aa8a352db 100644 --- a/src/framework/xr/xr-tracked-image.js +++ b/src/framework/xr/xr-tracked-image.js @@ -11,6 +11,28 @@ import { Quat } from '../../core/math/quat.js'; * @category XR */ class XrTrackedImage extends EventHandler { + /** + * Fired when image becomes actively tracked. + * + * @event + * @example + * trackedImage.on('tracked', () => { + * console.log('Image is now tracked'); + * }); + */ + static EVENT_TRACKED = 'tracked'; + + /** + * Fired when image is no longer actively tracked. + * + * @event + * @example + * trackedImage.on('untracked', () => { + * console.log('Image is no longer tracked'); + * }); + */ + static EVENT_UNTRACKED = 'untracked'; + /** * @type {HTMLCanvasElement|HTMLImageElement|SVGImageElement|HTMLVideoElement|Blob|ImageData|ImageBitmap} * @private @@ -92,18 +114,6 @@ class XrTrackedImage extends EventHandler { this._width = width; } - /** - * Fired when image becomes actively tracked. - * - * @event XrTrackedImage#tracked - */ - - /** - * Fired when image is no more actively tracked. - * - * @event XrTrackedImage#untracked - */ - /** * Image that is used for tracking. * diff --git a/src/framework/xr/xr-view.js b/src/framework/xr/xr-view.js index e766c4f9b8a..1c21dca75f8 100644 --- a/src/framework/xr/xr-view.js +++ b/src/framework/xr/xr-view.js @@ -14,6 +14,19 @@ import { ADDRESS_CLAMP_TO_EDGE, FILTER_LINEAR, PIXELFORMAT_RGB8 } from '../../pl * @category XR */ class XrView extends EventHandler { + /** + * Fired when the depth sensing texture been resized. The {@link XrView#depthUvMatrix} needs + * to be updated for relevant shaders. The handler is passed the new width and height of the + * depth texture in pixels. + * + * @event + * @example + * view.on('depth:resize', () => { + * material.setParameter('matrix_depth_uv', view.depthUvMatrix); + * }); + */ + static EVENT_DEPTHRESIZE = 'depth:resize'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -175,19 +188,6 @@ class XrView extends EventHandler { device.on('devicelost', this._onDeviceLost, this); } - /** - * Fired when the depth sensing texture been resized. The {@link XrView#depthUvMatrix} needs - * to be updated for relevant shaders. - * - * @event XrView#depth:resize - * @param {number} width - The new width of the depth texture in pixels. - * @param {number} height - The new height of the depth texture in pixels. - * @example - * view.on('depth:resize', function () { - * material.setParameter('matrix_depth_uv', view.depthUvMatrix); - * }); - */ - /** * Texture associated with this view's camera color. Equals to null if camera color is * not available or not supported. diff --git a/src/framework/xr/xr-views.js b/src/framework/xr/xr-views.js index f89596ac31c..d50329c7b96 100644 --- a/src/framework/xr/xr-views.js +++ b/src/framework/xr/xr-views.js @@ -11,6 +11,31 @@ import { PIXELFORMAT_LA8, PIXELFORMAT_R32F } from '../../platform/graphics/const * @category XR */ class XrViews extends EventHandler { + /** + * Fired when view has been added. Views are not available straight away on session start + * and are added mid-session. They can be added/removed mid session by underlyng system. The + * handler is passed the {@link XrView} that has been added. + * + * @event + * @example + * xr.views.on('add', (view) => { + * console.log('View added'); + * }); + */ + static EVENT_ADD = 'add'; + + /** + * Fired when view has been removed. They can be added/removed mid session by underlyng system. + * The handler is passed the {@link XrView} that has been removed. + * + * @event + * @example + * xr.views.on('remove', (view) => { + * console.log('View removed'); + * }); + */ + static EVENT_REMOVE = 'remove'; + /** * @type {import('./xr-manager.js').XrManager} * @private @@ -92,29 +117,6 @@ class XrViews extends EventHandler { this._manager.on('end', this._onSessionEnd, this); } - /** - * Fired when view has been added. Views are not available straight away on session start - * and are added mid-session. They can be added/removed mid session by underlyng system. - * - * @event XrViews#add - * @param {XrView} view - XrView that has been added. - * @example - * xr.views.on('add', function (view) { - * // view that has been added - * }); - */ - - /** - * Fired when view has been removed. They can be added/removed mid session by underlyng system. - * - * @event XrViews#remove - * @param {XrView} view - XrView that has been removed. - * @example - * xr.views.on('remove', function (view) { - * // view that has been added - * }); - */ - /** * An array of {@link XrView}'s of this session. Views are not available straight * away on session start, and can be added/removed mid-session. So use of add/remove diff --git a/src/platform/graphics/graphics-device.js b/src/platform/graphics/graphics-device.js index a2361c85e00..9be81f85af1 100644 --- a/src/platform/graphics/graphics-device.js +++ b/src/platform/graphics/graphics-device.js @@ -30,6 +30,17 @@ import { StencilParameters } from './stencil-parameters.js'; * @category Graphics */ class GraphicsDevice extends EventHandler { + /** + * Fired when the canvas is resized. The handler is passed the new width and height as number + * parameters. + * + * @event + * @example + * graphicsDevice.on('resizecanvas', (width, height) => { + * console.log(`The canvas was resized to ${width}x${height}`); + * }); + */ + /** * The canvas DOM element that provides the underlying WebGL context used by the graphics device. * @@ -435,14 +446,6 @@ class GraphicsDevice extends EventHandler { this.quadVertexBuffer = new VertexBuffer(this, vertexFormat, 4, BUFFER_STATIC, positions); } - /** - * Fired when the canvas is resized. - * - * @event GraphicsDevice#resizecanvas - * @param {number} width - The new width of the canvas in pixels. - * @param {number} height - The new height of the canvas in pixels. - */ - /** * Destroy the graphics device. */ diff --git a/src/platform/input/game-pads.js b/src/platform/input/game-pads.js index 18925696a2a..fcd2e7fc218 100644 --- a/src/platform/input/game-pads.js +++ b/src/platform/input/game-pads.js @@ -775,6 +775,38 @@ class GamePad { * @category Input */ class GamePads extends EventHandler { + /** + * Fired when a gamepad is connected. The handler is passed the {@link GamePad} object that was + * connected. + * + * @event + * @example + * const onPadConnected = (pad) => { + * if (!pad.mapping) { + * // Map the gamepad as the system could not find the proper map. + * } else { + * // Make the gamepad pulse. + * } + * }; + * + * app.keyboard.on("gamepadconnected", onPadConnected, this); + */ + static EVENT_GAMEPADCONNECTED = 'gamepadconnected'; + + /** + * Fired when a gamepad is disconnected. The handler is passed the {@link GamePad} object that + * was disconnected. + * + * @event + * @example + * const onPadDisconnected = (pad) => { + * // Pause the game. + * }; + * + * app.keyboard.on("gamepaddisconnected", onPadDisconnected, this); + */ + static EVENT_GAMEPADDISCONNECTED = 'gamepaddisconnected'; + /** * Create a new GamePads instance. */ @@ -812,34 +844,6 @@ class GamePads extends EventHandler { this.poll(); } - /** - * Fired when a gamepad is connected. - * - * @event GamePads#gamepadconnected - * @param {GamePad} gamepad - The gamepad that was just connected. - * @example - * const onPadConnected = function (pad) { - * if (!pad.mapping) { - * // Map the gamepad as the system could not find the proper map. - * } else { - * // Make the gamepad pulse. - * } - * }; - * app.keyboard.on("gamepadconnected", onPadConnected, this); - */ - - /** - * Fired when a gamepad is disconnected. - * - * @event GamePads#gamepaddisconnected - * @param {GamePad} gamepad - The gamepad that was just disconnected. - * @example - * const onPadDisconnected = function (pad) { - * // Pause the game. - * }; - * app.keyboard.on("gamepaddisconnected", onPadDisconnected, this); - */ - /** * Threshold for axes to return values. Must be between 0 and 1. * diff --git a/src/platform/input/keyboard.js b/src/platform/input/keyboard.js index 32b5c68544a..221d0586b38 100644 --- a/src/platform/input/keyboard.js +++ b/src/platform/input/keyboard.js @@ -60,6 +60,38 @@ const _keyCodeToKeyIdentifier = { * @category Input */ class Keyboard extends EventHandler { + /** + * Fired when a key is pressed. The handler is passed a {@link KeyboardEvent}. + * + * @event + * @example + * const onKeyDown = (e) => { + * if (e.key === pc.KEY_SPACE) { + * // space key pressed + * } + * e.event.preventDefault(); // Use original browser event to prevent browser action. + * }; + * + * app.keyboard.on("keydown", onKeyDown, this); + */ + static EVENT_KEYDOWN = 'keydown'; + + /** + * Fired when a key is released. The handler is passed a {@link KeyboardEvent}. + * + * @event + * @example + * const onKeyUp = (e) => { + * if (e.key === pc.KEY_SPACE) { + * // space key released + * } + * e.event.preventDefault(); // Use original browser event to prevent browser action. + * }; + * + * app.keyboard.on("keyup", onKeyUp, this); + */ + static EVENT_KEYUP = 'keyup'; + /** * Create a new Keyboard instance. * @@ -100,36 +132,6 @@ class Keyboard extends EventHandler { this.stopPropagation = options.stopPropagation || false; } - /** - * Fired when a key is pressed. - * - * @event Keyboard#keydown - * @param {KeyboardEvent} event - The Keyboard event object. Note, this event is only valid for the current callback. - * @example - * const onKeyDown = function (e) { - * if (e.key === pc.KEY_SPACE) { - * // space key pressed - * } - * e.event.preventDefault(); // Use original browser event to prevent browser action. - * }; - * app.keyboard.on("keydown", onKeyDown, this); - */ - - /** - * Fired when a key is released. - * - * @event Keyboard#keyup - * @param {KeyboardEvent} event - The Keyboard event object. Note, this event is only valid for the current callback. - * @example - * const onKeyUp = function (e) { - * if (e.key === pc.KEY_SPACE) { - * // space key released - * } - * e.event.preventDefault(); // Use original browser event to prevent browser action. - * }; - * app.keyboard.on("keyup", onKeyUp, this); - */ - /** * Attach the keyboard event handlers to an Element. * diff --git a/src/platform/input/mouse.js b/src/platform/input/mouse.js index d9a86b6cfb3..20b80af6b0d 100644 --- a/src/platform/input/mouse.js +++ b/src/platform/input/mouse.js @@ -17,6 +17,50 @@ import { isMousePointerLocked, MouseEvent } from './mouse-event.js'; * @category Input */ class Mouse extends EventHandler { + /** + * Fired when the mouse is moved. The handler is passed a {@link MouseEvent}. + * + * @event + * @example + * app.mouse.on('mousemove', (e) => { + * console.log(`Current mouse position is: ${e.x}, ${e.y}`); + * }); + */ + static EVENT_MOUSEMOVE = EVENT_MOUSEMOVE; + + /** + * Fired when a mouse button is pressed. The handler is passed a {@link MouseEvent}. + * + * @event + * @example + * app.mouse.on('mousedown', (e) => { + * console.log(`The ${e.button} button was pressed at position: ${e.x}, ${e.y}`); + * }); + */ + static EVENT_MOUSEDOWN = EVENT_MOUSEDOWN; + + /** + * Fired when a mouse button is released. The handler is passed a {@link MouseEvent}. + * + * @event + * @example + * app.mouse.on('mouseup', (e) => { + * console.log(`The ${e.button} button was released at position: ${e.x}, ${e.y}`); + * }); + */ + static EVENT_MOUSEUP = EVENT_MOUSEUP; + + /** + * Fired when a mouse wheel is moved. The handler is passed a {@link MouseEvent}. + * + * @event + * @example + * app.mouse.on('mousewheel', (e) => { + * console.log(`The mouse wheel was moved by ${e.wheelDelta}`); + * }); + */ + static EVENT_MOUSEWHEEL = EVENT_MOUSEWHEEL; + /** * Create a new Mouse instance. * @@ -47,34 +91,6 @@ class Mouse extends EventHandler { this.attach(element); } - /** - * Fired when the mouse is moved. - * - * @event Mouse#mousemove - * @param {MouseEvent} event - The MouseEvent object. - */ - - /** - * Fired when a mouse button is pressed. - * - * @event Mouse#mousedown - * @param {MouseEvent} event - The MouseEvent object. - */ - - /** - * Fired when a mouse button is released. - * - * @event Mouse#mouseup - * @param {MouseEvent} event - The MouseEvent object. - */ - - /** - * Fired when a mouse wheel is moved. - * - * @event Mouse#mousewheel - * @param {MouseEvent} event - The MouseEvent object. - */ - /** * Check if the mouse pointer has been locked, using {@link Mouse#enablePointerLock}. * diff --git a/src/platform/sound/instance.js b/src/platform/sound/instance.js index 4e232eba41c..fe516aa9b0b 100644 --- a/src/platform/sound/instance.js +++ b/src/platform/sound/instance.js @@ -27,6 +27,61 @@ function capTime(time, duration) { * @category Sound */ class SoundInstance extends EventHandler { + /** + * Fired when the instance starts playing its source. + * + * @event + * @example + * instance.on('play', () => { + * console.log('Instance started playing'); + * }); + */ + static EVENT_PLAY = 'play'; + + /** + * Fired when the instance is paused. + * + * @event + * @example + * instance.on('pause', () => { + * console.log('Instance paused'); + * }); + */ + static EVENT_PAUSE = 'pause'; + + /** + * Fired when the instance is resumed. + * + * @event + * @example + * instance.on('resume', () => { + * console.log('Instance resumed'); + * }); + */ + static EVENT_RESUME = 'resume'; + + /** + * Fired when the instance is stopped. + * + * @event + * @example + * instance.on('stop', () => { + * console.log('Instance stopped'); + * }); + */ + static EVENT_STOP = 'stop'; + + /** + * Fired when the sound currently played by the instance ends. + * + * @event + * @example + * instance.on('end', () => { + * console.log('Instance ended'); + * }); + */ + static EVENT_END = 'end'; + /** * Gets the source that plays the sound resource. If the Web Audio API is not supported the * type of source is [Audio](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio). @@ -244,36 +299,6 @@ class SoundInstance extends EventHandler { } } - /** - * Fired when the instance starts playing its source. - * - * @event SoundInstance#play - */ - - /** - * Fired when the instance is paused. - * - * @event SoundInstance#pause - */ - - /** - * Fired when the instance is resumed. - * - * @event SoundInstance#resume - */ - - /** - * Fired when the instance is stopped. - * - * @event SoundInstance#stop - */ - - /** - * Fired when the sound currently played by the instance ends. - * - * @event SoundInstance#end - */ - /** * Gets or sets the current time of the sound that is playing. If the value provided is bigger * than the duration of the instance it will wrap from the beginning. diff --git a/src/scene/render.js b/src/scene/render.js index 5ccd666280c..13ff5c10cf8 100644 --- a/src/scene/render.js +++ b/src/scene/render.js @@ -9,6 +9,19 @@ import { EventHandler } from '../core/event-handler.js'; * @ignore */ class Render extends EventHandler { + /** + * Fired when the meshes are set on the render. The handler is passed the an array of + * {@link Mesh} objects. + * + * @event + * @example + * render.on('set:meshes', (meshes) => { + * console.log(`Render has ${meshes.length} meshes`); + * }); + * @ignore + */ + static EVENT_SETMESHES = 'set:meshes'; + /** * Create a new Render instance. These are usually created by the GLB loader and not created * by hand. @@ -26,14 +39,6 @@ class Render extends EventHandler { this._meshes = null; } - /** - * Fired when the meshes are set. - * - * @event Render#set:meshes - * @param {import('./mesh.js').Mesh[]} meshes - The meshes. - * @ignore - */ - /** * The meshes that the render contains. * diff --git a/src/scene/scene.js b/src/scene/scene.js index 5fdcb03eeec..f91eaa76fed 100644 --- a/src/scene/scene.js +++ b/src/scene/scene.js @@ -24,6 +24,44 @@ import { EnvLighting } from './graphics/env-lighting.js'; * @category Graphics */ class Scene extends EventHandler { + /** + * Fired when the layer composition is set. Use this event to add callbacks or advanced + * properties to your layers. The handler is passed the old and the new + * {@link LayerComposition}. + * + * @event + * @example + * app.scene.on('set:layers', (oldComp, newComp) => { + * const list = newComp.layerList; + * for (let i = 0; i < list.length; i++) { + * const layer = list[i]; + * switch (layer.name) { + * case 'MyLayer': + * layer.onEnable = myOnEnableFunction; + * layer.onDisable = myOnDisableFunction; + * break; + * case 'MyOtherLayer': + * layer.shaderPass = myShaderPass; + * break; + * } + * } + * }); + */ + static EVENT_SETLAYERS = 'set:layers'; + + /** + * Fired when the skybox is set. The handler is passed the {@link Texture} that is the + * previously used skybox cubemap texture. The new skybox cubemap texture is in the + * {@link Scene#skybox} property. + * + * @event + * @example + * app.scene.on('set:skybox', (oldSkybox) => { + * console.log(`Skybox changed from ${oldSkybox.name} to ${app.scene.skybox.name}`); + * }); + */ + static EVENT_SETSKYBOX = 'set:skybox'; + /** * If enabled, the ambient lighting will be baked into lightmaps. This will be either the * {@link Scene#skybox} if set up, otherwise {@link Scene#ambientLight}. Defaults to false. @@ -263,41 +301,6 @@ class Scene extends EventHandler { this.immediate = new Immediate(this.device); } - /** - * Fired when the skybox is set. - * - * @event Scene#set:skybox - * @param {import('../platform/graphics/texture.js').Texture} usedTex - Previously used cubemap - * texture. New is in the {@link Scene#skybox}. - */ - - /** - * Fired when the layer composition is set. Use this event to add callbacks or advanced - * properties to your layers. - * - * @event Scene#set:layers - * @param {import('./composition/layer-composition.js').LayerComposition} oldComp - Previously - * used {@link LayerComposition}. - * @param {import('./composition/layer-composition.js').LayerComposition} newComp - Newly set - * {@link LayerComposition}. - * @example - * this.app.scene.on('set:layers', function (oldComp, newComp) { - * const list = newComp.layerList; - * for (let i = 0; i < list.length; i++) { - * const layer = list[i]; - * switch (layer.name) { - * case 'MyLayer': - * layer.onEnable = myOnEnableFunction; - * layer.onDisable = myOnDisableFunction; - * break; - * case 'MyOtherLayer': - * layer.shaderPass = myShaderPass; - * break; - * } - * } - * }); - */ - /** * Returns the default layer used by the immediate drawing functions. *