minerender 2.1.0-beta.6 → 2.1.0-beta.7
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/Materials.mjs +3 -1
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/Ticker.mjs +3 -1
- package/dist/browser/esm/Ticker.mjs.map +1 -1
- package/dist/browser/esm/UVMapper.mjs +9 -9
- package/dist/browser/esm/UVMapper.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetKey.mjs +1 -1
- package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
- package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
- package/dist/browser/esm/assets/Assets.mjs +1 -5
- package/dist/browser/esm/assets/Assets.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockEntities.mjs +3 -1
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +1 -1
- package/dist/browser/esm/assets/Entities.mjs.map +1 -1
- package/dist/browser/esm/assets/Models.mjs +1 -1
- package/dist/browser/esm/assets/Models.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +5 -3
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -1
- package/dist/browser/esm/assets/index.mjs +1 -0
- package/dist/browser/esm/assets/index.mjs.map +1 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +7 -8
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserCache.mjs +3 -3
- package/dist/browser/esm/env/browser/BrowserCache.mjs.map +1 -1
- package/dist/browser/esm/image/ImageLoader.mjs +3 -3
- package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +64 -11
- package/dist/browser/esm/inspector/SceneInspector.mjs +3 -3
- package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
- package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
- package/dist/browser/esm/instance/InstanceManager.mjs.map +1 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs +3 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
- package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
- package/dist/browser/esm/model/scene/ModelObject.mjs +4 -4
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
- package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
- package/dist/browser/esm/renderer/Renderer.mjs +4 -2
- package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
- package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
- package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
- package/dist/browser/esm/request/Requests.mjs +3 -3
- package/dist/browser/esm/request/Requests.mjs.map +1 -1
- package/dist/browser/esm/skin/Skins.mjs +6 -4
- package/dist/browser/esm/skin/Skins.mjs.map +1 -1
- package/dist/browser/esm/texture/TextureLoader.mjs +4 -2
- package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
- package/dist/browser/esm/util/log.mjs +75 -0
- package/dist/browser/esm/util/log.mjs.map +1 -1
- package/dist/browser/esm/util/performance.mjs.map +1 -1
- package/dist/browser/esm/world/Chunk.mjs +8 -5
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +96 -54
- package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
- package/dist/browser/esm/world/WorldStreamer.mjs +21 -20
- package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
- package/dist/browser/index.d.ts +64 -11
- package/dist/browser/index.js +3071 -2956
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +6095 -5975
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +64 -11
- package/dist/node/index.d.ts +64 -11
- package/dist/node/index.js +3095 -2978
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +3087 -2971
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/assets/source/HostedAssetSource.ts"],"sourcesContent":["import { AssetLoadError, AssetSource } from \"./AssetSource\";\nimport { BlockState, Model, TextureAsset } from \"../../model\";\nimport type { RequestConfig, RequestResponse } from \"../../request\";\nimport { Maybe, prefix } from \"../../util\";\nimport { MinecraftTextureMeta } from \"../../MinecraftTextureMeta\";\nimport { NBTAsset, NBTHelper } from \"../../nbt\";\nimport { ImageLoader } from \"../../image\";\nimport { ListAsset } from \"../../ListAsset\";\nimport { MinecraftAsset } from \"../../MinecraftAsset\";\nimport { AssetKey } from \"../AssetKey\";\nimport { DEFAULT_NAMESPACE } from \"../Assets\";\nimport { RequestError, Requests } from \"../../request\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { AssetParser } from \"./parser\";\nimport { ResponseParser } from \"./parser\";\nimport { merge } from \"../../util/_internal/merge\";\n\nconst BINARY_TIMEOUT = 60_000;\n\nconst p = prefix(\"HostedAssetSource\");\n\nconst DEFAULT_OPTIONS: HostedAssetSourceOptions = {\n retryDefaults: true\n}\n\n/** Loads assets over HTTP from a Minecraft directory tree rooted at the constructor's URL. */\nexport class HostedAssetSource extends AssetSource {\n\n static readonly MODEL: ResponseParser<Model> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<Model> {\n return response.data as Model;\n }\n }\n static readonly BLOCKSTATE: ResponseParser<BlockState> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<BlockState> {\n return response.data as BlockState;\n }\n }\n static readonly META: ResponseParser<MinecraftTextureMeta> = {\n config(request: RequestConfig) {\n // request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Maybe<MinecraftTextureMeta> {\n return response.data as MinecraftTextureMeta;\n }\n }\n static readonly NBT: ResponseParser<NBTAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Promise<Maybe<NBTAsset>> {\n return NBTHelper.fromBuffer(response.data);\n }\n }\n static readonly IMAGE: ResponseParser<TextureAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n async parse(response: RequestResponse): Promise<Maybe<TextureAsset>> {\n return await ImageLoader.processResponse(response) as TextureAsset;\n }\n }\n static readonly LIST: ResponseParser<ListAsset> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<ListAsset> {\n return response.data as ListAsset;\n }\n }\n static readonly JSON: ResponseParser<any> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<any> {\n return response.data;\n }\n }\n static readonly BINARY: ResponseParser<BinaryAsset> = {\n config(request: RequestConfig) {\n request.timeout = BINARY_TIMEOUT;\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): BinaryAsset {\n return { data: new Uint8Array(response.data as ArrayBuffer) };\n }\n }\n\n static readonly PARSER_MAP: Map<AssetParser, ResponseParser<any>> = new Map<AssetParser, ResponseParser<any>>([\n [AssetParser.MODEL, HostedAssetSource.MODEL],\n [AssetParser.BLOCKSTATE, HostedAssetSource.BLOCKSTATE],\n [AssetParser.META, HostedAssetSource.META],\n [AssetParser.NBT, HostedAssetSource.NBT],\n [AssetParser.IMAGE, HostedAssetSource.IMAGE],\n [AssetParser.LIST, HostedAssetSource.LIST],\n [AssetParser.JSON, HostedAssetSource.JSON],\n [AssetParser.BINARY, HostedAssetSource.BINARY],\n ]);\n\n /** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */\n public async loadOrRetryWithDefaults<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const direct = await this.load<T>(key, parser);\n if (typeof direct !== \"undefined\") {\n return direct;\n }\n if (key.namespace !== DEFAULT_NAMESPACE) {\n console.info(p, \"Retrying\", key, \"with default namespace\");\n // Try on the same host but with default minecraft: namespace\n const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);\n const namespaced = await this.load<T>(namespaceKey, parser);\n if (typeof namespaced !== \"undefined\") {\n return namespaced;\n }\n if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root+namespace\");\n // Try both defaults\n const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const namespacedRooted = await this.load<T>(namespacedRootedKey, parser);\n if (typeof namespacedRooted !== \"undefined\") {\n return namespacedRooted;\n }\n }\n } else if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root\");\n // Try on default root\n const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const rooted = await this.load<T>(rootKey, parser);\n if (typeof rooted !== \"undefined\") {\n return rooted;\n }\n }\n return undefined;\n }\n\n\n protected async load<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n console.info(p, \"Loading\", key);\n const url = `${ this.assetBasePath(key) }${ key.type !== undefined ? key.type + '/' : '' }${ key.path }${ key.extension }`;\n console.debug(p, url);\n const request: RequestConfig = { url };\n try {\n parser.config(request);\n let response: RequestResponse;\n try {\n response = await Requests.mcAssetRequest(request);\n } catch (cause) {\n // HTTP 404 is the only request failure that permits source fallback.\n if (cause instanceof RequestError && cause.response?.status === 404) {\n return undefined;\n }\n throw cause;\n }\n if (response.data === undefined) {\n throw new Error(\"Asset response has no data\");\n }\n return await parser.parse(response);\n } catch (cause) {\n throw new AssetLoadError(this, key, request.url, cause);\n }\n }\n\n public assetBasePath(key: AssetKey) {\n return `${ key.root ?? this.root ?? AssetLoader.ROOT }/${ key.rootType !== undefined ? key.rootType + '/' : '' }${ key.namespace !== undefined ? key.namespace + '/' : '' }${ key.assetType !== undefined ? key.assetType + '/' : '' }`;\n }\n\n private readonly _root: string;\n private readonly _options: HostedAssetSourceOptions;\n\n /**\n * Creates a hosted source for {@link AssetLoader.addSource}.\n * Set `options.retryDefaults` to `false` to restrict lookups to the requested namespace and root.\n */\n public constructor(root: string, options?: Partial<HostedAssetSourceOptions>) {\n super();\n this._root = root;\n this._options = merge({}, DEFAULT_OPTIONS, options ?? {});\n }\n\n public get root(): string {\n return this._root;\n }\n\n public get cacheId(): string {\n return `hosted:${this._root}`;\n }\n\n public get options(): HostedAssetSourceOptions {\n return this._options;\n }\n\n public get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>> {\n const responseParser = HostedAssetSource.PARSER_MAP.get(parser) as ResponseParser<T>;\n if (this.options.retryDefaults && !(key.rootType === undefined && key.namespace === \"minerender-data\")) {\n return this.loadOrRetryWithDefaults(key, responseParser);\n }\n return this.load(key, responseParser);\n }\n\n}\n\ninterface HostedAssetSourceOptions {\n retryDefaults: boolean;\n}\n\n/** Encoded asset bytes loaded without JSON or image decoding. */\nexport interface BinaryAsset extends MinecraftAsset {\n data: Uint8Array;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/assets/source/HostedAssetSource.ts"],"sourcesContent":["import { AssetLoadError, AssetSource } from \"./AssetSource\";\nimport { BlockState, Model, TextureAsset } from \"../../model\";\nimport type { RequestConfig, RequestResponse } from \"../../request\";\nimport { Maybe } from \"../../util\";\nimport { logger } from \"../../util/log\";\nimport { MinecraftTextureMeta } from \"../../MinecraftTextureMeta\";\nimport { NBTAsset, NBTHelper } from \"../../nbt\";\nimport { ImageLoader } from \"../../image\";\nimport { ListAsset } from \"../../ListAsset\";\nimport { MinecraftAsset } from \"../../MinecraftAsset\";\nimport { AssetKey } from \"../AssetKey\";\nimport { DEFAULT_NAMESPACE } from \"../AssetDefaults\";\nimport { RequestError, Requests } from \"../../request\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { AssetParser } from \"./parser\";\nimport { ResponseParser } from \"./parser\";\nimport { merge } from \"../../util/_internal/merge\";\n\nconst BINARY_TIMEOUT = 60_000;\n\nconst log = logger(\"HostedAssetSource\");\n\nconst DEFAULT_OPTIONS: HostedAssetSourceOptions = {\n retryDefaults: true\n}\n\n/** Loads assets over HTTP from a Minecraft directory tree rooted at the constructor's URL. */\nexport class HostedAssetSource extends AssetSource {\n\n static readonly MODEL: ResponseParser<Model> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<Model> {\n return response.data as Model;\n }\n }\n static readonly BLOCKSTATE: ResponseParser<BlockState> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<BlockState> {\n return response.data as BlockState;\n }\n }\n static readonly META: ResponseParser<MinecraftTextureMeta> = {\n config(request: RequestConfig) {\n // request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Maybe<MinecraftTextureMeta> {\n return response.data as MinecraftTextureMeta;\n }\n }\n static readonly NBT: ResponseParser<NBTAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Promise<Maybe<NBTAsset>> {\n return NBTHelper.fromBuffer(response.data);\n }\n }\n static readonly IMAGE: ResponseParser<TextureAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n async parse(response: RequestResponse): Promise<Maybe<TextureAsset>> {\n return await ImageLoader.processResponse(response) as TextureAsset;\n }\n }\n static readonly LIST: ResponseParser<ListAsset> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<ListAsset> {\n return response.data as ListAsset;\n }\n }\n static readonly JSON: ResponseParser<any> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<any> {\n return response.data;\n }\n }\n static readonly BINARY: ResponseParser<BinaryAsset> = {\n config(request: RequestConfig) {\n request.timeout = BINARY_TIMEOUT;\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): BinaryAsset {\n return { data: new Uint8Array(response.data as ArrayBuffer) };\n }\n }\n\n static readonly PARSER_MAP: Map<AssetParser, ResponseParser<any>> = new Map<AssetParser, ResponseParser<any>>([\n [AssetParser.MODEL, HostedAssetSource.MODEL],\n [AssetParser.BLOCKSTATE, HostedAssetSource.BLOCKSTATE],\n [AssetParser.META, HostedAssetSource.META],\n [AssetParser.NBT, HostedAssetSource.NBT],\n [AssetParser.IMAGE, HostedAssetSource.IMAGE],\n [AssetParser.LIST, HostedAssetSource.LIST],\n [AssetParser.JSON, HostedAssetSource.JSON],\n [AssetParser.BINARY, HostedAssetSource.BINARY],\n ]);\n\n /** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */\n public async loadOrRetryWithDefaults<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const direct = await this.load<T>(key, parser);\n if (typeof direct !== \"undefined\") {\n return direct;\n }\n if (key.namespace !== DEFAULT_NAMESPACE) {\n log.debug(\"Retrying\", key, \"with default namespace\");\n // Try on the same host but with default minecraft: namespace\n const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);\n const namespaced = await this.load<T>(namespaceKey, parser);\n if (typeof namespaced !== \"undefined\") {\n return namespaced;\n }\n if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n log.debug(\"Retrying\", key, \"with default root+namespace\");\n // Try both defaults\n const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const namespacedRooted = await this.load<T>(namespacedRootedKey, parser);\n if (typeof namespacedRooted !== \"undefined\") {\n return namespacedRooted;\n }\n }\n } else if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n log.debug(\"Retrying\", key, \"with default root\");\n // Try on default root\n const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const rooted = await this.load<T>(rootKey, parser);\n if (typeof rooted !== \"undefined\") {\n return rooted;\n }\n }\n return undefined;\n }\n\n\n protected async load<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const url = `${ this.assetBasePath(key) }${ key.type !== undefined ? key.type + '/' : '' }${ key.path }${ key.extension }`;\n log.debug(\"Loading\", url);\n const request: RequestConfig = { url };\n try {\n parser.config(request);\n let response: RequestResponse;\n try {\n response = await Requests.mcAssetRequest(request);\n } catch (cause) {\n // HTTP 404 is the only request failure that permits source fallback.\n if (cause instanceof RequestError && cause.response?.status === 404) {\n return undefined;\n }\n throw cause;\n }\n if (response.data === undefined) {\n throw new Error(\"Asset response has no data\");\n }\n return await parser.parse(response);\n } catch (cause) {\n throw new AssetLoadError(this, key, request.url, cause);\n }\n }\n\n public assetBasePath(key: AssetKey) {\n return `${ key.root ?? this.root ?? AssetLoader.ROOT }/${ key.rootType !== undefined ? key.rootType + '/' : '' }${ key.namespace !== undefined ? key.namespace + '/' : '' }${ key.assetType !== undefined ? key.assetType + '/' : '' }`;\n }\n\n private readonly _root: string;\n private readonly _options: HostedAssetSourceOptions;\n\n /**\n * Creates a hosted source for {@link AssetLoader.addSource}.\n * Set `options.retryDefaults` to `false` to restrict lookups to the requested namespace and root.\n */\n public constructor(root: string, options?: Partial<HostedAssetSourceOptions>) {\n super();\n this._root = root;\n this._options = merge({}, DEFAULT_OPTIONS, options ?? {});\n }\n\n public get root(): string {\n return this._root;\n }\n\n public get cacheId(): string {\n return `hosted:${this._root}`;\n }\n\n public get options(): HostedAssetSourceOptions {\n return this._options;\n }\n\n public get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>> {\n const responseParser = HostedAssetSource.PARSER_MAP.get(parser) as ResponseParser<T>;\n if (this.options.retryDefaults && !(key.rootType === undefined && key.namespace === \"minerender-data\")) {\n return this.loadOrRetryWithDefaults(key, responseParser);\n }\n return this.load(key, responseParser);\n }\n\n}\n\ninterface HostedAssetSourceOptions {\n retryDefaults: boolean;\n}\n\n/** Encoded asset bytes loaded without JSON or image decoding. */\nexport interface BinaryAsset extends MinecraftAsset {\n data: Uint8Array;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/env/browser/BrowserCache.ts
|
|
2
2
|
import { PersistentCache } from "../../cache/PersistentCache.mjs";
|
|
3
|
-
import {
|
|
4
|
-
var
|
|
3
|
+
import { logger } from "../../util/log.mjs";
|
|
4
|
+
var log = logger("BrowserCache");
|
|
5
5
|
var BrowserCache = class extends PersistentCache {
|
|
6
6
|
constructor(backing) {
|
|
7
7
|
super(backing);
|
|
@@ -12,7 +12,7 @@ var BrowserCache = class extends PersistentCache {
|
|
|
12
12
|
return true;
|
|
13
13
|
} catch (error) {
|
|
14
14
|
this.memory = /* @__PURE__ */ new Map();
|
|
15
|
-
|
|
15
|
+
log.warn("Could not open browser storage; using an in-memory store", error);
|
|
16
16
|
return false;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/env/browser/BrowserCache.ts"],"sourcesContent":["import { PersistentCache } from \"../../cache/PersistentCache\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/env/browser/BrowserCache.ts"],"sourcesContent":["import { PersistentCache } from \"../../cache/PersistentCache\";\nimport { logger } from \"../../util/log\";\n\nconst log = logger(\"BrowserCache\");\n\n/**\n * {@link PersistentCache} backed by localforage (IndexedDB / WebSQL / localStorage).\n * Uses an in-memory store when browser storage cannot be opened.\n */\nexport class BrowserCache extends PersistentCache<LocalForage> {\n\n private initialized?: Promise<boolean>;\n private memory?: Map<string, unknown>;\n\n constructor(backing: LocalForage) {\n super(backing);\n }\n\n private async initialize(): Promise<boolean> {\n try {\n await this.backing.ready();\n return true;\n } catch (error) {\n this.memory = new Map();\n log.warn(\"Could not open browser storage; using an in-memory store\", error);\n return false;\n }\n }\n\n private async run<T>(operation: () => Promise<T>, fallback: (memory: Map<string, unknown>) => T): Promise<T> {\n if (await (this.initialized ??= this.initialize())) return operation();\n return fallback(this.memory!);\n }\n\n get<T>(key: string): Promise<T> {\n return this.run(() => this.backing.getItem<T>(key), memory => memory.get(key) as T) as Promise<T>;\n }\n\n put<T>(key: string, value: T): Promise<T> {\n return this.run(() => this.backing.setItem<T>(key, value), memory => {\n memory.set(key, value);\n return value;\n });\n }\n\n delete<T>(key: string): Promise<void> {\n return this.run(() => this.backing.removeItem(key), memory => { memory.delete(key); });\n }\n\n clear(): Promise<void> {\n return this.run(() => this.backing.clear(), memory => memory.clear());\n }\n\n length(): Promise<number> {\n return this.run(() => this.backing.length(), memory => memory.size);\n }\n\n keys(): Promise<string[]> {\n return this.run(() => this.backing.keys(), memory => [...memory.keys()]);\n }\n\n forEach<T>(callback: (v: T, k: string) => void): Promise<void> {\n return this.run(() => this.backing.iterate<T, void>((value, key) => {\n callback(value, key);\n }), memory => memory.forEach((value, key) => callback(value as T, key)));\n }\n\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,cAAc;AAEvB,IAAM,MAAM,OAAO,cAAc;AAM1B,IAAM,eAAN,cAA2B,gBAA6B;AAAA,EAK3D,YAAY,SAAsB;AAC9B,UAAM,OAAO;AAAA,EACjB;AAAA,EAEA,MAAc,aAA+B;AACzC,QAAI;AACA,YAAM,KAAK,QAAQ,MAAM;AACzB,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,WAAK,SAAS,oBAAI,IAAI;AACtB,UAAI,KAAK,4DAA4D,KAAK;AAC1E,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAc,IAAO,WAA6B,UAA2D;AACzG,QAAI,OAAO,KAAK,gBAAL,KAAK,cAAgB,KAAK,WAAW,IAAI,QAAO,UAAU;AACrE,WAAO,SAAS,KAAK,MAAO;AAAA,EAChC;AAAA,EAEA,IAAO,KAAyB;AAC5B,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAW,GAAG,GAAG,YAAU,OAAO,IAAI,GAAG,CAAM;AAAA,EACtF;AAAA,EAEA,IAAO,KAAa,OAAsB;AACtC,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAW,KAAK,KAAK,GAAG,YAAU;AACjE,aAAO,IAAI,KAAK,KAAK;AACrB,aAAO;AAAA,IACX,CAAC;AAAA,EACL;AAAA,EAEA,OAAU,KAA4B;AAClC,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,WAAW,GAAG,GAAG,YAAU;AAAE,aAAO,OAAO,GAAG;AAAA,IAAG,CAAC;AAAA,EACzF;AAAA,EAEA,QAAuB;AACnB,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,MAAM,GAAG,YAAU,OAAO,MAAM,CAAC;AAAA,EACxE;AAAA,EAEA,SAA0B;AACtB,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,OAAO,GAAG,YAAU,OAAO,IAAI;AAAA,EACtE;AAAA,EAEA,OAA0B;AACtB,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,KAAK,GAAG,YAAU,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC;AAAA,EAC3E;AAAA,EAEA,QAAW,UAAoD;AAC3D,WAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAiB,CAAC,OAAO,QAAQ;AAChE,eAAS,OAAO,GAAG;AAAA,IACvB,CAAC,GAAG,YAAU,OAAO,QAAQ,CAAC,OAAO,QAAQ,SAAS,OAAY,GAAG,CAAC,CAAC;AAAA,EAC3E;AAEJ;","names":[]}
|
|
@@ -6,8 +6,8 @@ import { Env } from "../Env.mjs";
|
|
|
6
6
|
import { Requests } from "../request/Requests.mjs";
|
|
7
7
|
import { WrappedImage } from "../WrappedImage.mjs";
|
|
8
8
|
import { base64ToBytes, bytesToBase64 } from "../util/_internal/base64.mjs";
|
|
9
|
-
import {
|
|
10
|
-
var
|
|
9
|
+
import { logger } from "../util/log.mjs";
|
|
10
|
+
var log = logger("ImageLoader");
|
|
11
11
|
var ImageLoader = class _ImageLoader {
|
|
12
12
|
static _createImage() {
|
|
13
13
|
return createImage();
|
|
@@ -32,7 +32,7 @@ var ImageLoader = class _ImageLoader {
|
|
|
32
32
|
return image;
|
|
33
33
|
}
|
|
34
34
|
static async loadData(src) {
|
|
35
|
-
|
|
35
|
+
log.debug("loadData", src);
|
|
36
36
|
const image = await this.loadCanvasData(src);
|
|
37
37
|
return image.data.getImageData(0, 0, image.width, image.height);
|
|
38
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/image/ImageLoader.ts"],"sourcesContent":["import { CompatImage, createCanvas, createImage } from \"../canvas/CanvasCompat\";\nimport { serializeImageKey } from \"../cache/CacheKey\";\nimport { Caching } from \"../cache/Caching\";\nimport type { RequestResponse } from \"../request/Requests\";\nimport { Env } from \"../Env\";\nimport { Requests } from \"../request/Requests\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { base64ToBytes, bytesToBase64 } from \"../util/_internal/base64\";\nimport { prefix } from \"../util/log\";\n\nconst p = prefix(\"ImageLoader\");\n\n/** Encoded image bytes with dimensions and format detected from the file header. */\nexport interface ImageInfo {\n src?: string;\n width: number;\n height: number;\n type?: string;\n data: Uint8Array;\n}\n\n/** Fetches and decodes images through the active browser or Node environment provider. */\nexport class ImageLoader {\n\n protected static _createImage(): CompatImage {\n return createImage();\n }\n\n /** Resolves when an image URL has decoded, or rejects if decoding fails. */\n public static async loadAsync(src: string): Promise<CompatImage> {\n return new Promise<CompatImage>((resolve, reject) => {\n const image = this._createImage();\n image.onload = () => resolve(image);\n image.onerror = (err: Error) => reject(err instanceof Error ? err : new Error(\"Failed to decode image\"));\n // Node images can finish decoding synchronously when src is assigned.\n image.src = src;\n });\n }\n\n /** Returns an image immediately. Use the callbacks to observe loading, or await {@link loadAsync}. */\n public static loadElement(src: string, onload?: () => void, onerr?: (err: Error) => void): CompatImage {\n const image = this._createImage();\n if (onload)\n image.onload = onload;\n if (onerr)\n image.onerror = onerr;\n image.src = src;\n return image;\n }\n\n public static async loadData(src: string): Promise<ImageData> {\n console.debug(p, \"loadData\", src);\n const image = await this.loadCanvasData(src);\n return image.data.getImageData(0, 0, image.width, image.height);\n }\n\n public static async loadCanvasData(src: string): Promise<ExtractableImageData> {\n const keyStr = serializeImageKey({ src });\n const info = this.getInfo(src);\n const cached = Caching.rawImageCache.getIfPresent(keyStr);\n try {\n return await this.infoToCanvasData(await info);\n } catch (err) {\n // A valid header can still contain corrupt pixels. Retry the fetch after a decode\n // failure, without evicting a replacement inserted while this load was pending.\n if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {\n Caching.rawImageCache.invalidate(keyStr);\n }\n throw err;\n }\n }\n\n /** Decodes the supplied bytes into a canvas without fetching the source URL again. */\n public static async infoToCanvasData(info: ImageInfo): Promise<ExtractableImageData> {\n const type = info.type === \"jpg\" ? \"jpeg\" : info.type ?? \"png\";\n // Both browser and Node images accept data URLs; src remains provenance, not a second fetch.\n const image = await ImageLoader.loadAsync(`data:image/${type};base64,${bytesToBase64(info.data)}`);\n const canvas = createCanvas(info.width, info.height);\n const context = canvas.getContext(\"2d\") as CanvasRenderingContext2D;\n context.drawImage(image as CanvasImageSource, 0, 0);\n return {\n data: context,\n width: info.width,\n height: info.height\n }\n }\n\n\n public static async infoToData(info: ImageInfo): Promise<ImageData> {\n const image = await this.infoToCanvasData(info);\n return image.data.getImageData(0, 0, image.width, image.height);\n }\n\n /** Returns cached RGBA pixels for an image URL or data URL. Failed loads can be retried. */\n public static async getData(src: string): Promise<ImageData> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.imageDataCache.get(keyStr, k => {\n return ImageLoader.loadData(src);\n }))!;\n }\n\n /** Returns a cached canvas context and dimensions for an image URL or data URL. */\n public static async getCanvasData(src: string): Promise<ExtractableImageData> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.canvasImageDataCache.get(keyStr, k => {\n return ImageLoader.loadCanvasData(src);\n }))!;\n }\n\n public static async processResponse(response: Pick<RequestResponse<ArrayBuffer>, \"data\" | \"url\">): Promise<ImageInfo> {\n const src = response.url;\n const data = new Uint8Array(response.data);\n const { width, height, type } = Env.provider.imageSize(data);\n if (!width || !height) {\n throw new Error(\"Invalid or unsupported image dimensions\");\n }\n return {\n src,\n width,\n height,\n type,\n data: data\n }\n }\n\n\n public static async loadInfo(src: string): Promise<ImageInfo> {\n if (/^data:/i.test(src.trimStart())) {\n const url = new URL(src);\n url.hash = \"\";\n const comma = url.href.indexOf(\",\");\n if (comma < 0) {\n throw new Error(\"Invalid image data URL\");\n }\n // Percent escapes represent image bytes, which need not be valid UTF-8.\n const bytes = url.href.slice(comma + 1).replace(/%([\\da-f]{2})/gi,\n (_, hex: string) => String.fromCharCode(parseInt(hex, 16)));\n const data = /; *base64 *$/i.test(url.href.slice(5, comma))\n ? base64ToBytes(bytes)\n : Uint8Array.from(bytes, char => char.charCodeAt(0));\n return this.processResponse({\n url: src,\n data: data.buffer\n });\n }\n\n return Requests.genericRequest({\n url: src,\n responseType: \"arraybuffer\"\n })\n .then(this.processResponse);\n }\n\n public static async getInfo(src: string): Promise<ImageInfo> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.rawImageCache.get(keyStr, k => {\n return ImageLoader.loadInfo(src);\n }))!;\n }\n\n public static async loadWrapped(src: string): Promise<WrappedImage> {\n const data = await this.getCanvasData(src);\n return new WrappedImage(data);\n }\n\n public static async getWrapped(src: string): Promise<WrappedImage> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.wrappedImageCache.get(keyStr, k => {\n return ImageLoader.loadWrapped(src);\n }))!;\n }\n\n\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/image/ImageLoader.ts"],"sourcesContent":["import { CompatImage, createCanvas, createImage } from \"../canvas/CanvasCompat\";\nimport { serializeImageKey } from \"../cache/CacheKey\";\nimport { Caching } from \"../cache/Caching\";\nimport type { RequestResponse } from \"../request/Requests\";\nimport { Env } from \"../Env\";\nimport { Requests } from \"../request/Requests\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { base64ToBytes, bytesToBase64 } from \"../util/_internal/base64\";\nimport { logger } from \"../util/log\";\n\nconst log = logger(\"ImageLoader\");\n\n/** Encoded image bytes with dimensions and format detected from the file header. */\nexport interface ImageInfo {\n src?: string;\n width: number;\n height: number;\n type?: string;\n data: Uint8Array;\n}\n\n/** Fetches and decodes images through the active browser or Node environment provider. */\nexport class ImageLoader {\n\n protected static _createImage(): CompatImage {\n return createImage();\n }\n\n /** Resolves when an image URL has decoded, or rejects if decoding fails. */\n public static async loadAsync(src: string): Promise<CompatImage> {\n return new Promise<CompatImage>((resolve, reject) => {\n const image = this._createImage();\n image.onload = () => resolve(image);\n image.onerror = (err: Error) => reject(err instanceof Error ? err : new Error(\"Failed to decode image\"));\n // Node images can finish decoding synchronously when src is assigned.\n image.src = src;\n });\n }\n\n /** Returns an image immediately. Use the callbacks to observe loading, or await {@link loadAsync}. */\n public static loadElement(src: string, onload?: () => void, onerr?: (err: Error) => void): CompatImage {\n const image = this._createImage();\n if (onload)\n image.onload = onload;\n if (onerr)\n image.onerror = onerr;\n image.src = src;\n return image;\n }\n\n public static async loadData(src: string): Promise<ImageData> {\n log.debug(\"loadData\", src);\n const image = await this.loadCanvasData(src);\n return image.data.getImageData(0, 0, image.width, image.height);\n }\n\n public static async loadCanvasData(src: string): Promise<ExtractableImageData> {\n const keyStr = serializeImageKey({ src });\n const info = this.getInfo(src);\n const cached = Caching.rawImageCache.getIfPresent(keyStr);\n try {\n return await this.infoToCanvasData(await info);\n } catch (err) {\n // A valid header can still contain corrupt pixels. Retry the fetch after a decode\n // failure, without evicting a replacement inserted while this load was pending.\n if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {\n Caching.rawImageCache.invalidate(keyStr);\n }\n throw err;\n }\n }\n\n /** Decodes the supplied bytes into a canvas without fetching the source URL again. */\n public static async infoToCanvasData(info: ImageInfo): Promise<ExtractableImageData> {\n const type = info.type === \"jpg\" ? \"jpeg\" : info.type ?? \"png\";\n // Both browser and Node images accept data URLs; src remains provenance, not a second fetch.\n const image = await ImageLoader.loadAsync(`data:image/${type};base64,${bytesToBase64(info.data)}`);\n const canvas = createCanvas(info.width, info.height);\n const context = canvas.getContext(\"2d\") as CanvasRenderingContext2D;\n context.drawImage(image as CanvasImageSource, 0, 0);\n return {\n data: context,\n width: info.width,\n height: info.height\n }\n }\n\n\n public static async infoToData(info: ImageInfo): Promise<ImageData> {\n const image = await this.infoToCanvasData(info);\n return image.data.getImageData(0, 0, image.width, image.height);\n }\n\n /** Returns cached RGBA pixels for an image URL or data URL. Failed loads can be retried. */\n public static async getData(src: string): Promise<ImageData> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.imageDataCache.get(keyStr, k => {\n return ImageLoader.loadData(src);\n }))!;\n }\n\n /** Returns a cached canvas context and dimensions for an image URL or data URL. */\n public static async getCanvasData(src: string): Promise<ExtractableImageData> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.canvasImageDataCache.get(keyStr, k => {\n return ImageLoader.loadCanvasData(src);\n }))!;\n }\n\n public static async processResponse(response: Pick<RequestResponse<ArrayBuffer>, \"data\" | \"url\">): Promise<ImageInfo> {\n const src = response.url;\n const data = new Uint8Array(response.data);\n const { width, height, type } = Env.provider.imageSize(data);\n if (!width || !height) {\n throw new Error(\"Invalid or unsupported image dimensions\");\n }\n return {\n src,\n width,\n height,\n type,\n data: data\n }\n }\n\n\n public static async loadInfo(src: string): Promise<ImageInfo> {\n if (/^data:/i.test(src.trimStart())) {\n const url = new URL(src);\n url.hash = \"\";\n const comma = url.href.indexOf(\",\");\n if (comma < 0) {\n throw new Error(\"Invalid image data URL\");\n }\n // Percent escapes represent image bytes, which need not be valid UTF-8.\n const bytes = url.href.slice(comma + 1).replace(/%([\\da-f]{2})/gi,\n (_, hex: string) => String.fromCharCode(parseInt(hex, 16)));\n const data = /; *base64 *$/i.test(url.href.slice(5, comma))\n ? base64ToBytes(bytes)\n : Uint8Array.from(bytes, char => char.charCodeAt(0));\n return this.processResponse({\n url: src,\n data: data.buffer\n });\n }\n\n return Requests.genericRequest({\n url: src,\n responseType: \"arraybuffer\"\n })\n .then(this.processResponse);\n }\n\n public static async getInfo(src: string): Promise<ImageInfo> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.rawImageCache.get(keyStr, k => {\n return ImageLoader.loadInfo(src);\n }))!;\n }\n\n public static async loadWrapped(src: string): Promise<WrappedImage> {\n const data = await this.getCanvasData(src);\n return new WrappedImage(data);\n }\n\n public static async getWrapped(src: string): Promise<WrappedImage> {\n const keyStr = serializeImageKey({ src });\n return (await Caching.wrappedImageCache.get(keyStr, k => {\n return ImageLoader.loadWrapped(src);\n }))!;\n }\n\n\n}\n"],"mappings":"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","names":[]}
|
|
@@ -913,6 +913,9 @@ declare class MinecraftFaceUV {
|
|
|
913
913
|
*/
|
|
914
914
|
declare function shutdown(): void;
|
|
915
915
|
|
|
916
|
+
declare const DEFAULT_ROOT = "https://assets.mcasset.cloud/1.21.11";
|
|
917
|
+
declare const DEFAULT_NAMESPACE = "minecraft";
|
|
918
|
+
|
|
916
919
|
/** Runs queued tasks in bounded batches. Idle executors do not keep a timer running. */
|
|
917
920
|
declare class BatchedExecutor {
|
|
918
921
|
readonly interval: number;
|
|
@@ -930,6 +933,34 @@ declare class BatchedExecutor {
|
|
|
930
933
|
}
|
|
931
934
|
type Task<T = unknown> = () => T | Promise<T>;
|
|
932
935
|
|
|
936
|
+
/** Severity of a log message, from most to least verbose. */
|
|
937
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
938
|
+
/** The lowest level that is printed, or `"silent"` to print nothing. */
|
|
939
|
+
type LogThreshold = LogLevel | "silent";
|
|
940
|
+
/** Receives each message that passes the threshold. `args` are the logger call's arguments, without a tag. */
|
|
941
|
+
type LogHandler = (level: LogLevel, namespace: string, args: unknown[]) => void;
|
|
942
|
+
interface LoggingOptions {
|
|
943
|
+
/** Threshold for namespaces without an override. Starts at `"warn"`. */
|
|
944
|
+
level?: LogThreshold;
|
|
945
|
+
/** Thresholds by logger name, such as `{ UVMapper: "debug" }`. Replaces earlier overrides. */
|
|
946
|
+
namespaces?: Record<string, LogThreshold>;
|
|
947
|
+
}
|
|
948
|
+
interface Logger {
|
|
949
|
+
debug(...args: unknown[]): void;
|
|
950
|
+
info(...args: unknown[]): void;
|
|
951
|
+
warn(...args: unknown[]): void;
|
|
952
|
+
error(...args: unknown[]): void;
|
|
953
|
+
}
|
|
954
|
+
/** Global log settings for every MineRender logger. */
|
|
955
|
+
declare class Logging {
|
|
956
|
+
/** Updates the given settings and keeps the others. */
|
|
957
|
+
static configure(options: LoggingOptions): void;
|
|
958
|
+
/** Sends messages to `handler` instead of the console. Call without an argument to restore console output. */
|
|
959
|
+
static setHandler(handler?: LogHandler): void;
|
|
960
|
+
}
|
|
961
|
+
/** Creates a logger whose messages are tagged and filtered as `namespace`. */
|
|
962
|
+
declare function logger(namespace: string): Logger;
|
|
963
|
+
/** @deprecated Use {@link logger}. */
|
|
933
964
|
declare function prefix(prefix?: string): string;
|
|
934
965
|
|
|
935
966
|
/** Rotates geometry in place around the element's origin. The supplied angle is in degrees. */
|
|
@@ -941,8 +972,11 @@ declare function addWireframeToObject(obj: Object3D, color?: number, w?: number)
|
|
|
941
972
|
/** Adds edge and axis helpers to a mesh and returns a function that disposes their resources. */
|
|
942
973
|
declare function addWireframeToMesh(geo: BufferGeometry, mesh: Mesh, color?: number, w?: number): () => void;
|
|
943
974
|
|
|
975
|
+
/** @deprecated Unused by MineRender. */
|
|
944
976
|
declare function captureException(e: any, ...extra: any[]): void;
|
|
977
|
+
/** @deprecated Unused by MineRender. */
|
|
945
978
|
declare function timingStart(marker: string): void;
|
|
979
|
+
/** @deprecated Unused by MineRender. */
|
|
946
980
|
declare function timingEnd(marker: string): void;
|
|
947
981
|
|
|
948
982
|
declare function sha1(str: string): string;
|
|
@@ -1057,8 +1091,6 @@ type MultipartCondition = Record<string, string> | {
|
|
|
1057
1091
|
AND: MultipartCondition[];
|
|
1058
1092
|
};
|
|
1059
1093
|
|
|
1060
|
-
declare const DEFAULT_ROOT = "https://assets.mcasset.cloud/1.21.11";
|
|
1061
|
-
declare const DEFAULT_NAMESPACE = "minecraft";
|
|
1062
1094
|
/** Convenience accessors for model and blockstate loading. */
|
|
1063
1095
|
declare class Assets {
|
|
1064
1096
|
/**
|
|
@@ -2459,11 +2491,21 @@ interface Palette {
|
|
|
2459
2491
|
};
|
|
2460
2492
|
}
|
|
2461
2493
|
interface PaletteEntry {
|
|
2462
|
-
Name
|
|
2494
|
+
Name?: {
|
|
2463
2495
|
type: "string";
|
|
2464
2496
|
value: string;
|
|
2465
2497
|
};
|
|
2466
|
-
|
|
2498
|
+
id?: {
|
|
2499
|
+
type: "string";
|
|
2500
|
+
value: string;
|
|
2501
|
+
};
|
|
2502
|
+
Properties?: {
|
|
2503
|
+
type: "compound";
|
|
2504
|
+
value: {
|
|
2505
|
+
[property: string]: PalettePropertyValue;
|
|
2506
|
+
};
|
|
2507
|
+
};
|
|
2508
|
+
properties?: {
|
|
2467
2509
|
type: "compound";
|
|
2468
2510
|
value: {
|
|
2469
2511
|
[property: string]: PalettePropertyValue;
|
|
@@ -4034,7 +4076,7 @@ declare class Chunk<SectionMeshing extends boolean = false> {
|
|
|
4034
4076
|
private ambientOcclusionCells?;
|
|
4035
4077
|
private readonly blockChanges;
|
|
4036
4078
|
private biomeChange?;
|
|
4037
|
-
constructor(scene: MineRenderScene, x: number, y: number, z: number, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined, sectionModels?: SectionModels | undefined, neighborCell?: ((x: number, y: number, z: number) => number) | undefined, biomeAt?: ((x: number, y: number, z: number) => Maybe<string>) | undefined, onBiomesChanged?: ((biomes?: readonly string[]) => Promise<void>) | undefined, lightAt?: ((x: number, y: number, z: number) => number) | undefined, onLightCleared?: (() => Promise<void>) | undefined, ambientLight?: number, biomeBlend?: (() => BiomeBlend | undefined) | undefined);
|
|
4079
|
+
constructor(scene: MineRenderScene, x: number, y: number, z: number, onBlocksChanged?: ((positions: Vector3[], deferCulling?: boolean) => Promise<void>) | undefined, sectionModels?: SectionModels | undefined, neighborCell?: ((x: number, y: number, z: number) => number) | undefined, biomeAt?: ((x: number, y: number, z: number) => Maybe<string>) | undefined, onBiomesChanged?: ((biomes?: readonly string[]) => Promise<void>) | undefined, lightAt?: ((x: number, y: number, z: number) => number) | undefined, onLightCleared?: (() => Promise<void>) | undefined, ambientLight?: number, biomeBlend?: (() => BiomeBlend | undefined) | undefined);
|
|
4038
4080
|
/** Finds the nearest owned block hit across sections, testing each shared mesh once. */
|
|
4039
4081
|
static raycast<SectionMeshing extends boolean>(chunks: Iterable<Chunk<SectionMeshing>>, raycaster: Raycaster): WorldBlockIntersection | undefined;
|
|
4040
4082
|
getBlockAt(x: number, y: number, z: number): Maybe<BlockInfo<SectionMeshing>>;
|
|
@@ -4046,11 +4088,14 @@ declare class Chunk<SectionMeshing extends boolean = false> {
|
|
|
4046
4088
|
getBiomeAt(pos: TripleArray): Maybe<string>;
|
|
4047
4089
|
/** Copies 64 biome IDs in x + z * 4 + y * 16 order and refreshes placed blocks. Omit the array to clear biome data. */
|
|
4048
4090
|
setBiomes(biomes?: readonly string[]): Promise<void>;
|
|
4049
|
-
/**
|
|
4091
|
+
/**
|
|
4092
|
+
* Rebuilds biome-tinted blocks while preserving hidden blocks and unrelated render objects.
|
|
4093
|
+
* The owning world can defer neighbor culling until all affected chunks are refreshed.
|
|
4094
|
+
*/
|
|
4050
4095
|
refreshBiomes(columns?: readonly {
|
|
4051
4096
|
x: number;
|
|
4052
4097
|
z: number;
|
|
4053
|
-
}[]): Promise<void>;
|
|
4098
|
+
}[], deferCulling?: boolean): Promise<void>;
|
|
4054
4099
|
private refreshBiomeBlocks;
|
|
4055
4100
|
/**
|
|
4056
4101
|
* Places a block at integer world block coordinates. Pass `undefined` to remove it.
|
|
@@ -4061,7 +4106,7 @@ declare class Chunk<SectionMeshing extends boolean = false> {
|
|
|
4061
4106
|
/**
|
|
4062
4107
|
* Places a block at integer chunk-local coordinates from 0 to 15.
|
|
4063
4108
|
*/
|
|
4064
|
-
setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<Maybe<BlockInfo<SectionMeshing>>>;
|
|
4109
|
+
setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[], deferCulling?: boolean) => Promise<void>) | undefined): Promise<Maybe<BlockInfo<SectionMeshing>>>;
|
|
4065
4110
|
/** Places cells in input order and returns changed world positions without refreshing neighbors. */
|
|
4066
4111
|
placeBlocks(blocks: readonly {
|
|
4067
4112
|
index: number;
|
|
@@ -4226,6 +4271,14 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
|
|
|
4226
4271
|
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
4227
4272
|
*/
|
|
4228
4273
|
unloadChunkColumn(x: number, z: number): Promise<void>;
|
|
4274
|
+
/**
|
|
4275
|
+
* Removes chunk columns together and refreshes surviving neighbors once.
|
|
4276
|
+
* Coordinates are absolute chunk columns. Duplicate and missing columns are ignored.
|
|
4277
|
+
*/
|
|
4278
|
+
unloadChunkColumns(positions: readonly {
|
|
4279
|
+
x: number;
|
|
4280
|
+
z: number;
|
|
4281
|
+
}[]): Promise<void>;
|
|
4229
4282
|
private clearChunkColumn;
|
|
4230
4283
|
private markSectionChanged;
|
|
4231
4284
|
/** Removes all chunks and releases their blocks, section meshes, and owned entities. */
|
|
@@ -4303,7 +4356,7 @@ declare class WorldStreamer {
|
|
|
4303
4356
|
private running?;
|
|
4304
4357
|
private disposal?;
|
|
4305
4358
|
private disposed;
|
|
4306
|
-
constructor(world: Pick<MineRenderWorld<boolean>, "placeChunk" | "
|
|
4359
|
+
constructor(world: Pick<MineRenderWorld<boolean>, "placeChunk" | "unloadChunkColumns">, source: WorldChunkSource, options?: WorldStreamerOptions);
|
|
4307
4360
|
/** Returns absolute coordinates of successfully placed columns, including retained columns. */
|
|
4308
4361
|
get loadedChunks(): readonly {
|
|
4309
4362
|
x: number;
|
|
@@ -4337,7 +4390,7 @@ declare class WorldStreamer {
|
|
|
4337
4390
|
dispose(): Promise<void>;
|
|
4338
4391
|
private drain;
|
|
4339
4392
|
private needsLoad;
|
|
4340
|
-
private
|
|
4393
|
+
private unloadMany;
|
|
4341
4394
|
private validateChunk;
|
|
4342
4395
|
private within;
|
|
4343
4396
|
private key;
|
|
@@ -4386,4 +4439,4 @@ declare class BrowserCache extends PersistentCache<LocalForage> {
|
|
|
4386
4439
|
*/
|
|
4387
4440
|
declare function probeImageSize(data: Uint8Array): ImageSizeInfo;
|
|
4388
4441
|
|
|
4389
|
-
export { AXES, type AnimationFrame, type AnimationMeta, type AnimatorFunction, type AnvilChunk, type AnvilEntityChunk, type AnvilExternalChunkReader, type AnvilParseOptions, AnvilParser, type AnvilRegion, type AnvilRegionReader, AnvilWorldSource, type AnvilWorldSourceOptions, ArchiveAssetSource, type ArchiveAssetSourceOptions, type ArchiveEntry, type ArchiveProxy, AssetKey, AssetLoadError, AssetLoader, AssetParser, AssetSource, type AssetType, Assets, Axis, BUILTIN_ENTITY, BUILTIN_GENERATED, type BannerPattern, type BannerPatternDraw, BannerPatterns, BasicAssetKey, type BasicMinecraftAsset, BatchedExecutor, type BedrockBone, type BedrockCube, type BedrockEntityDescription, type BedrockEntityFile, type BedrockGeometry, type BedrockGeometryFile, type BinaryAsset, type Biome, type BiomeColorKind, Biomes, type BitmapFont, type BitmapGlyph, type Block, BlockEntities, type BlockEntityEntry, type BlockEntityIndex, type BlockEntityPart, type BlockEntityRotation, type BlockFluidState, type BlockInfo, type BlockModel, type BlockModelTextures, BlockObject, type BlockObjectOptions, type BlockState, type BlockStateMultipart, type BlockStateProperties, type BlockStateProperty, type BlockStatePropertyDefaults, type BlockStatePropertyValue, BlockStateResolver, type BlockStateVariant, type BlockStateVariants, BlockStates, BlockTints, type BoxGeometryKey, BrowserArchiveProxy, BrowserCache, BrowserEnv, CUBE_FACES, CUBE_FACE_OFFSETS, type CacheKey, Caching, type CameraOptions, CanvasImage, type CapeLayout, Chunk, ChunkData, Colormaps, type CompatCanvas, type CompatImage, type ComposerOptions, type ControlsMode, type ControlsOptions, CubeFace, CubeFaceIndex, DEFAULT_ELEMENTS, DEFAULT_NAMESPACE, DEFAULT_ROOT, DEFAULT_UV, DISPLAY_POSITIONS, DYE_COLORS, type DebugOptions, type DecoratedPotSide, DecoratedPots, type DeepPartial, DefaultBlockStates, DisplayPosition, DisplayTransforms, type Disposable, type DoubleArray, type DyeColor, ENTITY_ANIMATION_CHANNELS, type ElementFace, type ElementRotation, Entities, type EntityAnimation, type EntityAnimationBone, type EntityAnimationChannel, type EntityAnimationFile, type EntityAnimationKeyframe, type EntityAnimationOptions, EntityAnimationPlayer, type EntityAnimationPose, type EntityLayer, type EntityModel, type EntityModelCube, type EntityModelFile, type EntityModelLayer, type EntityModelOptions, type EntityModelPart, type EntityModelPass, EntityObject, type EntityObjectOptions, type EntityRenderMode, type EntityTransformOp, Env, type EnvProvider, type ExtractableImageData, type FluidKind, FluidModelObject, type FluidQuads, type FluidRules, type FluidSample, type FluidSampler, type FlyAction, FlyControls, type FlyControlsEventMap, Fonts, type FrameCallback, type FromTo, GUI_CONTAINER_LAYOUTS, Geometries, type GuiBookButtonState, type GuiBookOptions, type GuiBossBarColor, type GuiBossBarOptions, type GuiContainerType, GuiHelper, type GuiItemLayer, type GuiLayer, GuiLight, GuiObject, type GuiObjectOptions, type GuiRecipe, type GuiRecipeIngredient, type GuiRecipeOptions, type GuiSpriteScaling, type GuiText, type GuiTextLayer, type GuiTextLayout, type GuiTextOptions, type GuiTextRun, type GuiTextStyle, type GuiTextureLayer, type GuiTooltipOptions, HostedAssetSource, type IModelTextures, ITEM_GENERATED, type ImageInfo, ImageLoader, type ImageSizeInfo, InstanceManager, InstanceReference, type Instanceable, ItemDefaults, ItemGlint, type ItemModel, type ItemModelContext, type ItemModelTextures, type ItemTintColor, type ItemTintSource, ItemTints, type ListAsset, LitematicaParser, type LitematicaRegion, type LitematicaStructure, type LoadedSceneDocument, type LoadedSceneObject, MapControls, type MaterialKey, Materials, type Maybe, type MeshKey, Meshes, MineRenderData, type MineRenderDataManifest, type MineRenderDatasets, MineRenderError, MineRenderScene, type MineRenderSceneOptions, MineRenderWorld, type MineRenderWorldOptions, type MinecraftAsset, MinecraftCubeTexture, MinecraftFaceUV, type MinecraftTextureMeta, type Model, ModelCulling, type ModelDisplay, type ModelElement, type ModelFaces, ModelGenerator, ModelMerger, ModelObject, type ModelObjectOptions, ModelTextures, Models, type MultiBlockBlock, type MultiBlockEntity, type MultiBlockStructure, type MultipartCondition, type NBTAsset, NBTHelper, OrbitControls, type PackFormat, PackFormats, PackMetadata, PersistentCache, PlayerHeadTextures, type PositionedGuiGlyph, type QuadArray, type RawImageKey, type RenameKind, Renames, type RenderOptions, Renderer, type RendererControls, type RendererFrame, type RendererOptions, type RendererSurface, type RequestConfig, RequestError, type RequestResponse, Requests, type ResolvedBlockEntity, type ResolvedMineRenderData, type ResponseParser, SCENE_DOCUMENT_MAX_BYTES, SKIN_PARTS, type SavedLightSample, type SceneBlockDefinition, type SceneDocument, SceneDocumentLoader, type SceneEntityDefinition, SceneExporter, type SceneGLTFExportOptions, type SceneGuiDefinition, type SceneGuiLayer, SceneInspector, type SceneItemContext, type SceneModelDefinition, SceneObject, type SceneObjectDefinition, type SceneObjectDefinitionBase, type SceneObjectOptions, type SceneSkinDefinition, type SceneSkinPosePart, SceneStats, SceneStatsDisplay, SchematicParser, type SchematicParserOptions, type SectionAtlasSize, type SectionFluidInput, type SectionFluidKind, type SectionFluids, type SectionGeometryInput, type SectionGeometryPage, type SectionLightData, SectionMesh, type SectionMeshEntry, type SectionMeshTemplate, SectionModels, type SectionTemplateData, SectionWorker, type Serializable, type SkinGeometries, SkinImage, SkinObject, type SkinObjectOptions, SkinPart, type SkinTexture, type SkinTextureCoordinates, SkinTextures, Skins, type SpecialItemPart, type SpecialItemRenderer, SpecialItems, SpongeSchematicParser, type StructureNBT, StructureParser, type TextureAsset, TextureAtlas, type TextureKey, TextureLoader, Textures, Ticker, type TickerFunction, TintColors, type Transformable, type TripleArray, UVMapper, type VideoExportOptions, VideoExporter, type WorldBlockIntersection, type WorldChunkSource, type WorldEntityIntersection, WorldStreamer, type WorldStreamerOptions, WrappedImage, addBox3WireframeToObject, addWireframeToMesh, addWireframeToObject, applyElementRotation, applyGenericRotation, axisToVec3, base64decode, base64encode, buildFluidQuads, buildSectionGeometry, capeTextureSizes, captureException, changeEvent, clampRotationDegrees, classicSkinGeometries, classicSkinTextureCoordinates, computeMorphedAttributes, copySectionLight, createCanvas, createFluidGeometry, createGuiTextGeometry, createGuiTextureGeometry, createImage, decodeSceneDocument, encodeSceneDocument, entityAnimationTime, estimateBytesUsed, fluidKindOf, getBlockFluidState, getFluidKind, interleaveAttributes, isAssetKey, isBasicAssetKey, isBlockObject, isDisposable, isDoubleArray, isEntityObject, isFlyControls, isGuiObject, isInstanceManager, isInstanceReference, isInstanceable, isInstancedMesh, isMesh, isMineRenderScene, isModelObject, isObject3D, isOrthographicCamera, isPerspectiveCamera, isQuadArray, isResourceLocation, isSceneObject, isTransformable, isTripleArray, isVector3, layoutGuiText, md5, mergeBufferAttributes, mergeBufferGeometries, mergeVertices, parseSceneDocument, prefix, probeImageSize, registerBrowserEnv, resolveBlockFluidState, resolveLegacyBlock, resolveLegacyBlockState, sampleEntityAnimation, sampleEntityKeyframes, sampleFluid, sampleSectionLight, sectionGeometryTransferables, serializeBoxGeometryKey, serializeImageKey, serializeMaterialKey, serializeMeshKey, serializeTextureKey, sha1, sha256, sha512, shutdown, sleep, slimSkinGeometries, slimSkinTextureCoordinates, timingEnd, timingStart, toDegrees, toRadians, toTrianglesDrawMode, trimCanvas, validateAnimationWeights, yieldToEventLoop };
|
|
4442
|
+
export { AXES, type AnimationFrame, type AnimationMeta, type AnimatorFunction, type AnvilChunk, type AnvilEntityChunk, type AnvilExternalChunkReader, type AnvilParseOptions, AnvilParser, type AnvilRegion, type AnvilRegionReader, AnvilWorldSource, type AnvilWorldSourceOptions, ArchiveAssetSource, type ArchiveAssetSourceOptions, type ArchiveEntry, type ArchiveProxy, AssetKey, AssetLoadError, AssetLoader, AssetParser, AssetSource, type AssetType, Assets, Axis, BUILTIN_ENTITY, BUILTIN_GENERATED, type BannerPattern, type BannerPatternDraw, BannerPatterns, BasicAssetKey, type BasicMinecraftAsset, BatchedExecutor, type BedrockBone, type BedrockCube, type BedrockEntityDescription, type BedrockEntityFile, type BedrockGeometry, type BedrockGeometryFile, type BinaryAsset, type Biome, type BiomeColorKind, Biomes, type BitmapFont, type BitmapGlyph, type Block, BlockEntities, type BlockEntityEntry, type BlockEntityIndex, type BlockEntityPart, type BlockEntityRotation, type BlockFluidState, type BlockInfo, type BlockModel, type BlockModelTextures, BlockObject, type BlockObjectOptions, type BlockState, type BlockStateMultipart, type BlockStateProperties, type BlockStateProperty, type BlockStatePropertyDefaults, type BlockStatePropertyValue, BlockStateResolver, type BlockStateVariant, type BlockStateVariants, BlockStates, BlockTints, type BoxGeometryKey, BrowserArchiveProxy, BrowserCache, BrowserEnv, CUBE_FACES, CUBE_FACE_OFFSETS, type CacheKey, Caching, type CameraOptions, CanvasImage, type CapeLayout, Chunk, ChunkData, Colormaps, type CompatCanvas, type CompatImage, type ComposerOptions, type ControlsMode, type ControlsOptions, CubeFace, CubeFaceIndex, DEFAULT_ELEMENTS, DEFAULT_NAMESPACE, DEFAULT_ROOT, DEFAULT_UV, DISPLAY_POSITIONS, DYE_COLORS, type DebugOptions, type DecoratedPotSide, DecoratedPots, type DeepPartial, DefaultBlockStates, DisplayPosition, DisplayTransforms, type Disposable, type DoubleArray, type DyeColor, ENTITY_ANIMATION_CHANNELS, type ElementFace, type ElementRotation, Entities, type EntityAnimation, type EntityAnimationBone, type EntityAnimationChannel, type EntityAnimationFile, type EntityAnimationKeyframe, type EntityAnimationOptions, EntityAnimationPlayer, type EntityAnimationPose, type EntityLayer, type EntityModel, type EntityModelCube, type EntityModelFile, type EntityModelLayer, type EntityModelOptions, type EntityModelPart, type EntityModelPass, EntityObject, type EntityObjectOptions, type EntityRenderMode, type EntityTransformOp, Env, type EnvProvider, type ExtractableImageData, type FluidKind, FluidModelObject, type FluidQuads, type FluidRules, type FluidSample, type FluidSampler, type FlyAction, FlyControls, type FlyControlsEventMap, Fonts, type FrameCallback, type FromTo, GUI_CONTAINER_LAYOUTS, Geometries, type GuiBookButtonState, type GuiBookOptions, type GuiBossBarColor, type GuiBossBarOptions, type GuiContainerType, GuiHelper, type GuiItemLayer, type GuiLayer, GuiLight, GuiObject, type GuiObjectOptions, type GuiRecipe, type GuiRecipeIngredient, type GuiRecipeOptions, type GuiSpriteScaling, type GuiText, type GuiTextLayer, type GuiTextLayout, type GuiTextOptions, type GuiTextRun, type GuiTextStyle, type GuiTextureLayer, type GuiTooltipOptions, HostedAssetSource, type IModelTextures, ITEM_GENERATED, type ImageInfo, ImageLoader, type ImageSizeInfo, InstanceManager, InstanceReference, type Instanceable, ItemDefaults, ItemGlint, type ItemModel, type ItemModelContext, type ItemModelTextures, type ItemTintColor, type ItemTintSource, ItemTints, type ListAsset, LitematicaParser, type LitematicaRegion, type LitematicaStructure, type LoadedSceneDocument, type LoadedSceneObject, type LogHandler, type LogLevel, type LogThreshold, type Logger, Logging, type LoggingOptions, MapControls, type MaterialKey, Materials, type Maybe, type MeshKey, Meshes, MineRenderData, type MineRenderDataManifest, type MineRenderDatasets, MineRenderError, MineRenderScene, type MineRenderSceneOptions, MineRenderWorld, type MineRenderWorldOptions, type MinecraftAsset, MinecraftCubeTexture, MinecraftFaceUV, type MinecraftTextureMeta, type Model, ModelCulling, type ModelDisplay, type ModelElement, type ModelFaces, ModelGenerator, ModelMerger, ModelObject, type ModelObjectOptions, ModelTextures, Models, type MultiBlockBlock, type MultiBlockEntity, type MultiBlockStructure, type MultipartCondition, type NBTAsset, NBTHelper, OrbitControls, type PackFormat, PackFormats, PackMetadata, PersistentCache, PlayerHeadTextures, type PositionedGuiGlyph, type QuadArray, type RawImageKey, type RenameKind, Renames, type RenderOptions, Renderer, type RendererControls, type RendererFrame, type RendererOptions, type RendererSurface, type RequestConfig, RequestError, type RequestResponse, Requests, type ResolvedBlockEntity, type ResolvedMineRenderData, type ResponseParser, SCENE_DOCUMENT_MAX_BYTES, SKIN_PARTS, type SavedLightSample, type SceneBlockDefinition, type SceneDocument, SceneDocumentLoader, type SceneEntityDefinition, SceneExporter, type SceneGLTFExportOptions, type SceneGuiDefinition, type SceneGuiLayer, SceneInspector, type SceneItemContext, type SceneModelDefinition, SceneObject, type SceneObjectDefinition, type SceneObjectDefinitionBase, type SceneObjectOptions, type SceneSkinDefinition, type SceneSkinPosePart, SceneStats, SceneStatsDisplay, SchematicParser, type SchematicParserOptions, type SectionAtlasSize, type SectionFluidInput, type SectionFluidKind, type SectionFluids, type SectionGeometryInput, type SectionGeometryPage, type SectionLightData, SectionMesh, type SectionMeshEntry, type SectionMeshTemplate, SectionModels, type SectionTemplateData, SectionWorker, type Serializable, type SkinGeometries, SkinImage, SkinObject, type SkinObjectOptions, SkinPart, type SkinTexture, type SkinTextureCoordinates, SkinTextures, Skins, type SpecialItemPart, type SpecialItemRenderer, SpecialItems, SpongeSchematicParser, type StructureNBT, StructureParser, type TextureAsset, TextureAtlas, type TextureKey, TextureLoader, Textures, Ticker, type TickerFunction, TintColors, type Transformable, type TripleArray, UVMapper, type VideoExportOptions, VideoExporter, type WorldBlockIntersection, type WorldChunkSource, type WorldEntityIntersection, WorldStreamer, type WorldStreamerOptions, WrappedImage, addBox3WireframeToObject, addWireframeToMesh, addWireframeToObject, applyElementRotation, applyGenericRotation, axisToVec3, base64decode, base64encode, buildFluidQuads, buildSectionGeometry, capeTextureSizes, captureException, changeEvent, clampRotationDegrees, classicSkinGeometries, classicSkinTextureCoordinates, computeMorphedAttributes, copySectionLight, createCanvas, createFluidGeometry, createGuiTextGeometry, createGuiTextureGeometry, createImage, decodeSceneDocument, encodeSceneDocument, entityAnimationTime, estimateBytesUsed, fluidKindOf, getBlockFluidState, getFluidKind, interleaveAttributes, isAssetKey, isBasicAssetKey, isBlockObject, isDisposable, isDoubleArray, isEntityObject, isFlyControls, isGuiObject, isInstanceManager, isInstanceReference, isInstanceable, isInstancedMesh, isMesh, isMineRenderScene, isModelObject, isObject3D, isOrthographicCamera, isPerspectiveCamera, isQuadArray, isResourceLocation, isSceneObject, isTransformable, isTripleArray, isVector3, layoutGuiText, logger, md5, mergeBufferAttributes, mergeBufferGeometries, mergeVertices, parseSceneDocument, prefix, probeImageSize, registerBrowserEnv, resolveBlockFluidState, resolveLegacyBlock, resolveLegacyBlockState, sampleEntityAnimation, sampleEntityKeyframes, sampleFluid, sampleSectionLight, sectionGeometryTransferables, serializeBoxGeometryKey, serializeImageKey, serializeMaterialKey, serializeMeshKey, serializeTextureKey, sha1, sha256, sha512, shutdown, sleep, slimSkinGeometries, slimSkinTextureCoordinates, timingEnd, timingStart, toDegrees, toRadians, toTrianglesDrawMode, trimCanvas, validateAnimationWeights, yieldToEventLoop };
|
|
@@ -3,9 +3,9 @@ import { Raycaster, Vector2 } from "three";
|
|
|
3
3
|
import { isSceneObject } from "../renderer/SceneObject.mjs";
|
|
4
4
|
import { toDegrees, toRadians } from "../util/util.mjs";
|
|
5
5
|
import { isTransformable } from "../Transformable.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { logger } from "../util/log.mjs";
|
|
7
7
|
import { isMesh } from "../util/three.mjs";
|
|
8
|
-
var
|
|
8
|
+
var log = logger("SceneInspector");
|
|
9
9
|
var help = "<span>Ctrl/Cmd+Click to Select<br/></span><br/>";
|
|
10
10
|
var SceneInspector = class {
|
|
11
11
|
constructor(renderer) {
|
|
@@ -99,7 +99,7 @@ var SceneInspector = class {
|
|
|
99
99
|
}
|
|
100
100
|
selectObject(targetObject, targetIntersection, instance = this.getIntersectionInstance(targetIntersection)) {
|
|
101
101
|
this.selectedObject = targetObject;
|
|
102
|
-
|
|
102
|
+
log.debug("selected", targetObject);
|
|
103
103
|
this.redraw(targetObject, targetIntersection, instance);
|
|
104
104
|
}
|
|
105
105
|
redraw(targetObject, targetIntersection, instance) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/inspector/SceneInspector.ts"],"sourcesContent":["import { Renderer } from \"../renderer/Renderer\";\nimport { Intersection, Mesh, Object3D, Raycaster, Vector2 } from \"three\";\nimport { isSceneObject, SceneObject } from \"../renderer/SceneObject\";\nimport { Maybe, toDegrees, toRadians } from \"../util/util\";\nimport { isTransformable, Transformable } from \"../Transformable\";\nimport { prefix } from \"../util/log\";\nimport { isMesh } from \"../util/three\";\nimport { TextureAtlas } from \"../texture\";\nimport { InstanceReference } from \"../instance/InstanceReference\";\n\nconst p = prefix(\"SceneInspector\");\n\nconst help = \"<span>Ctrl/Cmd+Click to Select<br/></span><br/>\";\n\n/**\n * Browser controls for inspecting and editing scene objects with Ctrl/Cmd-click selection.\n * Construct it with a renderer, attach its panels with {@link appendTo}, and call {@link dispose} when finished.\n */\nexport class SceneInspector {\n\n readonly objectInfoContainer: HTMLDivElement;\n readonly objectControlsContainer: HTMLDivElement;\n\n protected readonly raycaster: Raycaster;\n private readonly mouse: Vector2 = new Vector2();\n\n private selectedObject?: Object3D;\n private pointer?: PointerEvent;\n private readonly listeners = new AbortController();\n\n constructor(readonly renderer: Renderer) {\n this.objectInfoContainer = document.createElement(\"div\");\n this.objectControlsContainer = document.createElement(\"div\");\n\n this.raycaster = new Raycaster();\n\n this.init();\n }\n\n protected init() {\n this.objectInfoContainer.classList.add(\"minerender-inspector\", \"minerender-object-info\");\n this.objectControlsContainer.classList.add(\"minerender-inspector\", \"minerender-object-controls\");\n\n this.objectInfoContainer.innerHTML = help;\n\n const canvas = this.renderer.renderer.domElement;\n const options = { signal: this.listeners.signal };\n canvas.addEventListener(\"pointerdown\", event => {\n this.pointer = event.button === 0 && (event.ctrlKey || event.metaKey) ? event : undefined;\n }, options);\n canvas.addEventListener(\"pointermove\", event => {\n if (this.pointer?.pointerId === event.pointerId\n && Math.hypot(event.clientX - this.pointer.clientX, event.clientY - this.pointer.clientY) > 5) {\n this.pointer = undefined;\n }\n }, options);\n canvas.addEventListener(\"pointerup\", event => {\n const start = this.pointer;\n this.pointer = undefined;\n if (start?.pointerId === event.pointerId\n && Math.hypot(event.clientX - start.clientX, event.clientY - start.clientY) <= 5) {\n this.onClick(event);\n }\n }, options);\n canvas.addEventListener(\"pointercancel\", () => { this.pointer = undefined; }, options);\n canvas.addEventListener(\"pointerleave\", () => { this.pointer = undefined; }, options);\n canvas.addEventListener(\"contextmenu\", event => {\n // macOS Ctrl+click opens a context menu instead of firing click.\n if (this.pointer?.ctrlKey) event.preventDefault();\n }, options);\n }\n\n public dispose(): void {\n this.listeners.abort();\n this.pointer = undefined;\n this.selectedObject = undefined;\n this.objectInfoContainer.remove();\n this.objectControlsContainer.remove();\n }\n\n findMeshChildren(from: Object3D, out: Mesh[] = []) {\n if (!from.visible) return out;\n for (let c of from.children) {\n if (c.visible && isMesh(c)) {\n out.push(c);\n }\n this.findMeshChildren(c, out);\n }\n return out;\n }\n\n onClick(event: MouseEvent) {\n const canvas = this.renderer.renderer.domElement;\n if (event.target !== canvas || event.button !== 0 || !(event.ctrlKey || event.metaKey)) return;\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left, y = event.clientY - rect.top;\n if (rect.width <= 0 || rect.height <= 0 || x < 0 || y < 0 || x >= rect.width || y >= rect.height) return;\n this.mouse.set(x / rect.width * 2 - 1, 1 - y / rect.height * 2);\n this.renderer.camera.updateWorldMatrix(true, false);\n this.renderer.scene.updateMatrixWorld(true);\n this.raycaster.setFromCamera(this.mouse, this.renderer.camera);\n this.handleRaycasterObjects(this.raycaster.intersectObjects(this.findMeshChildren(this.renderer.scene), false));\n }\n\n appendTo(el: HTMLElement) {\n el.append(this.objectInfoContainer);\n el.append(this.objectControlsContainer);\n }\n\n protected handleRaycasterObjects(intersections: Intersection[]) {\n const hit = intersections[0];\n if (!hit) return;\n const instance = this.getIntersectionInstance(hit);\n this.selectObject(instance?.instanceable ?? hit.object, hit, instance);\n }\n\n private getIntersectionInstance(hit?: Intersection): Maybe<InstanceReference<SceneObject>> {\n if (hit?.instanceId === undefined) return undefined;\n for (let parent = hit.object.parent; parent; parent = parent.parent) {\n if (isSceneObject(parent)) {\n const instance = parent.getInstanceReference(hit.object, hit.instanceId);\n if (instance) return instance;\n }\n }\n return undefined;\n }\n\n public selectObject(targetObject: Object3D, targetIntersection?: Intersection,\n instance = this.getIntersectionInstance(targetIntersection)) {\n this.selectedObject = targetObject;\n console.log(p, \"selected\", targetObject);\n this.redraw(targetObject, targetIntersection, instance);\n }\n\n protected redraw(targetObject: Object3D, targetIntersection?: Intersection, instance?: InstanceReference<SceneObject>) {\n this.objectInfoContainer.innerHTML = help;\n if (targetIntersection) {\n this.addInfoLine(\"Distance\", \"D\", targetIntersection.distance);\n this.addInfoLine(\"Instance #\", \"I\", targetIntersection.instanceId);\n }\n this.addInfoLine(\"Type\", \"T\", targetObject.constructor.name + \"/\" + targetObject.type);\n this.addInfoLine(\"Name\", \"N\", targetObject.name);\n if (targetObject.parent) {\n this.addInfoLine(\"Parent\", \"P\", targetObject.parent.constructor.name);\n if (isSceneObject(targetObject.parent)) {\n //...\n }\n }\n\n const atlas = 'atlas' in targetObject ? targetObject['atlas'] as Maybe<TextureAtlas> : undefined;\n if (atlas?.image.canvas) {\n // const img = document.createElement(\"img\");\n const img = atlas.image.canvas as HTMLCanvasElement;\n // img.src = atlas.image.dataUrl;\n img.style.width = \"100px\";\n img.style.height = \"100px\";\n img.style.float = \"right\";\n img.style.imageRendering = \"pixelated\";\n this.objectInfoContainer.prepend(img);\n }\n\n this.objectControlsContainer.innerHTML = '';\n this.addControls(targetObject, targetIntersection, instance);\n }\n\n protected addControls(object: Object3D, intersection?: Intersection, instance?: InstanceReference<SceneObject>) {\n const container = document.createElement(\"div\");\n\n container.append(this.separator(\"Select Parent/Child\"));\n\n if (object.parent) {\n container.append(this.buttonControl(\"Select Parent \" + object.parent.constructor.name + \" \" + object.parent.name, \"P\", () => {\n this.selectObject(object.parent!, intersection, instance);\n }));\n }\n if (object.children.length > 0) {\n let i = 1;\n for (let child of object.children) {\n container.append(this.buttonControl(\"Select Child \" + child.constructor.name + \" \" + child.name, \"C\" + (i++), () => {\n this.selectObject(child, intersection, instance);\n }));\n }\n }\n container.append(this.separator());\n\n const selectedInstance = instance && (object === instance.instanceable || object === intersection?.object) ? instance : undefined;\n if (!selectedInstance) {\n container.append(this.toggleControl(\"Visibility\", \"V\", object.visible, v => object.visible = v));\n }\n\n container.append(this.separator(\"Mesh\"))\n this.addObjectControls(object, intersection, container, selectedInstance);\n container.append(this.separator());\n\n\n this.objectControlsContainer.append(container);\n }\n\n\n protected addInfoLine(name: string, id: string, value: any): HTMLElement {\n const el = document.createElement(\"span\");\n el.innerText = `${ id }: ${ value }`;\n el.setAttribute(\"title\", name);\n\n this.objectInfoContainer.append(el);\n this.objectInfoContainer.append(document.createElement(\"br\"));\n\n return el;\n }\n\n\n protected addObjectControls(target: Object3D, intersection: Maybe<Intersection>, container: HTMLElement, instance?: InstanceReference<SceneObject>) {\n\n const posRange = 16 * 16;\n const rotRange = 360;\n const scaleRange = 4;\n\n const transform = instance ?? (isTransformable(target) ? target : undefined);\n if (transform) {\n const parent: Transformable = transform;\n\n container.append(this.separator(\"Position\"))\n\n let pos = parent.getPosition();\n container.append(this.rangeControl(\"X Position\", \"X\", pos.x - posRange, pos.x + posRange, pos.x, 1, v => {\n pos = parent.getPosition();\n pos.x = v;\n parent.setPosition(pos)\n }));\n container.append(this.rangeControl(\"Y Position\", \"Y\", pos.y - posRange, pos.y + posRange, pos.y, 1, v => {\n pos = parent.getPosition();\n pos.y = v;\n parent.setPosition(pos)\n }));\n container.append(this.rangeControl(\"Z Position\", \"Z\", pos.z - posRange, pos.z + posRange, pos.z, 1, v => {\n pos = parent.getPosition();\n pos.z = v;\n parent.setPosition(pos)\n }));\n\n container.append(this.separator(\"Rotation\"))\n\n let rot = parent.getRotation();\n container.append(this.rangeControl(\"X Rotation\", \"X\", 0, rotRange, Math.round(toDegrees(rot.x)), 1, v => {\n rot = parent.getRotation();\n rot.x = toRadians(v);\n parent.setRotation(rot);\n }));\n container.append(this.rangeControl(\"Y Rotation\", \"Y\", 0, rotRange, Math.round(toDegrees(rot.y)), 1, v => {\n rot = parent.getRotation();\n rot.y = toRadians(v);\n parent.setRotation(rot);\n }));\n container.append(this.rangeControl(\"Z Rotation\", \"Z\", 0, rotRange, Math.round(toDegrees(rot.z)), 1, v => {\n rot = parent.getRotation();\n rot.z = toRadians(v);\n parent.setRotation(rot);\n }));\n\n container.append(this.separator(\"Scale\"))\n\n let scl = parent.getScale();\n container.append(this.rangeControl(\"X Scale\", \"X\", 0, scaleRange, scl.x, 0.1, v => {\n scl = parent.getScale();\n scl.x = v;\n parent.setScale(scl);\n }));\n container.append(this.rangeControl(\"Y Scale\", \"Y\", 0, scaleRange, scl.y, 0.1, v => {\n scl = parent.getScale();\n scl.y = v;\n parent.setScale(scl);\n }));\n container.append(this.rangeControl(\"Z Scale\", \"Z\", 0, scaleRange, scl.z, 0.1, v => {\n scl = parent.getScale();\n scl.z = v;\n parent.setScale(scl);\n }));\n } else {\n container.append(this.separator(\"Position\"))\n\n container.append(this.rangeControl(\"X Position\", \"X\", -posRange, posRange, target.position.x, 1, v => target!.position.setX(v)));\n container.append(this.rangeControl(\"Y Position\", \"Y\", -posRange, posRange, target.position.y, 1, v => target!.position.setY(v)));\n container.append(this.rangeControl(\"Z Position\", \"Z\", -posRange, posRange, target.position.z, 1, v => target!.position.setZ(v)));\n\n container.append(this.separator(\"Rotation\"))\n\n container.append(this.rangeControl(\"X Rotation\", \"X\", 0, rotRange, toDegrees(target.rotation.x), 1, v => target!.rotation.x = toRadians(v)));\n container.append(this.rangeControl(\"Y Rotation\", \"Y\", 0, rotRange, toDegrees(target.rotation.y), 1, v => target!.rotation.y = toRadians(v)));\n container.append(this.rangeControl(\"Z Rotation\", \"Z\", 0, rotRange, toDegrees(target.rotation.z), 1, v => target!.rotation.z = toRadians(v)));\n\n container.append(this.separator(\"Scale\"))\n\n container.append(this.rangeControl(\"X Scale\", \"X\", 0, scaleRange, target.scale.x, 0.1, v => target!.scale.x = v));\n container.append(this.rangeControl(\"Y Scale\", \"Y\", 0, scaleRange, target.scale.y, 0.1, v => target!.scale.y = v));\n container.append(this.rangeControl(\"Z Scale\", \"Z\", 0, scaleRange, target.scale.z, 0.1, v => target!.scale.z = v));\n }\n }\n\n protected buttonControl(name: string, id: string, click: () => void): HTMLElement {\n const button = document.createElement(\"button\");\n button.innerText = id;\n button.setAttribute(\"title\", name);\n button.addEventListener(\"click\", click);\n return button;\n }\n\n protected selectControl(name: string, id: string, options: string[], change: (v: string) => void): HTMLElement {\n const label = document.createElement(\"label\");\n label.innerText = id;\n label.setAttribute(\"title\", name);\n\n const select = document.createElement(\"select\");\n options.forEach(o => {\n const opt = document.createElement(\"option\");\n opt.value = o;\n opt.innerText = o;\n select.append(opt);\n });\n select.addEventListener(\"change\", e => {\n change(options[select.selectedIndex]);\n });\n select.selectedIndex = 0;\n label.append(select);\n label.append(document.createElement(\"br\"));\n return label;\n }\n\n protected toggleControl(name: string, id: string, val: boolean, change: (v: boolean) => void): HTMLElement {\n const label = document.createElement(\"label\");\n label.innerText = id;\n label.setAttribute(\"title\", name);\n\n const toggle = document.createElement(\"input\");\n toggle.setAttribute(\"type\", \"checkbox\");\n toggle.checked = val; //TODO: instance\n toggle.addEventListener(\"change\", e => {\n change(toggle.checked);\n this.renderer.scene.dirty = true;\n });\n label.append(toggle);\n label.append(document.createElement(\"br\"));\n return label;\n }\n\n protected rangeControl(name: string, id: string, min: number, max: number, val: number, step: number, change: (v: number) => void): HTMLElement {\n const label = document.createElement(\"label\");\n const labelText = document.createElement(\"span\");\n label.append(labelText);\n label.setAttribute(\"title\", name);\n labelText.style.width = \"18%\";\n labelText.style.display = \"inline-block\";\n\n const range = document.createElement(\"input\");\n range.setAttribute(\"type\", \"range\");\n range.style.width = \"80%\";\n range.max = `${ max }`;\n range.min = `${ min }`;\n range.step = `${ step }`;\n range.value = `${ val }`;\n labelText.innerText = `${ id } (${ range.value })`;\n const onChange = () => {\n change(parseFloat(range.value));\n this.renderer.scene.dirty = true;\n labelText.innerText = `${ id } (${ range.value })`\n };\n // range.addEventListener(\"change\", onChange);\n range.addEventListener(\"input\", onChange);\n range.addEventListener(\"wheel\", e => {\n e.preventDefault();\n if (e.deltaY < 0) {\n range.value = `${ parseFloat(range.value) + step }`;\n onChange();\n } else if (e.deltaY > 0) {\n range.value = `${ parseFloat(range.value) - step }`;\n onChange();\n }\n })\n label.append(range);\n label.append(document.createElement(\"br\"));\n return label;\n }\n\n protected separator(name?: string): HTMLElement {\n const span = document.createElement(\"span\");\n if (name) {\n span.innerText = name;\n }\n span.prepend(document.createElement(\"br\"));\n span.append(document.createElement(\"br\"));\n return span;\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/inspector/SceneInspector.ts"],"sourcesContent":["import { Renderer } from \"../renderer/Renderer\";\nimport { Intersection, Mesh, Object3D, Raycaster, Vector2 } from \"three\";\nimport { isSceneObject, SceneObject } from \"../renderer/SceneObject\";\nimport { Maybe, toDegrees, toRadians } from \"../util/util\";\nimport { isTransformable, Transformable } from \"../Transformable\";\nimport { logger } from \"../util/log\";\nimport { isMesh } from \"../util/three\";\nimport { TextureAtlas } from \"../texture\";\nimport { InstanceReference } from \"../instance/InstanceReference\";\n\nconst log = logger(\"SceneInspector\");\n\nconst help = \"<span>Ctrl/Cmd+Click to Select<br/></span><br/>\";\n\n/**\n * Browser controls for inspecting and editing scene objects with Ctrl/Cmd-click selection.\n * Construct it with a renderer, attach its panels with {@link appendTo}, and call {@link dispose} when finished.\n */\nexport class SceneInspector {\n\n readonly objectInfoContainer: HTMLDivElement;\n readonly objectControlsContainer: HTMLDivElement;\n\n protected readonly raycaster: Raycaster;\n private readonly mouse: Vector2 = new Vector2();\n\n private selectedObject?: Object3D;\n private pointer?: PointerEvent;\n private readonly listeners = new AbortController();\n\n constructor(readonly renderer: Renderer) {\n this.objectInfoContainer = document.createElement(\"div\");\n this.objectControlsContainer = document.createElement(\"div\");\n\n this.raycaster = new Raycaster();\n\n this.init();\n }\n\n protected init() {\n this.objectInfoContainer.classList.add(\"minerender-inspector\", \"minerender-object-info\");\n this.objectControlsContainer.classList.add(\"minerender-inspector\", \"minerender-object-controls\");\n\n this.objectInfoContainer.innerHTML = help;\n\n const canvas = this.renderer.renderer.domElement;\n const options = { signal: this.listeners.signal };\n canvas.addEventListener(\"pointerdown\", event => {\n this.pointer = event.button === 0 && (event.ctrlKey || event.metaKey) ? event : undefined;\n }, options);\n canvas.addEventListener(\"pointermove\", event => {\n if (this.pointer?.pointerId === event.pointerId\n && Math.hypot(event.clientX - this.pointer.clientX, event.clientY - this.pointer.clientY) > 5) {\n this.pointer = undefined;\n }\n }, options);\n canvas.addEventListener(\"pointerup\", event => {\n const start = this.pointer;\n this.pointer = undefined;\n if (start?.pointerId === event.pointerId\n && Math.hypot(event.clientX - start.clientX, event.clientY - start.clientY) <= 5) {\n this.onClick(event);\n }\n }, options);\n canvas.addEventListener(\"pointercancel\", () => { this.pointer = undefined; }, options);\n canvas.addEventListener(\"pointerleave\", () => { this.pointer = undefined; }, options);\n canvas.addEventListener(\"contextmenu\", event => {\n // macOS Ctrl+click opens a context menu instead of firing click.\n if (this.pointer?.ctrlKey) event.preventDefault();\n }, options);\n }\n\n public dispose(): void {\n this.listeners.abort();\n this.pointer = undefined;\n this.selectedObject = undefined;\n this.objectInfoContainer.remove();\n this.objectControlsContainer.remove();\n }\n\n findMeshChildren(from: Object3D, out: Mesh[] = []) {\n if (!from.visible) return out;\n for (let c of from.children) {\n if (c.visible && isMesh(c)) {\n out.push(c);\n }\n this.findMeshChildren(c, out);\n }\n return out;\n }\n\n onClick(event: MouseEvent) {\n const canvas = this.renderer.renderer.domElement;\n if (event.target !== canvas || event.button !== 0 || !(event.ctrlKey || event.metaKey)) return;\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left, y = event.clientY - rect.top;\n if (rect.width <= 0 || rect.height <= 0 || x < 0 || y < 0 || x >= rect.width || y >= rect.height) return;\n this.mouse.set(x / rect.width * 2 - 1, 1 - y / rect.height * 2);\n this.renderer.camera.updateWorldMatrix(true, false);\n this.renderer.scene.updateMatrixWorld(true);\n this.raycaster.setFromCamera(this.mouse, this.renderer.camera);\n this.handleRaycasterObjects(this.raycaster.intersectObjects(this.findMeshChildren(this.renderer.scene), false));\n }\n\n appendTo(el: HTMLElement) {\n el.append(this.objectInfoContainer);\n el.append(this.objectControlsContainer);\n }\n\n protected handleRaycasterObjects(intersections: Intersection[]) {\n const hit = intersections[0];\n if (!hit) return;\n const instance = this.getIntersectionInstance(hit);\n this.selectObject(instance?.instanceable ?? hit.object, hit, instance);\n }\n\n private getIntersectionInstance(hit?: Intersection): Maybe<InstanceReference<SceneObject>> {\n if (hit?.instanceId === undefined) return undefined;\n for (let parent = hit.object.parent; parent; parent = parent.parent) {\n if (isSceneObject(parent)) {\n const instance = parent.getInstanceReference(hit.object, hit.instanceId);\n if (instance) return instance;\n }\n }\n return undefined;\n }\n\n public selectObject(targetObject: Object3D, targetIntersection?: Intersection,\n instance = this.getIntersectionInstance(targetIntersection)) {\n this.selectedObject = targetObject;\n log.debug(\"selected\", targetObject);\n this.redraw(targetObject, targetIntersection, instance);\n }\n\n protected redraw(targetObject: Object3D, targetIntersection?: Intersection, instance?: InstanceReference<SceneObject>) {\n this.objectInfoContainer.innerHTML = help;\n if (targetIntersection) {\n this.addInfoLine(\"Distance\", \"D\", targetIntersection.distance);\n this.addInfoLine(\"Instance #\", \"I\", targetIntersection.instanceId);\n }\n this.addInfoLine(\"Type\", \"T\", targetObject.constructor.name + \"/\" + targetObject.type);\n this.addInfoLine(\"Name\", \"N\", targetObject.name);\n if (targetObject.parent) {\n this.addInfoLine(\"Parent\", \"P\", targetObject.parent.constructor.name);\n if (isSceneObject(targetObject.parent)) {\n //...\n }\n }\n\n const atlas = 'atlas' in targetObject ? targetObject['atlas'] as Maybe<TextureAtlas> : undefined;\n if (atlas?.image.canvas) {\n // const img = document.createElement(\"img\");\n const img = atlas.image.canvas as HTMLCanvasElement;\n // img.src = atlas.image.dataUrl;\n img.style.width = \"100px\";\n img.style.height = \"100px\";\n img.style.float = \"right\";\n img.style.imageRendering = \"pixelated\";\n this.objectInfoContainer.prepend(img);\n }\n\n this.objectControlsContainer.innerHTML = '';\n this.addControls(targetObject, targetIntersection, instance);\n }\n\n protected addControls(object: Object3D, intersection?: Intersection, instance?: InstanceReference<SceneObject>) {\n const container = document.createElement(\"div\");\n\n container.append(this.separator(\"Select Parent/Child\"));\n\n if (object.parent) {\n container.append(this.buttonControl(\"Select Parent \" + object.parent.constructor.name + \" \" + object.parent.name, \"P\", () => {\n this.selectObject(object.parent!, intersection, instance);\n }));\n }\n if (object.children.length > 0) {\n let i = 1;\n for (let child of object.children) {\n container.append(this.buttonControl(\"Select Child \" + child.constructor.name + \" \" + child.name, \"C\" + (i++), () => {\n this.selectObject(child, intersection, instance);\n }));\n }\n }\n container.append(this.separator());\n\n const selectedInstance = instance && (object === instance.instanceable || object === intersection?.object) ? instance : undefined;\n if (!selectedInstance) {\n container.append(this.toggleControl(\"Visibility\", \"V\", object.visible, v => object.visible = v));\n }\n\n container.append(this.separator(\"Mesh\"))\n this.addObjectControls(object, intersection, container, selectedInstance);\n container.append(this.separator());\n\n\n this.objectControlsContainer.append(container);\n }\n\n\n protected addInfoLine(name: string, id: string, value: any): HTMLElement {\n const el = document.createElement(\"span\");\n el.innerText = `${ id }: ${ value }`;\n el.setAttribute(\"title\", name);\n\n this.objectInfoContainer.append(el);\n this.objectInfoContainer.append(document.createElement(\"br\"));\n\n return el;\n }\n\n\n protected addObjectControls(target: Object3D, intersection: Maybe<Intersection>, container: HTMLElement, instance?: InstanceReference<SceneObject>) {\n\n const posRange = 16 * 16;\n const rotRange = 360;\n const scaleRange = 4;\n\n const transform = instance ?? (isTransformable(target) ? target : undefined);\n if (transform) {\n const parent: Transformable = transform;\n\n container.append(this.separator(\"Position\"))\n\n let pos = parent.getPosition();\n container.append(this.rangeControl(\"X Position\", \"X\", pos.x - posRange, pos.x + posRange, pos.x, 1, v => {\n pos = parent.getPosition();\n pos.x = v;\n parent.setPosition(pos)\n }));\n container.append(this.rangeControl(\"Y Position\", \"Y\", pos.y - posRange, pos.y + posRange, pos.y, 1, v => {\n pos = parent.getPosition();\n pos.y = v;\n parent.setPosition(pos)\n }));\n container.append(this.rangeControl(\"Z Position\", \"Z\", pos.z - posRange, pos.z + posRange, pos.z, 1, v => {\n pos = parent.getPosition();\n pos.z = v;\n parent.setPosition(pos)\n }));\n\n container.append(this.separator(\"Rotation\"))\n\n let rot = parent.getRotation();\n container.append(this.rangeControl(\"X Rotation\", \"X\", 0, rotRange, Math.round(toDegrees(rot.x)), 1, v => {\n rot = parent.getRotation();\n rot.x = toRadians(v);\n parent.setRotation(rot);\n }));\n container.append(this.rangeControl(\"Y Rotation\", \"Y\", 0, rotRange, Math.round(toDegrees(rot.y)), 1, v => {\n rot = parent.getRotation();\n rot.y = toRadians(v);\n parent.setRotation(rot);\n }));\n container.append(this.rangeControl(\"Z Rotation\", \"Z\", 0, rotRange, Math.round(toDegrees(rot.z)), 1, v => {\n rot = parent.getRotation();\n rot.z = toRadians(v);\n parent.setRotation(rot);\n }));\n\n container.append(this.separator(\"Scale\"))\n\n let scl = parent.getScale();\n container.append(this.rangeControl(\"X Scale\", \"X\", 0, scaleRange, scl.x, 0.1, v => {\n scl = parent.getScale();\n scl.x = v;\n parent.setScale(scl);\n }));\n container.append(this.rangeControl(\"Y Scale\", \"Y\", 0, scaleRange, scl.y, 0.1, v => {\n scl = parent.getScale();\n scl.y = v;\n parent.setScale(scl);\n }));\n container.append(this.rangeControl(\"Z Scale\", \"Z\", 0, scaleRange, scl.z, 0.1, v => {\n scl = parent.getScale();\n scl.z = v;\n parent.setScale(scl);\n }));\n } else {\n container.append(this.separator(\"Position\"))\n\n container.append(this.rangeControl(\"X Position\", \"X\", -posRange, posRange, target.position.x, 1, v => target!.position.setX(v)));\n container.append(this.rangeControl(\"Y Position\", \"Y\", -posRange, posRange, target.position.y, 1, v => target!.position.setY(v)));\n container.append(this.rangeControl(\"Z Position\", \"Z\", -posRange, posRange, target.position.z, 1, v => target!.position.setZ(v)));\n\n container.append(this.separator(\"Rotation\"))\n\n container.append(this.rangeControl(\"X Rotation\", \"X\", 0, rotRange, toDegrees(target.rotation.x), 1, v => target!.rotation.x = toRadians(v)));\n container.append(this.rangeControl(\"Y Rotation\", \"Y\", 0, rotRange, toDegrees(target.rotation.y), 1, v => target!.rotation.y = toRadians(v)));\n container.append(this.rangeControl(\"Z Rotation\", \"Z\", 0, rotRange, toDegrees(target.rotation.z), 1, v => target!.rotation.z = toRadians(v)));\n\n container.append(this.separator(\"Scale\"))\n\n container.append(this.rangeControl(\"X Scale\", \"X\", 0, scaleRange, target.scale.x, 0.1, v => target!.scale.x = v));\n container.append(this.rangeControl(\"Y Scale\", \"Y\", 0, scaleRange, target.scale.y, 0.1, v => target!.scale.y = v));\n container.append(this.rangeControl(\"Z Scale\", \"Z\", 0, scaleRange, target.scale.z, 0.1, v => target!.scale.z = v));\n }\n }\n\n protected buttonControl(name: string, id: string, click: () => void): HTMLElement {\n const button = document.createElement(\"button\");\n button.innerText = id;\n button.setAttribute(\"title\", name);\n button.addEventListener(\"click\", click);\n return button;\n }\n\n protected selectControl(name: string, id: string, options: string[], change: (v: string) => void): HTMLElement {\n const label = document.createElement(\"label\");\n label.innerText = id;\n label.setAttribute(\"title\", name);\n\n const select = document.createElement(\"select\");\n options.forEach(o => {\n const opt = document.createElement(\"option\");\n opt.value = o;\n opt.innerText = o;\n select.append(opt);\n });\n select.addEventListener(\"change\", e => {\n change(options[select.selectedIndex]);\n });\n select.selectedIndex = 0;\n label.append(select);\n label.append(document.createElement(\"br\"));\n return label;\n }\n\n protected toggleControl(name: string, id: string, val: boolean, change: (v: boolean) => void): HTMLElement {\n const label = document.createElement(\"label\");\n label.innerText = id;\n label.setAttribute(\"title\", name);\n\n const toggle = document.createElement(\"input\");\n toggle.setAttribute(\"type\", \"checkbox\");\n toggle.checked = val; //TODO: instance\n toggle.addEventListener(\"change\", e => {\n change(toggle.checked);\n this.renderer.scene.dirty = true;\n });\n label.append(toggle);\n label.append(document.createElement(\"br\"));\n return label;\n }\n\n protected rangeControl(name: string, id: string, min: number, max: number, val: number, step: number, change: (v: number) => void): HTMLElement {\n const label = document.createElement(\"label\");\n const labelText = document.createElement(\"span\");\n label.append(labelText);\n label.setAttribute(\"title\", name);\n labelText.style.width = \"18%\";\n labelText.style.display = \"inline-block\";\n\n const range = document.createElement(\"input\");\n range.setAttribute(\"type\", \"range\");\n range.style.width = \"80%\";\n range.max = `${ max }`;\n range.min = `${ min }`;\n range.step = `${ step }`;\n range.value = `${ val }`;\n labelText.innerText = `${ id } (${ range.value })`;\n const onChange = () => {\n change(parseFloat(range.value));\n this.renderer.scene.dirty = true;\n labelText.innerText = `${ id } (${ range.value })`\n };\n // range.addEventListener(\"change\", onChange);\n range.addEventListener(\"input\", onChange);\n range.addEventListener(\"wheel\", e => {\n e.preventDefault();\n if (e.deltaY < 0) {\n range.value = `${ parseFloat(range.value) + step }`;\n onChange();\n } else if (e.deltaY > 0) {\n range.value = `${ parseFloat(range.value) - step }`;\n onChange();\n }\n })\n label.append(range);\n label.append(document.createElement(\"br\"));\n return label;\n }\n\n protected separator(name?: string): HTMLElement {\n const span = document.createElement(\"span\");\n if (name) {\n span.innerText = name;\n }\n span.prepend(document.createElement(\"br\"));\n span.append(document.createElement(\"br\"));\n return span;\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/instance/InstanceManager.ts
|
|
2
|
-
import {
|
|
3
|
-
var
|
|
2
|
+
import { logger } from "../util/log.mjs";
|
|
3
|
+
var log = logger("InstanceManager");
|
|
4
4
|
var InstanceManager = class {
|
|
5
5
|
constructor() {
|
|
6
6
|
this.isInstanceManager = true;
|
|
@@ -9,7 +9,7 @@ var InstanceManager = class {
|
|
|
9
9
|
/** Allocates a new placement of a cached model, or returns `undefined` if the key is unknown. */
|
|
10
10
|
async get(key) {
|
|
11
11
|
if (key in this.instanceCache) {
|
|
12
|
-
|
|
12
|
+
log.debug("key in cache", key);
|
|
13
13
|
return (await this.instanceCache[key]).nextInstance();
|
|
14
14
|
}
|
|
15
15
|
return void 0;
|
|
@@ -19,7 +19,7 @@ var InstanceManager = class {
|
|
|
19
19
|
if (key in this.instanceCache) {
|
|
20
20
|
return await this.get(key);
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
log.debug("key not in cache", key);
|
|
23
23
|
const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
|
|
24
24
|
this.instanceCache[key] = pending;
|
|
25
25
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/instance/InstanceManager.ts"],"sourcesContent":["import { InstanceReference } from \"./InstanceReference\";\nimport { SceneObject } from \"../renderer/SceneObject\";\nimport { Maybe } from \"../util/util\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../src/instance/InstanceManager.ts"],"sourcesContent":["import { InstanceReference } from \"./InstanceReference\";\nimport { SceneObject } from \"../renderer/SceneObject\";\nimport { Maybe } from \"../util/util\";\nimport { logger } from \"../util/log\";\n\nconst log = logger(\"InstanceManager\");\n\n/** Shares initialized model objects by cache key and allocates references to their placements. */\nexport class InstanceManager {\n\n public readonly isInstanceManager: true = true;\n\n protected readonly instanceCache: { [key: string]: Promise<InstanceReference<SceneObject>>; } = {};\n\n constructor() {\n }\n\n /** Allocates a new placement of a cached model, or returns `undefined` if the key is unknown. */\n public async get<T extends SceneObject>(key: string): Promise<Maybe<InstanceReference<T>>> {\n if (key in this.instanceCache) {\n log.debug(\"key in cache\", key)\n // create next instance of existing object\n return (await this.instanceCache[key]).nextInstance() as InstanceReference<T>;\n }\n return undefined;\n }\n\n /** Allocates a placement, calling the supplier once when the shared model is first needed. */\n public async getOrCreate<T extends SceneObject>(key: string, supplier: () => T | Promise<T>): Promise<InstanceReference<T>> {\n if (key in this.instanceCache) {\n return await (this.get<T>(key)) as InstanceReference<T>;\n }\n log.debug(\"key not in cache\", key)\n const pending = Promise.resolve().then(supplier).then(obj => obj.nextInstance());\n this.instanceCache[key] = pending;\n try {\n return await pending as InstanceReference<T>;\n } catch (error) {\n if (this.instanceCache[key] === pending) {\n delete this.instanceCache[key];\n }\n throw error;\n }\n }\n\n /** Forgets cached models without disposing them or releasing their existing placements. */\n public reset() {\n for (let instanceCacheKey in this.instanceCache) {\n delete this.instanceCache[instanceCacheKey];\n }\n }\n\n\n}\n\nexport function isInstanceManager(obj: any): obj is InstanceManager {\n return (<InstanceManager>obj).isInstanceManager;\n}\n"],"mappings":";AAGA,SAAS,cAAc;AAEvB,IAAM,MAAM,OAAO,iBAAiB;AAG7B,IAAM,kBAAN,MAAsB;AAAA,EAMzB,cAAc;AAJd,SAAgB,oBAA0B;AAE1C,SAAmB,gBAA6E,CAAC;AAAA,EAGjG;AAAA;AAAA,EAGA,MAAa,IAA2B,KAAmD;AACvF,QAAI,OAAO,KAAK,eAAe;AAC3B,UAAI,MAAM,gBAAgB,GAAG;AAE7B,cAAQ,MAAM,KAAK,cAAc,GAAG,GAAG,aAAa;AAAA,IACxD;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,MAAa,YAAmC,KAAa,UAA+D;AACxH,QAAI,OAAO,KAAK,eAAe;AAC3B,aAAO,MAAO,KAAK,IAAO,GAAG;AAAA,IACjC;AACA,QAAI,MAAM,oBAAoB,GAAG;AACjC,UAAM,UAAU,QAAQ,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAO,IAAI,aAAa,CAAC;AAC/E,SAAK,cAAc,GAAG,IAAI;AAC1B,QAAI;AACA,aAAO,MAAM;AAAA,IACjB,SAAS,OAAO;AACZ,UAAI,KAAK,cAAc,GAAG,MAAM,SAAS;AACrC,eAAO,KAAK,cAAc,GAAG;AAAA,MACjC;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA,EAGO,QAAQ;AACX,aAAS,oBAAoB,KAAK,eAAe;AAC7C,aAAO,KAAK,cAAc,gBAAgB;AAAA,IAC9C;AAAA,EACJ;AAGJ;AAEO,SAAS,kBAAkB,KAAkC;AAChE,SAAyB,IAAK;AAClC;","names":[]}
|
|
@@ -15,6 +15,8 @@ import { MineRenderData } from "../../../assets/MineRenderData.mjs";
|
|
|
15
15
|
import { BlockEntities } from "../../../assets/BlockEntities.mjs";
|
|
16
16
|
import { Entities } from "../../../assets/Entities.mjs";
|
|
17
17
|
import { Biomes } from "../../../assets/Biomes.mjs";
|
|
18
|
+
import { logger } from "../../../util/log.mjs";
|
|
19
|
+
var log = logger("BlockObject");
|
|
18
20
|
var _BlockObject = class _BlockObject extends SceneObject {
|
|
19
21
|
constructor(blockState, options) {
|
|
20
22
|
super(options);
|
|
@@ -119,7 +121,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
119
121
|
created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }));
|
|
120
122
|
}
|
|
121
123
|
} catch (error) {
|
|
122
|
-
|
|
124
|
+
log.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);
|
|
123
125
|
this.removeEntities(created);
|
|
124
126
|
return false;
|
|
125
127
|
}
|