minerender 2.1.0-alpha.131 → 2.1.0-alpha.132
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/browser/esm/entity/scene/EntityAnimationPlayer.mjs +62 -11
- package/dist/browser/esm/entity/scene/EntityAnimationPlayer.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityObject.mjs +53 -20
- package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +28 -7
- package/dist/browser/index.d.ts +28 -7
- package/dist/browser/index.js +112 -28
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +112 -28
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +28 -7
- package/dist/node/index.d.ts +28 -7
- package/dist/node/index.js +113 -28
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +112 -28
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -5003,6 +5003,13 @@ var init_EntityAnimation = __esm({
|
|
|
5003
5003
|
|
|
5004
5004
|
// src/entity/scene/EntityAnimationPlayer.ts
|
|
5005
5005
|
import { Euler as Euler3, Vector3 as Vector35 } from "three";
|
|
5006
|
+
function validateAnimationWeights(weights, count) {
|
|
5007
|
+
const values = Array.from(weights);
|
|
5008
|
+
if (values.length !== count || values.some((weight) => !Number.isFinite(weight) || weight < 0)) {
|
|
5009
|
+
throw new Error("Animation weights must match the clip count and contain only finite nonnegative numbers");
|
|
5010
|
+
}
|
|
5011
|
+
return values;
|
|
5012
|
+
}
|
|
5006
5013
|
var ZERO, EntityAnimationPlayer;
|
|
5007
5014
|
var init_EntityAnimationPlayer = __esm({
|
|
5008
5015
|
"src/entity/scene/EntityAnimationPlayer.ts"() {
|
|
@@ -5011,12 +5018,20 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5011
5018
|
EntityAnimationPlayer = class {
|
|
5012
5019
|
constructor() {
|
|
5013
5020
|
this.parts = [];
|
|
5021
|
+
this._animations = [];
|
|
5022
|
+
this._weights = [];
|
|
5023
|
+
this.loops = [];
|
|
5014
5024
|
this._time = 0;
|
|
5015
|
-
this.loop = false;
|
|
5016
5025
|
this.speed = 1;
|
|
5017
5026
|
}
|
|
5018
5027
|
get animation() {
|
|
5019
|
-
return this.
|
|
5028
|
+
return this._animations[0];
|
|
5029
|
+
}
|
|
5030
|
+
get animations() {
|
|
5031
|
+
return this._animations.slice();
|
|
5032
|
+
}
|
|
5033
|
+
get weights() {
|
|
5034
|
+
return this._weights.slice();
|
|
5020
5035
|
}
|
|
5021
5036
|
get time() {
|
|
5022
5037
|
return this._time;
|
|
@@ -5026,10 +5041,20 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5026
5041
|
* without them, the current pose is used. Stopping restores the pose from before playback.
|
|
5027
5042
|
*/
|
|
5028
5043
|
play(layers, animation, options = {}, poses) {
|
|
5044
|
+
this.playAnimations(layers, [animation], options, poses);
|
|
5045
|
+
}
|
|
5046
|
+
/**
|
|
5047
|
+
* Starts clips on matching parts with a shared clock. Weighted offsets add to the supplied baked poses
|
|
5048
|
+
* or, without poses, to each animated part's pose when playback starts.
|
|
5049
|
+
*/
|
|
5050
|
+
playAnimations(layers, animations, options = {}, poses) {
|
|
5051
|
+
const weights = validateAnimationWeights(options.weights ?? animations.map(() => 1), animations.length);
|
|
5029
5052
|
this.stop();
|
|
5030
|
-
this.
|
|
5053
|
+
this._animations = animations.slice();
|
|
5054
|
+
this._weights = weights;
|
|
5055
|
+
if (!animations.length) return;
|
|
5031
5056
|
this._time = options.time ?? 0;
|
|
5032
|
-
this.
|
|
5057
|
+
this.loops = animations.map((animation) => options.loop ?? animation.loop);
|
|
5033
5058
|
this.speed = options.speed ?? 1;
|
|
5034
5059
|
for (const layer of layers) {
|
|
5035
5060
|
const objects = [];
|
|
@@ -5038,7 +5063,8 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5038
5063
|
if (poses.has(object4)) objects.push(object4);
|
|
5039
5064
|
});
|
|
5040
5065
|
} else {
|
|
5041
|
-
|
|
5066
|
+
const bones = new Set(animations.flatMap((animation) => Object.keys(animation.bones)));
|
|
5067
|
+
for (const bone of bones) {
|
|
5042
5068
|
const object4 = layer.getObjectByName(`group:${bone}`);
|
|
5043
5069
|
if (object4) objects.push(object4);
|
|
5044
5070
|
}
|
|
@@ -5062,7 +5088,7 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5062
5088
|
}
|
|
5063
5089
|
/** Restores the poses from before playback. Returns whether an animation was active. */
|
|
5064
5090
|
stop() {
|
|
5065
|
-
if (!this.
|
|
5091
|
+
if (!this._animations.length) return false;
|
|
5066
5092
|
for (const part of this.parts) {
|
|
5067
5093
|
part.object.position.copy(part.position);
|
|
5068
5094
|
part.object.rotation.copy(part.rotation);
|
|
@@ -5074,12 +5100,14 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5074
5100
|
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
5075
5101
|
clear() {
|
|
5076
5102
|
this.parts = [];
|
|
5077
|
-
this.
|
|
5103
|
+
this._animations = [];
|
|
5104
|
+
this._weights = [];
|
|
5105
|
+
this.loops = [];
|
|
5078
5106
|
this._time = 0;
|
|
5079
5107
|
}
|
|
5080
5108
|
/** Applies the pose at an absolute playback time. Returns `false` when no clip is active. */
|
|
5081
5109
|
setTime(seconds) {
|
|
5082
|
-
if (!this.
|
|
5110
|
+
if (!this._animations.length) return false;
|
|
5083
5111
|
this._time = seconds;
|
|
5084
5112
|
this.apply();
|
|
5085
5113
|
return true;
|
|
@@ -5088,8 +5116,30 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5088
5116
|
advance(deltaSeconds) {
|
|
5089
5117
|
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
5090
5118
|
}
|
|
5119
|
+
/** Changes weights in clip order and reapplies the current time without restarting playback. */
|
|
5120
|
+
setWeights(weights) {
|
|
5121
|
+
if (!this._animations.length) return false;
|
|
5122
|
+
const validated = validateAnimationWeights(weights, this._animations.length);
|
|
5123
|
+
this._weights = validated;
|
|
5124
|
+
this.apply();
|
|
5125
|
+
return true;
|
|
5126
|
+
}
|
|
5091
5127
|
apply() {
|
|
5092
|
-
const pose =
|
|
5128
|
+
const pose = /* @__PURE__ */ Object.create(null);
|
|
5129
|
+
for (let i = 0; i < this._animations.length; i++) {
|
|
5130
|
+
const weight = this._weights[i];
|
|
5131
|
+
if (weight === 0) continue;
|
|
5132
|
+
const sampled = sampleEntityAnimation(this._animations[i], this._time, this.loops[i]);
|
|
5133
|
+
for (const [bone, channels] of Object.entries(sampled)) {
|
|
5134
|
+
const blended = pose[bone] ??= {};
|
|
5135
|
+
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
5136
|
+
const value = channels[channel];
|
|
5137
|
+
if (!value) continue;
|
|
5138
|
+
const target = blended[channel] ??= [0, 0, 0];
|
|
5139
|
+
for (let axis = 0; axis < 3; axis++) target[axis] += value[axis] * weight;
|
|
5140
|
+
}
|
|
5141
|
+
}
|
|
5142
|
+
}
|
|
5093
5143
|
for (const part of this.parts) {
|
|
5094
5144
|
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};
|
|
5095
5145
|
part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);
|
|
@@ -5713,7 +5763,7 @@ var init_EntityObject = __esm({
|
|
|
5713
5763
|
for (const geometry of this.geometries) geometry.dispose();
|
|
5714
5764
|
this.geometries.clear();
|
|
5715
5765
|
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
5716
|
-
for (const player of this.animationPlayers.splice(0)) player.clear();
|
|
5766
|
+
for (const { player } of this.animationPlayers.splice(0)) player.clear();
|
|
5717
5767
|
this.partPoses.clear();
|
|
5718
5768
|
super.disposeAndRemoveAllChildren();
|
|
5719
5769
|
}
|
|
@@ -5748,15 +5798,31 @@ var init_EntityObject = __esm({
|
|
|
5748
5798
|
//<editor-fold desc="ANIMATION">
|
|
5749
5799
|
/** The first active clip, until playback is stopped or the object is disposed. */
|
|
5750
5800
|
get animation() {
|
|
5751
|
-
return this.animationPlayers[0]?.animation;
|
|
5801
|
+
return this.animationPlayers[0]?.player.animation;
|
|
5752
5802
|
}
|
|
5753
|
-
/** Clips playing together,
|
|
5803
|
+
/** Clips playing together, in the order passed to {@link playAnimations}. */
|
|
5754
5804
|
get activeAnimations() {
|
|
5755
|
-
|
|
5805
|
+
const animations = [];
|
|
5806
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
5807
|
+
player.animations.forEach((animation, i) => {
|
|
5808
|
+
animations[indices[i]] = animation;
|
|
5809
|
+
});
|
|
5810
|
+
}
|
|
5811
|
+
return animations;
|
|
5812
|
+
}
|
|
5813
|
+
/** Weights of the active clips, in the same order as {@link activeAnimations}. */
|
|
5814
|
+
get animationWeights() {
|
|
5815
|
+
const weights = [];
|
|
5816
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
5817
|
+
player.weights.forEach((weight, i) => {
|
|
5818
|
+
weights[indices[i]] = weight;
|
|
5819
|
+
});
|
|
5820
|
+
}
|
|
5821
|
+
return weights;
|
|
5756
5822
|
}
|
|
5757
5823
|
/** Seconds since the animation started, before looping. */
|
|
5758
5824
|
get animationTime() {
|
|
5759
|
-
return this.animationPlayers[0]?.time ?? 0;
|
|
5825
|
+
return this.animationPlayers[0]?.player.time ?? 0;
|
|
5760
5826
|
}
|
|
5761
5827
|
/**
|
|
5762
5828
|
* Plays a clip from {@link Entities.getAnimations}, replacing all active clips.
|
|
@@ -5767,42 +5833,59 @@ var init_EntityObject = __esm({
|
|
|
5767
5833
|
playAnimation(animation, options) {
|
|
5768
5834
|
this.playAnimations([animation], options);
|
|
5769
5835
|
}
|
|
5770
|
-
/**
|
|
5836
|
+
/**
|
|
5837
|
+
* Plays clips with a shared clock, adding their weighted offsets within each geometry layer.
|
|
5838
|
+
* Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.
|
|
5839
|
+
*/
|
|
5771
5840
|
playAnimations(animations, options) {
|
|
5772
|
-
const
|
|
5773
|
-
const selections =
|
|
5841
|
+
const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);
|
|
5842
|
+
const selections = /* @__PURE__ */ new Map();
|
|
5843
|
+
animations.forEach((animation, index) => {
|
|
5774
5844
|
const layer = animation.layer ?? "main";
|
|
5775
|
-
if (targets.has(layer)) throw new Error(`Multiple animations target layer "${layer}"`);
|
|
5776
|
-
targets.add(layer);
|
|
5777
5845
|
const names = Object.keys(this.entityLayers).filter((name) => name.split("#")[0] === layer);
|
|
5778
5846
|
if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer "${layer}"`);
|
|
5779
|
-
|
|
5847
|
+
let selection = selections.get(layer);
|
|
5848
|
+
if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });
|
|
5849
|
+
selection.animations.push(animation);
|
|
5850
|
+
selection.indices.push(index);
|
|
5780
5851
|
});
|
|
5781
|
-
const main = selections.
|
|
5782
|
-
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !
|
|
5852
|
+
const main = selections.get("main");
|
|
5853
|
+
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !selections.has(name.split("#")[0])));
|
|
5783
5854
|
this.createMeshes();
|
|
5784
5855
|
this.stopAnimation();
|
|
5785
|
-
for (const {
|
|
5856
|
+
for (const { animations: clips, names, indices } of selections.values()) {
|
|
5786
5857
|
const player = new EntityAnimationPlayer();
|
|
5787
|
-
player.
|
|
5788
|
-
|
|
5858
|
+
player.playAnimations(
|
|
5859
|
+
names.map((name) => this.getLayerGroup(name)),
|
|
5860
|
+
clips,
|
|
5861
|
+
{ ...options, weights: indices.map((index) => weights[index]) },
|
|
5862
|
+
this.partPoses
|
|
5863
|
+
);
|
|
5864
|
+
this.animationPlayers.push({ player, indices });
|
|
5789
5865
|
}
|
|
5790
5866
|
this.notifyDirty();
|
|
5791
5867
|
}
|
|
5868
|
+
/** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */
|
|
5869
|
+
setAnimationWeights(weights) {
|
|
5870
|
+
if (!this.animationPlayers.length) return;
|
|
5871
|
+
const values = validateAnimationWeights(weights, this.activeAnimations.length);
|
|
5872
|
+
for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map((index) => values[index]));
|
|
5873
|
+
this.notifyDirty();
|
|
5874
|
+
}
|
|
5792
5875
|
/** Stops all clips and restores the poses from before playback. */
|
|
5793
5876
|
stopAnimation() {
|
|
5794
5877
|
const players = this.animationPlayers.splice(0);
|
|
5795
|
-
for (const player of players) player.stop();
|
|
5878
|
+
for (const { player } of players) player.stop();
|
|
5796
5879
|
if (players.length) this.notifyDirty();
|
|
5797
5880
|
}
|
|
5798
5881
|
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
5799
5882
|
setAnimationTime(seconds) {
|
|
5800
|
-
for (const player of this.animationPlayers) player.setTime(seconds);
|
|
5883
|
+
for (const { player } of this.animationPlayers) player.setTime(seconds);
|
|
5801
5884
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
5802
5885
|
}
|
|
5803
5886
|
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
5804
5887
|
advanceAnimation(deltaSeconds) {
|
|
5805
|
-
for (const player of this.animationPlayers) player.advance(deltaSeconds);
|
|
5888
|
+
for (const { player } of this.animationPlayers) player.advance(deltaSeconds);
|
|
5806
5889
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
5807
5890
|
}
|
|
5808
5891
|
//</editor-fold>
|
|
@@ -20523,6 +20606,7 @@ export {
|
|
|
20523
20606
|
toRadians,
|
|
20524
20607
|
toTrianglesDrawMode,
|
|
20525
20608
|
trimCanvas,
|
|
20609
|
+
validateAnimationWeights,
|
|
20526
20610
|
yieldToEventLoop
|
|
20527
20611
|
};
|
|
20528
20612
|
//# sourceMappingURL=index.mjs.map
|