emeraldengine 2.2.1 → 3.1.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 (208) hide show
  1. package/README.md +2198 -968
  2. package/dist/types/index.d.ts +75 -32
  3. package/dist/types/src/Animator.d.ts +50 -0
  4. package/dist/types/{BitmapText.d.ts → src/BitmapText.d.ts} +19 -21
  5. package/dist/types/src/Camera.d.ts +122 -0
  6. package/dist/types/src/CameraController.d.ts +107 -0
  7. package/dist/types/src/CanvasText.d.ts +91 -0
  8. package/dist/types/src/CollisionLayers.d.ts +58 -0
  9. package/dist/types/{Color.d.ts → src/Color.d.ts} +6 -6
  10. package/dist/types/src/Coroutine.d.ts +111 -0
  11. package/dist/types/src/DebugOverlay.d.ts +86 -0
  12. package/dist/types/src/Drawable.d.ts +271 -0
  13. package/dist/types/src/Easing.d.ts +22 -0
  14. package/dist/types/src/Emerald.d.ts +420 -0
  15. package/dist/types/src/EmeraldDB.d.ts +159 -0
  16. package/dist/types/{FPSCounter.d.ts → src/FPSCounter.d.ts} +1 -3
  17. package/dist/types/src/GLUtils.d.ts +4 -0
  18. package/dist/types/{Instance.d.ts → src/Instance.d.ts} +37 -15
  19. package/dist/types/{InstancedTexture.d.ts → src/InstancedTexture.d.ts} +75 -23
  20. package/dist/types/src/Interpolator.d.ts +66 -0
  21. package/dist/types/src/Material.d.ts +87 -0
  22. package/dist/types/src/MathUtils.d.ts +81 -0
  23. package/dist/types/src/ParticleEmitter.d.ts +131 -0
  24. package/dist/types/src/Physics.d.ts +337 -0
  25. package/dist/types/src/Pool.d.ts +53 -0
  26. package/dist/types/src/PostEffects.d.ts +68 -0
  27. package/dist/types/src/PostProcessor.d.ts +124 -0
  28. package/dist/types/src/RenderTarget.d.ts +56 -0
  29. package/dist/types/src/Scene.d.ts +62 -0
  30. package/dist/types/src/ScreenEffects.d.ts +111 -0
  31. package/dist/types/src/Serializer.d.ts +86 -0
  32. package/dist/types/src/Shaders.d.ts +2 -0
  33. package/dist/types/{Shapes.d.ts → src/Shapes.d.ts} +4 -6
  34. package/dist/types/src/SpatialGrid.d.ts +50 -0
  35. package/dist/types/src/SpriteBatch.d.ts +89 -0
  36. package/dist/types/src/StateMachine.d.ts +59 -0
  37. package/dist/types/src/Storage.d.ts +89 -0
  38. package/dist/types/{Texture.d.ts → src/Texture.d.ts} +3 -4
  39. package/dist/types/src/TextureAtlas.d.ts +55 -0
  40. package/dist/types/src/Tilemap.d.ts +91 -0
  41. package/dist/types/src/Time.d.ts +53 -0
  42. package/dist/types/src/Timer.d.ts +54 -0
  43. package/dist/types/src/Transform.d.ts +94 -0
  44. package/dist/types/src/Tween.d.ts +81 -0
  45. package/dist/types/src/UI.d.ts +121 -0
  46. package/dist/types/src/components/Behaviour.d.ts +71 -0
  47. package/dist/types/{components → src/components}/BoxCollider.d.ts +14 -14
  48. package/dist/types/src/components/BoxColliderDebug.d.ts +15 -0
  49. package/dist/types/{components → src/components}/CircleCollider.d.ts +14 -12
  50. package/dist/types/src/components/CircleColliderDebug.d.ts +15 -0
  51. package/dist/types/src/components/Collider.d.ts +102 -0
  52. package/dist/types/src/components/GameObject.d.ts +135 -0
  53. package/dist/types/src/components/PolygonCollider.d.ts +33 -0
  54. package/dist/types/src/components/RigidBody.d.ts +456 -0
  55. package/dist/types/src/importers/Aseprite.d.ts +79 -0
  56. package/dist/types/src/importers/ForgeLevel.d.ts +97 -0
  57. package/dist/types/src/importers/TiledMap.d.ts +62 -0
  58. package/dist/types/{lights → src/lights}/DirectionalLight.d.ts +7 -9
  59. package/dist/types/{lights → src/lights}/PointLight.d.ts +6 -9
  60. package/dist/types/src/managers/AssetManager.d.ts +116 -0
  61. package/dist/types/src/managers/AudioManager.d.ts +259 -0
  62. package/dist/types/{managers → src/managers}/CameraManager.d.ts +8 -8
  63. package/dist/types/{managers → src/managers}/EventManager.d.ts +46 -32
  64. package/dist/types/src/managers/GLManager.d.ts +84 -0
  65. package/dist/types/src/managers/GLState.d.ts +37 -0
  66. package/dist/types/src/managers/Gamepad.d.ts +102 -0
  67. package/dist/types/src/managers/IDManager.d.ts +31 -0
  68. package/dist/types/src/managers/InputManager.d.ts +381 -0
  69. package/dist/types/src/managers/NetworkManager.d.ts +93 -0
  70. package/dist/types/src/managers/RenderStats.d.ts +34 -0
  71. package/dist/types/src/managers/SceneManager.d.ts +44 -0
  72. package/dist/types/src/managers/ShaderManager.d.ts +55 -0
  73. package/dist/types/src/managers/TextureManager.d.ts +102 -0
  74. package/dist/types/src/particlesystem/Particle.d.ts +64 -0
  75. package/dist/types/{particlesystem → src/particlesystem}/ParticleSettings.d.ts +32 -24
  76. package/dist/types/{particlesystem → src/particlesystem}/Particles.d.ts +20 -12
  77. package/dist/types/src/physics/AABB.d.ts +92 -0
  78. package/dist/types/src/physics/Body.d.ts +435 -0
  79. package/dist/types/src/physics/BodyType.d.ts +6 -0
  80. package/dist/types/src/physics/BroadPhase.d.ts +210 -0
  81. package/dist/types/src/physics/Collision.d.ts +102 -0
  82. package/dist/types/src/physics/Contact.d.ts +206 -0
  83. package/dist/types/src/physics/ContactSolver.d.ts +108 -0
  84. package/dist/types/src/physics/Distance.d.ts +54 -0
  85. package/dist/types/src/physics/DistanceJoint.d.ts +90 -0
  86. package/dist/types/src/physics/Fixture.d.ts +221 -0
  87. package/dist/types/src/physics/Island.d.ts +52 -0
  88. package/dist/types/src/physics/Joint.d.ts +59 -0
  89. package/dist/types/src/physics/Math2D.d.ts +371 -0
  90. package/dist/types/src/physics/RevoluteJoint.d.ts +119 -0
  91. package/dist/types/src/physics/Settings.d.ts +22 -0
  92. package/dist/types/src/physics/Shapes.d.ts +207 -0
  93. package/dist/types/src/physics/TimeOfImpact.d.ts +22 -0
  94. package/dist/types/src/physics/World.d.ts +274 -0
  95. package/dist/types/src/physics/index.d.ts +34 -0
  96. package/index.js +78 -0
  97. package/package.json +73 -60
  98. package/src/Animator.js +95 -0
  99. package/src/BitmapText.js +6 -5
  100. package/src/Camera.js +183 -0
  101. package/src/CameraController.js +192 -0
  102. package/src/CanvasText.js +281 -0
  103. package/src/CollisionLayers.js +86 -0
  104. package/src/Color.js +26 -18
  105. package/src/Coroutine.js +259 -0
  106. package/src/DebugOverlay.js +246 -0
  107. package/src/Drawable.js +842 -582
  108. package/src/Easing.js +57 -0
  109. package/src/Emerald.js +1150 -459
  110. package/src/EmeraldDB.js +328 -0
  111. package/src/FPSCounter.js +43 -43
  112. package/src/GLUtils.js +60 -67
  113. package/src/Instance.js +41 -5
  114. package/src/InstancedTexture.js +308 -127
  115. package/src/Interpolator.js +124 -0
  116. package/src/Material.js +202 -0
  117. package/src/MathUtils.js +134 -0
  118. package/src/ParticleEmitter.js +284 -0
  119. package/src/Physics.js +431 -40
  120. package/src/Pool.js +85 -0
  121. package/src/PostEffects.js +296 -0
  122. package/src/PostProcessor.js +304 -0
  123. package/src/RenderTarget.js +134 -0
  124. package/src/Scene.js +115 -83
  125. package/src/ScreenEffects.js +266 -0
  126. package/src/Serializer.js +131 -0
  127. package/src/Shaders.js +150 -165
  128. package/src/Shapes.js +118 -129
  129. package/src/SpatialGrid.js +111 -0
  130. package/src/SpriteBatch.js +299 -0
  131. package/src/StateMachine.js +82 -0
  132. package/src/Storage.js +175 -47
  133. package/src/Texture.js +58 -67
  134. package/src/TextureAtlas.js +96 -0
  135. package/src/Tilemap.js +274 -0
  136. package/src/Time.js +51 -6
  137. package/src/Timer.js +99 -0
  138. package/src/Transform.js +100 -7
  139. package/src/Tween.js +160 -0
  140. package/src/UI.js +394 -0
  141. package/src/components/Behaviour.js +90 -0
  142. package/src/components/BoxCollider.js +29 -12
  143. package/src/components/BoxColliderDebug.js +3 -4
  144. package/src/components/CircleCollider.js +26 -12
  145. package/src/components/CircleColliderDebug.js +25 -24
  146. package/src/components/Collider.js +150 -34
  147. package/src/components/GameObject.js +130 -21
  148. package/src/components/PolygonCollider.js +55 -0
  149. package/src/components/RigidBody.js +556 -8
  150. package/src/importers/Aseprite.js +142 -0
  151. package/src/importers/ForgeLevel.js +581 -0
  152. package/src/importers/TiledMap.js +158 -0
  153. package/src/lights/DirectionalLight.js +6 -15
  154. package/src/lights/PointLight.js +4 -4
  155. package/src/managers/AssetManager.js +239 -0
  156. package/src/managers/AudioManager.js +565 -146
  157. package/src/managers/EventManager.js +488 -477
  158. package/src/managers/GLManager.js +57 -0
  159. package/src/managers/GLState.js +70 -0
  160. package/src/managers/Gamepad.js +126 -0
  161. package/src/managers/IDManager.js +24 -2
  162. package/src/managers/InputManager.js +905 -0
  163. package/src/managers/NetworkManager.js +178 -0
  164. package/src/managers/RenderStats.js +34 -0
  165. package/src/managers/SceneManager.js +30 -0
  166. package/src/managers/ShaderManager.js +0 -2
  167. package/src/managers/TextureManager.js +218 -0
  168. package/src/particlesystem/Particle.js +82 -7
  169. package/src/particlesystem/ParticleSettings.js +21 -3
  170. package/src/particlesystem/Particles.js +80 -31
  171. package/src/physics/AABB.js +207 -0
  172. package/src/physics/Body.js +862 -0
  173. package/src/physics/BodyType.js +16 -0
  174. package/src/physics/BroadPhase.js +641 -0
  175. package/src/physics/Collision.js +534 -0
  176. package/src/physics/Contact.js +500 -0
  177. package/src/physics/ContactSolver.js +526 -0
  178. package/src/physics/Distance.js +403 -0
  179. package/src/physics/DistanceJoint.js +227 -0
  180. package/src/physics/Fixture.js +346 -0
  181. package/src/physics/Island.js +203 -0
  182. package/src/physics/Joint.js +78 -0
  183. package/src/physics/Math2D.js +573 -0
  184. package/src/physics/RevoluteJoint.js +278 -0
  185. package/src/physics/Settings.js +78 -0
  186. package/src/physics/Shapes.js +549 -0
  187. package/src/physics/TimeOfImpact.js +87 -0
  188. package/src/physics/World.js +731 -0
  189. package/src/physics/index.js +79 -0
  190. package/dist/types/Drawable.d.ts +0 -157
  191. package/dist/types/Emerald.d.ts +0 -73
  192. package/dist/types/GLUtils.d.ts +0 -6
  193. package/dist/types/Physics.d.ts +0 -139
  194. package/dist/types/Scene.d.ts +0 -39
  195. package/dist/types/Shaders.d.ts +0 -4
  196. package/dist/types/Storage.d.ts +0 -46
  197. package/dist/types/Time.d.ts +0 -22
  198. package/dist/types/Transform.d.ts +0 -41
  199. package/dist/types/components/BoxColliderDebug.d.ts +0 -19
  200. package/dist/types/components/CircleColliderDebug.d.ts +0 -19
  201. package/dist/types/components/Collider.d.ts +0 -53
  202. package/dist/types/components/GameObject.d.ts +0 -72
  203. package/dist/types/components/RigidBody.d.ts +0 -104
  204. package/dist/types/managers/AudioManager.d.ts +0 -60
  205. package/dist/types/managers/GLManager.d.ts +0 -47
  206. package/dist/types/managers/IDManager.d.ts +0 -21
  207. package/dist/types/managers/SceneManager.d.ts +0 -22
  208. package/dist/types/particlesystem/Particle.d.ts +0 -42
