minerender 2.1.0-alpha.131 → 2.1.0-alpha.133
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/assets/Fonts.mjs +31 -4
- package/dist/browser/esm/assets/Fonts.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +166 -0
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -0
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +12 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs +1 -0
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs.map +1 -1
- package/dist/browser/esm/cache/Caching.mjs +2 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- 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/gui/GuiText.mjs +4 -3
- package/dist/browser/esm/gui/GuiText.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +50 -10
- package/dist/browser/index.d.ts +50 -10
- package/dist/browser/index.js +357 -59
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +400 -59
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +50 -10
- package/dist/node/index.d.ts +50 -10
- package/dist/node/index.js +362 -59
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +361 -59
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -286,6 +286,7 @@ var init_Caching = __esm({
|
|
|
286
286
|
this.entityAnimationCache,
|
|
287
287
|
this.blockEntityIndexCache,
|
|
288
288
|
this.fontCache,
|
|
289
|
+
this.unihexCache,
|
|
289
290
|
this.bannerPatternCache,
|
|
290
291
|
this.mineRenderDataCache,
|
|
291
292
|
this.usernameUuidCache,
|
|
@@ -339,6 +340,7 @@ var init_Caching = __esm({
|
|
|
339
340
|
_Caching.entityTextureCache = _Caching.createAssetCache();
|
|
340
341
|
_Caching.entityAnimationCache = _Caching.createAssetCache();
|
|
341
342
|
_Caching.blockEntityIndexCache = _Caching.createAssetCache();
|
|
343
|
+
_Caching.unihexCache = _Caching.createAssetCache();
|
|
342
344
|
_Caching.fontCache = _Caching.createAssetCache();
|
|
343
345
|
_Caching.bannerPatternCache = _Caching.createAssetCache();
|
|
344
346
|
_Caching.mineRenderDataCache = _Caching.createAssetCache();
|
|
@@ -1351,6 +1353,7 @@ var init_AssetParsers = __esm({
|
|
|
1351
1353
|
AssetParser2["IMAGE"] = "image";
|
|
1352
1354
|
AssetParser2["LIST"] = "list";
|
|
1353
1355
|
AssetParser2["JSON"] = "json";
|
|
1356
|
+
AssetParser2["BINARY"] = "binary";
|
|
1354
1357
|
return AssetParser2;
|
|
1355
1358
|
})(AssetParser || {});
|
|
1356
1359
|
}
|
|
@@ -2821,7 +2824,7 @@ var init_parser = __esm({
|
|
|
2821
2824
|
});
|
|
2822
2825
|
|
|
2823
2826
|
// src/assets/source/HostedAssetSource.ts
|
|
2824
|
-
var p4, DEFAULT_OPTIONS, _HostedAssetSource, HostedAssetSource;
|
|
2827
|
+
var BINARY_TIMEOUT, p4, DEFAULT_OPTIONS, _HostedAssetSource, HostedAssetSource;
|
|
2825
2828
|
var init_HostedAssetSource = __esm({
|
|
2826
2829
|
"src/assets/source/HostedAssetSource.ts"() {
|
|
2827
2830
|
init_AssetSource();
|
|
@@ -2834,6 +2837,7 @@ var init_HostedAssetSource = __esm({
|
|
|
2834
2837
|
init_AssetLoader();
|
|
2835
2838
|
init_parser();
|
|
2836
2839
|
init_merge();
|
|
2840
|
+
BINARY_TIMEOUT = 6e4;
|
|
2837
2841
|
p4 = prefix("HostedAssetSource");
|
|
2838
2842
|
DEFAULT_OPTIONS = {
|
|
2839
2843
|
retryDefaults: true
|
|
@@ -2974,6 +2978,15 @@ var init_HostedAssetSource = __esm({
|
|
|
2974
2978
|
return response.data;
|
|
2975
2979
|
}
|
|
2976
2980
|
};
|
|
2981
|
+
_HostedAssetSource.BINARY = {
|
|
2982
|
+
config(request) {
|
|
2983
|
+
request.timeout = BINARY_TIMEOUT;
|
|
2984
|
+
request.responseType = "arraybuffer";
|
|
2985
|
+
},
|
|
2986
|
+
parse(response) {
|
|
2987
|
+
return { data: new Uint8Array(response.data) };
|
|
2988
|
+
}
|
|
2989
|
+
};
|
|
2977
2990
|
_HostedAssetSource.PARSER_MAP = /* @__PURE__ */ new Map([
|
|
2978
2991
|
["model" /* MODEL */, _HostedAssetSource.MODEL],
|
|
2979
2992
|
["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
|
|
@@ -2981,7 +2994,8 @@ var init_HostedAssetSource = __esm({
|
|
|
2981
2994
|
["nbt" /* NBT */, _HostedAssetSource.NBT],
|
|
2982
2995
|
["image" /* IMAGE */, _HostedAssetSource.IMAGE],
|
|
2983
2996
|
["list" /* LIST */, _HostedAssetSource.LIST],
|
|
2984
|
-
["json" /* JSON */, _HostedAssetSource.JSON]
|
|
2997
|
+
["json" /* JSON */, _HostedAssetSource.JSON],
|
|
2998
|
+
["binary" /* BINARY */, _HostedAssetSource.BINARY]
|
|
2985
2999
|
]);
|
|
2986
3000
|
HostedAssetSource = _HostedAssetSource;
|
|
2987
3001
|
}
|
|
@@ -4762,6 +4776,178 @@ var init_Entities = __esm({
|
|
|
4762
4776
|
}
|
|
4763
4777
|
});
|
|
4764
4778
|
|
|
4779
|
+
// src/assets/_fonts/Unihex.ts
|
|
4780
|
+
var Unihex_exports = {};
|
|
4781
|
+
__export(Unihex_exports, {
|
|
4782
|
+
loadUnihex: () => loadUnihex
|
|
4783
|
+
});
|
|
4784
|
+
function readHex(text2, filename, glyphs) {
|
|
4785
|
+
const lines = text2.split("\n");
|
|
4786
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
4787
|
+
lines.forEach((line, index) => {
|
|
4788
|
+
const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);
|
|
4789
|
+
if (!match || ![32, 64, 96, 128].includes(match[2].length)) {
|
|
4790
|
+
throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);
|
|
4791
|
+
}
|
|
4792
|
+
const codepoint = parseInt(match[1], 16);
|
|
4793
|
+
if (codepoint > 1114111) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);
|
|
4794
|
+
const bitWidth = match[2].length / 4;
|
|
4795
|
+
const rowLength = bitWidth / 4;
|
|
4796
|
+
const rows = new Uint32Array(GLYPH_HEIGHT);
|
|
4797
|
+
let mask = 0;
|
|
4798
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
4799
|
+
rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);
|
|
4800
|
+
mask |= rows[y];
|
|
4801
|
+
}
|
|
4802
|
+
let left = 0, right = bitWidth;
|
|
4803
|
+
if (mask) {
|
|
4804
|
+
while (!(mask >>> bitWidth - left - 1 & 1)) left++;
|
|
4805
|
+
right = bitWidth - 1;
|
|
4806
|
+
while (!(mask >>> bitWidth - right - 1 & 1)) right--;
|
|
4807
|
+
}
|
|
4808
|
+
glyphs.set(codepoint, { rows, bitWidth, left, right });
|
|
4809
|
+
});
|
|
4810
|
+
}
|
|
4811
|
+
async function parseUnihex(key) {
|
|
4812
|
+
try {
|
|
4813
|
+
const asset2 = await AssetLoader.get(key, "binary" /* BINARY */);
|
|
4814
|
+
if (!asset2) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);
|
|
4815
|
+
const records = /* @__PURE__ */ new Map();
|
|
4816
|
+
const reader = new import_zip2.ZipReader(new import_zip2.Uint8ArrayReader(asset2.data), { useWebWorkers: false, useCompressionStream: false });
|
|
4817
|
+
try {
|
|
4818
|
+
for (const entry of await reader.getEntries()) {
|
|
4819
|
+
if (!entry.directory && entry.filename.endsWith(".hex")) {
|
|
4820
|
+
readHex(await entry.getData(new import_zip2.TextWriter(), { checkSignature: true }), entry.filename, records);
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4823
|
+
} finally {
|
|
4824
|
+
await reader.close();
|
|
4825
|
+
}
|
|
4826
|
+
const indices = new Int32Array(1114112).fill(-1);
|
|
4827
|
+
const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);
|
|
4828
|
+
let index = 0;
|
|
4829
|
+
for (const [codepoint, record] of records) {
|
|
4830
|
+
indices[codepoint] = index;
|
|
4831
|
+
rows.set(record.rows, index * GLYPH_HEIGHT);
|
|
4832
|
+
metrics.set([record.bitWidth, record.left, record.right], index * 3);
|
|
4833
|
+
index++;
|
|
4834
|
+
}
|
|
4835
|
+
return { indices, rows, metrics };
|
|
4836
|
+
} catch (error) {
|
|
4837
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4838
|
+
return void 0;
|
|
4839
|
+
}
|
|
4840
|
+
}
|
|
4841
|
+
async function loadUnihex(provider, fontKey, characters) {
|
|
4842
|
+
const origin = new AssetKey(DEFAULT_NAMESPACE, "", void 0, void 0, "assets", "", fontKey.root);
|
|
4843
|
+
const key = AssetKey.parse("font", provider.hex_file, origin);
|
|
4844
|
+
key.assetType = void 0;
|
|
4845
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
4846
|
+
let overrides;
|
|
4847
|
+
try {
|
|
4848
|
+
overrides = (provider.size_overrides ?? []).map((override) => {
|
|
4849
|
+
const from = override.from.codePointAt(0), to = override.to.codePointAt(0);
|
|
4850
|
+
if ([...override.from].length !== 1 || [...override.to].length !== 1 || from >= to || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {
|
|
4851
|
+
throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);
|
|
4852
|
+
}
|
|
4853
|
+
return { ...override, from, to };
|
|
4854
|
+
});
|
|
4855
|
+
} catch (error) {
|
|
4856
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4857
|
+
return glyphs;
|
|
4858
|
+
}
|
|
4859
|
+
const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
|
|
4860
|
+
if (!file) return glyphs;
|
|
4861
|
+
let atlas = atlases.get(provider);
|
|
4862
|
+
if (!atlas) {
|
|
4863
|
+
atlas = new UnihexAtlas();
|
|
4864
|
+
atlases.set(provider, atlas);
|
|
4865
|
+
}
|
|
4866
|
+
for (const character of characters) {
|
|
4867
|
+
const codepoint = character.codePointAt(0), index = file.indices[codepoint];
|
|
4868
|
+
if (index < 0) continue;
|
|
4869
|
+
const record = {
|
|
4870
|
+
rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),
|
|
4871
|
+
bitWidth: file.metrics[index * 3],
|
|
4872
|
+
left: file.metrics[index * 3 + 1],
|
|
4873
|
+
right: file.metrics[index * 3 + 2]
|
|
4874
|
+
};
|
|
4875
|
+
const override = overrides.find((range) => codepoint >= range.from && codepoint <= range.to);
|
|
4876
|
+
if (override) {
|
|
4877
|
+
record.left = override.left;
|
|
4878
|
+
record.right = override.right;
|
|
4879
|
+
}
|
|
4880
|
+
const width = record.right - record.left + 1;
|
|
4881
|
+
let rendered;
|
|
4882
|
+
const render = () => rendered ?? (rendered = atlas.draw(record));
|
|
4883
|
+
glyphs.set(character, {
|
|
4884
|
+
get image() {
|
|
4885
|
+
return render().image;
|
|
4886
|
+
},
|
|
4887
|
+
get x() {
|
|
4888
|
+
return render().x;
|
|
4889
|
+
},
|
|
4890
|
+
get y() {
|
|
4891
|
+
return render().y;
|
|
4892
|
+
},
|
|
4893
|
+
width,
|
|
4894
|
+
height: GLYPH_HEIGHT,
|
|
4895
|
+
scale: 0.5,
|
|
4896
|
+
ascent: 7,
|
|
4897
|
+
advance: Math.floor(width / 2) + 1,
|
|
4898
|
+
boldOffset: 0.5,
|
|
4899
|
+
shadowOffset: 0.5
|
|
4900
|
+
});
|
|
4901
|
+
}
|
|
4902
|
+
return glyphs;
|
|
4903
|
+
}
|
|
4904
|
+
var import_zip2, ATLAS_SIZE, GLYPH_HEIGHT, UnihexAtlas, atlases;
|
|
4905
|
+
var init_Unihex = __esm({
|
|
4906
|
+
"src/assets/_fonts/Unihex.ts"() {
|
|
4907
|
+
import_zip2 = require("@zip.js/zip.js");
|
|
4908
|
+
init_AssetKey();
|
|
4909
|
+
init_AssetLoader();
|
|
4910
|
+
init_Assets();
|
|
4911
|
+
init_Caching();
|
|
4912
|
+
init_AssetParsers();
|
|
4913
|
+
init_CanvasCompat();
|
|
4914
|
+
ATLAS_SIZE = 512;
|
|
4915
|
+
GLYPH_HEIGHT = 16;
|
|
4916
|
+
UnihexAtlas = class {
|
|
4917
|
+
constructor() {
|
|
4918
|
+
this.x = 0;
|
|
4919
|
+
this.y = 0;
|
|
4920
|
+
}
|
|
4921
|
+
draw(glyph) {
|
|
4922
|
+
const width = glyph.right - glyph.left + 1;
|
|
4923
|
+
if (this.image && this.x + width > this.image.width) {
|
|
4924
|
+
this.x = 0;
|
|
4925
|
+
this.y += GLYPH_HEIGHT;
|
|
4926
|
+
}
|
|
4927
|
+
if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {
|
|
4928
|
+
this.image = createCanvas(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);
|
|
4929
|
+
this.x = 0;
|
|
4930
|
+
this.y = 0;
|
|
4931
|
+
}
|
|
4932
|
+
const context = this.image.getContext("2d");
|
|
4933
|
+
const pixels = context.createImageData(width, GLYPH_HEIGHT);
|
|
4934
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
4935
|
+
for (let x = 0; x < width; x++) {
|
|
4936
|
+
const column = glyph.left + x;
|
|
4937
|
+
if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> glyph.bitWidth - column - 1 & 1)) continue;
|
|
4938
|
+
pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
const result = { image: this.image, x: this.x, y: this.y };
|
|
4942
|
+
context.putImageData(pixels, this.x, this.y);
|
|
4943
|
+
this.x += width;
|
|
4944
|
+
return result;
|
|
4945
|
+
}
|
|
4946
|
+
};
|
|
4947
|
+
atlases = /* @__PURE__ */ new WeakMap();
|
|
4948
|
+
}
|
|
4949
|
+
});
|
|
4950
|
+
|
|
4765
4951
|
// src/assets/Fonts.ts
|
|
4766
4952
|
var Fonts;
|
|
4767
4953
|
var init_Fonts = __esm({
|
|
@@ -4772,7 +4958,7 @@ var init_Fonts = __esm({
|
|
|
4772
4958
|
init_ModelTextures();
|
|
4773
4959
|
init_Caching();
|
|
4774
4960
|
Fonts = class {
|
|
4775
|
-
/** Combines font definitions in source-priority order.
|
|
4961
|
+
/** Combines font definitions in source-priority order. TrueType providers are skipped. */
|
|
4776
4962
|
static async get(key = "minecraft:default") {
|
|
4777
4963
|
const fontKey = typeof key === "string" ? AssetKey.parse("font", key) : key;
|
|
4778
4964
|
return await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, []));
|
|
@@ -4788,6 +4974,7 @@ var init_Fonts = __esm({
|
|
|
4788
4974
|
const stack = await AssetLoader.getAll(key, "json" /* JSON */);
|
|
4789
4975
|
if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);
|
|
4790
4976
|
const glyphs = /* @__PURE__ */ new Map();
|
|
4977
|
+
const providers = [];
|
|
4791
4978
|
for (const asset2 of stack) {
|
|
4792
4979
|
for (const provider of asset2.providers) {
|
|
4793
4980
|
if (provider.filter?.uniform || provider.filter?.jp) continue;
|
|
@@ -4806,17 +4993,43 @@ var init_Fonts = __esm({
|
|
|
4806
4993
|
break;
|
|
4807
4994
|
case "reference":
|
|
4808
4995
|
case "minecraft:reference":
|
|
4809
|
-
|
|
4996
|
+
const reference = await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized]);
|
|
4997
|
+
if (reference.resolve) {
|
|
4998
|
+
providers.push(async (characters) => {
|
|
4999
|
+
await reference.resolve(characters);
|
|
5000
|
+
return reference.glyphs;
|
|
5001
|
+
});
|
|
5002
|
+
continue;
|
|
5003
|
+
}
|
|
5004
|
+
provided = reference.glyphs;
|
|
4810
5005
|
break;
|
|
5006
|
+
case "unihex":
|
|
5007
|
+
case "minecraft:unihex":
|
|
5008
|
+
providers.push(async (characters) => (await Promise.resolve().then(() => (init_Unihex(), Unihex_exports))).loadUnihex(provider, key, characters));
|
|
5009
|
+
continue;
|
|
4811
5010
|
default:
|
|
4812
5011
|
continue;
|
|
4813
5012
|
}
|
|
4814
|
-
for (const [character, glyph] of provided) {
|
|
5013
|
+
if (providers.every((provider2) => provider2 instanceof Map)) for (const [character, glyph] of provided) {
|
|
4815
5014
|
if (character !== "\0" && !glyphs.has(character)) glyphs.set(character, glyph);
|
|
4816
5015
|
}
|
|
5016
|
+
providers.push(provided);
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
return { glyphs, resolve: providers.every((provider) => provider instanceof Map) ? void 0 : async (characters) => {
|
|
5020
|
+
const remaining = new Set([...characters].filter((character) => character !== "\0" && character !== "\n" && character !== "\r" && !glyphs.has(character)));
|
|
5021
|
+
for (const provider of providers) {
|
|
5022
|
+
if (!remaining.size) break;
|
|
5023
|
+
const provided = provider instanceof Map ? provider : await provider([...remaining].join(""));
|
|
5024
|
+
for (const character of remaining) {
|
|
5025
|
+
const glyph = provided.get(character);
|
|
5026
|
+
if (glyph) {
|
|
5027
|
+
glyphs.set(character, glyph);
|
|
5028
|
+
remaining.delete(character);
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
4817
5031
|
}
|
|
4818
|
-
}
|
|
4819
|
-
return { glyphs };
|
|
5032
|
+
} };
|
|
4820
5033
|
}
|
|
4821
5034
|
static async bitmap(provider, fontKey) {
|
|
4822
5035
|
const rows = provider.chars.map((row) => [...row]);
|
|
@@ -4909,6 +5122,13 @@ var init_EntityAnimation = __esm({
|
|
|
4909
5122
|
});
|
|
4910
5123
|
|
|
4911
5124
|
// src/entity/scene/EntityAnimationPlayer.ts
|
|
5125
|
+
function validateAnimationWeights(weights, count) {
|
|
5126
|
+
const values = Array.from(weights);
|
|
5127
|
+
if (values.length !== count || values.some((weight) => !Number.isFinite(weight) || weight < 0)) {
|
|
5128
|
+
throw new Error("Animation weights must match the clip count and contain only finite nonnegative numbers");
|
|
5129
|
+
}
|
|
5130
|
+
return values;
|
|
5131
|
+
}
|
|
4912
5132
|
var import_three11, ZERO, EntityAnimationPlayer;
|
|
4913
5133
|
var init_EntityAnimationPlayer = __esm({
|
|
4914
5134
|
"src/entity/scene/EntityAnimationPlayer.ts"() {
|
|
@@ -4918,12 +5138,20 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
4918
5138
|
EntityAnimationPlayer = class {
|
|
4919
5139
|
constructor() {
|
|
4920
5140
|
this.parts = [];
|
|
5141
|
+
this._animations = [];
|
|
5142
|
+
this._weights = [];
|
|
5143
|
+
this.loops = [];
|
|
4921
5144
|
this._time = 0;
|
|
4922
|
-
this.loop = false;
|
|
4923
5145
|
this.speed = 1;
|
|
4924
5146
|
}
|
|
4925
5147
|
get animation() {
|
|
4926
|
-
return this.
|
|
5148
|
+
return this._animations[0];
|
|
5149
|
+
}
|
|
5150
|
+
get animations() {
|
|
5151
|
+
return this._animations.slice();
|
|
5152
|
+
}
|
|
5153
|
+
get weights() {
|
|
5154
|
+
return this._weights.slice();
|
|
4927
5155
|
}
|
|
4928
5156
|
get time() {
|
|
4929
5157
|
return this._time;
|
|
@@ -4933,10 +5161,20 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
4933
5161
|
* without them, the current pose is used. Stopping restores the pose from before playback.
|
|
4934
5162
|
*/
|
|
4935
5163
|
play(layers, animation, options = {}, poses) {
|
|
5164
|
+
this.playAnimations(layers, [animation], options, poses);
|
|
5165
|
+
}
|
|
5166
|
+
/**
|
|
5167
|
+
* Starts clips on matching parts with a shared clock. Weighted offsets add to the supplied baked poses
|
|
5168
|
+
* or, without poses, to each animated part's pose when playback starts.
|
|
5169
|
+
*/
|
|
5170
|
+
playAnimations(layers, animations, options = {}, poses) {
|
|
5171
|
+
const weights = validateAnimationWeights(options.weights ?? animations.map(() => 1), animations.length);
|
|
4936
5172
|
this.stop();
|
|
4937
|
-
this.
|
|
5173
|
+
this._animations = animations.slice();
|
|
5174
|
+
this._weights = weights;
|
|
5175
|
+
if (!animations.length) return;
|
|
4938
5176
|
this._time = options.time ?? 0;
|
|
4939
|
-
this.
|
|
5177
|
+
this.loops = animations.map((animation) => options.loop ?? animation.loop);
|
|
4940
5178
|
this.speed = options.speed ?? 1;
|
|
4941
5179
|
for (const layer of layers) {
|
|
4942
5180
|
const objects = [];
|
|
@@ -4945,7 +5183,8 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
4945
5183
|
if (poses.has(object4)) objects.push(object4);
|
|
4946
5184
|
});
|
|
4947
5185
|
} else {
|
|
4948
|
-
|
|
5186
|
+
const bones = new Set(animations.flatMap((animation) => Object.keys(animation.bones)));
|
|
5187
|
+
for (const bone of bones) {
|
|
4949
5188
|
const object4 = layer.getObjectByName(`group:${bone}`);
|
|
4950
5189
|
if (object4) objects.push(object4);
|
|
4951
5190
|
}
|
|
@@ -4969,7 +5208,7 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
4969
5208
|
}
|
|
4970
5209
|
/** Restores the poses from before playback. Returns whether an animation was active. */
|
|
4971
5210
|
stop() {
|
|
4972
|
-
if (!this.
|
|
5211
|
+
if (!this._animations.length) return false;
|
|
4973
5212
|
for (const part of this.parts) {
|
|
4974
5213
|
part.object.position.copy(part.position);
|
|
4975
5214
|
part.object.rotation.copy(part.rotation);
|
|
@@ -4981,12 +5220,14 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
4981
5220
|
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
4982
5221
|
clear() {
|
|
4983
5222
|
this.parts = [];
|
|
4984
|
-
this.
|
|
5223
|
+
this._animations = [];
|
|
5224
|
+
this._weights = [];
|
|
5225
|
+
this.loops = [];
|
|
4985
5226
|
this._time = 0;
|
|
4986
5227
|
}
|
|
4987
5228
|
/** Applies the pose at an absolute playback time. Returns `false` when no clip is active. */
|
|
4988
5229
|
setTime(seconds) {
|
|
4989
|
-
if (!this.
|
|
5230
|
+
if (!this._animations.length) return false;
|
|
4990
5231
|
this._time = seconds;
|
|
4991
5232
|
this.apply();
|
|
4992
5233
|
return true;
|
|
@@ -4995,8 +5236,30 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
4995
5236
|
advance(deltaSeconds) {
|
|
4996
5237
|
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
4997
5238
|
}
|
|
5239
|
+
/** Changes weights in clip order and reapplies the current time without restarting playback. */
|
|
5240
|
+
setWeights(weights) {
|
|
5241
|
+
if (!this._animations.length) return false;
|
|
5242
|
+
const validated = validateAnimationWeights(weights, this._animations.length);
|
|
5243
|
+
this._weights = validated;
|
|
5244
|
+
this.apply();
|
|
5245
|
+
return true;
|
|
5246
|
+
}
|
|
4998
5247
|
apply() {
|
|
4999
|
-
const pose =
|
|
5248
|
+
const pose = /* @__PURE__ */ Object.create(null);
|
|
5249
|
+
for (let i = 0; i < this._animations.length; i++) {
|
|
5250
|
+
const weight = this._weights[i];
|
|
5251
|
+
if (weight === 0) continue;
|
|
5252
|
+
const sampled = sampleEntityAnimation(this._animations[i], this._time, this.loops[i]);
|
|
5253
|
+
for (const [bone, channels] of Object.entries(sampled)) {
|
|
5254
|
+
const blended = pose[bone] ?? (pose[bone] = {});
|
|
5255
|
+
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
5256
|
+
const value = channels[channel];
|
|
5257
|
+
if (!value) continue;
|
|
5258
|
+
const target = blended[channel] ?? (blended[channel] = [0, 0, 0]);
|
|
5259
|
+
for (let axis = 0; axis < 3; axis++) target[axis] += value[axis] * weight;
|
|
5260
|
+
}
|
|
5261
|
+
}
|
|
5262
|
+
}
|
|
5000
5263
|
for (const part of this.parts) {
|
|
5001
5264
|
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};
|
|
5002
5265
|
part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);
|
|
@@ -5616,7 +5879,7 @@ var init_EntityObject = __esm({
|
|
|
5616
5879
|
for (const geometry of this.geometries) geometry.dispose();
|
|
5617
5880
|
this.geometries.clear();
|
|
5618
5881
|
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
5619
|
-
for (const player of this.animationPlayers.splice(0)) player.clear();
|
|
5882
|
+
for (const { player } of this.animationPlayers.splice(0)) player.clear();
|
|
5620
5883
|
this.partPoses.clear();
|
|
5621
5884
|
super.disposeAndRemoveAllChildren();
|
|
5622
5885
|
}
|
|
@@ -5651,15 +5914,31 @@ var init_EntityObject = __esm({
|
|
|
5651
5914
|
//<editor-fold desc="ANIMATION">
|
|
5652
5915
|
/** The first active clip, until playback is stopped or the object is disposed. */
|
|
5653
5916
|
get animation() {
|
|
5654
|
-
return this.animationPlayers[0]?.animation;
|
|
5917
|
+
return this.animationPlayers[0]?.player.animation;
|
|
5655
5918
|
}
|
|
5656
|
-
/** Clips playing together,
|
|
5919
|
+
/** Clips playing together, in the order passed to {@link playAnimations}. */
|
|
5657
5920
|
get activeAnimations() {
|
|
5658
|
-
|
|
5921
|
+
const animations = [];
|
|
5922
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
5923
|
+
player.animations.forEach((animation, i) => {
|
|
5924
|
+
animations[indices[i]] = animation;
|
|
5925
|
+
});
|
|
5926
|
+
}
|
|
5927
|
+
return animations;
|
|
5928
|
+
}
|
|
5929
|
+
/** Weights of the active clips, in the same order as {@link activeAnimations}. */
|
|
5930
|
+
get animationWeights() {
|
|
5931
|
+
const weights = [];
|
|
5932
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
5933
|
+
player.weights.forEach((weight, i) => {
|
|
5934
|
+
weights[indices[i]] = weight;
|
|
5935
|
+
});
|
|
5936
|
+
}
|
|
5937
|
+
return weights;
|
|
5659
5938
|
}
|
|
5660
5939
|
/** Seconds since the animation started, before looping. */
|
|
5661
5940
|
get animationTime() {
|
|
5662
|
-
return this.animationPlayers[0]?.time ?? 0;
|
|
5941
|
+
return this.animationPlayers[0]?.player.time ?? 0;
|
|
5663
5942
|
}
|
|
5664
5943
|
/**
|
|
5665
5944
|
* Plays a clip from {@link Entities.getAnimations}, replacing all active clips.
|
|
@@ -5670,42 +5949,59 @@ var init_EntityObject = __esm({
|
|
|
5670
5949
|
playAnimation(animation, options) {
|
|
5671
5950
|
this.playAnimations([animation], options);
|
|
5672
5951
|
}
|
|
5673
|
-
/**
|
|
5952
|
+
/**
|
|
5953
|
+
* Plays clips with a shared clock, adding their weighted offsets within each geometry layer.
|
|
5954
|
+
* Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.
|
|
5955
|
+
*/
|
|
5674
5956
|
playAnimations(animations, options) {
|
|
5675
|
-
const
|
|
5676
|
-
const selections =
|
|
5957
|
+
const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);
|
|
5958
|
+
const selections = /* @__PURE__ */ new Map();
|
|
5959
|
+
animations.forEach((animation, index) => {
|
|
5677
5960
|
const layer = animation.layer ?? "main";
|
|
5678
|
-
if (targets.has(layer)) throw new Error(`Multiple animations target layer "${layer}"`);
|
|
5679
|
-
targets.add(layer);
|
|
5680
5961
|
const names = Object.keys(this.entityLayers).filter((name) => name.split("#")[0] === layer);
|
|
5681
5962
|
if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer "${layer}"`);
|
|
5682
|
-
|
|
5963
|
+
let selection = selections.get(layer);
|
|
5964
|
+
if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });
|
|
5965
|
+
selection.animations.push(animation);
|
|
5966
|
+
selection.indices.push(index);
|
|
5683
5967
|
});
|
|
5684
|
-
const main = selections.
|
|
5685
|
-
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !
|
|
5968
|
+
const main = selections.get("main");
|
|
5969
|
+
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !selections.has(name.split("#")[0])));
|
|
5686
5970
|
this.createMeshes();
|
|
5687
5971
|
this.stopAnimation();
|
|
5688
|
-
for (const {
|
|
5972
|
+
for (const { animations: clips, names, indices } of selections.values()) {
|
|
5689
5973
|
const player = new EntityAnimationPlayer();
|
|
5690
|
-
player.
|
|
5691
|
-
|
|
5974
|
+
player.playAnimations(
|
|
5975
|
+
names.map((name) => this.getLayerGroup(name)),
|
|
5976
|
+
clips,
|
|
5977
|
+
{ ...options, weights: indices.map((index) => weights[index]) },
|
|
5978
|
+
this.partPoses
|
|
5979
|
+
);
|
|
5980
|
+
this.animationPlayers.push({ player, indices });
|
|
5692
5981
|
}
|
|
5693
5982
|
this.notifyDirty();
|
|
5694
5983
|
}
|
|
5984
|
+
/** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */
|
|
5985
|
+
setAnimationWeights(weights) {
|
|
5986
|
+
if (!this.animationPlayers.length) return;
|
|
5987
|
+
const values = validateAnimationWeights(weights, this.activeAnimations.length);
|
|
5988
|
+
for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map((index) => values[index]));
|
|
5989
|
+
this.notifyDirty();
|
|
5990
|
+
}
|
|
5695
5991
|
/** Stops all clips and restores the poses from before playback. */
|
|
5696
5992
|
stopAnimation() {
|
|
5697
5993
|
const players = this.animationPlayers.splice(0);
|
|
5698
|
-
for (const player of players) player.stop();
|
|
5994
|
+
for (const { player } of players) player.stop();
|
|
5699
5995
|
if (players.length) this.notifyDirty();
|
|
5700
5996
|
}
|
|
5701
5997
|
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
5702
5998
|
setAnimationTime(seconds) {
|
|
5703
|
-
for (const player of this.animationPlayers) player.setTime(seconds);
|
|
5999
|
+
for (const { player } of this.animationPlayers) player.setTime(seconds);
|
|
5704
6000
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
5705
6001
|
}
|
|
5706
6002
|
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
5707
6003
|
advanceAnimation(deltaSeconds) {
|
|
5708
|
-
for (const player of this.animationPlayers) player.advance(deltaSeconds);
|
|
6004
|
+
for (const { player } of this.animationPlayers) player.advance(deltaSeconds);
|
|
5709
6005
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
5710
6006
|
}
|
|
5711
6007
|
//</editor-fold>
|
|
@@ -7940,6 +8236,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
7940
8236
|
}
|
|
7941
8237
|
const font = await Fonts.get(options.font);
|
|
7942
8238
|
const runs = typeof text2 === "string" ? [{ text: text2 }] : text2;
|
|
8239
|
+
await font.resolve?.(runs.map((run) => run.text).join(""));
|
|
7943
8240
|
const glyphs = [], lineWidths = [];
|
|
7944
8241
|
let line = [], width = 0;
|
|
7945
8242
|
let trailingNewline = false;
|
|
@@ -7966,7 +8263,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
7966
8263
|
continue;
|
|
7967
8264
|
}
|
|
7968
8265
|
const glyph = font.glyphs.get(character);
|
|
7969
|
-
const advance = (glyph?.advance ?? 6) + (style.bold ? 1 : 0);
|
|
8266
|
+
const advance = (glyph?.advance ?? 6) + (style.bold ? glyph?.boldOffset ?? 1 : 0);
|
|
7970
8267
|
line.push({ character, glyph, advance, style, x: 0, y: 0 });
|
|
7971
8268
|
width += advance;
|
|
7972
8269
|
while (width > maxWidth && line.length > 1) {
|
|
@@ -7994,7 +8291,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
7994
8291
|
batches.push(batch);
|
|
7995
8292
|
}
|
|
7996
8293
|
const color2 = new import_three20.Color(isShadow ? (style.color & 16579836) >> 2 : style.color);
|
|
7997
|
-
const offset = isShadow ? 1 : 0;
|
|
8294
|
+
const offset = isShadow ? glyph?.shadowOffset ?? 1 : 0;
|
|
7998
8295
|
const top = glyph ? 7 - glyph.ascent : 0;
|
|
7999
8296
|
const height = glyph ? glyph.height * glyph.scale : 8;
|
|
8000
8297
|
const width = glyph ? glyph.width * glyph.scale : 5;
|
|
@@ -8024,7 +8321,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
8024
8321
|
for (let i = 0; i < 4; i++) batch.colors.push(color2.r, color2.g, color2.b);
|
|
8025
8322
|
batch.indices.push(base, base + 2, base + 1, base + 2, base + 3, base + 1);
|
|
8026
8323
|
};
|
|
8027
|
-
for (const boldOffset of style.bold ? [0, 1] : [0]) {
|
|
8324
|
+
for (const boldOffset of style.bold ? [0, glyph?.boldOffset ?? 1] : [0]) {
|
|
8028
8325
|
if (glyph) quad(0, top, width, top + height, boldOffset);
|
|
8029
8326
|
else {
|
|
8030
8327
|
quad(0, 0, 5, 1, boldOffset);
|
|
@@ -11299,6 +11596,7 @@ __export(index_browser_exports, {
|
|
|
11299
11596
|
toRadians: () => toRadians,
|
|
11300
11597
|
toTrianglesDrawMode: () => toTrianglesDrawMode,
|
|
11301
11598
|
trimCanvas: () => trimCanvas,
|
|
11599
|
+
validateAnimationWeights: () => validateAnimationWeights,
|
|
11302
11600
|
yieldToEventLoop: () => yieldToEventLoop
|
|
11303
11601
|
});
|
|
11304
11602
|
module.exports = __toCommonJS(index_browser_exports);
|
|
@@ -18916,7 +19214,7 @@ var LIGHT_SAMPLE_OFFSETS = [0, 1, -1, 324, -324, 18, -18];
|
|
|
18916
19214
|
|
|
18917
19215
|
// src/world/SectionGeometry.ts
|
|
18918
19216
|
function buildSectionGeometry(input) {
|
|
18919
|
-
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
19217
|
+
const { count, indices, templates, cullMasks, templateData, atlases: atlases2, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
18920
19218
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
18921
19219
|
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
18922
19220
|
if (biomeTints && biomeTints.length !== count * 3) throw new RangeError("Section biome tints must contain RGB for each placement");
|
|
@@ -18951,8 +19249,8 @@ function buildSectionGeometry(input) {
|
|
|
18951
19249
|
const locations = /* @__PURE__ */ new Map();
|
|
18952
19250
|
for (const [layer, layerAtlases] of [...visibleAtlases].sort(([a], [b]) => a - b)) {
|
|
18953
19251
|
const firstPage = pages.length;
|
|
18954
|
-
for (const atlas of [...layerAtlases].sort((a, b) => Number(
|
|
18955
|
-
const { width, height, animated } =
|
|
19252
|
+
for (const atlas of [...layerAtlases].sort((a, b) => Number(atlases2[a].animated) - Number(atlases2[b].animated) || (atlases2[a].animated ? a - b : atlases2[b].height - atlases2[a].height))) {
|
|
19253
|
+
const { width, height, animated } = atlases2[atlas];
|
|
18956
19254
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
18957
19255
|
let selected = -1;
|
|
18958
19256
|
for (let i = firstPage; !animated && i < pages.length; i++) {
|
|
@@ -18995,7 +19293,7 @@ function buildSectionGeometry(input) {
|
|
|
18995
19293
|
});
|
|
18996
19294
|
if (!quads.sprites.length) continue;
|
|
18997
19295
|
if (!fluidPages.has(fluid)) {
|
|
18998
|
-
const { width, height } =
|
|
19296
|
+
const { width, height } = atlases2[data.atlas];
|
|
18999
19297
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
19000
19298
|
fluidPages.set(fluid, {
|
|
19001
19299
|
layer: 2,
|
|
@@ -19013,7 +19311,7 @@ function buildSectionGeometry(input) {
|
|
|
19013
19311
|
const tint = fluid === "water" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;
|
|
19014
19312
|
fluidPages.get(fluid).fluids.push({ quads, x, y, z, data, tint });
|
|
19015
19313
|
}
|
|
19016
|
-
pages.push(...[...fluidPages.values()].sort((a, b) => Number(
|
|
19314
|
+
pages.push(...[...fluidPages.values()].sort((a, b) => Number(atlases2[a.placements[0].atlas].animated) - Number(atlases2[b.placements[0].atlas].animated) || a.placements[0].atlas - b.placements[0].atlas));
|
|
19017
19315
|
}
|
|
19018
19316
|
return pages.map((page) => {
|
|
19019
19317
|
let faces = page.fluids.reduce((sum, fluid) => sum + fluid.quads.sprites.length, 0);
|
|
@@ -19030,7 +19328,7 @@ function buildSectionGeometry(input) {
|
|
|
19030
19328
|
let vertex = 0, indexOffset = 0;
|
|
19031
19329
|
for (const entry of page.entries) {
|
|
19032
19330
|
const template = templateData[templates[entry]];
|
|
19033
|
-
const atlas =
|
|
19331
|
+
const atlas = atlases2[template.atlas];
|
|
19034
19332
|
const placement = locations.get(template.atlas);
|
|
19035
19333
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19036
19334
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19069,7 +19367,7 @@ function buildSectionGeometry(input) {
|
|
|
19069
19367
|
}
|
|
19070
19368
|
}
|
|
19071
19369
|
for (const { quads, x, y, z, data, tint } of page.fluids) {
|
|
19072
|
-
const atlas =
|
|
19370
|
+
const atlas = atlases2[data.atlas];
|
|
19073
19371
|
const placement = page.placements[0];
|
|
19074
19372
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19075
19373
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19170,7 +19468,7 @@ var templateCache = /* @__PURE__ */ new WeakMap();
|
|
|
19170
19468
|
var WATER_TINT = new import_three46.Color(4159204).toArray();
|
|
19171
19469
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
19172
19470
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
19173
|
-
const
|
|
19471
|
+
const atlases2 = [];
|
|
19174
19472
|
const atlasIds = /* @__PURE__ */ new Map();
|
|
19175
19473
|
const templateIds = /* @__PURE__ */ new Map();
|
|
19176
19474
|
const input = {
|
|
@@ -19193,9 +19491,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19193
19491
|
if (id === void 0) {
|
|
19194
19492
|
let atlas = atlasIds.get(template.atlas);
|
|
19195
19493
|
if (atlas === void 0) {
|
|
19196
|
-
atlas =
|
|
19494
|
+
atlas = atlases2.length;
|
|
19197
19495
|
atlasIds.set(template.atlas, atlas);
|
|
19198
|
-
|
|
19496
|
+
atlases2.push(template.atlas);
|
|
19199
19497
|
input.atlases.push({ width: template.atlas.image.width, height: template.atlas.image.height, animated: template.atlas.hasAnimation });
|
|
19200
19498
|
}
|
|
19201
19499
|
let data = templateCache.get(template);
|
|
@@ -19254,9 +19552,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19254
19552
|
if (!atlas) continue;
|
|
19255
19553
|
let id = atlasIds.get(atlas);
|
|
19256
19554
|
if (id === void 0) {
|
|
19257
|
-
id =
|
|
19555
|
+
id = atlases2.length;
|
|
19258
19556
|
atlasIds.set(atlas, id);
|
|
19259
|
-
|
|
19557
|
+
atlases2.push(atlas);
|
|
19260
19558
|
input.atlases.push({ width: atlas.image.width, height: atlas.image.height, animated: atlas.hasAnimation });
|
|
19261
19559
|
}
|
|
19262
19560
|
input.fluids[kind] = {
|
|
@@ -19267,7 +19565,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19267
19565
|
};
|
|
19268
19566
|
}
|
|
19269
19567
|
}
|
|
19270
|
-
return { input, atlases };
|
|
19568
|
+
return { input, atlases: atlases2 };
|
|
19271
19569
|
}
|
|
19272
19570
|
var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
19273
19571
|
constructor() {
|
|
@@ -19282,23 +19580,23 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19282
19580
|
}
|
|
19283
19581
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
19284
19582
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19285
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19286
|
-
return this.fromPages(buildSectionGeometry(input),
|
|
19583
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19584
|
+
return this.fromPages(buildSectionGeometry(input), atlases2);
|
|
19287
19585
|
}
|
|
19288
19586
|
/** Builds section-local meshes in a browser worker when available, with synchronous fallback. */
|
|
19289
19587
|
static async buildAsync(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19290
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19588
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19291
19589
|
const worker = SectionWorker.shared();
|
|
19292
19590
|
const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);
|
|
19293
|
-
return this.fromPages(pages,
|
|
19591
|
+
return this.fromPages(pages, atlases2);
|
|
19294
19592
|
}
|
|
19295
|
-
static fromPages(pages,
|
|
19593
|
+
static fromPages(pages, atlases2) {
|
|
19296
19594
|
const section = new _SectionMesh();
|
|
19297
19595
|
for (const page of pages) {
|
|
19298
19596
|
const canvas = createCanvas(page.width, page.height);
|
|
19299
19597
|
const context = canvas.getContext("2d");
|
|
19300
19598
|
for (const { atlas, x, y } of page.placements) {
|
|
19301
|
-
context.drawImage(
|
|
19599
|
+
context.drawImage(atlases2[atlas].image.canvas, x, y);
|
|
19302
19600
|
}
|
|
19303
19601
|
const geometry = new import_three46.BufferGeometry();
|
|
19304
19602
|
geometry.setAttribute("position", new import_three46.Float32BufferAttribute(page.positions.buffer, 3));
|
|
@@ -19309,7 +19607,7 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19309
19607
|
geometry.setIndex(new import_three46.Uint32BufferAttribute(page.indices.buffer, 1));
|
|
19310
19608
|
geometry.computeBoundingBox();
|
|
19311
19609
|
geometry.computeBoundingSphere();
|
|
19312
|
-
const transparent = page.layer === 2 ?
|
|
19610
|
+
const transparent = page.layer === 2 ? atlases2[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
19313
19611
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
19314
19612
|
material.side = import_three46.FrontSide;
|
|
19315
19613
|
if (page.layer === 2) {
|
|
@@ -19324,7 +19622,7 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19324
19622
|
section.blockIndices.set(mesh, page.blockIndices);
|
|
19325
19623
|
const unsubscribe = [];
|
|
19326
19624
|
for (const { atlas: id, x, y } of page.placements) {
|
|
19327
|
-
const atlas =
|
|
19625
|
+
const atlas = atlases2[id];
|
|
19328
19626
|
if (!atlas.hasAnimation) continue;
|
|
19329
19627
|
unsubscribe.push(atlas.subscribe(() => {
|
|
19330
19628
|
context.clearRect(x, y, atlas.image.width, atlas.image.height);
|