incanto 0.37.0 → 0.38.0

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.
Files changed (41) hide show
  1. package/dist/2d.d.ts +2 -2
  2. package/dist/2d.js +3 -3
  3. package/dist/3d.d.ts +33 -3
  4. package/dist/3d.js +3 -31
  5. package/dist/{behavior-5o1EkbLD.d.ts → behavior-B5PJ32eu.d.ts} +95 -6
  6. package/dist/{create-game-DmGc-Mrn.js → create-game-C4t5gVhc.js} +3 -3
  7. package/dist/{create-game-QqrrK3yr.js → create-game-DqY2lMBc.js} +781 -687
  8. package/dist/debug.d.ts +1 -1
  9. package/dist/editor.js +21 -0
  10. package/dist/{environment-presets-DWHxLHM5.js → environment-presets-C0Axpfth.js} +1 -1
  11. package/dist/gameplay.d.ts +1 -1
  12. package/dist/index.d.ts +4 -4
  13. package/dist/index.js +3 -3
  14. package/dist/{loader-iGq2PT_k.d.ts → loader-DSMdqasu.d.ts} +1 -1
  15. package/dist/net.d.ts +1 -1
  16. package/dist/net.js +2 -2
  17. package/dist/{pathfinding-pPrqtlWS.d.ts → pathfinding-BrE5Uec6.d.ts} +1 -1
  18. package/dist/{physics-2d-C8Hi40qb.js → physics-2d-OfKb0PV_.js} +1 -1
  19. package/dist/{physics-3d-C0mWoWXC.js → physics-3d-C8242nXr.js} +1 -1
  20. package/dist/react.d.ts +1 -1
  21. package/dist/react.js +1 -1
  22. package/dist/{register-t15rydSm.js → register-B4RRQbyq.js} +1 -1
  23. package/dist/{register-DOWGnxe1.js → register-Dm7nrd-E.js} +321 -33
  24. package/dist/{register-DFSW2Y30.js → register-DnB9m7Rl.js} +1 -1
  25. package/dist/{replay-DGzhZWrM.d.ts → replay-Cxrr-ApH.d.ts} +1 -1
  26. package/dist/{replay-BuOTl5rM.js → replay-DH0UOuZ-.js} +1 -1
  27. package/dist/{test-BiIO9ULW.js → test-CoDPWx-m.js} +9 -9
  28. package/dist/test.d.ts +3 -3
  29. package/dist/test.js +2 -2
  30. package/dist/vite.js +1 -1
  31. package/editor/assets/{agent8-CeeI7P_0.js → agent8-BtIlblPm.js} +1 -1
  32. package/editor/assets/{debug-DN9X9G6z.js → debug-BvTmHXI7.js} +1 -1
  33. package/editor/assets/{index-C833FBzB.js → index-BS01WWgM.js} +91 -91
  34. package/editor/index.html +1 -1
  35. package/package.json +1 -1
  36. package/schemas/scene.schema.json +294 -0
  37. package/skills/incanto-node-reference.md +45 -0
  38. package/skills/incanto-performance.md +212 -0
  39. package/templates-app/beacon-isle-3d/package.json +1 -1
  40. package/templates-app/tps-3d/package.json +1 -1
  41. package/templates-app/village-quest-3d/package.json +1 -1