@@ -0,0 +1,328 @@
1
+ /**
2
+ * @class EmeraldDB
3
+ * @description Async game-save storage on IndexedDB, the big-world companion
4
+ * to `Storage` (localStorage). Same versioned-envelope semantics (`{v,t,data}`
5
+ * with a `.bak` backup and forward migration), but with no ~5MB quota and no
6
+ * JSON round-trip: values are structured-cloned, so large nested world state
7
+ * (tile grids, inventories, NPC state) saves fast and loads intact, including
8
+ * Maps, Sets, Dates, and typed arrays.
9
+ *
10
+ * All methods are async. The database opens lazily on first use; call
11
+ * `configure()` first if you want a custom database/store name.
12
+ *
13
+ * @example
14
+ * // Save / load a world with schema migration:
15
+ * await EmeraldDB.save("world", world, { version: 3 });
16
+ * const world = await EmeraldDB.load("world", {
17
+ * version: 3,
18
+ * fallback: makeNewWorld(),
19
+ * migrate: (old, from) => upgradeWorld(old, from),
20
+ * });
21
+ *
22
+ * // Plain key/value (no envelope):
23
+ * await EmeraldDB.set("settings", { volume: 0.8 });
24
+ * const settings = await EmeraldDB.get("settings", {});
25
+ */
26
+ class EmeraldDB {
27
+ /**
28
+ * @method isSupported
29
+ * @description Whether IndexedDB exists in this environment.
30
+ * @returns {boolean}
31
+ */
32
+ static isSupported() {
33
+ return typeof indexedDB !== "undefined" && indexedDB !== null;
34
+ }
35
+
36
+ /**
37
+ * @method configure
38
+ * @description Sets the database and object-store names. Call before the
39
+ * first read/write (once the database is open the names are fixed until
40
+ * `close()`).
41
+ * @param {Object} [options] - { name = "emerald-db", store = "kv" }
42
+ * @returns {EmeraldDB} - the class, for chaining
43
+ */
44
+ static configure(options = {}) {
45
+ if (options.name) EmeraldDB._name = options.name;
46
+ if (options.store) EmeraldDB._store = options.store;
47
+ return EmeraldDB;
48
+ }
49
+
50
+ /**
51
+ * @method _open
52
+ * @description Lazily opens (and creates) the database. Shared promise so
53
+ * concurrent calls open once.
54
+ * @private
55
+ */
56
+ static _open() {
57
+ if (EmeraldDB._db) return EmeraldDB._db;
58
+ if (!EmeraldDB.isSupported()) {
59
+ return Promise.reject(
60
+ new Error(
61
+ "[EmeraldDB] > IndexedDB is not available in this environment."
62
+ )
63
+ );
64
+ }
65
+ EmeraldDB._db = new Promise((resolve, reject) => {
66
+ const request = indexedDB.open(EmeraldDB._name, 1);
67
+ request.onupgradeneeded = () => {
68
+ const db = request.result;
69
+ if (!db.objectStoreNames.contains(EmeraldDB._store)) {
70
+ db.createObjectStore(EmeraldDB._store);
71
+ }
72
+ };
73
+ request.onsuccess = () => {
74
+ const db = request.result;
75
+ db.onversionchange = () => {
76
+ db.close();
77
+ EmeraldDB._db = null;
78
+ };
79
+ resolve(db);
80
+ };
81
+ request.onerror = () => {
82
+ EmeraldDB._db = null;
83
+ reject(
84
+ request.error || new Error("[EmeraldDB] > Failed to open database.")
85
+ );
86
+ };
87
+ });
88
+ return EmeraldDB._db;
89
+ }
90
+
91
+ /**
92
+ * @method _tx
93
+ * @description Runs `fn(store)` inside a transaction and resolves with its
94
+ * request's result when the transaction completes.
95
+ * @private
96
+ */
97
+ static async _tx(mode, fn) {
98
+ const db = await EmeraldDB._open();
99
+ return new Promise((resolve, reject) => {
100
+ const tx = db.transaction(EmeraldDB._store, mode);
101
+ const store = tx.objectStore(EmeraldDB._store);
102
+ let result;
103
+ const request = fn(store);
104
+ if (request) {
105
+ request.onsuccess = () => {
106
+ result = request.result;
107
+ };
108
+ }
109
+ tx.oncomplete = () => resolve(result);
110
+ tx.onerror = () => reject(tx.error);
111
+ tx.onabort = () =>
112
+ reject(tx.error || new Error("[EmeraldDB] > Transaction aborted."));
113
+ });
114
+ }
115
+
116
+ /**
117
+ * @method set
118
+ * @description Stores a value under a key (structured clone: objects, Maps,
119
+ * Sets, typed arrays all survive).
120
+ * @param {string} key
121
+ * @param {*} value
122
+ * @returns {Promise<void>}
123
+ */
124
+ static async set(key, value) {
125
+ await EmeraldDB._tx("readwrite", (store) => store.put(value, key));
126
+ }
127
+
128
+ /**
129
+ * @method get
130
+ * @description Reads a value; resolves `fallback` when the key is missing.
131
+ * @param {string} key
132
+ * @param {*} [fallback=undefined]
133
+ * @returns {Promise<*>}
134
+ */
135
+ static async get(key, fallback = undefined) {
136
+ const value = await EmeraldDB._tx("readonly", (store) => store.get(key));
137
+ return value === undefined ? fallback : value;
138
+ }
139
+
140
+ /**
141
+ * @method remove
142
+ * @description Deletes a key.
143
+ * @returns {Promise<void>}
144
+ */
145
+ static async remove(key) {
146
+ await EmeraldDB._tx("readwrite", (store) => store.delete(key));
147
+ }
148
+
149
+ /**
150
+ * @method keys
151
+ * @description Lists every key in the store.
152
+ * @returns {Promise<string[]>}
153
+ */
154
+ static async keys() {
155
+ const keys = await EmeraldDB._tx("readonly", (store) => store.getAllKeys());
156
+ return keys || [];
157
+ }
158
+
159
+ /**
160
+ * @method clear
161
+ * @description Deletes everything in the store.
162
+ * @returns {Promise<void>}
163
+ */
164
+ static async clear() {
165
+ await EmeraldDB._tx("readwrite", (store) => store.clear());
166
+ }
167
+
168
+ /**
169
+ * @method save
170
+ * @description Writes a versioned save: the payload is wrapped in a
171
+ * `{ v, t, data }` envelope and the previous value (if any) is mirrored to
172
+ * `key + ".bak"` in the same transaction, so a torn write can always recover.
173
+ * @param {string} key
174
+ * @param {*} data - Any structured-cloneable value
175
+ * @param {Object} [options] - { version = 1, backup = true }
176
+ * @returns {Promise<void>}
177
+ */
178
+ static async save(key, data, options = {}) {
179
+ const version = options.version ?? 1;
180
+ const envelope = { v: version, t: Date.now(), data };
181
+ const backup = options.backup !== false;
182
+ const db = await EmeraldDB._open();
183
+ return new Promise((resolve, reject) => {
184
+ const tx = db.transaction(EmeraldDB._store, "readwrite");
185
+ const store = tx.objectStore(EmeraldDB._store);
186
+ if (backup) {
187
+ const read = store.get(key);
188
+ read.onsuccess = () => {
189
+ if (read.result !== undefined) store.put(read.result, key + ".bak");
190
+ store.put(envelope, key);
191
+ };
192
+ } else {
193
+ store.put(envelope, key);
194
+ }
195
+ tx.oncomplete = () => resolve();
196
+ tx.onerror = () => reject(tx.error);
197
+ tx.onabort = () =>
198
+ reject(tx.error || new Error("[EmeraldDB] > Save aborted."));
199
+ });
200
+ }
201
+
202
+ /**
203
+ * @method load
204
+ * @description Reads a versioned save. Falls back to the `.bak` mirror when
205
+ * the primary is missing/invalid, migrates old versions forward via
206
+ * `migrate(data, fromVersion)`, and (by default) rewrites migrated data in
207
+ * the new format.
208
+ * @param {string} key
209
+ * @param {Object} [options] - { version = 1, fallback = null, migrate, rewrite = true }
210
+ * @returns {Promise<*>}
211
+ */
212
+ static async load(key, options = {}) {
213
+ let envelope = EmeraldDB._asEnvelope(await EmeraldDB.get(key));
214
+ if (!envelope) {
215
+ envelope = EmeraldDB._asEnvelope(await EmeraldDB.get(key + ".bak"));
216
+ }
217
+ const { data, migrated } = EmeraldDB._resolveEnvelope(envelope, options);
218
+ if (migrated && options.rewrite !== false) {
219
+ await EmeraldDB.save(key, data, { version: options.version ?? 1 });
220
+ }
221
+ return data;
222
+ }
223
+
224
+ /**
225
+ * @method hasSave
226
+ * @description Whether a versioned save (or its backup) exists.
227
+ * @returns {Promise<boolean>}
228
+ */
229
+ static async hasSave(key) {
230
+ if ((await EmeraldDB.get(key)) !== undefined) return true;
231
+ return (await EmeraldDB.get(key + ".bak")) !== undefined;
232
+ }
233
+
234
+ /**
235
+ * @method removeSave
236
+ * @description Deletes a versioned save AND its backup.
237
+ * @returns {Promise<void>}
238
+ */
239
+ static async removeSave(key) {
240
+ await EmeraldDB.remove(key);
241
+ await EmeraldDB.remove(key + ".bak");
242
+ }
243
+
244
+ /**
245
+ * @method importFromStorage
246
+ * @description Copies a save written by the localStorage `Storage` class
247
+ * into EmeraldDB (envelope preserved). Use once when upgrading an existing
248
+ * game to IndexedDB saves.
249
+ * @param {string} key
250
+ * @returns {Promise<boolean>} - true if something was imported
251
+ */
252
+ static async importFromStorage(key) {
253
+ if (typeof localStorage === "undefined") return false;
254
+ const raw = localStorage.getItem(key);
255
+ if (raw == null) return false;
256
+ let value;
257
+ try {
258
+ value = JSON.parse(raw);
259
+ } catch {
260
+ return false;
261
+ }
262
+ await EmeraldDB.set(key, value);
263
+ const bak = localStorage.getItem(key + ".bak");
264
+ if (bak != null) {
265
+ try {
266
+ await EmeraldDB.set(key + ".bak", JSON.parse(bak));
267
+ } catch {}
268
+ }
269
+ return true;
270
+ }
271
+
272
+ /**
273
+ * @method close
274
+ * @description Closes the database handle (reopens lazily on next use).
275
+ */
276
+ static async close() {
277
+ if (!EmeraldDB._db) return;
278
+ try {
279
+ const db = await EmeraldDB._db;
280
+ db.close();
281
+ } catch {}
282
+ EmeraldDB._db = null;
283
+ }
284
+
285
+ /**
286
+ * @method _asEnvelope
287
+ * @description Returns the value if it looks like a save envelope, else null.
288
+ * A plain (pre-versioning) object is wrapped as version 0 so it can migrate.
289
+ * @private
290
+ */
291
+ static _asEnvelope(value) {
292
+ if (value === undefined || value === null) return null;
293
+ if (
294
+ typeof value === "object" &&
295
+ typeof value.v === "number" &&
296
+ "data" in value
297
+ ) {
298
+ return value;
299
+ }
300
+ return { v: 0, t: 0, data: value };
301
+ }
302
+
303
+ /**
304
+ * @method _resolveEnvelope
305
+ * @description Pure envelope resolution shared by load(): applies fallback
306
+ * and forward migration. Exposed for tests.
307
+ * @private
308
+ */
309
+ static _resolveEnvelope(envelope, options = {}) {
310
+ const version = options.version ?? 1;
311
+ const fallback = options.fallback ?? null;
312
+ if (!envelope) return { data: fallback, migrated: false };
313
+ if (envelope.v === version) return { data: envelope.data, migrated: false };
314
+ if (typeof options.migrate === "function") {
315
+ return {
316
+ data: options.migrate(envelope.data, envelope.v),
317
+ migrated: true,
318
+ };
319
+ }
320
+ return { data: fallback, migrated: false };
321
+ }
322
+ }
323
+
324
+ EmeraldDB._name = "emerald-db";
325
+ EmeraldDB._store = "kv";
326
+ EmeraldDB._db = null;
327
+
328
+ export default EmeraldDB;
package/src/FPSCounter.js CHANGED
@@ -1,43 +1,43 @@
1
- /**
2
- * @class FPSCounter
3
- * @description Represents a FPS counter
4
- */
5
- class FPSCounter {
6
- constructor() {
7
- this.lastFrameTime = performance.now();
8
- this.frameCount = 0;
9
- this.fps = 0;
10
- this.fpsElement = document.createElement("div");
11
- this.fpsElement.style.position = "absolute";
12
- this.fpsElement.style.top = "10px";
13
- this.fpsElement.style.left = "10px";
14
- this.fpsElement.style.color = "white";
15
- this.fpsElement.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
16
- this.fpsElement.style.padding = "5px";
17
- this.fpsElement.style.fontFamily = "Arial";
18
- this.fpsElement.style.fontSize = "14px";
19
- document.body.appendChild(this.fpsElement);
20
- this.accumulatedTime = 0;
21
- }
22
-
23
- /**
24
- * @method update
25
- * @description Updates the FPS counter
26
- */
27
- update() {
28
- const now = performance.now();
29
- const delta = now - this.lastFrameTime;
30
- this.lastFrameTime = now;
31
- this.accumulatedTime += delta;
32
- this.frameCount++;
33
-
34
- if (this.accumulatedTime >= 1000) {
35
- this.fps = this.frameCount;
36
- this.frameCount = 0;
37
- this.accumulatedTime = 0;
38
- this.fpsElement.textContent = `FPS: ${this.fps}`;
39
- }
40
- }
41
- }
42
-
43
- export default FPSCounter;
1
+ /**
2
+ * @class FPSCounter
3
+ * @description Represents a FPS counter
4
+ */
5
+ class FPSCounter {
6
+ constructor() {
7
+ this.lastFrameTime = performance.now();
8
+ this.frameCount = 0;
9
+ this.fps = 0;
10
+ this.fpsElement = document.createElement("div");
11
+ this.fpsElement.style.position = "absolute";
12
+ this.fpsElement.style.top = "10px";
13
+ this.fpsElement.style.left = "10px";
14
+ this.fpsElement.style.color = "white";
15
+ this.fpsElement.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
16
+ this.fpsElement.style.padding = "5px";
17
+ this.fpsElement.style.fontFamily = "Arial";
18
+ this.fpsElement.style.fontSize = "14px";
19
+ document.body.appendChild(this.fpsElement);
20
+ this.accumulatedTime = 0;
21
+ }
22
+
23
+ /**
24
+ * @method update
25
+ * @description Updates the FPS counter
26
+ */
27
+ update() {
28
+ const now = performance.now();
29
+ const delta = now - this.lastFrameTime;
30
+ this.lastFrameTime = now;
31
+ this.accumulatedTime += delta;
32
+ this.frameCount++;
33
+
34
+ if (this.accumulatedTime >= 1000) {
35
+ this.fps = this.frameCount;
36
+ this.frameCount = 0;
37
+ this.accumulatedTime = 0;
38
+ this.fpsElement.textContent = `FPS: ${this.fps}`;
39
+ }
40
+ }
41
+ }
42
+
43
+ export default FPSCounter;
package/src/GLUtils.js CHANGED
@@ -1,67 +1,60 @@
1
- // Initializing a shader program
2
-
3
- function initShaderProgram(gl, vShader, fShader) {
4
- const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vShader);
5
- const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fShader);
6
-
7
- // Create the shader program
8
- const shaderProgram = gl.createProgram();
9
- gl.attachShader(shaderProgram, vertexShader);
10
- gl.attachShader(shaderProgram, fragmentShader);
11
- gl.linkProgram(shaderProgram);
12
-
13
- // Error handling
14
- if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
15
- alert(
16
- `[GLUtils.js] > Unable to initialize the shader program: ${gl.getProgramInfoLog(
17
- shaderProgram
18
- )}`
19
- );
20
- return null;
21
- }
22
- return shaderProgram;
23
- }
24
-
25
- // Loading a shader
26
-
27
- function loadShader(gl, type, source) {
28
- const shader = gl.createShader(type);
29
-
30
- // Send the source to the shader object
31
- gl.shaderSource(shader, source);
32
-
33
- // Compile the shader program
34
- gl.compileShader(shader);
35
-
36
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
37
- alert(
38
- `[GLUtils.js] An error occurred compiling the shaders: ${gl.getShaderInfoLog(
39
- shader
40
- )}`
41
- );
42
- gl.deleteShader(shader);
43
- return null;
44
- }
45
-
46
- return shader;
47
- }
48
-
49
- const initVertexBuffer = (gl, vertices) => {
50
- const floatArray = new Float32Array(vertices);
51
- const buffer = gl.createBuffer();
52
- gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
53
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
54
- buffer._bufferSize = floatArray.byteLength;
55
- return buffer;
56
- };
57
-
58
- function initInstancedBuffer(gl, data, itemSize) {
59
- const buffer = gl.createBuffer();
60
- gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
61
- gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
62
- buffer.itemSize = itemSize;
63
- buffer.numItems = data.length / itemSize;
64
- return buffer;
65
- }
66
-
67
- export { initShaderProgram, loadShader, initVertexBuffer, initInstancedBuffer };
1
+ function initShaderProgram(gl, vShader, fShader) {
2
+ const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vShader);
3
+ const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fShader);
4
+
5
+ const shaderProgram = gl.createProgram();
6
+ gl.attachShader(shaderProgram, vertexShader);
7
+ gl.attachShader(shaderProgram, fragmentShader);
8
+ gl.linkProgram(shaderProgram);
9
+
10
+ if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
11
+ alert(
12
+ `[GLUtils.js] > Unable to initialize the shader program: ${gl.getProgramInfoLog(
13
+ shaderProgram
14
+ )}`
15
+ );
16
+ return null;
17
+ }
18
+ return shaderProgram;
19
+ }
20
+
21
+ function loadShader(gl, type, source) {
22
+ const shader = gl.createShader(type);
23
+
24
+ gl.shaderSource(shader, source);
25
+
26
+ gl.compileShader(shader);
27
+
28
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
29
+ alert(
30
+ `[GLUtils.js] An error occurred compiling the shaders: ${gl.getShaderInfoLog(
31
+ shader
32
+ )}`
33
+ );
34
+ gl.deleteShader(shader);
35
+ return null;
36
+ }
37
+
38
+ return shader;
39
+ }
40
+
41
+ const initVertexBuffer = (gl, vertices) => {
42
+ const floatArray = new Float32Array(vertices);
43
+ const buffer = gl.createBuffer();
44
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
45
+ gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW);
46
+ buffer._bufferSize = floatArray.byteLength;
47
+ buffer._src = floatArray;
48
+ return buffer;
49
+ };
50
+
51
+ function initInstancedBuffer(gl, data, itemSize) {
52
+ const buffer = gl.createBuffer();
53
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
54
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
55
+ buffer.itemSize = itemSize;
56
+ buffer.numItems = data.length / itemSize;
57
+ return buffer;
58
+ }
59
+
60
+ export { initShaderProgram, loadShader, initVertexBuffer, initInstancedBuffer };
package/src/Instance.js CHANGED
@@ -26,7 +26,6 @@ class Instance {
26
26
  this.parent = null;
27
27
  this.frame = frame;
28
28
 
29
- // Animation properties
30
29
  this.isAnimating = false;
31
30
  this.animationFrames = [];
32
31
  this.currentAnimationIndex = 0;
@@ -35,8 +34,45 @@ class Instance {
35
34
  this.playOnce = false;
36
35
  this.originalFrame = frame;
37
36
 
38
- // Components
39
37
  this.components = [];
38
+
39
+ /** @private */
40
+ this._tint = null;
41
+ }
42
+
43
+ /**
44
+ * @method setColor
45
+ * @description Sets this instance's tint. Accepts a Color (0..255 channels) or
46
+ * raw 0..1 components. Multiplies the texture/base color in the shader.
47
+ * @param {Color|number} colorOrR - A Color instance, or the red channel
48
+ * @param {number} [g]
49
+ * @param {number} [b]
50
+ * @param {number} [a]
51
+ */
52
+ setColor(colorOrR, g, b, a = 1) {
53
+ if (colorOrR && typeof colorOrR === "object") {
54
+ this._tint = [
55
+ (colorOrR.r ?? 255) / 255,
56
+ (colorOrR.g ?? 255) / 255,
57
+ (colorOrR.b ?? 255) / 255,
58
+ (colorOrR.a ?? 255) / 255,
59
+ ];
60
+ } else {
61
+ this._tint = [colorOrR, g, b, a];
62
+ }
63
+ }
64
+
65
+ /**
66
+ * @method setTexCoords
67
+ * @description Gives this instance an explicit UV quad (8 floats, one vec2
68
+ * per corner in the same order as getFrameTexCoords) instead of the shared
69
+ * frame grid. Lets one InstancedTexture batch tiles from an atlas with
70
+ * margins/spacing or per-instance flips. Pass null to go back to `frame`.
71
+ * @param {number[]|Float32Array|null} uv8 - 8 UV floats, or null to clear
72
+ */
73
+ setTexCoords(uv8) {
74
+ /** @private */
75
+ this._regionUV = uv8 ? Array.from(uv8) : null;
40
76
  }
41
77
 
42
78
  /**
@@ -131,15 +167,15 @@ class Instance {
131
167
  if (this.playOnce) {
132
168
  this.stopAnimation();
133
169
  } else {
134
- this.currentAnimationIndex = 0; // Loop animation
170
+ this.currentAnimationIndex = 0;
135
171
  }
136
172
  }
137
173
 
138
174
  this.lastFrameTime = currentTime;
139
- return true; // Frame changed
175
+ return true;
140
176
  }
141
177
 
142
- return false; // No frame change
178
+ return false;
143
179
  }
144
180
 
145
181
  /**