mage-engine 3.24.3 → 3.24.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mage.js +522 -30
- package/package.json +1 -1
package/dist/mage.js
CHANGED
|
@@ -58250,7 +58250,7 @@ function applyMiddleware() {
|
|
|
58250
58250
|
|
|
58251
58251
|
var thunk = createThunkMiddleware();
|
|
58252
58252
|
thunk.withExtraArgument = createThunkMiddleware;var name = "mage-engine";
|
|
58253
|
-
var version$1 = "3.24.
|
|
58253
|
+
var version$1 = "3.24.4";
|
|
58254
58254
|
var description = "A WebGL Javascript Game Engine, built on top of THREE.js and many other libraries.";
|
|
58255
58255
|
var main = "dist/mage.js";
|
|
58256
58256
|
var author$1 = {
|
|
@@ -60666,7 +60666,6 @@ const extractMaterialProperty = (elementBody, property) => {
|
|
|
60666
60666
|
return found;
|
|
60667
60667
|
}
|
|
60668
60668
|
};
|
|
60669
|
-
const serialiseMaterial = material => omit(UNDESIRED_SERIALISED_MATERIAL_PROPERTIES, material === null || material === void 0 ? void 0 : material.toJSON());
|
|
60670
60669
|
const processMaterial = (material, callback) => Array.isArray(material) ? material.map(callback) : callback(material);
|
|
60671
60670
|
const replaceMaterialByName = (name, mesh, materialOptions) => {
|
|
60672
60671
|
if (!hasMaterial(mesh)) return;
|
|
@@ -60906,7 +60905,16 @@ const tweenTo = function (origin, target) {
|
|
|
60906
60905
|
const qz = Number(z) || 0;
|
|
60907
60906
|
const qw = Number(w) || 1;
|
|
60908
60907
|
|
|
60909
|
-
_this.getBody().quaternion.set(qx, qy, qz, qw);
|
|
60908
|
+
_this.getBody().quaternion.set(qx, qy, qz, qw); // Update matrix world and skeleton for skinned meshes
|
|
60909
|
+
|
|
60910
|
+
|
|
60911
|
+
_this.getBody().updateMatrixWorld(true);
|
|
60912
|
+
|
|
60913
|
+
_this.getBody().traverse(child => {
|
|
60914
|
+
if (child.isSkinnedMesh && child.skeleton) {
|
|
60915
|
+
child.skeleton.update();
|
|
60916
|
+
}
|
|
60917
|
+
});
|
|
60910
60918
|
});
|
|
60911
60919
|
|
|
60912
60920
|
_defineProperty$1(_assertThisInitialized(_this), "setUuid", uuid => {
|
|
@@ -61525,7 +61533,9 @@ const tweenTo = function (origin, target) {
|
|
|
61525
61533
|
const sx = Number(scale.x) || 1;
|
|
61526
61534
|
const sy = Number(scale.y) || 1;
|
|
61527
61535
|
const sz = Number(scale.z) || 1;
|
|
61528
|
-
this.body.scale.set(sx, sy, sz);
|
|
61536
|
+
this.body.scale.set(sx, sy, sz); // Update matrix world for all children including skinned meshes
|
|
61537
|
+
|
|
61538
|
+
this.getBody().updateMatrixWorld(true);
|
|
61529
61539
|
}
|
|
61530
61540
|
}
|
|
61531
61541
|
}, {
|
|
@@ -61559,7 +61569,17 @@ const tweenTo = function (origin, target) {
|
|
|
61559
61569
|
const px = Number(position.x) || 0;
|
|
61560
61570
|
const py = Number(position.y) || 0;
|
|
61561
61571
|
const pz = Number(position.z) || 0;
|
|
61562
|
-
this.getBody().position.set(px, py, pz);
|
|
61572
|
+
this.getBody().position.set(px, py, pz); // Update matrix world to ensure skinned mesh skeletons follow the parent transform
|
|
61573
|
+
|
|
61574
|
+
this.getBody().updateMatrixWorld(true); // For skinned meshes, we need to rebind the skeleton after position change
|
|
61575
|
+
// The bindMatrix captures where the mesh was when bound, so we need to update it
|
|
61576
|
+
|
|
61577
|
+
this.getBody().traverse(child => {
|
|
61578
|
+
if (child.isSkinnedMesh && child.skeleton) {
|
|
61579
|
+
// Rebind with current matrix to update the bind pose
|
|
61580
|
+
child.bind(child.skeleton, child.matrixWorld);
|
|
61581
|
+
}
|
|
61582
|
+
});
|
|
61563
61583
|
}
|
|
61564
61584
|
}
|
|
61565
61585
|
}, {
|
|
@@ -61586,7 +61606,9 @@ const tweenTo = function (origin, target) {
|
|
|
61586
61606
|
const rx = Number(rotation.x) || 0;
|
|
61587
61607
|
const ry = Number(rotation.y) || 0;
|
|
61588
61608
|
const rz = Number(rotation.z) || 0;
|
|
61589
|
-
this.getBody().rotation.set(rx, ry, rz);
|
|
61609
|
+
this.getBody().rotation.set(rx, ry, rz); // Update matrix world for all children including skinned meshes
|
|
61610
|
+
|
|
61611
|
+
this.getBody().updateMatrixWorld(true);
|
|
61590
61612
|
}
|
|
61591
61613
|
}
|
|
61592
61614
|
}, {
|
|
@@ -61609,7 +61631,14 @@ const tweenTo = function (origin, target) {
|
|
|
61609
61631
|
quaternion
|
|
61610
61632
|
} = worldTransform;
|
|
61611
61633
|
this.getBody().setWorldPosition(position);
|
|
61612
|
-
this.getBody().setWorldQuaternion(quaternion);
|
|
61634
|
+
this.getBody().setWorldQuaternion(quaternion); // Update matrix world and skeleton for skinned meshes
|
|
61635
|
+
|
|
61636
|
+
this.getBody().updateMatrixWorld(true);
|
|
61637
|
+
this.getBody().traverse(child => {
|
|
61638
|
+
if (child.isSkinnedMesh && child.skeleton) {
|
|
61639
|
+
child.skeleton.update();
|
|
61640
|
+
}
|
|
61641
|
+
});
|
|
61613
61642
|
}
|
|
61614
61643
|
}, {
|
|
61615
61644
|
key: "translate",
|
|
@@ -61623,7 +61652,9 @@ const tweenTo = function (origin, target) {
|
|
|
61623
61652
|
if (this.hasBody()) {
|
|
61624
61653
|
this.body.translateX(x);
|
|
61625
61654
|
this.body.translateY(y);
|
|
61626
|
-
this.body.translateZ(z);
|
|
61655
|
+
this.body.translateZ(z); // Update matrix world for all children including skinned meshes
|
|
61656
|
+
|
|
61657
|
+
this.getBody().updateMatrixWorld(true);
|
|
61627
61658
|
}
|
|
61628
61659
|
}
|
|
61629
61660
|
}, {
|
|
@@ -61850,7 +61881,9 @@ const tweenTo = function (origin, target) {
|
|
|
61850
61881
|
}]);
|
|
61851
61882
|
|
|
61852
61883
|
return Entity;
|
|
61853
|
-
}(EventDispatcher);
|
|
61884
|
+
}(EventDispatcher);const DEFAULT_BLEND_DURATION = 0.3;
|
|
61885
|
+
|
|
61886
|
+
let AnimationHandler = /*#__PURE__*/function (_EventDispatcher) {
|
|
61854
61887
|
_inherits(AnimationHandler, _EventDispatcher);
|
|
61855
61888
|
|
|
61856
61889
|
var _super = _createSuper(AnimationHandler);
|
|
@@ -61880,6 +61913,8 @@ const tweenTo = function (origin, target) {
|
|
|
61880
61913
|
_this.mixer = new AnimationMixer(mesh);
|
|
61881
61914
|
_this.animations = animations;
|
|
61882
61915
|
_this.isPlaying = false;
|
|
61916
|
+
_this.currentAction = null;
|
|
61917
|
+
_this.activeActions = new Map(); // Track multiple active actions for layered blending
|
|
61883
61918
|
|
|
61884
61919
|
_this.addEventsListeners();
|
|
61885
61920
|
|
|
@@ -61930,39 +61965,260 @@ const tweenTo = function (origin, target) {
|
|
|
61930
61965
|
|
|
61931
61966
|
this.isPlaying = false;
|
|
61932
61967
|
}
|
|
61968
|
+
/**
|
|
61969
|
+
* Stop a specific animation by name/index with optional fade out
|
|
61970
|
+
* @param {string|number} id - Animation name or index
|
|
61971
|
+
* @param {number} fadeOutDuration - Duration to fade out (0 for immediate stop)
|
|
61972
|
+
*/
|
|
61973
|
+
|
|
61974
|
+
}, {
|
|
61975
|
+
key: "stopAnimation",
|
|
61976
|
+
value: function stopAnimation(id) {
|
|
61977
|
+
let fadeOutDuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
61978
|
+
const clip = this.getAction(id);
|
|
61979
|
+
if (!clip) return;
|
|
61980
|
+
const action = this.mixer.clipAction(clip);
|
|
61981
|
+
|
|
61982
|
+
if (fadeOutDuration > 0) {
|
|
61983
|
+
action.fadeOut(fadeOutDuration);
|
|
61984
|
+
} else {
|
|
61985
|
+
action.stop();
|
|
61986
|
+
}
|
|
61987
|
+
|
|
61988
|
+
this.activeActions.delete(id);
|
|
61989
|
+
|
|
61990
|
+
if (this.currentAction === action) {
|
|
61991
|
+
this.currentAction = null;
|
|
61992
|
+
this.isPlaying = false;
|
|
61993
|
+
}
|
|
61994
|
+
}
|
|
61995
|
+
/**
|
|
61996
|
+
* Play an animation with optional blending from current animation
|
|
61997
|
+
* @param {string|number} id - Animation name or index
|
|
61998
|
+
* @param {Object} options - Playback options
|
|
61999
|
+
* @param {number} options.loop - Loop mode (LoopRepeat, LoopOnce, etc.)
|
|
62000
|
+
* @param {number} options.blendDuration - Duration to blend from previous animation
|
|
62001
|
+
* @param {number} options.timeScale - Playback speed (1 = normal, 2 = double speed)
|
|
62002
|
+
* @param {number} options.weight - Animation weight for layered blending (0-1)
|
|
62003
|
+
* @param {boolean} options.clampWhenFinished - Keep last frame when finished (for LoopOnce)
|
|
62004
|
+
*/
|
|
62005
|
+
|
|
61933
62006
|
}, {
|
|
61934
62007
|
key: "playAnimation",
|
|
61935
|
-
value: function playAnimation(id
|
|
61936
|
-
|
|
62008
|
+
value: function playAnimation(id) {
|
|
62009
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
62010
|
+
const clip = this.getAction(id);
|
|
62011
|
+
|
|
62012
|
+
if (!clip) {
|
|
62013
|
+
console.warn(ANIMATION_NOT_FOUND);
|
|
62014
|
+
return null;
|
|
62015
|
+
}
|
|
62016
|
+
|
|
61937
62017
|
const {
|
|
61938
|
-
loop = LoopRepeat
|
|
62018
|
+
loop = LoopRepeat,
|
|
62019
|
+
blendDuration = DEFAULT_BLEND_DURATION,
|
|
62020
|
+
timeScale = 1,
|
|
62021
|
+
weight = 1,
|
|
62022
|
+
clampWhenFinished = true
|
|
61939
62023
|
} = options;
|
|
61940
62024
|
this.isPlaying = true;
|
|
61941
62025
|
|
|
61942
62026
|
if (this.currentAction) {
|
|
61943
|
-
this.
|
|
61944
|
-
|
|
61945
|
-
|
|
62027
|
+
return this.crossFadeTo(id, { ...options,
|
|
62028
|
+
blendDuration
|
|
62029
|
+
});
|
|
61946
62030
|
} else {
|
|
62031
|
+
const action = this.mixer.clipAction(clip);
|
|
62032
|
+
this.currentAction = action;
|
|
62033
|
+
this.activeActions.set(id, action);
|
|
62034
|
+
action.reset().setLoop(loop).setEffectiveTimeScale(timeScale).setEffectiveWeight(weight);
|
|
62035
|
+
|
|
62036
|
+
if (loop === LoopOnce) {
|
|
62037
|
+
action.clampWhenFinished = clampWhenFinished;
|
|
62038
|
+
}
|
|
62039
|
+
|
|
62040
|
+
action.play();
|
|
62041
|
+
return action;
|
|
62042
|
+
}
|
|
62043
|
+
}
|
|
62044
|
+
/**
|
|
62045
|
+
* Crossfade from current animation to a new animation
|
|
62046
|
+
* @param {string|number} id - Target animation name or index
|
|
62047
|
+
* @param {Object} options - Blend options
|
|
62048
|
+
* @param {number} options.blendDuration - Duration of the crossfade
|
|
62049
|
+
* @param {number} options.loop - Loop mode for the new animation
|
|
62050
|
+
* @param {number} options.timeScale - Playback speed
|
|
62051
|
+
* @param {boolean} options.warp - Whether to warp time scales during blend
|
|
62052
|
+
*/
|
|
62053
|
+
|
|
62054
|
+
}, {
|
|
62055
|
+
key: "crossFadeTo",
|
|
62056
|
+
value: function crossFadeTo(id) {
|
|
62057
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
62058
|
+
const clip = this.getAction(id);
|
|
62059
|
+
|
|
62060
|
+
if (!clip) {
|
|
61947
62061
|
console.warn(ANIMATION_NOT_FOUND);
|
|
62062
|
+
return null;
|
|
62063
|
+
}
|
|
62064
|
+
|
|
62065
|
+
const {
|
|
62066
|
+
blendDuration = DEFAULT_BLEND_DURATION,
|
|
62067
|
+
loop = LoopRepeat,
|
|
62068
|
+
timeScale = 1,
|
|
62069
|
+
warp = false,
|
|
62070
|
+
clampWhenFinished = true
|
|
62071
|
+
} = options;
|
|
62072
|
+
const previousAction = this.currentAction;
|
|
62073
|
+
const newAction = this.mixer.clipAction(clip);
|
|
62074
|
+
|
|
62075
|
+
if (previousAction === newAction) {
|
|
62076
|
+
return newAction; // Already playing this animation
|
|
62077
|
+
}
|
|
62078
|
+
|
|
62079
|
+
this.currentAction = newAction;
|
|
62080
|
+
this.activeActions.set(id, newAction);
|
|
62081
|
+
newAction.reset().setLoop(loop).setEffectiveTimeScale(timeScale).setEffectiveWeight(1);
|
|
62082
|
+
|
|
62083
|
+
if (loop === LoopOnce) {
|
|
62084
|
+
newAction.clampWhenFinished = clampWhenFinished;
|
|
62085
|
+
}
|
|
62086
|
+
|
|
62087
|
+
newAction.play();
|
|
62088
|
+
|
|
62089
|
+
if (previousAction) {
|
|
62090
|
+
if (warp) {
|
|
62091
|
+
// Synchronize time scales during crossfade
|
|
62092
|
+
previousAction.crossFadeTo(newAction, blendDuration, true);
|
|
62093
|
+
} else {
|
|
62094
|
+
// Standard crossfade
|
|
62095
|
+
previousAction.fadeOut(blendDuration);
|
|
62096
|
+
newAction.fadeIn(blendDuration);
|
|
62097
|
+
}
|
|
61948
62098
|
}
|
|
62099
|
+
|
|
62100
|
+
return newAction;
|
|
61949
62101
|
}
|
|
62102
|
+
/**
|
|
62103
|
+
* Legacy method - kept for backwards compatibility
|
|
62104
|
+
*/
|
|
62105
|
+
|
|
61950
62106
|
}, {
|
|
61951
62107
|
key: "fadeToAnimation",
|
|
61952
62108
|
value: function fadeToAnimation(action) {
|
|
61953
62109
|
let {
|
|
61954
|
-
duration =
|
|
62110
|
+
duration = DEFAULT_BLEND_DURATION,
|
|
61955
62111
|
loop = LoopRepeat
|
|
61956
62112
|
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
61957
62113
|
const previousAction = this.currentAction;
|
|
61958
62114
|
this.currentAction = this.mixer.clipAction(action);
|
|
61959
62115
|
|
|
61960
|
-
if (previousAction !== this.currentAction) {
|
|
62116
|
+
if (previousAction && previousAction !== this.currentAction) {
|
|
61961
62117
|
previousAction.fadeOut(duration);
|
|
61962
62118
|
}
|
|
61963
62119
|
|
|
61964
62120
|
this.currentAction.reset().setEffectiveTimeScale(1).setEffectiveWeight(1).fadeIn(duration).setLoop(loop).play();
|
|
61965
62121
|
}
|
|
62122
|
+
/**
|
|
62123
|
+
* Set the weight of an animation for layered blending
|
|
62124
|
+
* @param {string|number} id - Animation name or index
|
|
62125
|
+
* @param {number} weight - Weight value (0-1)
|
|
62126
|
+
* @param {number} fadeDuration - Optional fade duration to reach target weight
|
|
62127
|
+
*/
|
|
62128
|
+
|
|
62129
|
+
}, {
|
|
62130
|
+
key: "setAnimationWeight",
|
|
62131
|
+
value: function setAnimationWeight(id, weight) {
|
|
62132
|
+
let fadeDuration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
62133
|
+
const clip = this.getAction(id);
|
|
62134
|
+
if (!clip) return;
|
|
62135
|
+
const action = this.mixer.clipAction(clip);
|
|
62136
|
+
|
|
62137
|
+
if (fadeDuration > 0) {
|
|
62138
|
+
// Gradually change weight
|
|
62139
|
+
const startWeight = action.getEffectiveWeight();
|
|
62140
|
+
const startTime = this.mixer.time;
|
|
62141
|
+
|
|
62142
|
+
const updateWeight = () => {
|
|
62143
|
+
const elapsed = this.mixer.time - startTime;
|
|
62144
|
+
const t = Math.min(elapsed / fadeDuration, 1);
|
|
62145
|
+
action.setEffectiveWeight(startWeight + (weight - startWeight) * t);
|
|
62146
|
+
}; // This will be called in the update loop
|
|
62147
|
+
|
|
62148
|
+
|
|
62149
|
+
action._weightUpdateFn = updateWeight;
|
|
62150
|
+
} else {
|
|
62151
|
+
action.setEffectiveWeight(weight);
|
|
62152
|
+
}
|
|
62153
|
+
}
|
|
62154
|
+
/**
|
|
62155
|
+
* Set the time scale (speed) of an animation
|
|
62156
|
+
* @param {string|number} id - Animation name or index
|
|
62157
|
+
* @param {number} timeScale - Speed multiplier (1 = normal)
|
|
62158
|
+
*/
|
|
62159
|
+
|
|
62160
|
+
}, {
|
|
62161
|
+
key: "setAnimationTimeScale",
|
|
62162
|
+
value: function setAnimationTimeScale(id, timeScale) {
|
|
62163
|
+
const clip = this.getAction(id);
|
|
62164
|
+
if (!clip) return;
|
|
62165
|
+
const action = this.mixer.clipAction(clip);
|
|
62166
|
+
action.setEffectiveTimeScale(timeScale);
|
|
62167
|
+
}
|
|
62168
|
+
/**
|
|
62169
|
+
* Get the current time of an animation
|
|
62170
|
+
* @param {string|number} id - Animation name or index
|
|
62171
|
+
* @returns {number} Current time in seconds
|
|
62172
|
+
*/
|
|
62173
|
+
|
|
62174
|
+
}, {
|
|
62175
|
+
key: "getAnimationTime",
|
|
62176
|
+
value: function getAnimationTime(id) {
|
|
62177
|
+
const clip = this.getAction(id);
|
|
62178
|
+
if (!clip) return 0;
|
|
62179
|
+
const action = this.mixer.clipAction(clip);
|
|
62180
|
+
return action.time;
|
|
62181
|
+
}
|
|
62182
|
+
/**
|
|
62183
|
+
* Set the current time of an animation
|
|
62184
|
+
* @param {string|number} id - Animation name or index
|
|
62185
|
+
* @param {number} time - Time in seconds
|
|
62186
|
+
*/
|
|
62187
|
+
|
|
62188
|
+
}, {
|
|
62189
|
+
key: "setAnimationTime",
|
|
62190
|
+
value: function setAnimationTime(id, time) {
|
|
62191
|
+
const clip = this.getAction(id);
|
|
62192
|
+
if (!clip) return;
|
|
62193
|
+
const action = this.mixer.clipAction(clip);
|
|
62194
|
+
action.time = time;
|
|
62195
|
+
}
|
|
62196
|
+
/**
|
|
62197
|
+
* Check if a specific animation is currently playing
|
|
62198
|
+
* @param {string|number} id - Animation name or index
|
|
62199
|
+
* @returns {boolean}
|
|
62200
|
+
*/
|
|
62201
|
+
|
|
62202
|
+
}, {
|
|
62203
|
+
key: "isAnimationPlaying",
|
|
62204
|
+
value: function isAnimationPlaying(id) {
|
|
62205
|
+
const clip = this.getAction(id);
|
|
62206
|
+
if (!clip) return false;
|
|
62207
|
+
const action = this.mixer.clipAction(clip);
|
|
62208
|
+
return action.isRunning();
|
|
62209
|
+
}
|
|
62210
|
+
/**
|
|
62211
|
+
* Get the duration of an animation clip
|
|
62212
|
+
* @param {string|number} id - Animation name or index
|
|
62213
|
+
* @returns {number} Duration in seconds
|
|
62214
|
+
*/
|
|
62215
|
+
|
|
62216
|
+
}, {
|
|
62217
|
+
key: "getAnimationDuration",
|
|
62218
|
+
value: function getAnimationDuration(id) {
|
|
62219
|
+
const clip = this.getAction(id);
|
|
62220
|
+
return clip ? clip.duration : 0;
|
|
62221
|
+
}
|
|
61966
62222
|
}, {
|
|
61967
62223
|
key: "update",
|
|
61968
62224
|
value: function update(dt) {
|
|
@@ -62407,8 +62663,8 @@ let Element$1 = /*#__PURE__*/function (_Entity) {
|
|
|
62407
62663
|
}
|
|
62408
62664
|
}
|
|
62409
62665
|
}, {
|
|
62410
|
-
key: "
|
|
62411
|
-
value: function
|
|
62666
|
+
key: "stopCurrentAnimation",
|
|
62667
|
+
value: function stopCurrentAnimation() {
|
|
62412
62668
|
if (!this.hasAnimations()) return;
|
|
62413
62669
|
|
|
62414
62670
|
if (this.hasAnimationHandler()) {
|
|
@@ -62430,6 +62686,123 @@ let Element$1 = /*#__PURE__*/function (_Entity) {
|
|
|
62430
62686
|
|
|
62431
62687
|
return [];
|
|
62432
62688
|
}
|
|
62689
|
+
/**
|
|
62690
|
+
* Crossfade from current animation to a new animation
|
|
62691
|
+
* @param {string|number} id - Target animation name or index
|
|
62692
|
+
* @param {Object} options - Blend options
|
|
62693
|
+
* @param {number} options.blendDuration - Duration of the crossfade (default: 0.3)
|
|
62694
|
+
* @param {number} options.loop - Loop mode (LoopRepeat, LoopOnce)
|
|
62695
|
+
* @param {number} options.timeScale - Playback speed (1 = normal)
|
|
62696
|
+
* @param {boolean} options.warp - Whether to warp time scales during blend
|
|
62697
|
+
*/
|
|
62698
|
+
|
|
62699
|
+
}, {
|
|
62700
|
+
key: "crossFadeTo",
|
|
62701
|
+
value: function crossFadeTo(id) {
|
|
62702
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
62703
|
+
if (!this.hasAnimations()) return;
|
|
62704
|
+
|
|
62705
|
+
if (this.hasAnimationHandler()) {
|
|
62706
|
+
return this.animationHandler.crossFadeTo(id, options);
|
|
62707
|
+
} else {
|
|
62708
|
+
console.warn(ANIMATION_HANDLER_NOT_FOUND);
|
|
62709
|
+
}
|
|
62710
|
+
}
|
|
62711
|
+
/**
|
|
62712
|
+
* Stop an animation. If no id is provided, stops the current animation.
|
|
62713
|
+
* @param {string|number} [id] - Animation name or index (optional)
|
|
62714
|
+
* @param {number} fadeOutDuration - Duration to fade out (0 for immediate)
|
|
62715
|
+
*/
|
|
62716
|
+
|
|
62717
|
+
}, {
|
|
62718
|
+
key: "stopAnimation",
|
|
62719
|
+
value: function stopAnimation(id) {
|
|
62720
|
+
let fadeOutDuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
62721
|
+
if (!this.hasAnimations()) return;
|
|
62722
|
+
|
|
62723
|
+
if (this.hasAnimationHandler()) {
|
|
62724
|
+
// If no id provided, stop the current animation
|
|
62725
|
+
if (id === undefined || id === null) {
|
|
62726
|
+
this.animationHandler.stopCurrentAnimation();
|
|
62727
|
+
} else {
|
|
62728
|
+
this.animationHandler.stopAnimation(id, fadeOutDuration);
|
|
62729
|
+
}
|
|
62730
|
+
} else {
|
|
62731
|
+
console.warn(ANIMATION_HANDLER_NOT_FOUND);
|
|
62732
|
+
}
|
|
62733
|
+
}
|
|
62734
|
+
/**
|
|
62735
|
+
* Set the weight of an animation for layered blending
|
|
62736
|
+
* @param {string|number} id - Animation name or index
|
|
62737
|
+
* @param {number} weight - Weight value (0-1)
|
|
62738
|
+
* @param {number} fadeDuration - Optional fade duration
|
|
62739
|
+
*/
|
|
62740
|
+
|
|
62741
|
+
}, {
|
|
62742
|
+
key: "setAnimationWeight",
|
|
62743
|
+
value: function setAnimationWeight(id, weight) {
|
|
62744
|
+
let fadeDuration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
62745
|
+
if (!this.hasAnimations()) return;
|
|
62746
|
+
|
|
62747
|
+
if (this.hasAnimationHandler()) {
|
|
62748
|
+
this.animationHandler.setAnimationWeight(id, weight, fadeDuration);
|
|
62749
|
+
} else {
|
|
62750
|
+
console.warn(ANIMATION_HANDLER_NOT_FOUND);
|
|
62751
|
+
}
|
|
62752
|
+
}
|
|
62753
|
+
/**
|
|
62754
|
+
* Set the playback speed of an animation
|
|
62755
|
+
* @param {string|number} id - Animation name or index
|
|
62756
|
+
* @param {number} timeScale - Speed multiplier (1 = normal, 2 = double speed)
|
|
62757
|
+
*/
|
|
62758
|
+
|
|
62759
|
+
}, {
|
|
62760
|
+
key: "setAnimationTimeScale",
|
|
62761
|
+
value: function setAnimationTimeScale(id, timeScale) {
|
|
62762
|
+
if (!this.hasAnimations()) return;
|
|
62763
|
+
|
|
62764
|
+
if (this.hasAnimationHandler()) {
|
|
62765
|
+
this.animationHandler.setAnimationTimeScale(id, timeScale);
|
|
62766
|
+
} else {
|
|
62767
|
+
console.warn(ANIMATION_HANDLER_NOT_FOUND);
|
|
62768
|
+
}
|
|
62769
|
+
}
|
|
62770
|
+
/**
|
|
62771
|
+
* Get the duration of an animation clip
|
|
62772
|
+
* @param {string|number} id - Animation name or index
|
|
62773
|
+
* @returns {number} Duration in seconds
|
|
62774
|
+
*/
|
|
62775
|
+
|
|
62776
|
+
}, {
|
|
62777
|
+
key: "getAnimationDuration",
|
|
62778
|
+
value: function getAnimationDuration(id) {
|
|
62779
|
+
if (!this.hasAnimations()) return 0;
|
|
62780
|
+
|
|
62781
|
+
if (this.hasAnimationHandler()) {
|
|
62782
|
+
return this.animationHandler.getAnimationDuration(id);
|
|
62783
|
+
} else {
|
|
62784
|
+
console.warn(ANIMATION_HANDLER_NOT_FOUND);
|
|
62785
|
+
return 0;
|
|
62786
|
+
}
|
|
62787
|
+
}
|
|
62788
|
+
/**
|
|
62789
|
+
* Check if a specific animation is currently playing
|
|
62790
|
+
* @param {string|number} id - Animation name or index
|
|
62791
|
+
* @returns {boolean}
|
|
62792
|
+
*/
|
|
62793
|
+
|
|
62794
|
+
}, {
|
|
62795
|
+
key: "isAnimationPlaying",
|
|
62796
|
+
value: function isAnimationPlaying(id) {
|
|
62797
|
+
if (!this.hasAnimations()) return false;
|
|
62798
|
+
|
|
62799
|
+
if (this.hasAnimationHandler()) {
|
|
62800
|
+
return this.animationHandler.isAnimationPlaying(id);
|
|
62801
|
+
} else {
|
|
62802
|
+
console.warn(ANIMATION_HANDLER_NOT_FOUND);
|
|
62803
|
+
return false;
|
|
62804
|
+
}
|
|
62805
|
+
}
|
|
62433
62806
|
/**
|
|
62434
62807
|
* TODO: the entire physics system needs to be a component
|
|
62435
62808
|
* e.g.
|
|
@@ -63161,6 +63534,50 @@ let Element$1 = /*#__PURE__*/function (_Entity) {
|
|
|
63161
63534
|
|
|
63162
63535
|
Physics$1.disposeElement(this);
|
|
63163
63536
|
}
|
|
63537
|
+
/**
|
|
63538
|
+
* Serialize only the material properties that the Importer actually uses.
|
|
63539
|
+
* This avoids bloating the JSON with full Three.js material data.
|
|
63540
|
+
*/
|
|
63541
|
+
|
|
63542
|
+
}, {
|
|
63543
|
+
key: "serializeMaterialProperties",
|
|
63544
|
+
value: function serializeMaterialProperties() {
|
|
63545
|
+
const materialType = this.getMaterialType(); // Use allowed properties for known material types, or fallback to STANDARD properties
|
|
63546
|
+
// which has the most comprehensive set
|
|
63547
|
+
|
|
63548
|
+
const allowedProperties = MATERIAL_PROPERTIES_MAP[materialType] || MATERIAL_PROPERTIES_MAP[MATERIALS.STANDARD] || [];
|
|
63549
|
+
const materials = this.getMaterials();
|
|
63550
|
+
if (!materials.length) return [];
|
|
63551
|
+
return materials.map(material => {
|
|
63552
|
+
const serialized = {
|
|
63553
|
+
// Always include the material type for the inspector
|
|
63554
|
+
type: material.type
|
|
63555
|
+
};
|
|
63556
|
+
|
|
63557
|
+
for (const prop of allowedProperties) {
|
|
63558
|
+
if (material[prop] !== undefined) {
|
|
63559
|
+
const value = material[prop]; // Serialize Color objects to plain objects
|
|
63560
|
+
|
|
63561
|
+
if (value && value.isColor) {
|
|
63562
|
+
serialized[prop] = {
|
|
63563
|
+
r: value.r,
|
|
63564
|
+
g: value.g,
|
|
63565
|
+
b: value.b
|
|
63566
|
+
};
|
|
63567
|
+
} else if (value && value.isVector2) {
|
|
63568
|
+
serialized[prop] = {
|
|
63569
|
+
x: value.x,
|
|
63570
|
+
y: value.y
|
|
63571
|
+
};
|
|
63572
|
+
} else {
|
|
63573
|
+
serialized[prop] = value;
|
|
63574
|
+
}
|
|
63575
|
+
}
|
|
63576
|
+
}
|
|
63577
|
+
|
|
63578
|
+
return serialized;
|
|
63579
|
+
});
|
|
63580
|
+
}
|
|
63164
63581
|
}, {
|
|
63165
63582
|
key: "toJSON",
|
|
63166
63583
|
value: function toJSON() {
|
|
@@ -63169,18 +63586,26 @@ let Element$1 = /*#__PURE__*/function (_Entity) {
|
|
|
63169
63586
|
if (this.isSerializable()) {
|
|
63170
63587
|
const color = this.getColor();
|
|
63171
63588
|
return { ..._get(_getPrototypeOf(Element.prototype), "toJSON", this).call(this, parseJSON),
|
|
63589
|
+
// Physics options (state is not used by Importer, only options)
|
|
63172
63590
|
physics: {
|
|
63173
|
-
state: serializeMap(this.getPhysicsState()),
|
|
63174
63591
|
options: this.getPhysicsOptions()
|
|
63175
63592
|
},
|
|
63176
|
-
//
|
|
63593
|
+
// Textures with serialized map
|
|
63177
63594
|
textures: serializeMap(this.textures),
|
|
63595
|
+
// Material type name (e.g., "STANDARD", "BASIC")
|
|
63178
63596
|
materialType: this.getMaterialType(),
|
|
63179
|
-
|
|
63180
|
-
|
|
63181
|
-
//
|
|
63597
|
+
// Lightweight material properties (type + allowed properties only)
|
|
63598
|
+
materials: this.serializeMaterialProperties(),
|
|
63599
|
+
// Opacity
|
|
63182
63600
|
opacity: this.opacity,
|
|
63183
|
-
|
|
63601
|
+
// Color (for inspector display)
|
|
63602
|
+
color: parseJSON ? {
|
|
63603
|
+
r: color === null || color === void 0 ? void 0 : color.r,
|
|
63604
|
+
g: color === null || color === void 0 ? void 0 : color.g,
|
|
63605
|
+
b: color === null || color === void 0 ? void 0 : color.b
|
|
63606
|
+
} : color,
|
|
63607
|
+
// Animation names (for inspector display - actual animations loaded from model file)
|
|
63608
|
+
animations: this.getAvailableAnimations()
|
|
63184
63609
|
};
|
|
63185
63610
|
}
|
|
63186
63611
|
}
|
|
@@ -81237,6 +81662,10 @@ const glbParser = gltf => {
|
|
|
81237
81662
|
if (object.isMesh) {
|
|
81238
81663
|
object.castShadow = true;
|
|
81239
81664
|
}
|
|
81665
|
+
|
|
81666
|
+
if (object.isSkinnedMesh) {
|
|
81667
|
+
object.frustumCulled = false;
|
|
81668
|
+
}
|
|
81240
81669
|
});
|
|
81241
81670
|
return {
|
|
81242
81671
|
animations,
|
|
@@ -81256,6 +81685,11 @@ const gltfParser = gltf => {
|
|
|
81256
81685
|
return null;
|
|
81257
81686
|
}
|
|
81258
81687
|
|
|
81688
|
+
gltf.scene.traverse(node => {
|
|
81689
|
+
if (node.isSkinnedMesh) {
|
|
81690
|
+
node.frustumCulled = false;
|
|
81691
|
+
}
|
|
81692
|
+
});
|
|
81259
81693
|
return {
|
|
81260
81694
|
scene: gltf.scene,
|
|
81261
81695
|
animations: gltf.animations
|
|
@@ -81326,6 +81760,7 @@ const fbxParser = scene => {
|
|
|
81326
81760
|
|
|
81327
81761
|
scene.traverse(node => {
|
|
81328
81762
|
if (node.isSkinnedMesh) {
|
|
81763
|
+
node.frustumCulled = false;
|
|
81329
81764
|
processMaterial(node.material, material => material.skinning = true);
|
|
81330
81765
|
}
|
|
81331
81766
|
});
|
|
@@ -81383,6 +81818,8 @@ let Models = /*#__PURE__*/function (_EventDispatcher) {
|
|
|
81383
81818
|
});
|
|
81384
81819
|
|
|
81385
81820
|
_defineProperty$1(_assertThisInitialized(_this), "create", function (name) {
|
|
81821
|
+
var _scene$children, _scene$traverse, _element$getBody;
|
|
81822
|
+
|
|
81386
81823
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
81387
81824
|
const builtAssetId = buildAssetId(name, _this.currentLevel);
|
|
81388
81825
|
const modelData = _this.map[name] || _this.map[builtAssetId];
|
|
@@ -81396,7 +81833,23 @@ let Models = /*#__PURE__*/function (_EventDispatcher) {
|
|
|
81396
81833
|
scene,
|
|
81397
81834
|
animations,
|
|
81398
81835
|
extension
|
|
81399
|
-
} = modelData; //
|
|
81836
|
+
} = modelData; // Debug: Log model structure
|
|
81837
|
+
|
|
81838
|
+
console.log(`[Mage] Creating model "${name}":`, {
|
|
81839
|
+
hasScene: !!scene,
|
|
81840
|
+
sceneType: scene === null || scene === void 0 ? void 0 : scene.type,
|
|
81841
|
+
childrenCount: scene === null || scene === void 0 ? void 0 : (_scene$children = scene.children) === null || _scene$children === void 0 ? void 0 : _scene$children.length,
|
|
81842
|
+
animations: (animations === null || animations === void 0 ? void 0 : animations.length) || 0,
|
|
81843
|
+
extension
|
|
81844
|
+
}); // Debug: Check for meshes in the scene
|
|
81845
|
+
|
|
81846
|
+
let meshCount = 0;
|
|
81847
|
+
let skinnedMeshCount = 0;
|
|
81848
|
+
scene === null || scene === void 0 ? void 0 : (_scene$traverse = scene.traverse) === null || _scene$traverse === void 0 ? void 0 : _scene$traverse.call(scene, node => {
|
|
81849
|
+
if (node.isMesh) meshCount++;
|
|
81850
|
+
if (node.isSkinnedMesh) skinnedMeshCount++;
|
|
81851
|
+
});
|
|
81852
|
+
console.log(`[Mage] Model "${name}" contains: ${meshCount} meshes, ${skinnedMeshCount} skinned meshes`); // Validate that scene is a valid THREE.js object with required methods
|
|
81400
81853
|
|
|
81401
81854
|
if (!scene || typeof scene.clone !== 'function' || typeof scene.traverse !== 'function') {
|
|
81402
81855
|
console.warn(`[Mage] Model "${name}" has invalid scene object. Got:`, Object.keys(modelData));
|
|
@@ -81408,8 +81861,17 @@ let Models = /*#__PURE__*/function (_EventDispatcher) {
|
|
|
81408
81861
|
builtAssetId,
|
|
81409
81862
|
...options
|
|
81410
81863
|
};
|
|
81411
|
-
let model;
|
|
81412
|
-
|
|
81864
|
+
let model; // Check if the scene contains any skinned meshes
|
|
81865
|
+
|
|
81866
|
+
let hasSkinnedMeshes = false;
|
|
81867
|
+
scene.traverse(node => {
|
|
81868
|
+
if (node.isSkinnedMesh) {
|
|
81869
|
+
hasSkinnedMeshes = true;
|
|
81870
|
+
}
|
|
81871
|
+
}); // Use SkeletonUtils.clone for models with skinned meshes OR animations
|
|
81872
|
+
// Regular clone() doesn't properly handle skeleton binding
|
|
81873
|
+
|
|
81874
|
+
const useSkeletonClone = extension !== EXTENSIONS.COLLADA && (hasAnimations(animations) || hasSkinnedMeshes);
|
|
81413
81875
|
|
|
81414
81876
|
try {
|
|
81415
81877
|
if (useSkeletonClone) {
|
|
@@ -81440,6 +81902,21 @@ let Models = /*#__PURE__*/function (_EventDispatcher) {
|
|
|
81440
81902
|
|
|
81441
81903
|
if (hasAnimations(animations)) {
|
|
81442
81904
|
element.addAnimationHandler(animations);
|
|
81905
|
+
} // Debug: Log element body info
|
|
81906
|
+
|
|
81907
|
+
|
|
81908
|
+
const body = (_element$getBody = element.getBody) === null || _element$getBody === void 0 ? void 0 : _element$getBody.call(element);
|
|
81909
|
+
|
|
81910
|
+
if (body) {
|
|
81911
|
+
var _body$position, _body$position$toArra, _body$scale, _body$scale$toArray, _body$children;
|
|
81912
|
+
|
|
81913
|
+
console.log(`[Mage] Element "${name}" body:`, {
|
|
81914
|
+
type: body.type,
|
|
81915
|
+
visible: body.visible,
|
|
81916
|
+
position: (_body$position = body.position) === null || _body$position === void 0 ? void 0 : (_body$position$toArra = _body$position.toArray) === null || _body$position$toArra === void 0 ? void 0 : _body$position$toArra.call(_body$position),
|
|
81917
|
+
scale: (_body$scale = body.scale) === null || _body$scale === void 0 ? void 0 : (_body$scale$toArray = _body$scale.toArray) === null || _body$scale$toArray === void 0 ? void 0 : _body$scale$toArray.call(_body$scale),
|
|
81918
|
+
childrenCount: (_body$children = body.children) === null || _body$children === void 0 ? void 0 : _body$children.length
|
|
81919
|
+
});
|
|
81443
81920
|
}
|
|
81444
81921
|
|
|
81445
81922
|
return element;
|
|
@@ -90964,7 +91441,10 @@ var Particles$1 = new Particles();let Orbit = /*#__PURE__*/function (_EventDispa
|
|
|
90964
91441
|
object.quaternion.copy(_this._tempQuaternion.setFromAxisAngle(_this.rotationAxis, _this.rotationAngle));
|
|
90965
91442
|
object.quaternion.multiply(_this._quaternionStart);
|
|
90966
91443
|
}
|
|
90967
|
-
}
|
|
91444
|
+
} // Update skinned mesh skeletons after transform
|
|
91445
|
+
|
|
91446
|
+
|
|
91447
|
+
_this.updateSkinnedMeshSkeletons();
|
|
90968
91448
|
|
|
90969
91449
|
_this.dispatchEvent(_this.changeEvent);
|
|
90970
91450
|
|
|
@@ -91247,7 +91727,19 @@ var Particles$1 = new Particles();let Orbit = /*#__PURE__*/function (_EventDispa
|
|
|
91247
91727
|
value: function attach(element) {
|
|
91248
91728
|
if (!element) return;
|
|
91249
91729
|
this.object = element.getBody();
|
|
91250
|
-
this.visible = true;
|
|
91730
|
+
this.visible = true; // Force immediate matrix world update to ensure gizmo position is correct
|
|
91731
|
+
// This is especially important for skinned meshes where the matrix may not be current
|
|
91732
|
+
|
|
91733
|
+
if (this.object) {
|
|
91734
|
+
this.object.updateMatrixWorld(true);
|
|
91735
|
+
}
|
|
91736
|
+
} // Update matrix world for skinned meshes after transform changes
|
|
91737
|
+
|
|
91738
|
+
}, {
|
|
91739
|
+
key: "updateSkinnedMeshSkeletons",
|
|
91740
|
+
value: function updateSkinnedMeshSkeletons() {
|
|
91741
|
+
if (!this.object) return;
|
|
91742
|
+
this.object.updateMatrixWorld(true);
|
|
91251
91743
|
}
|
|
91252
91744
|
}, {
|
|
91253
91745
|
key: "detach",
|