package/dist/2d.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { N as Scene$1, S as Scheduler, T as RendererStats, Tt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-5o1EkbLD.js";
1
+ import { N as Scene$1, S as Scheduler, T as RendererStats, Tt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-B5PJ32eu.js";
2
2
  import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DVwIGZdK.js";
3
3
  import { i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
4
- import { t as LoadSceneOptions } from "./loader-iGq2PT_k.js";
4
+ import { t as LoadSceneOptions } from "./loader-DSMdqasu.js";
5
5
  import { t as ParticleSim } from "./particle-sim-BzJ1yxoE.js";
6
6
  import { Group, Mesh, Object3D, Scene, Texture } from "three";
7
7
  import * as RapierNs from "@dimforge/rapier2d-compat";
package/dist/2d.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
- import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-DmGc-Mrn.js";
3
- import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-DFSW2Y30.js";
4
- import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-C8Hi40qb.js";
2
+ import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-C4t5gVhc.js";
3
+ import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-DnB9m7Rl.js";
4
+ import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-OfKb0PV_.js";
5
5
  //#region src/2d/library-sprite.ts
6
6
  /**
7
7
  * Turn a library sprite-animation JSON into a scene-ready spritesheet asset
package/dist/3d.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { N as Scene$1, S as Scheduler, T as RendererStats, Tt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-5o1EkbLD.js";
1
+ import { N as Scene$1, S as Scheduler, T as RendererStats, Tt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-B5PJ32eu.js";
2
2
  import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DVwIGZdK.js";
3
3
  import { i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
4
- import { t as LoadSceneOptions } from "./loader-iGq2PT_k.js";
4
+ import { t as LoadSceneOptions } from "./loader-DSMdqasu.js";
5
5
  import { t as ParticleSim } from "./particle-sim-BzJ1yxoE.js";
6
- import { n as PathGrid, s as SpatialPose } from "./pathfinding-pPrqtlWS.js";
6
+ import { n as PathGrid, s as SpatialPose } from "./pathfinding-BrE5Uec6.js";
7
7
  import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
8
8
  import { VRM } from "@pixiv/three-vrm";
9
9
  import { Sky } from "three/examples/jsm/objects/Sky.js";
@@ -3125,6 +3125,19 @@ interface Renderer3DOptions {
3125
3125
  /** Defaults to `window.devicePixelRatio` capped at 2. */
3126
3126
  pixelRatio?: number;
3127
3127
  /**
3128
+ * Starting point for the rendering knobs, from the player's quality tier.
3129
+ *
3130
+ * DEFAULTS, not overrides: a scene's own `environment.rendering` is a decision
3131
+ * about that scene and still wins, and an explicit `pixelRatio` option wins
3132
+ * over both. This only decides what a device that has said nothing gets —
3133
+ * which for `antialias` is the only chance there is, since it is a WebGL
3134
+ * context attribute and cannot change after the context exists.
3135
+ */
3136
+ qualityDefaults?: {
3137
+ antialias: boolean;
3138
+ pixelRatio: number;
3139
+ };
3140
+ /**
3128
3141
  * Keep the frame rate by rendering at fewer pixels when frames run slow, and
3129
3142
  * hand them back when they recover (default ON). A retina display asks for
3130
3143
  * 4× the pixels; shaded water is fragment-heavy; the honest answer is fewer
@@ -3222,6 +3235,8 @@ declare class Renderer3D {
3222
3235
  /** The pixel ratio the scene ASKED for — the governor scales this, never replaces it. */
3223
3236
  private readonly basePixelRatio;
3224
3237
  private readonly adaptive;
3238
+ private renderScale;
3239
+ private adaptiveScale;
3225
3240
  private lastFrameAt;
3226
3241
  private readonly debugLines;
3227
3242
  private readonly selectionLines;
@@ -3236,6 +3251,21 @@ declare class Renderer3D {
3236
3251
  */
3237
3252
  private governResolution;
3238
3253
  /**
3254
+ * The player's resolution multiplier, on top of whatever the scene and the
3255
+ * quality tier resolved to.
3256
+ *
3257
+ * The cheapest lever there is on a weak GPU: at 0.66 the fragment shaders run
3258
+ * over 44% of the pixels for a soft image and nothing else, where dropping a
3259
+ * quality tier costs the shadows outright. Live — a settings menu writes it
3260
+ * mid-game — and it multiplies with the adaptive governor rather than
3261
+ * fighting it, so a player who has already scaled down does not get scaled
3262
+ * down twice as hard.
3263
+ */
3264
+ setRenderScale(scale: number): void;
3265
+ /** Judge frames against `fps` — see AdaptiveResolution.setTarget. */
3266
+ setFrameTarget(fps: number): void;
3267
+ private applyPixelRatio;
3268
+ /**
3239
3269
  * Compile the scene's GPU programs off the critical path.
3240
3270
  *
3241
3271
  * The compile itself is unavoidable — a dressed outdoor scene is 40+ programs
package/dist/3d.js CHANGED
@@ -1,36 +1,8 @@
1
- import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
1
  import { A as Water3D, F as PhysicsBody3D, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D, V as WATER_MAX_RIPPLES, j as WATER_CUTOUT_MAX } from "./gameplay-CsJDUQh_.js";
3
- import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-DWHxLHM5.js";
4
- import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-QqrrK3yr.js";
2
+ import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-C0Axpfth.js";
3
+ import { a as Environment3D, c as parseEnvironment3D, d as AssetStore3D, i as syncTree, l as sunDirectionFromElevationAzimuth, o as setEnvironment3D, r as Renderer3D, s as horizonColorFromSky, t as createGame3D, u as sunDirectionFromSky } from "./create-game-DqY2lMBc.js";
5
4
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
6
- import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-C0mWoWXC.js";
7
- //#region src/3d/environment-runtime.ts
8
- /**
9
- * Live environment editing — the renderer re-applies `scene.environment`
10
- * every frame (cheap when unchanged), so changing the LOOK at runtime is
11
- * just writing that object. This helper does it safely:
12
- *
13
- * setEnvironment3D(engine, { sky: { elevationDeg: 4 }, exposure: 0.8 });
14
- * setEnvironment3D(engine, { fog: null }); // null DELETES a key
15
- *
16
- * - one-level deep merge (patching `sky.elevationDeg` keeps the other sky keys)
17
- * - hard-validates the merged result NOW (in your call stack), so a bad patch
18
- * throws where you wrote it — never inside the render loop
19
- */
20
- function setEnvironment3D(engine, patch) {
21
- const scene = engine.scene;
22
- if (!scene) throw new IncantoError("BAD_FORMAT", "setEnvironment3D: the engine has no scene.");
23
- const merged = { ...scene.environment ?? {} };
24
- for (const [key, value] of Object.entries(patch)) if (value === null) delete merged[key];
25
- else if (typeof value === "object" && !Array.isArray(value) && typeof merged[key] === "object" && merged[key] !== null && !Array.isArray(merged[key])) merged[key] = {
26
- ...merged[key],
27
- ...value
28
- };
29
- else merged[key] = value;
30
- parseEnvironment3D(merged);
31
- scene.environment = merged;
32
- }
33
- //#endregion
5
+ import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-C8242nXr.js";
34
6
  //#region src/3d/terrain-nav.ts
35
7
  function buildTerrainNav(terrain, opts) {
36
8
  const cellSize = opts?.cellSize ?? 2;
@@ -1091,6 +1091,21 @@ interface SettingsValues {
1091
1091
  * does not translate falls back to English, silently and on purpose.
1092
1092
  */
1093
1093
  language: string;
1094
+ /**
1095
+ * Has a HUMAN chosen the quality tier?
1096
+ *
1097
+ * Without this, a first boot cannot tell "the default happens to be high" from
1098
+ * "the player picked high", so device auto-detection would either never run or
1099
+ * would overwrite a deliberate choice on every launch.
1100
+ */
1101
+ qualityChosen: boolean;
1102
+ /** Frames per second to draw at most. 0 = uncapped (draw every rAF). */
1103
+ maxFps: number;
1104
+ /**
1105
+ * Extra multiplier on the render resolution, on top of the tier's pixel ratio.
1106
+ * 1 = as the tier says. Below 1 trades sharpness for frame rate.
1107
+ */
1108
+ renderScale: number;
1094
1109
  }
1095
1110
  /** What a device probe can see without a GPU context. */
1096
1111
  interface DeviceHints {
@@ -1122,6 +1137,43 @@ declare class Settings {
1122
1137
  /** Back to defaults, on disk too. */
1123
1138
  reset(): void;
1124
1139
  /**
1140
+ * Choose a starting tier from the device, ONCE.
1141
+ *
1142
+ * Only on a first visit: after someone has picked a tier, re-detecting on
1143
+ * every launch would silently undo their choice — which is the behaviour every
1144
+ * player experiences as "the settings do not save".
1145
+ */
1146
+ autoQuality(hints?: DeviceHints): QualityTier;
1147
+ /** Record that the tier came from a person, not from the device probe. */
1148
+ chooseQuality(tier: QualityTier): void;
1149
+ /**
1150
+ * Apply the saved quality tier to a live scene, and keep applying it.
1151
+ *
1152
+ * The same shape as `bindAudio` and `bindLocale`. Until 0.38 this did not
1153
+ * exist: `settings.quality` was written to disk and read by NOBODY, and
1154
+ * `qualityEnvironment` — the function that turns a tier into something the
1155
+ * renderer understands — emitted patches the environment parser rejects, for
1156
+ * all three tiers. Both were public, documented and never once called.
1157
+ */
1158
+ bindQuality(apply: (patch: Record<string, JsonValue>) => void): () => void;
1159
+ /**
1160
+ * Apply the saved frame cap, and again whenever it changes.
1161
+ *
1162
+ * Separate from `bindQuality` because it is not a tier: a player caps the
1163
+ * frame rate to keep a phone cool or a battery alive, on the highest visual
1164
+ * settings the device can hold, and those two choices do not belong on one
1165
+ * slider. 0 means uncapped. Returns the unsubscribe.
1166
+ */
1167
+ bindFrameCap(apply: (fps: number) => void): () => void;
1168
+ /**
1169
+ * Apply the saved resolution multiplier, and again whenever it changes.
1170
+ *
1171
+ * The lever that buys the most frames per unit of ugliness on a weak GPU —
1172
+ * shading 44% of the pixels at 0.66 costs a soft image and nothing else,
1173
+ * while dropping a quality tier costs shadows entirely.
1174
+ */
1175
+ bindRenderScale(apply: (scale: number) => void): () => void;
1176
+ /**
1125
1177
  * Apply the saved language, and keep it in step both ways.
1126
1178
  *
1127
1179
  * The same shape as `bindAudio`: a game that writes
@@ -1139,13 +1191,22 @@ declare class Settings {
1139
1191
  bindAudio(audio: AudioBuses): () => void;
1140
1192
  }
1141
1193
  /**
1142
- * What a quality tier MEANS, as an environment patch.
1194
+ * What a quality tier MEANS, as a LIVE environment patch.
1143
1195
  *
1144
- * Only the levers that actually cost: shadows, post, clouds, and the resolution
1145
- * the renderer draws at. Deliberately an `environment` patch, because
1146
- * `setEnvironment3D(engine, patch)` already applies one live and validated —
1147
- * this is not a second rendering pipeline, it is three presets for the one that
1148
- * exists.
1196
+ * Only the levers that actually cost: shadows, post, bloom and clouds.
1197
+ * Deliberately an `environment` patch, because `setEnvironment3D(engine, patch)`
1198
+ * already applies one live and validated — this is not a second rendering
1199
+ * pipeline, it is three presets for the one that exists.
1200
+ *
1201
+ * The `off` spelling matters and got this wrong for three releases: every tier
1202
+ * emitted `{ enabled: false }`, which the environment parser rejects
1203
+ * (`environment.bloom has unknown key 'enabled'`). Nothing called this function,
1204
+ * so nothing found out. In a live patch `null` DELETES a key — that is how a
1205
+ * stage is turned off — and `shadows` alone takes a real `false`.
1206
+ *
1207
+ * Antialiasing and pixel ratio are NOT here: `antialias` is a WebGL context
1208
+ * attribute and cannot change without rebuilding the renderer. See
1209
+ * `qualityRendering`.
1149
1210
  */
1150
1211
  declare function qualityEnvironment(tier: QualityTier): Record<string, JsonValue>;
1151
1212
  //#endregion
@@ -1195,6 +1256,8 @@ interface EngineOptions {
1195
1256
  scheduler?: Scheduler;
1196
1257
  /** Seed for `engine.rng` — set it to make a run reproducible (default: random). */
1197
1258
  seed?: number;
1259
+ /** Frame cap in fps; 0 (default) runs at whatever the display offers. */
1260
+ maxFps?: number;
1198
1261
  }
1199
1262
  /**
1200
1263
  * The game loop: drives a Scene's tree with fixed-timestep `fixedUpdate`
@@ -1306,6 +1369,32 @@ declare class Engine {
1306
1369
  setScene(scene: Scene): void;
1307
1370
  start(): void;
1308
1371
  /**
1372
+ * The frame cap: fps, or 0 for "as fast as the display goes" (the default).
1373
+ *
1374
+ * Live — a settings menu writes it mid-game. It gates the whole frame, not
1375
+ * just the render: an uncapped loop on a 144 Hz phone burns battery running
1376
+ * game logic nobody sees.
1377
+ *
1378
+ * `tick()` is deliberately NOT gated. A headless harness driving its own
1379
+ * clock asked for that frame; the cap is about the real-time loop.
1380
+ */
1381
+ maxFps: number;
1382
+ private nextFrameAt;
1383
+ private lastOfferedAt;
1384
+ private displayPeriodMs;
1385
+ /**
1386
+ * Should this display frame run?
1387
+ *
1388
+ * The obvious `if (now - last < interval) return` is wrong in a way that only
1389
+ * shows up between the round numbers: a 45 fps cap on a 60 Hz display misses
1390
+ * every other deadline by a fraction of a millisecond, waits a whole display
1391
+ * frame more, and delivers 30 — asking for 45 makes the game slower than not
1392
+ * capping at all. The fix is to allow a frame that is within half a display
1393
+ * period of its deadline, and to advance the deadline by the interval rather
1394
+ * than from `now`, so the error does not accumulate.
1395
+ */
1396
+ private frameIsDue;
1397
+ /**
1309
1398
  * A frame threw somewhere outside a single node (a renderer, physics, a
1310
1399
  * signal handler). Report the first one and count the rest: a broken frame
1311
1400
  * repeats sixty times a second, and sixty identical traces a second is how
@@ -1,13 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { n as loadScene, o as computeViewport, s as resolveViewport, v as diagnose, w as registerBehavior } from "./loader-r49nDwB4.js";
3
- import { h as Engine, m as AudioPlayer } from "./register-DOWGnxe1.js";
3
+ import { h as Engine, m as AudioPlayer } from "./register-Dm7nrd-E.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-BoNg_MnF.js";
6
6
  import { i as openBundledEditor, n as crossFade, r as devServerLibrary, t as teardown } from "./teardown-CCtAMDLB.js";
7
7
  import { n as registerGameplayBehaviors } from "./gameplay-CsJDUQh_.js";
8
- import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-DFSW2Y30.js";
8
+ import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-DnB9m7Rl.js";
9
9
  import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
10
- import { n as enablePhysics2D } from "./physics-2d-C8Hi40qb.js";
10
+ import { n as enablePhysics2D } from "./physics-2d-OfKb0PV_.js";
11
11
  import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
12
12
  //#region src/2d/assets.ts
13
13
  /**