minerender 2.1.0-alpha.54 → 2.1.0-alpha.59
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/index.d.mts +163 -2
- package/dist/browser/index.d.ts +163 -2
- package/dist/browser/index.js +574 -266
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +338 -30
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +324 -7
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +163 -2
- package/dist/node/index.d.ts +163 -2
- package/dist/node/index.js +584 -266
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +342 -30
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.mjs
CHANGED
|
@@ -256,7 +256,9 @@ var init_Caching = __esm({
|
|
|
256
256
|
this.defaultBlockStatesCache,
|
|
257
257
|
this.blockTintCache,
|
|
258
258
|
this.entityModelCache,
|
|
259
|
-
this.entityTextureCache
|
|
259
|
+
this.entityTextureCache,
|
|
260
|
+
this.entityAnimationCache,
|
|
261
|
+
this.blockEntityIndexCache
|
|
260
262
|
];
|
|
261
263
|
}
|
|
262
264
|
static clear() {
|
|
@@ -301,6 +303,8 @@ var init_Caching = __esm({
|
|
|
301
303
|
_Caching.blockTintCache = _Caching.createAssetCache();
|
|
302
304
|
_Caching.entityModelCache = _Caching.createAssetCache();
|
|
303
305
|
_Caching.entityTextureCache = _Caching.createAssetCache();
|
|
306
|
+
_Caching.entityAnimationCache = _Caching.createAssetCache();
|
|
307
|
+
_Caching.blockEntityIndexCache = _Caching.createAssetCache();
|
|
304
308
|
Caching = _Caching;
|
|
305
309
|
}
|
|
306
310
|
});
|
|
@@ -1725,6 +1729,11 @@ function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
|
|
|
1725
1729
|
mesh.add(wireframe);
|
|
1726
1730
|
let axes = new AxesHelper(1);
|
|
1727
1731
|
mesh.add(axes);
|
|
1732
|
+
return () => {
|
|
1733
|
+
wireGeo.dispose();
|
|
1734
|
+
wireMat.dispose();
|
|
1735
|
+
axes.dispose();
|
|
1736
|
+
};
|
|
1728
1737
|
}
|
|
1729
1738
|
var init_model = __esm({
|
|
1730
1739
|
"src/util/model.ts"() {
|
|
@@ -3079,7 +3088,7 @@ var init_InstanceReference = __esm({
|
|
|
3079
3088
|
});
|
|
3080
3089
|
|
|
3081
3090
|
// src/renderer/SceneObject.ts
|
|
3082
|
-
import { Color as Color2, Euler as Euler3, InstancedBufferAttribute, InstancedMesh, MathUtils, Matrix4 as
|
|
3091
|
+
import { Color as Color2, Euler as Euler3, InstancedBufferAttribute, InstancedMesh, MathUtils, Matrix4 as Matrix44, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector35 } from "three";
|
|
3083
3092
|
function isSceneObject(obj) {
|
|
3084
3093
|
return obj.isSceneObject;
|
|
3085
3094
|
}
|
|
@@ -3287,7 +3296,7 @@ var init_SceneObject = __esm({
|
|
|
3287
3296
|
mesh.instanceColor.needsUpdate = true;
|
|
3288
3297
|
}
|
|
3289
3298
|
if (this._scene) this._scene.stats.instanceCount++;
|
|
3290
|
-
this.setMatrixAt(index, new
|
|
3299
|
+
this.setMatrixAt(index, new Matrix44());
|
|
3291
3300
|
return reference;
|
|
3292
3301
|
}
|
|
3293
3302
|
/** Returns the live reference for a raycast hit on this object's instance mesh. */
|
|
@@ -3300,7 +3309,7 @@ var init_SceneObject = __esm({
|
|
|
3300
3309
|
removeInstanceAt(index) {
|
|
3301
3310
|
if (!this.instanceReferences.has(index)) return;
|
|
3302
3311
|
const mesh = this.instanceMesh;
|
|
3303
|
-
this.setMatrixAt(index, new
|
|
3312
|
+
this.setMatrixAt(index, new Matrix44().makeScale(0, 0, 0));
|
|
3304
3313
|
this.instanceReferences.delete(index);
|
|
3305
3314
|
this.freeInstanceIndices.push(index);
|
|
3306
3315
|
this._instanceCounter = this.instanceReferences.size;
|
|
@@ -3330,7 +3339,7 @@ var init_SceneObject = __esm({
|
|
|
3330
3339
|
}
|
|
3331
3340
|
//</editor-fold>
|
|
3332
3341
|
//<editor-fold desc="TRANSFORMATION">
|
|
3333
|
-
getMatrixAt(index, matrix = new
|
|
3342
|
+
getMatrixAt(index, matrix = new Matrix44()) {
|
|
3334
3343
|
if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
|
|
3335
3344
|
this.instanceMesh.getMatrixAt(index, matrix);
|
|
3336
3345
|
return matrix;
|
|
@@ -3349,7 +3358,7 @@ var init_SceneObject = __esm({
|
|
|
3349
3358
|
const oldPosition = new Vector35();
|
|
3350
3359
|
const oldRotation = new Quaternion3();
|
|
3351
3360
|
const oldScale = new Vector35();
|
|
3352
|
-
const matrix = new
|
|
3361
|
+
const matrix = new Matrix44();
|
|
3353
3362
|
if (!scale || !rotation || !position) {
|
|
3354
3363
|
this.getMatrixAt(index, matrix).decompose(oldPosition, oldRotation, oldScale);
|
|
3355
3364
|
}
|
|
@@ -4104,7 +4113,7 @@ var init_ModelCulling = __esm({
|
|
|
4104
4113
|
});
|
|
4105
4114
|
|
|
4106
4115
|
// src/model/scene/ModelObject.ts
|
|
4107
|
-
import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as
|
|
4116
|
+
import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as Matrix48 } from "three";
|
|
4108
4117
|
function isModelObject(obj) {
|
|
4109
4118
|
return obj.isModelObject;
|
|
4110
4119
|
}
|
|
@@ -4183,12 +4192,12 @@ var init_ModelObject = __esm({
|
|
|
4183
4192
|
}
|
|
4184
4193
|
elGeo.setAttribute("color", new BufferAttribute5(colors, 3));
|
|
4185
4194
|
}
|
|
4186
|
-
elGeo.applyMatrix4(new
|
|
4187
|
-
elGeo.applyMatrix4(new
|
|
4195
|
+
elGeo.applyMatrix4(new Matrix48().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
|
|
4196
|
+
elGeo.applyMatrix4(new Matrix48().makeTranslation(el.from[0], el.from[1], el.from[2]));
|
|
4188
4197
|
if (el.rotation) {
|
|
4189
4198
|
applyElementRotation(el.rotation, elGeo);
|
|
4190
4199
|
}
|
|
4191
|
-
elGeo.applyMatrix4(new
|
|
4200
|
+
elGeo.applyMatrix4(new Matrix48().makeTranslation(-8, -8, -8));
|
|
4192
4201
|
if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
|
|
4193
4202
|
if (this.options.mergeMeshes) {
|
|
4194
4203
|
allGeos.push(elGeo);
|
|
@@ -4797,6 +4806,59 @@ function shutdown() {
|
|
|
4797
4806
|
init_AssetKey();
|
|
4798
4807
|
init_AssetLoader();
|
|
4799
4808
|
init_Assets();
|
|
4809
|
+
|
|
4810
|
+
// src/assets/BlockEntities.ts
|
|
4811
|
+
init_AssetKey();
|
|
4812
|
+
init_AssetLoader();
|
|
4813
|
+
init_source();
|
|
4814
|
+
init_Caching();
|
|
4815
|
+
import { Matrix4 as Matrix43 } from "three";
|
|
4816
|
+
var BlockEntities = class {
|
|
4817
|
+
/**
|
|
4818
|
+
* Loads the block index of a version. Versions and sources without one yield an empty index, and so does
|
|
4819
|
+
* a failed load: the index is optional, and blocks must not retry or fail with it one by one. The empty
|
|
4820
|
+
* result is cached like any other; `Caching.clear()` or `AssetLoader.setVersion()` forces a new attempt.
|
|
4821
|
+
*/
|
|
4822
|
+
static async getIndex(root) {
|
|
4823
|
+
const key = new AssetKey("entity-models", "blocks", void 0, void 0, void 0, ".json", root);
|
|
4824
|
+
key.rootType = void 0;
|
|
4825
|
+
const index = await Caching.blockEntityIndexCache.get(key.serialize(), async () => {
|
|
4826
|
+
try {
|
|
4827
|
+
return await AssetLoader.get(key, "json" /* JSON */) ?? {};
|
|
4828
|
+
} catch (error) {
|
|
4829
|
+
console.warn("Could not load the block entity index; block entities are drawn as plain block models", error);
|
|
4830
|
+
return {};
|
|
4831
|
+
}
|
|
4832
|
+
});
|
|
4833
|
+
return index ?? {};
|
|
4834
|
+
}
|
|
4835
|
+
/** The index entry of a block ID such as `minecraft:chest`. */
|
|
4836
|
+
static entry(index, block) {
|
|
4837
|
+
const entry = Object.prototype.hasOwnProperty.call(index, block) ? index[block] : void 0;
|
|
4838
|
+
return Array.isArray(entry?.parts) ? entry : void 0;
|
|
4839
|
+
}
|
|
4840
|
+
/** Selects the parts and placement for a block ID such as `minecraft:chest`; undefined when nothing is drawn. */
|
|
4841
|
+
static resolve(index, block, state = {}) {
|
|
4842
|
+
const entry = this.entry(index, block);
|
|
4843
|
+
if (!entry) return void 0;
|
|
4844
|
+
const value = (property) => String(state[property]).toLowerCase();
|
|
4845
|
+
const parts = entry.parts.filter((part) => Object.entries(part.when ?? {}).every(([property, values]) => String(values).split("|").includes(value(property))));
|
|
4846
|
+
if (!parts.length) return void 0;
|
|
4847
|
+
let rotation = 0;
|
|
4848
|
+
if (entry.rotation) {
|
|
4849
|
+
const selected = value(entry.rotation.property);
|
|
4850
|
+
rotation = "degrees" in entry.rotation ? entry.rotation.degrees[selected] : Number(selected) * entry.rotation.step;
|
|
4851
|
+
if (!Number.isFinite(rotation)) rotation = 0;
|
|
4852
|
+
}
|
|
4853
|
+
return { parts, rotation, translation: entry.translation ?? [0, 0, 0] };
|
|
4854
|
+
}
|
|
4855
|
+
/** Placement in block space (0..16 per axis), applied on top of the model's own transform. */
|
|
4856
|
+
static matrix(resolved, matrix = new Matrix43()) {
|
|
4857
|
+
return matrix.makeTranslation(8, 0, 8).multiply(new Matrix43().makeRotationY(resolved.rotation * Math.PI / 180)).multiply(new Matrix43().makeTranslation(resolved.translation[0] - 8, resolved.translation[1], resolved.translation[2] - 8));
|
|
4858
|
+
}
|
|
4859
|
+
};
|
|
4860
|
+
|
|
4861
|
+
// src/assets/index.ts
|
|
4800
4862
|
init_BlockStates();
|
|
4801
4863
|
|
|
4802
4864
|
// src/assets/Entities.ts
|
|
@@ -4867,6 +4929,15 @@ var Entities = class {
|
|
|
4867
4929
|
})));
|
|
4868
4930
|
return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
|
|
4869
4931
|
}
|
|
4932
|
+
/**
|
|
4933
|
+
* Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
|
|
4934
|
+
*/
|
|
4935
|
+
static async getAnimations(modelKey) {
|
|
4936
|
+
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4937
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
|
|
4938
|
+
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
4939
|
+
return file?.animations;
|
|
4940
|
+
}
|
|
4870
4941
|
static async resolveTexture(modelKey) {
|
|
4871
4942
|
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4872
4943
|
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
|
|
@@ -4943,6 +5014,119 @@ function trimCanvas(source) {
|
|
|
4943
5014
|
return canvas;
|
|
4944
5015
|
}
|
|
4945
5016
|
|
|
5017
|
+
// src/entity/EntityAnimation.ts
|
|
5018
|
+
var ENTITY_ANIMATION_CHANNELS = ["position", "rotation", "scale"];
|
|
5019
|
+
function catmullRom(delta, p0, p1, p22, p32) {
|
|
5020
|
+
return 0.5 * (2 * p1 + (p22 - p0) * delta + (2 * p0 - 5 * p1 + 4 * p22 - p32) * delta * delta + (3 * p1 - p0 - 3 * p22 + p32) * delta * delta * delta);
|
|
5021
|
+
}
|
|
5022
|
+
function sampleEntityKeyframes(keyframes, time) {
|
|
5023
|
+
if (keyframes.length === 0) return [0, 0, 0];
|
|
5024
|
+
let low = 0, high = keyframes.length;
|
|
5025
|
+
while (low < high) {
|
|
5026
|
+
const middle = low + high >>> 1;
|
|
5027
|
+
if (time <= keyframes[middle].time) high = middle;
|
|
5028
|
+
else low = middle + 1;
|
|
5029
|
+
}
|
|
5030
|
+
const a = Math.max(0, low - 1);
|
|
5031
|
+
const b = Math.min(keyframes.length - 1, a + 1);
|
|
5032
|
+
const from = keyframes[a];
|
|
5033
|
+
const to = keyframes[b];
|
|
5034
|
+
const delta = a === b ? 0 : Math.min(1, Math.max(0, (time - from.time) / (to.time - from.time)));
|
|
5035
|
+
if (to.interpolation === "catmullrom") {
|
|
5036
|
+
const before = keyframes[Math.max(0, a - 1)].value;
|
|
5037
|
+
const after = keyframes[Math.min(keyframes.length - 1, b + 1)].value;
|
|
5038
|
+
return [0, 1, 2].map((i) => catmullRom(delta, before[i], from.value[i], to.value[i], after[i]));
|
|
5039
|
+
}
|
|
5040
|
+
const target = to.pre ?? to.value;
|
|
5041
|
+
return [0, 1, 2].map((i) => from.value[i] + (target[i] - from.value[i]) * delta);
|
|
5042
|
+
}
|
|
5043
|
+
function entityAnimationTime(animation, time, loop = animation.loop) {
|
|
5044
|
+
return loop && animation.length > 0 ? time % animation.length : time;
|
|
5045
|
+
}
|
|
5046
|
+
function sampleEntityAnimation(animation, time, loop = animation.loop) {
|
|
5047
|
+
const elapsed = entityAnimationTime(animation, time, loop);
|
|
5048
|
+
const pose = {};
|
|
5049
|
+
for (const [name, bone] of Object.entries(animation.bones)) {
|
|
5050
|
+
const sampled = pose[name] = {};
|
|
5051
|
+
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
5052
|
+
const keyframes = bone[channel];
|
|
5053
|
+
if (keyframes?.length) sampled[channel] = sampleEntityKeyframes(keyframes, elapsed);
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
return pose;
|
|
5057
|
+
}
|
|
5058
|
+
|
|
5059
|
+
// src/entity/scene/EntityAnimationPlayer.ts
|
|
5060
|
+
var ZERO = [0, 0, 0];
|
|
5061
|
+
var EntityAnimationPlayer = class {
|
|
5062
|
+
constructor() {
|
|
5063
|
+
this.parts = [];
|
|
5064
|
+
this._time = 0;
|
|
5065
|
+
this.loop = false;
|
|
5066
|
+
this.speed = 1;
|
|
5067
|
+
}
|
|
5068
|
+
get animation() {
|
|
5069
|
+
return this._animation;
|
|
5070
|
+
}
|
|
5071
|
+
get time() {
|
|
5072
|
+
return this._time;
|
|
5073
|
+
}
|
|
5074
|
+
/**
|
|
5075
|
+
* Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
|
|
5076
|
+
* bones without a matching part are skipped.
|
|
5077
|
+
*/
|
|
5078
|
+
play(layers, animation, options = {}) {
|
|
5079
|
+
this.stop();
|
|
5080
|
+
this._animation = animation;
|
|
5081
|
+
this._time = options.time ?? 0;
|
|
5082
|
+
this.loop = options.loop ?? animation.loop;
|
|
5083
|
+
this.speed = options.speed ?? 1;
|
|
5084
|
+
for (const layer of layers) {
|
|
5085
|
+
for (const bone of Object.keys(animation.bones)) {
|
|
5086
|
+
const object = layer.getObjectByName(`group:${bone}`);
|
|
5087
|
+
if (!object) continue;
|
|
5088
|
+
this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
|
|
5089
|
+
}
|
|
5090
|
+
}
|
|
5091
|
+
this.apply();
|
|
5092
|
+
}
|
|
5093
|
+
/** Restores the default poses. Returns whether an animation was active. */
|
|
5094
|
+
stop() {
|
|
5095
|
+
if (!this._animation) return false;
|
|
5096
|
+
for (const part of this.parts) {
|
|
5097
|
+
part.object.position.copy(part.position);
|
|
5098
|
+
part.object.rotation.copy(part.rotation);
|
|
5099
|
+
part.object.scale.copy(part.scale);
|
|
5100
|
+
}
|
|
5101
|
+
this.clear();
|
|
5102
|
+
return true;
|
|
5103
|
+
}
|
|
5104
|
+
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
5105
|
+
clear() {
|
|
5106
|
+
this.parts = [];
|
|
5107
|
+
this._animation = void 0;
|
|
5108
|
+
this._time = 0;
|
|
5109
|
+
}
|
|
5110
|
+
setTime(seconds) {
|
|
5111
|
+
if (!this._animation) return false;
|
|
5112
|
+
this._time = seconds;
|
|
5113
|
+
this.apply();
|
|
5114
|
+
return true;
|
|
5115
|
+
}
|
|
5116
|
+
advance(deltaSeconds) {
|
|
5117
|
+
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
5118
|
+
}
|
|
5119
|
+
apply() {
|
|
5120
|
+
const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
|
|
5121
|
+
for (const part of this.parts) {
|
|
5122
|
+
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
|
|
5123
|
+
part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
|
|
5124
|
+
part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
|
|
5125
|
+
part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
};
|
|
5129
|
+
|
|
4946
5130
|
// src/entity/scene/EntityObject.ts
|
|
4947
5131
|
init_SceneObject();
|
|
4948
5132
|
init_Caching();
|
|
@@ -4952,7 +5136,7 @@ init_model();
|
|
|
4952
5136
|
init_ModelTextures();
|
|
4953
5137
|
init_AssetKey();
|
|
4954
5138
|
init_Materials();
|
|
4955
|
-
import { Color as Color3, Euler as Euler4, Matrix4 as
|
|
5139
|
+
import { Color as Color3, Euler as Euler4, Matrix4 as Matrix45, Object3D as Object3D3 } from "three";
|
|
4956
5140
|
init_three();
|
|
4957
5141
|
var _EntityObject = class _EntityObject extends SceneObject {
|
|
4958
5142
|
constructor(entity, options) {
|
|
@@ -4960,11 +5144,16 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
4960
5144
|
this.entity = entity;
|
|
4961
5145
|
this.isEntityObject = true;
|
|
4962
5146
|
this.meshesCreated = false;
|
|
5147
|
+
this.geometries = /* @__PURE__ */ new Set();
|
|
5148
|
+
this.disposeWireframes = [];
|
|
4963
5149
|
/** Scrolling materials are owned: their texture offset follows this entity's age. */
|
|
4964
5150
|
this.scrollMaterials = [];
|
|
4965
5151
|
/** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
|
|
4966
5152
|
this.age = 0;
|
|
5153
|
+
this.animationPlayer = new EntityAnimationPlayer();
|
|
4967
5154
|
this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
|
|
5155
|
+
this.addEventListener("added", () => this.updateScrollSubscription());
|
|
5156
|
+
this.addEventListener("removed", () => this.updateScrollSubscription());
|
|
4968
5157
|
}
|
|
4969
5158
|
async init() {
|
|
4970
5159
|
this.createMeshes();
|
|
@@ -4975,6 +5164,10 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
4975
5164
|
}
|
|
4976
5165
|
disposeAndRemoveAllChildren() {
|
|
4977
5166
|
this.clearScrollMaterials();
|
|
5167
|
+
for (const geometry of this.geometries) geometry.dispose();
|
|
5168
|
+
this.geometries.clear();
|
|
5169
|
+
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
5170
|
+
this.animationPlayer.clear();
|
|
4978
5171
|
super.disposeAndRemoveAllChildren();
|
|
4979
5172
|
}
|
|
4980
5173
|
clearScrollMaterials() {
|
|
@@ -4985,6 +5178,19 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
4985
5178
|
material.dispose();
|
|
4986
5179
|
}
|
|
4987
5180
|
}
|
|
5181
|
+
updateScrollSubscription() {
|
|
5182
|
+
if (this.parent && this.scrollMaterials.length) {
|
|
5183
|
+
if (this.scrollTicker === void 0) {
|
|
5184
|
+
this.scrollTicker = Ticker.add(() => {
|
|
5185
|
+
this.age++;
|
|
5186
|
+
this.updateScroll();
|
|
5187
|
+
});
|
|
5188
|
+
}
|
|
5189
|
+
} else {
|
|
5190
|
+
Ticker.remove(this.scrollTicker);
|
|
5191
|
+
this.scrollTicker = void 0;
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
4988
5194
|
/** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
|
|
4989
5195
|
updateScroll() {
|
|
4990
5196
|
for (const { offset, speed } of this.scrollMaterials) {
|
|
@@ -4992,6 +5198,39 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
4992
5198
|
}
|
|
4993
5199
|
this.notifyDirty();
|
|
4994
5200
|
}
|
|
5201
|
+
//<editor-fold desc="ANIMATION">
|
|
5202
|
+
/** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
|
|
5203
|
+
get animation() {
|
|
5204
|
+
return this.animationPlayer.animation;
|
|
5205
|
+
}
|
|
5206
|
+
/** Seconds since the animation started, before looping. */
|
|
5207
|
+
get animationTime() {
|
|
5208
|
+
return this.animationPlayer.time;
|
|
5209
|
+
}
|
|
5210
|
+
/**
|
|
5211
|
+
* Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
|
|
5212
|
+
* Parts of every layer are matched by name and their current pose is the default the offsets add to.
|
|
5213
|
+
* The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
|
|
5214
|
+
*/
|
|
5215
|
+
playAnimation(animation, options) {
|
|
5216
|
+
this.createMeshes();
|
|
5217
|
+
const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
|
|
5218
|
+
this.animationPlayer.play(layers, animation, options);
|
|
5219
|
+
this.notifyDirty();
|
|
5220
|
+
}
|
|
5221
|
+
/** Stops the animation and restores the default pose. */
|
|
5222
|
+
stopAnimation() {
|
|
5223
|
+
if (this.animationPlayer.stop()) this.notifyDirty();
|
|
5224
|
+
}
|
|
5225
|
+
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
5226
|
+
setAnimationTime(seconds) {
|
|
5227
|
+
if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
|
|
5228
|
+
}
|
|
5229
|
+
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
5230
|
+
advanceAnimation(deltaSeconds) {
|
|
5231
|
+
if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
|
|
5232
|
+
}
|
|
5233
|
+
//</editor-fold>
|
|
4995
5234
|
getLayerGroup(name) {
|
|
4996
5235
|
return super.getGroupByName(`layer:${name}`);
|
|
4997
5236
|
}
|
|
@@ -5025,7 +5264,7 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
5025
5264
|
const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
|
|
5026
5265
|
if (transform) {
|
|
5027
5266
|
for (const op of transform) {
|
|
5028
|
-
const matrix = new
|
|
5267
|
+
const matrix = new Matrix45();
|
|
5029
5268
|
if ("scale" in op) matrix.makeScale(...op.scale);
|
|
5030
5269
|
else if ("translate" in op) matrix.makeTranslation(...op.translate);
|
|
5031
5270
|
else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
|
|
@@ -5062,6 +5301,7 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
5062
5301
|
depth + growZ * 2,
|
|
5063
5302
|
uv
|
|
5064
5303
|
).clone();
|
|
5304
|
+
this.geometries.add(geometry);
|
|
5065
5305
|
geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
|
|
5066
5306
|
if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
|
|
5067
5307
|
const index = Array.from(geometry.getIndex().array);
|
|
@@ -5070,7 +5310,7 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
5070
5310
|
const mesh = this.createMesh(name, geometry, material);
|
|
5071
5311
|
mesh.renderOrder = renderOrder;
|
|
5072
5312
|
anchor.add(mesh);
|
|
5073
|
-
if (this.options.wireframe) addWireframeToMesh(geometry, mesh);
|
|
5313
|
+
if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));
|
|
5074
5314
|
}
|
|
5075
5315
|
for (const [childName, child] of Object.entries(part.children)) {
|
|
5076
5316
|
this.createPart(childName, child, anchor, size, material, renderOrder, inward);
|
|
@@ -5104,11 +5344,8 @@ var _EntityObject = class _EntityObject extends SceneObject {
|
|
|
5104
5344
|
this.clearScrollMaterials();
|
|
5105
5345
|
} else if (this.scrollMaterials.length) {
|
|
5106
5346
|
this.updateScroll();
|
|
5107
|
-
this.scrollTicker = Ticker.add(() => {
|
|
5108
|
-
this.age++;
|
|
5109
|
-
this.updateScroll();
|
|
5110
|
-
});
|
|
5111
5347
|
}
|
|
5348
|
+
this.updateScrollSubscription();
|
|
5112
5349
|
this.notifyDirty();
|
|
5113
5350
|
}
|
|
5114
5351
|
};
|
|
@@ -5122,7 +5359,7 @@ function isEntityObject(obj) {
|
|
|
5122
5359
|
init_MineRenderError();
|
|
5123
5360
|
|
|
5124
5361
|
// src/export/SceneExporter.ts
|
|
5125
|
-
import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color7, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as
|
|
5362
|
+
import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color7, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as Matrix47, Mesh as Mesh5, MeshBasicMaterial as MeshBasicMaterial2, NearestFilter as NearestFilter3, RGBAFormat as RGBAFormat3, Scene as Scene4, Source as Source2, Texture as Texture4, UnsignedByteType } from "three";
|
|
5126
5363
|
|
|
5127
5364
|
// ../../node_modules/three/examples/jsm/exporters/OBJExporter.js
|
|
5128
5365
|
import {
|
|
@@ -5548,7 +5785,7 @@ import {
|
|
|
5548
5785
|
LinearMipmapLinearFilter,
|
|
5549
5786
|
LinearMipmapNearestFilter,
|
|
5550
5787
|
MathUtils as MathUtils2,
|
|
5551
|
-
Matrix4 as
|
|
5788
|
+
Matrix4 as Matrix46,
|
|
5552
5789
|
MirroredRepeatWrapping,
|
|
5553
5790
|
NearestFilter as NearestFilter2,
|
|
5554
5791
|
NearestMipmapLinearFilter,
|
|
@@ -6838,7 +7075,7 @@ var GLTFWriter = class {
|
|
|
6838
7075
|
if (rootJoint === void 0) return null;
|
|
6839
7076
|
const joints = [];
|
|
6840
7077
|
const inverseBindMatrices = new Float32Array(skeleton.bones.length * 16);
|
|
6841
|
-
const temporaryBoneInverse = new
|
|
7078
|
+
const temporaryBoneInverse = new Matrix46();
|
|
6842
7079
|
for (let i = 0; i < skeleton.bones.length; ++i) {
|
|
6843
7080
|
joints.push(nodeMap.get(skeleton.bones[i]));
|
|
6844
7081
|
temporaryBoneInverse.copy(skeleton.boneInverses[i]);
|
|
@@ -7304,7 +7541,7 @@ var GLTFMeshGpuInstancing = class {
|
|
|
7304
7541
|
const translationAttr = new Float32Array(mesh.count * 3);
|
|
7305
7542
|
const rotationAttr = new Float32Array(mesh.count * 4);
|
|
7306
7543
|
const scaleAttr = new Float32Array(mesh.count * 3);
|
|
7307
|
-
const matrix = new
|
|
7544
|
+
const matrix = new Matrix46();
|
|
7308
7545
|
const position = new Vector38();
|
|
7309
7546
|
const quaternion = new Quaternion4();
|
|
7310
7547
|
const scale = new Vector38();
|
|
@@ -7478,7 +7715,7 @@ var SceneExporter = class {
|
|
|
7478
7715
|
}
|
|
7479
7716
|
};
|
|
7480
7717
|
function localMatrix(object) {
|
|
7481
|
-
return object.matrixAutoUpdate ? new
|
|
7718
|
+
return object.matrixAutoUpdate ? new Matrix47().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
|
|
7482
7719
|
}
|
|
7483
7720
|
function createSnapshot(root, gltf, bakeColors = false) {
|
|
7484
7721
|
const scene = new Scene4();
|
|
@@ -7590,7 +7827,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
|
|
|
7590
7827
|
const instanced = mesh;
|
|
7591
7828
|
if (instanced.isInstancedMesh) {
|
|
7592
7829
|
for (let i = 0; i < instanced.count; i++) {
|
|
7593
|
-
const matrix = new
|
|
7830
|
+
const matrix = new Matrix47();
|
|
7594
7831
|
instanced.getMatrixAt(i, matrix);
|
|
7595
7832
|
const color = instanced.instanceColor ? new Color7().fromBufferAttribute(instanced.instanceColor, i) : void 0;
|
|
7596
7833
|
addMesh(mesh, world.clone().multiply(matrix), color);
|
|
@@ -7604,7 +7841,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
|
|
|
7604
7841
|
try {
|
|
7605
7842
|
const ancestors = [];
|
|
7606
7843
|
for (let parent = root.parent; parent; parent = parent.parent) ancestors.unshift(parent);
|
|
7607
|
-
const world = new
|
|
7844
|
+
const world = new Matrix47();
|
|
7608
7845
|
for (const ancestor of ancestors) {
|
|
7609
7846
|
if (!ancestor.visible) return { scene, dispose };
|
|
7610
7847
|
world.multiply(localMatrix(ancestor));
|
|
@@ -8506,7 +8743,7 @@ var import_ts_deepmerge6 = __toESM(require_dist());
|
|
|
8506
8743
|
init_MineRenderError();
|
|
8507
8744
|
init_InstanceReference();
|
|
8508
8745
|
init_AssetKey();
|
|
8509
|
-
import { Euler as Euler8, Matrix4 as
|
|
8746
|
+
import { Euler as Euler8, Matrix4 as Matrix49, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
|
|
8510
8747
|
init_ModelCulling();
|
|
8511
8748
|
init_FluidGeometry();
|
|
8512
8749
|
var _BlockObject = class _BlockObject extends SceneObject {
|
|
@@ -8523,6 +8760,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8523
8760
|
this._variants = [];
|
|
8524
8761
|
this._models = [];
|
|
8525
8762
|
this._cullMask = 0;
|
|
8763
|
+
this._entities = [];
|
|
8764
|
+
this._entityPlacement = new Matrix49();
|
|
8765
|
+
this._entityGeneration = 0;
|
|
8526
8766
|
this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
|
|
8527
8767
|
}
|
|
8528
8768
|
async init() {
|
|
@@ -8542,6 +8782,8 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8542
8782
|
}
|
|
8543
8783
|
clearModels() {
|
|
8544
8784
|
this.removeModels(this._models.splice(0));
|
|
8785
|
+
this._entityGeneration++;
|
|
8786
|
+
this.removeEntities(this._entities.splice(0));
|
|
8545
8787
|
this._fluidKey = void 0;
|
|
8546
8788
|
this._fluidModel = void 0;
|
|
8547
8789
|
this._isInstanced = false;
|
|
@@ -8553,6 +8795,57 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8553
8795
|
if (!isInstanceReference(model)) model.dispose();
|
|
8554
8796
|
}
|
|
8555
8797
|
}
|
|
8798
|
+
removeEntities(entities) {
|
|
8799
|
+
for (const entity of entities) {
|
|
8800
|
+
entity.removeFromScene();
|
|
8801
|
+
entity.dispose();
|
|
8802
|
+
}
|
|
8803
|
+
}
|
|
8804
|
+
/** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */
|
|
8805
|
+
get blockEntities() {
|
|
8806
|
+
return this._entities;
|
|
8807
|
+
}
|
|
8808
|
+
/**
|
|
8809
|
+
* Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
|
|
8810
|
+
* when the block is not listed or one of its models cannot be loaded.
|
|
8811
|
+
*/
|
|
8812
|
+
async createBlockEntities() {
|
|
8813
|
+
const key = this.blockState.key;
|
|
8814
|
+
if (!key || this.options.displayPosition) return false;
|
|
8815
|
+
const generation = this._entityGeneration;
|
|
8816
|
+
const created = [];
|
|
8817
|
+
let resolved;
|
|
8818
|
+
try {
|
|
8819
|
+
resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);
|
|
8820
|
+
if (!resolved) return false;
|
|
8821
|
+
for (const part of resolved.parts) {
|
|
8822
|
+
const [namespace, path] = part.model.includes(":") ? part.model.split(":") : [key.namespace, part.model];
|
|
8823
|
+
const texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
|
|
8824
|
+
if (texture) texture.root = key.root;
|
|
8825
|
+
const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });
|
|
8826
|
+
if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);
|
|
8827
|
+
created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }));
|
|
8828
|
+
}
|
|
8829
|
+
} catch (error) {
|
|
8830
|
+
console.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);
|
|
8831
|
+
this.removeEntities(created);
|
|
8832
|
+
return false;
|
|
8833
|
+
}
|
|
8834
|
+
if (generation !== this._entityGeneration) {
|
|
8835
|
+
this.removeEntities(created);
|
|
8836
|
+
return true;
|
|
8837
|
+
}
|
|
8838
|
+
BlockEntities.matrix(resolved, this._entityPlacement);
|
|
8839
|
+
this._entities = created;
|
|
8840
|
+
this.placeEntities();
|
|
8841
|
+
return true;
|
|
8842
|
+
}
|
|
8843
|
+
placeEntities() {
|
|
8844
|
+
const matrix = new Matrix49().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
|
|
8845
|
+
for (const entity of this._entities) {
|
|
8846
|
+
matrix.decompose(entity.position, entity.quaternion, entity.scale);
|
|
8847
|
+
}
|
|
8848
|
+
}
|
|
8556
8849
|
get isOccluding() {
|
|
8557
8850
|
return this._models.some((model) => {
|
|
8558
8851
|
const object = isInstanceReference(model) ? model.instanceable : model;
|
|
@@ -8634,7 +8927,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8634
8927
|
() => new FluidModelObject2(kind, surface.sample, this.blockState.key, this.options)
|
|
8635
8928
|
);
|
|
8636
8929
|
const previous = this._fluidModel;
|
|
8637
|
-
const matrix = previous ? this.getModelMatrix(previous) : new
|
|
8930
|
+
const matrix = previous ? this.getModelMatrix(previous) : new Matrix49().makeTranslation(...this.position.toArray());
|
|
8638
8931
|
if (isInstanceReference(replacement)) replacement.setMatrix(matrix);
|
|
8639
8932
|
else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
|
|
8640
8933
|
this._models = this._models.filter((model) => model !== previous);
|
|
@@ -8664,13 +8957,20 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8664
8957
|
await this.updateFluid(this._fluidSampler);
|
|
8665
8958
|
return;
|
|
8666
8959
|
}
|
|
8960
|
+
const hasEntities = await this.createBlockEntities();
|
|
8667
8961
|
const variantsToCreate = await this.mapStateToVariant(this.state);
|
|
8668
8962
|
this._variants = variantsToCreate;
|
|
8669
8963
|
for (let blockStateVariant of variantsToCreate) {
|
|
8964
|
+
if (hasEntities && !await this.hasGeometry(blockStateVariant)) continue;
|
|
8670
8965
|
this._models.push(await this.createVariant(blockStateVariant));
|
|
8671
8966
|
}
|
|
8672
8967
|
await this.updateFluid(this._fluidSampler);
|
|
8673
8968
|
}
|
|
8969
|
+
async hasGeometry(variant) {
|
|
8970
|
+
const modelKey = AssetKey.parse("models", variant.model);
|
|
8971
|
+
modelKey.root = this.blockState.key?.root;
|
|
8972
|
+
return !!(await Models.getMerged(modelKey))?.elements?.length;
|
|
8973
|
+
}
|
|
8674
8974
|
getSingleVariant(variants) {
|
|
8675
8975
|
return BlockStateResolver.choose(variants);
|
|
8676
8976
|
}
|
|
@@ -8765,7 +9065,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8765
9065
|
setPositionRotationScaleAt(index, position, rotation, scale) {
|
|
8766
9066
|
super.setPositionRotationScaleAt(index, position, rotation, scale);
|
|
8767
9067
|
}
|
|
8768
|
-
getMatrixAt(index, matrix = new
|
|
9068
|
+
getMatrixAt(index, matrix = new Matrix49()) {
|
|
8769
9069
|
if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
|
|
8770
9070
|
const child = this._models[0];
|
|
8771
9071
|
if (child && isModelObject(child)) {
|
|
@@ -8790,6 +9090,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8790
9090
|
for (let model of this._models) {
|
|
8791
9091
|
model.setPosition(position);
|
|
8792
9092
|
}
|
|
9093
|
+
this.placeEntities();
|
|
8793
9094
|
this.notifyDirty();
|
|
8794
9095
|
}
|
|
8795
9096
|
//TODO: should override rotation + scale methods
|
|
@@ -13329,7 +13630,7 @@ init_CubeFace();
|
|
|
13329
13630
|
init_AssetKey();
|
|
13330
13631
|
init_Models();
|
|
13331
13632
|
init_CubeFace();
|
|
13332
|
-
import { Matrix4 as
|
|
13633
|
+
import { Matrix4 as Matrix410, Vector3 as Vector314 } from "three";
|
|
13333
13634
|
init_ModelCulling();
|
|
13334
13635
|
init_ModelObject();
|
|
13335
13636
|
init_UVMapper();
|
|
@@ -13392,7 +13693,7 @@ var SectionModels = class {
|
|
|
13392
13693
|
});
|
|
13393
13694
|
await object.init();
|
|
13394
13695
|
const geometry = object.children[0].geometry;
|
|
13395
|
-
geometry.applyMatrix4(new
|
|
13696
|
+
geometry.applyMatrix4(new Matrix410().makeRotationFromEuler(rotation));
|
|
13396
13697
|
object.clear();
|
|
13397
13698
|
const cullFaces = CUBE_FACES.map((face) => {
|
|
13398
13699
|
const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
|
|
@@ -13804,7 +14105,8 @@ var Chunk = class _Chunk {
|
|
|
13804
14105
|
this.data.set(index, void 0);
|
|
13805
14106
|
return void 0;
|
|
13806
14107
|
}
|
|
13807
|
-
const
|
|
14108
|
+
const perBlock = !this.sectionModels || getFluidKind(blockState.key, stored.properties) || blockState.key && BlockEntities.entry(await BlockEntities.getIndex(blockState.key.root), blockState.key.toNamespacedString());
|
|
14109
|
+
const template = perBlock ? void 0 : await this.sectionModels.get(blockState, stored.properties);
|
|
13808
14110
|
if (template) {
|
|
13809
14111
|
this.sectionBlocks.set(index, { index, template, cullMask: 0 });
|
|
13810
14112
|
this.meshDirty = true;
|
|
@@ -13913,6 +14215,7 @@ export {
|
|
|
13913
14215
|
BUILTIN_GENERATED,
|
|
13914
14216
|
BasicAssetKey,
|
|
13915
14217
|
BatchedExecutor,
|
|
14218
|
+
BlockEntities,
|
|
13916
14219
|
BlockObject,
|
|
13917
14220
|
BlockStateResolver,
|
|
13918
14221
|
BlockStates,
|
|
@@ -13936,7 +14239,9 @@ export {
|
|
|
13936
14239
|
DefaultBlockStates,
|
|
13937
14240
|
DisplayPosition,
|
|
13938
14241
|
DisplayTransforms,
|
|
14242
|
+
ENTITY_ANIMATION_CHANNELS,
|
|
13939
14243
|
Entities,
|
|
14244
|
+
EntityAnimationPlayer,
|
|
13940
14245
|
EntityObject,
|
|
13941
14246
|
Env,
|
|
13942
14247
|
FluidModelObject,
|
|
@@ -14010,6 +14315,7 @@ export {
|
|
|
14010
14315
|
createCanvas,
|
|
14011
14316
|
createFluidGeometry,
|
|
14012
14317
|
createImage,
|
|
14318
|
+
entityAnimationTime,
|
|
14013
14319
|
estimateBytesUsed,
|
|
14014
14320
|
getBlockFluidState,
|
|
14015
14321
|
getFluidKind,
|
|
@@ -14043,6 +14349,8 @@ export {
|
|
|
14043
14349
|
prefix,
|
|
14044
14350
|
probeImageSize,
|
|
14045
14351
|
registerBrowserEnv,
|
|
14352
|
+
sampleEntityAnimation,
|
|
14353
|
+
sampleEntityKeyframes,
|
|
14046
14354
|
sampleFluid,
|
|
14047
14355
|
serializeBoxGeometryKey,
|
|
14048
14356
|
serializeImageKey,
|