diff --git a/dist/mr.js b/dist/mr.js
index c89a6233..3ed75494 100644
--- a/dist/mr.js
+++ b/dist/mr.js
@@ -498,7 +498,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AnimationSystem: () => (/* binding */ AnimationSystem)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mrjs/core/MRSystem */ \"./src/core/MRSystem.js\");\n/* harmony import */ var mrjs_core_MREntity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mrjs/core/MREntity */ \"./src/core/MREntity.js\");\n/* harmony import */ var mrjs_core_entities_MRDivEntity__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! mrjs/core/entities/MRDivEntity */ \"./src/core/entities/MRDivEntity.js\");\n/* harmony import */ var mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! mrjs/core/entities/MRModelEntity */ \"./src/core/entities/MRModelEntity.js\");\n/* harmony import */ var mrjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! mrjs */ \"./src/index.js\");\n\n\n\n\n\n\n\n\n\n/**\n * @class AnimationSystem\n * @classdesc Handles specific needs for setting up the masking for all necessary items.\n * @augments MRSystem\n */\nclass AnimationSystem extends mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_0__.MRSystem {\n /**\n * @class\n * @description AnimationSystem's default constructor.\n */\n constructor() {\n super();\n }\n\n /**\n * @function\n * @description Updates each animation mixer in the registry. This function should be called\n * within the main animation loop of the application. It iterates through all the\n * animation mixers stored in the registry and updates them with the given deltaTime.\n * The deltaTime parameter is typically the time elapsed since the last frame\n * which is used to ensure smooth animation playback.\n * @param {number} deltaTime - The time elapsed since the last update call, used to update the animation mixers.\n * @param {object} frame - Additional frame information, not used in the current implementation but can be utilized for future enhancements.\n */\n update(deltaTime, frame) {\n for (const entity of this.registry) {\n if (entity.mixer) {\n entity.mixer.update(deltaTime);\n }\n }\n }\n\n /**\n * @function\n * @description (async) Called when the entity component is initialized\n * @param {object} entity - the entity being attached/initialized.\n */\n async attachedComponent(entity) {\n let comp = entity.components.get('animation');\n // the animations list does not load immediately, so we set a promise to wait for the model to load.\n await new Promise((resolve) => {\n const interval = setInterval(() => {\n if (entity.loaded) {\n clearInterval(interval);\n resolve();\n }\n }, 100); // Checks every 100ms\n });\n\n if (entity instanceof mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__.MRModelEntity && entity.animations.length > 0) {\n // Create a mixer for each Model instance with animations\n entity.mixer = new three__WEBPACK_IMPORTED_MODULE_5__.AnimationMixer(entity.object3D);\n this.setAnimation(entity, comp);\n }\n }\n\n /**\n * @function\n * @description Called when the entity component is updated\n * @param {object} entity - the entity being updated based on the component.\n */\n updatedComponent(entity) {\n let comp = entity.components.get('animation');\n if (entity instanceof mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__.MRModelEntity && entity.animations.length > 0) {\n this.setAnimation(entity, comp);\n }\n }\n\n /**\n * @function\n * @description Called when the entity component is detached\n * @param {object} entity - the entity being updated based on the component being detached.\n */\n detachedComponent(entity) {\n entity.mixer.stopAllActions();\n }\n\n /**\n * @function\n * @description When the system swaps to a new entity, this handles setting up the animations for the system runs.\n * @param {object} entity - given entity that might be handled by the system.\n */\n onNewEntity(entity) {\n if (entity instanceof mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__.MRModelEntity && entity.animations.length > 0) {\n let comp = entity.components.get('animation');\n if (!comp) {\n return;\n }\n this.registry.add(entity);\n entity.mixer = new three__WEBPACK_IMPORTED_MODULE_5__.AnimationMixer(entity.object3D);\n this.setAnimation(entity, comp);\n }\n }\n\n /**\n * @function\n * @description Sets the Animation of the entity object based on the component value associated with it. Otherwise lets those\n * be handled by the threejs default setup. (Always looping, always playing based on browser type, etc).\n * @param {object} entity - the entity being updated based on the component being detached.\n * @param {object} comp - component that contains the values of 'action', 'loop', and/or 'loopMode'\n */\n setAnimation(entity, comp) {\n let clip = entity.animations[comp.clip];\n let action = entity.mixer.clipAction(clip);\n\n if (comp.hasOwnProperty('action')) {\n switch (comp.action) {\n case 'play':\n action.play();\n break;\n case 'pause':\n action.pause();\n break;\n case 'stop':\n action.stop();\n break;\n default:\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('Unknown case hit for action in the AnimationSystem from entity:', entity, '. Comp is:', comp);\n return;\n }\n }\n\n let hasLoop = comp.hasOwnProperty('loop');\n let hasLoopMode = comp.hasOwnProperty('loopMode');\n if (hasLoop || hasLoopMode) {\n if (hasLoop && !hasLoopMode) {\n switch (comp.loop) {\n case true:\n case 'true':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopRepeat, Infinity);\n break;\n case false:\n case 'false':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopOnce, 1);\n break;\n default:\n // loopMode doesnt exist so we hit an unexpected value\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err(\n 'Bad configuration for loop. It isnt set to true/false (did you mean to pair it with loopMode?) specified in the AnimationSystem from entity:',\n entity,\n ' Comp:',\n comp\n );\n return;\n }\n } else if (hasLoopMode && !hasLoop) {\n // The only time where loop doesnt need to exist but loopMode does is for 'once'. Additionally, note that we also\n // handle this version of loopMode even in the case where loop count exists.\n if (comp.loopMode === 'once') {\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopOnce, 1);\n } else {\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err(\n 'Bad configuration, loopMode isnt `once`, but loop isnt set (did you mean to pair it with loop?) specified in the AnimationSystem from entity:',\n entity,\n ' Comp:',\n comp\n );\n return;\n }\n } else if (hasLoop && hasLoopMode) {\n // Convert comp.loop to a number, and check if it's a valid normal number or Infinity\n let loopCount = Number(comp.loop);\n if (!((Number.isInteger(loopCount) && loopCount >= 0) || loopCount === Infinity)) {\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('loop must be a non-negative integer or Infinity when using loop as count. Entity:', entity, ' Comp:', comp);\n return;\n }\n // Use the appropriate looping based on loopMode\n switch (comp.loopMode) {\n case 'repeat':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopRepeat, loopCount);\n break;\n case 'pingpong':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopPingPong, loopCount);\n break;\n case 'once':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopOnce, 1);\n break;\n default:\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('Unknown loopMode specified in the AnimationSystem from entity:', entity, ' Comp:', comp);\n break;\n }\n } else {\n // hasLoop and both hasLoopMode are false, should never reach this case so error as failsafe\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('Hit unreachable code - major error in AnimationSystem loop handling');\n }\n }\n }\n}\n\n\n//# sourceURL=webpack://mrjs/./src/core/componentSystems/AnimationSystem.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AnimationSystem: () => (/* binding */ AnimationSystem)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mrjs/core/MRSystem */ \"./src/core/MRSystem.js\");\n/* harmony import */ var mrjs_core_MREntity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mrjs/core/MREntity */ \"./src/core/MREntity.js\");\n/* harmony import */ var mrjs_core_entities_MRDivEntity__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! mrjs/core/entities/MRDivEntity */ \"./src/core/entities/MRDivEntity.js\");\n/* harmony import */ var mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! mrjs/core/entities/MRModelEntity */ \"./src/core/entities/MRModelEntity.js\");\n/* harmony import */ var mrjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! mrjs */ \"./src/index.js\");\n\n\n\n\n\n\n\n\n\n/**\n * @class AnimationSystem\n * @classdesc Handles specific needs for setting up the masking for all necessary items.\n * @augments MRSystem\n */\nclass AnimationSystem extends mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_0__.MRSystem {\n /**\n * @class\n * @description AnimationSystem's default constructor.\n */\n constructor() {\n super();\n }\n\n /**\n * @function\n * @description Updates each animation mixer in the registry. This function should be called\n * within the main animation loop of the application. It iterates through all the\n * animation mixers stored in the registry and updates them with the given deltaTime.\n * The deltaTime parameter is typically the time elapsed since the last frame\n * which is used to ensure smooth animation playback.\n * @param {number} deltaTime - The time elapsed since the last update call, used to update the animation mixers.\n * @param {object} frame - Additional frame information, not used in the current implementation but can be utilized for future enhancements.\n */\n update(deltaTime, frame) {\n for (const entity of this.registry) {\n if (entity.mixer) {\n entity.mixer.update(deltaTime);\n }\n }\n }\n\n /**\n * @function\n * @description (async) Called when the entity component is initialized\n * @param {object} entity - the entity being attached/initialized.\n */\n async attachedComponent(entity) {\n let comp = entity.components.get('animation');\n // the animations list does not load immediately, so we set a promise to wait for the model to load.\n await new Promise((resolve) => {\n const interval = setInterval(() => {\n if (entity.loaded) {\n clearInterval(interval);\n resolve();\n }\n }, 100); // Checks every 100ms\n });\n\n if (entity instanceof mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__.MRModelEntity && entity.animations.length > 0) {\n // Create a mixer for each Model instance with animations\n entity.mixer = new three__WEBPACK_IMPORTED_MODULE_5__.AnimationMixer(entity.object3D);\n this.setAnimation(entity, comp);\n }\n }\n\n /**\n * @function\n * @description Called when the entity component is updated\n * @param {object} entity - the entity being updated based on the component.\n */\n updatedComponent(entity) {\n let comp = entity.components.get('animation');\n if (entity instanceof mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__.MRModelEntity && entity.animations.length > 0) {\n this.setAnimation(entity, comp);\n }\n }\n\n /**\n * @function\n * @description Called when the entity component is detached\n * @param {object} entity - the entity being updated based on the component being detached.\n */\n detachedComponent(entity) {\n entity.mixer.stopAllActions();\n }\n\n /**\n * @function\n * @description When the system swaps to a new entity, this handles setting up the animations for the system runs.\n * @param {object} entity - given entity that might be handled by the system.\n */\n onNewEntity(entity) {\n if (entity instanceof mrjs_core_entities_MRModelEntity__WEBPACK_IMPORTED_MODULE_3__.MRModelEntity && entity.animations.length > 0) {\n let comp = entity.components.get('animation');\n if (!comp) {\n return;\n }\n this.registry.add(entity);\n entity.mixer = new three__WEBPACK_IMPORTED_MODULE_5__.AnimationMixer(entity.object3D);\n this.setAnimation(entity, comp);\n }\n }\n\n /**\n * @function\n * @description Sets the Animation of the entity object based on the component value associated with it. Otherwise lets those\n * be handled by the threejs default setup. (Always looping, always playing based on browser type, etc).\n * @param {object} entity - the entity being updated based on the component being detached.\n * @param {object} comp - component that contains the values of 'action', 'loop', and/or 'loopMode'\n */\n setAnimation(entity, comp) {\n console.log(entity.animations);\n let clip = entity.animations[comp.clip];\n let action = entity.mixer.clipAction(clip);\n\n // Handle ending position.\n // Threejs defaults to the starting position. `clampWhenFinished` being true, makes it default to the ending position.\n // action.clampWhenFinished = comp.clampWhenFinished ?? false;\n\n if (comp.hasOwnProperty('action')) {\n switch (comp.action) {\n case 'play':\n action.play();\n break;\n case 'pause':\n action.pause();\n break;\n case 'stop':\n action.stop();\n break;\n default:\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('Unknown case hit for action in the AnimationSystem from entity:', entity, '. Comp is:', comp);\n return;\n }\n }\n\n let hasLoop = comp.hasOwnProperty('loop');\n let hasLoopMode = comp.hasOwnProperty('loopMode');\n if (hasLoop || hasLoopMode) {\n if (hasLoop && !hasLoopMode) {\n switch (comp.loop) {\n case true:\n case 'true':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopRepeat, Infinity);\n break;\n case false:\n case 'false':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopOnce, 1);\n break;\n default:\n // loopMode doesnt exist so we hit an unexpected value\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err(\n 'Bad configuration for loop. It isnt set to true/false (did you mean to pair it with loopMode?) specified in the AnimationSystem from entity:',\n entity,\n ' Comp:',\n comp\n );\n return;\n }\n } else if (hasLoopMode && !hasLoop) {\n // The only time where loop doesnt need to exist but loopMode does is for 'once'. Additionally, note that we also\n // handle this version of loopMode even in the case where loop count exists.\n if (comp.loopMode === 'once') {\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopOnce, 1);\n } else {\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err(\n 'Bad configuration, loopMode isnt `once`, but loop isnt set (did you mean to pair it with loop?) specified in the AnimationSystem from entity:',\n entity,\n ' Comp:',\n comp\n );\n return;\n }\n } else if (hasLoop && hasLoopMode) {\n // Convert comp.loop to a number, and check if it's a valid normal number or Infinity\n let loopCount = Number(comp.loop);\n if (!((Number.isInteger(loopCount) && loopCount >= 0) || loopCount === Infinity)) {\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('loop must be a non-negative integer or Infinity when using loop as count. Entity:', entity, ' Comp:', comp);\n return;\n }\n // Use the appropriate looping based on loopMode\n switch (comp.loopMode) {\n case 'repeat':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopRepeat, loopCount);\n break;\n case 'pingpong':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopPingPong, loopCount);\n break;\n case 'once':\n action.setLoop(three__WEBPACK_IMPORTED_MODULE_5__.LoopOnce, 1);\n break;\n default:\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('Unknown loopMode specified in the AnimationSystem from entity:', entity, ' Comp:', comp);\n break;\n }\n } else {\n // hasLoop and both hasLoopMode are false, should never reach this case so error as failsafe\n mrjs__WEBPACK_IMPORTED_MODULE_4__.mrjsUtils.error.err('Hit unreachable code - major error in AnimationSystem loop handling');\n }\n }\n }\n}\n\n\n//# sourceURL=webpack://mrjs/./src/core/componentSystems/AnimationSystem.js?");
/***/ }),
diff --git a/samples/examples-assets/models/door1-UI.glb b/samples/examples-assets/models/door1-UI.glb
new file mode 100644
index 00000000..e8752ebe
Binary files /dev/null and b/samples/examples-assets/models/door1-UI.glb differ
diff --git a/samples/examples-assets/models/door1.glb b/samples/examples-assets/models/door1.glb
new file mode 100644
index 00000000..63243f14
Binary files /dev/null and b/samples/examples-assets/models/door1.glb differ
diff --git a/samples/examples/models.html b/samples/examples/models.html
index 6b1366d3..5b9845cd 100644
--- a/samples/examples/models.html
+++ b/samples/examples/models.html
@@ -267,6 +267,34 @@
+
+
+
+ loopMode = once, end at start position
+
+
+
+
+
+
+
+
+
+ loopMode = once, freeze at final position
+
+
+
+
+
+
model
diff --git a/src/core/componentSystems/AnimationSystem.js b/src/core/componentSystems/AnimationSystem.js
index 37403d55..3cdb4da3 100644
--- a/src/core/componentSystems/AnimationSystem.js
+++ b/src/core/componentSystems/AnimationSystem.js
@@ -109,89 +109,98 @@ export class AnimationSystem extends MRSystem {
* @param {object} comp - component that contains the values of 'action', 'loop', and/or 'loopMode'
*/
setAnimation(entity, comp) {
- let clip = entity.animations[comp.clip];
- let action = entity.mixer.clipAction(clip);
+ // XXX in future - add conditions to play specific animations based on names
+ // or other properties.
+ // For now, just looping through all existing ones to update as needed.
+ entity.animations.forEach((clip, index) => {
+ let action = entity.mixer.clipAction(clip);
- if (comp.hasOwnProperty('action')) {
- switch (comp.action) {
- case 'play':
- action.play();
- break;
- case 'pause':
- action.pause();
- break;
- case 'stop':
- action.stop();
- break;
- default:
- mrjsUtils.error.err('Unknown case hit for action in the AnimationSystem from entity:', entity, '. Comp is:', comp);
- return;
- }
- }
+ // Handle ending position. Threejs defaults to the starting position; when
+ // `clampWhenFinished` is true, it defaults the stop position as the ending
+ // clip of the animation.
+ action.clampWhenFinished = comp.clampWhenFinished ?? false;
- let hasLoop = comp.hasOwnProperty('loop');
- let hasLoopMode = comp.hasOwnProperty('loopMode');
- if (hasLoop || hasLoopMode) {
- if (hasLoop && !hasLoopMode) {
- switch (comp.loop) {
- case true:
- case 'true':
- action.setLoop(THREE.LoopRepeat, Infinity);
+ if (comp.hasOwnProperty('action')) {
+ switch (comp.action) {
+ case 'play':
+ action.play();
break;
- case false:
- case 'false':
- action.setLoop(THREE.LoopOnce, 1);
+ case 'pause':
+ action.pause();
+ break;
+ case 'stop':
+ action.stop();
break;
default:
- // loopMode doesnt exist so we hit an unexpected value
+ mrjsUtils.error.err('Unknown case hit for action in the AnimationSystem from entity:', entity, '. Comp is:', comp);
+ return;
+ }
+ }
+
+ let hasLoop = comp.hasOwnProperty('loop');
+ let hasLoopMode = comp.hasOwnProperty('loopMode');
+ if (hasLoop || hasLoopMode) {
+ if (hasLoop && !hasLoopMode) {
+ switch (comp.loop) {
+ case true:
+ case 'true':
+ action.setLoop(THREE.LoopRepeat, Infinity);
+ break;
+ case false:
+ case 'false':
+ action.setLoop(THREE.LoopOnce, 1);
+ break;
+ default:
+ // loopMode doesnt exist so we hit an unexpected value
+ mrjsUtils.error.err(
+ 'Bad configuration for loop. It isnt set to true/false (did you mean to pair it with loopMode?) specified in the AnimationSystem from entity:',
+ entity,
+ ' Comp:',
+ comp
+ );
+ return;
+ }
+ } else if (hasLoopMode && !hasLoop) {
+ // The only time where loop doesnt need to exist but loopMode does is for 'once'. Additionally, note that we also
+ // handle this version of loopMode even in the case where loop count exists.
+ if (comp.loopMode === 'once') {
+ action.setLoop(THREE.LoopOnce, 1);
+ } else {
mrjsUtils.error.err(
- 'Bad configuration for loop. It isnt set to true/false (did you mean to pair it with loopMode?) specified in the AnimationSystem from entity:',
+ 'Bad configuration, loopMode isnt `once`, but loop isnt set (did you mean to pair it with loop?) specified in the AnimationSystem from entity:',
entity,
' Comp:',
comp
);
return;
- }
- } else if (hasLoopMode && !hasLoop) {
- // The only time where loop doesnt need to exist but loopMode does is for 'once'. Additionally, note that we also
- // handle this version of loopMode even in the case where loop count exists.
- if (comp.loopMode === 'once') {
- action.setLoop(THREE.LoopOnce, 1);
+ }
+ } else if (hasLoop && hasLoopMode) {
+ // Convert comp.loop to a number, and check if it's a valid normal number or Infinity
+ let loopCount = Number(comp.loop);
+ if (!((Number.isInteger(loopCount) && loopCount >= 0) || loopCount === Infinity)) {
+ mrjsUtils.error.err('loop must be a non-negative integer or Infinity when using loop as count. Entity:', entity, ' Comp:', comp);
+ return;
+ }
+ // Use the appropriate looping based on loopMode
+ switch (comp.loopMode) {
+ case 'repeat':
+ action.setLoop(THREE.LoopRepeat, loopCount);
+ break;
+ case 'pingpong':
+ action.setLoop(THREE.LoopPingPong, loopCount);
+ break;
+ case 'once':
+ action.setLoop(THREE.LoopOnce, 1);
+ break;
+ default:
+ mrjsUtils.error.err('Unknown loopMode specified in the AnimationSystem from entity:', entity, ' Comp:', comp);
+ break;
+ }
} else {
- mrjsUtils.error.err(
- 'Bad configuration, loopMode isnt `once`, but loop isnt set (did you mean to pair it with loop?) specified in the AnimationSystem from entity:',
- entity,
- ' Comp:',
- comp
- );
- return;
+ // hasLoop and both hasLoopMode are false, should never reach this case so error as failsafe
+ mrjsUtils.error.err('Hit unreachable code - major error in AnimationSystem loop handling');
}
- } else if (hasLoop && hasLoopMode) {
- // Convert comp.loop to a number, and check if it's a valid normal number or Infinity
- let loopCount = Number(comp.loop);
- if (!((Number.isInteger(loopCount) && loopCount >= 0) || loopCount === Infinity)) {
- mrjsUtils.error.err('loop must be a non-negative integer or Infinity when using loop as count. Entity:', entity, ' Comp:', comp);
- return;
- }
- // Use the appropriate looping based on loopMode
- switch (comp.loopMode) {
- case 'repeat':
- action.setLoop(THREE.LoopRepeat, loopCount);
- break;
- case 'pingpong':
- action.setLoop(THREE.LoopPingPong, loopCount);
- break;
- case 'once':
- action.setLoop(THREE.LoopOnce, 1);
- break;
- default:
- mrjsUtils.error.err('Unknown loopMode specified in the AnimationSystem from entity:', entity, ' Comp:', comp);
- break;
- }
- } else {
- // hasLoop and both hasLoopMode are false, should never reach this case so error as failsafe
- mrjsUtils.error.err('Hit unreachable code - major error in AnimationSystem loop handling');
}
- }
+ });
}
}