@guinetik/gcanvas 1.0.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 (349) hide show
  1. package/.github/workflows/release.yaml +70 -0
  2. package/.jshintrc +4 -0
  3. package/.vscode/settings.json +22 -0
  4. package/CLAUDE.md +310 -0
  5. package/blackhole.jpg +0 -0
  6. package/demo.png +0 -0
  7. package/demos/CNAME +1 -0
  8. package/demos/animations.html +31 -0
  9. package/demos/basic.html +38 -0
  10. package/demos/baskara.html +31 -0
  11. package/demos/bezier.html +35 -0
  12. package/demos/beziersignature.html +29 -0
  13. package/demos/blackhole.html +28 -0
  14. package/demos/blob.html +35 -0
  15. package/demos/demos.css +289 -0
  16. package/demos/easing.html +28 -0
  17. package/demos/events.html +195 -0
  18. package/demos/fluent.html +647 -0
  19. package/demos/fractals.html +36 -0
  20. package/demos/genart.html +26 -0
  21. package/demos/gendream.html +26 -0
  22. package/demos/group.html +36 -0
  23. package/demos/home.html +587 -0
  24. package/demos/index.html +364 -0
  25. package/demos/isometric.html +34 -0
  26. package/demos/js/animations.js +452 -0
  27. package/demos/js/basic.js +204 -0
  28. package/demos/js/baskara.js +751 -0
  29. package/demos/js/bezier.js +692 -0
  30. package/demos/js/beziersignature.js +241 -0
  31. package/demos/js/blackhole/accretiondisk.obj.js +379 -0
  32. package/demos/js/blackhole/blackhole.obj.js +318 -0
  33. package/demos/js/blackhole/index.js +409 -0
  34. package/demos/js/blackhole/particle.js +56 -0
  35. package/demos/js/blackhole/starfield.obj.js +218 -0
  36. package/demos/js/blob.js +2263 -0
  37. package/demos/js/easing.js +477 -0
  38. package/demos/js/fluent.js +183 -0
  39. package/demos/js/fractals.js +931 -0
  40. package/demos/js/fractalworker.js +93 -0
  41. package/demos/js/genart.js +268 -0
  42. package/demos/js/gendream.js +209 -0
  43. package/demos/js/group.js +140 -0
  44. package/demos/js/info-toggle.js +25 -0
  45. package/demos/js/isometric.js +863 -0
  46. package/demos/js/kerr.js +1556 -0
  47. package/demos/js/lavalamp.js +590 -0
  48. package/demos/js/layout.js +354 -0
  49. package/demos/js/mondrian.js +285 -0
  50. package/demos/js/opacity.js +275 -0
  51. package/demos/js/painter.js +484 -0
  52. package/demos/js/particles-showcase.js +514 -0
  53. package/demos/js/particles.js +299 -0
  54. package/demos/js/patterns.js +397 -0
  55. package/demos/js/penrose/artifact.js +69 -0
  56. package/demos/js/penrose/blackhole.js +121 -0
  57. package/demos/js/penrose/constants.js +73 -0
  58. package/demos/js/penrose/game.js +943 -0
  59. package/demos/js/penrose/lore.js +278 -0
  60. package/demos/js/penrose/penrosescene.js +892 -0
  61. package/demos/js/penrose/ship.js +216 -0
  62. package/demos/js/penrose/sounds.js +211 -0
  63. package/demos/js/penrose/voidparticle.js +55 -0
  64. package/demos/js/penrose/voidscene.js +258 -0
  65. package/demos/js/penrose/voidship.js +144 -0
  66. package/demos/js/penrose/wormhole.js +46 -0
  67. package/demos/js/pipeline.js +555 -0
  68. package/demos/js/scene.js +304 -0
  69. package/demos/js/scenes.js +320 -0
  70. package/demos/js/schrodinger.js +410 -0
  71. package/demos/js/schwarzschild.js +1023 -0
  72. package/demos/js/shapes.js +628 -0
  73. package/demos/js/space/alien.js +171 -0
  74. package/demos/js/space/boom.js +98 -0
  75. package/demos/js/space/boss.js +353 -0
  76. package/demos/js/space/buff.js +73 -0
  77. package/demos/js/space/bullet.js +102 -0
  78. package/demos/js/space/constants.js +85 -0
  79. package/demos/js/space/game.js +1884 -0
  80. package/demos/js/space/hud.js +112 -0
  81. package/demos/js/space/laserbeam.js +179 -0
  82. package/demos/js/space/lightning.js +277 -0
  83. package/demos/js/space/minion.js +192 -0
  84. package/demos/js/space/missile.js +212 -0
  85. package/demos/js/space/player.js +430 -0
  86. package/demos/js/space/powerup.js +90 -0
  87. package/demos/js/space/starfield.js +58 -0
  88. package/demos/js/space/starpower.js +90 -0
  89. package/demos/js/spacetime.js +559 -0
  90. package/demos/js/svgtween.js +204 -0
  91. package/demos/js/tde/accretiondisk.js +418 -0
  92. package/demos/js/tde/blackhole.js +219 -0
  93. package/demos/js/tde/blackholescene.js +209 -0
  94. package/demos/js/tde/config.js +59 -0
  95. package/demos/js/tde/index.js +695 -0
  96. package/demos/js/tde/jets.js +290 -0
  97. package/demos/js/tde/lensedstarfield.js +147 -0
  98. package/demos/js/tde/tdestar.js +317 -0
  99. package/demos/js/tde/tidalstream.js +356 -0
  100. package/demos/js/tde_old/blackhole.obj.js +354 -0
  101. package/demos/js/tde_old/debris.obj.js +791 -0
  102. package/demos/js/tde_old/flare.obj.js +239 -0
  103. package/demos/js/tde_old/index.js +448 -0
  104. package/demos/js/tde_old/star.obj.js +812 -0
  105. package/demos/js/tiles.js +312 -0
  106. package/demos/js/tweendemo.js +79 -0
  107. package/demos/js/visibility.js +102 -0
  108. package/demos/kerr.html +28 -0
  109. package/demos/lavalamp.html +27 -0
  110. package/demos/layouts.html +37 -0
  111. package/demos/logo.svg +4 -0
  112. package/demos/loop.html +84 -0
  113. package/demos/mondrian.html +32 -0
  114. package/demos/og_image.png +0 -0
  115. package/demos/opacity.html +36 -0
  116. package/demos/painter.html +39 -0
  117. package/demos/particles-showcase.html +28 -0
  118. package/demos/particles.html +24 -0
  119. package/demos/patterns.html +33 -0
  120. package/demos/penrose-game.html +31 -0
  121. package/demos/pipeline.html +737 -0
  122. package/demos/scene.html +33 -0
  123. package/demos/scenes.html +96 -0
  124. package/demos/schrodinger.html +27 -0
  125. package/demos/schwarzschild.html +27 -0
  126. package/demos/shapes.html +16 -0
  127. package/demos/space.html +85 -0
  128. package/demos/spacetime.html +27 -0
  129. package/demos/svgtween.html +29 -0
  130. package/demos/tde.html +28 -0
  131. package/demos/tiles.html +28 -0
  132. package/demos/transforms.html +400 -0
  133. package/demos/tween.html +45 -0
  134. package/demos/visibility.html +33 -0
  135. package/disk_example.png +0 -0
  136. package/docs/README.md +222 -0
  137. package/docs/concepts/architecture-overview.md +204 -0
  138. package/docs/concepts/lifecycle.md +255 -0
  139. package/docs/concepts/rendering-pipeline.md +279 -0
  140. package/docs/concepts/tde-zorder.md +106 -0
  141. package/docs/concepts/two-layer-architecture.md +229 -0
  142. package/docs/getting-started/first-game.md +354 -0
  143. package/docs/getting-started/hello-world.md +269 -0
  144. package/docs/getting-started/installation.md +157 -0
  145. package/docs/modules/collision/README.md +453 -0
  146. package/docs/modules/fluent/README.md +1075 -0
  147. package/docs/modules/game/README.md +303 -0
  148. package/docs/modules/isometric-camera.md +210 -0
  149. package/docs/modules/isometric.md +275 -0
  150. package/docs/modules/painter/README.md +328 -0
  151. package/docs/modules/particle/README.md +559 -0
  152. package/docs/modules/shapes/README.md +221 -0
  153. package/docs/modules/shapes/base/euclidian.md +123 -0
  154. package/docs/modules/shapes/base/geometry2d.md +204 -0
  155. package/docs/modules/shapes/base/renderable.md +215 -0
  156. package/docs/modules/shapes/base/shape.md +262 -0
  157. package/docs/modules/shapes/base/transformable.md +243 -0
  158. package/docs/modules/shapes/hierarchy.md +218 -0
  159. package/docs/modules/state/README.md +577 -0
  160. package/docs/modules/util/README.md +99 -0
  161. package/docs/modules/util/camera3d.md +412 -0
  162. package/docs/modules/util/scene3d.md +395 -0
  163. package/index.html +17 -0
  164. package/jsdoc.json +50 -0
  165. package/package.json +55 -0
  166. package/readme.md +599 -0
  167. package/scripts/build-demo.js +69 -0
  168. package/scripts/bundle4llm.js +276 -0
  169. package/scripts/clearconsole.js +48 -0
  170. package/src/collision/collision-system.js +332 -0
  171. package/src/collision/collision.js +303 -0
  172. package/src/collision/index.js +10 -0
  173. package/src/fluent/fluent-game.js +430 -0
  174. package/src/fluent/fluent-go.js +1060 -0
  175. package/src/fluent/fluent-layer.js +152 -0
  176. package/src/fluent/fluent-scene.js +291 -0
  177. package/src/fluent/index.js +98 -0
  178. package/src/fluent/sketch.js +380 -0
  179. package/src/game/game.js +467 -0
  180. package/src/game/index.js +49 -0
  181. package/src/game/objects/go.js +220 -0
  182. package/src/game/objects/imagego.js +30 -0
  183. package/src/game/objects/index.js +54 -0
  184. package/src/game/objects/isometric-scene.js +260 -0
  185. package/src/game/objects/layoutscene.js +549 -0
  186. package/src/game/objects/scene.js +175 -0
  187. package/src/game/objects/scene3d.js +118 -0
  188. package/src/game/objects/text.js +221 -0
  189. package/src/game/objects/wrapper.js +232 -0
  190. package/src/game/pipeline.js +243 -0
  191. package/src/game/ui/button.js +396 -0
  192. package/src/game/ui/cursor.js +93 -0
  193. package/src/game/ui/fps.js +91 -0
  194. package/src/game/ui/index.js +5 -0
  195. package/src/game/ui/togglebutton.js +93 -0
  196. package/src/game/ui/tooltip.js +249 -0
  197. package/src/index.js +25 -0
  198. package/src/io/events.js +20 -0
  199. package/src/io/index.js +86 -0
  200. package/src/io/input.js +70 -0
  201. package/src/io/keys.js +152 -0
  202. package/src/io/mouse.js +61 -0
  203. package/src/io/touch.js +39 -0
  204. package/src/logger/debugtab.js +138 -0
  205. package/src/logger/index.js +3 -0
  206. package/src/logger/loggable.js +47 -0
  207. package/src/logger/logger.js +113 -0
  208. package/src/math/complex.js +37 -0
  209. package/src/math/constants.js +1 -0
  210. package/src/math/fractal.js +1271 -0
  211. package/src/math/gr.js +201 -0
  212. package/src/math/heat.js +202 -0
  213. package/src/math/index.js +12 -0
  214. package/src/math/noise.js +433 -0
  215. package/src/math/orbital.js +191 -0
  216. package/src/math/patterns.js +1339 -0
  217. package/src/math/penrose.js +259 -0
  218. package/src/math/quantum.js +115 -0
  219. package/src/math/random.js +195 -0
  220. package/src/math/tensor.js +1009 -0
  221. package/src/mixins/anchor.js +131 -0
  222. package/src/mixins/draggable.js +72 -0
  223. package/src/mixins/index.js +2 -0
  224. package/src/motion/bezier.js +132 -0
  225. package/src/motion/bounce.js +58 -0
  226. package/src/motion/easing.js +349 -0
  227. package/src/motion/float.js +130 -0
  228. package/src/motion/follow.js +125 -0
  229. package/src/motion/hop.js +52 -0
  230. package/src/motion/index.js +82 -0
  231. package/src/motion/motion.js +1124 -0
  232. package/src/motion/orbit.js +49 -0
  233. package/src/motion/oscillate.js +39 -0
  234. package/src/motion/parabolic.js +141 -0
  235. package/src/motion/patrol.js +147 -0
  236. package/src/motion/pendulum.js +48 -0
  237. package/src/motion/pulse.js +88 -0
  238. package/src/motion/shake.js +83 -0
  239. package/src/motion/spiral.js +144 -0
  240. package/src/motion/spring.js +150 -0
  241. package/src/motion/swing.js +47 -0
  242. package/src/motion/tween.js +92 -0
  243. package/src/motion/tweenetik.js +139 -0
  244. package/src/motion/waypoint.js +210 -0
  245. package/src/painter/index.js +8 -0
  246. package/src/painter/painter.colors.js +331 -0
  247. package/src/painter/painter.effects.js +230 -0
  248. package/src/painter/painter.img.js +229 -0
  249. package/src/painter/painter.js +295 -0
  250. package/src/painter/painter.lines.js +189 -0
  251. package/src/painter/painter.opacity.js +41 -0
  252. package/src/painter/painter.shapes.js +277 -0
  253. package/src/painter/painter.text.js +273 -0
  254. package/src/particle/emitter.js +124 -0
  255. package/src/particle/index.js +11 -0
  256. package/src/particle/particle-system.js +322 -0
  257. package/src/particle/particle.js +71 -0
  258. package/src/particle/updaters.js +170 -0
  259. package/src/shapes/arc.js +43 -0
  260. package/src/shapes/arrow.js +33 -0
  261. package/src/shapes/bezier.js +42 -0
  262. package/src/shapes/circle.js +62 -0
  263. package/src/shapes/clouds.js +56 -0
  264. package/src/shapes/cone.js +219 -0
  265. package/src/shapes/cross.js +70 -0
  266. package/src/shapes/cube.js +244 -0
  267. package/src/shapes/cylinder.js +254 -0
  268. package/src/shapes/diamond.js +48 -0
  269. package/src/shapes/euclidian.js +111 -0
  270. package/src/shapes/figure.js +115 -0
  271. package/src/shapes/geometry.js +220 -0
  272. package/src/shapes/group.js +375 -0
  273. package/src/shapes/heart.js +42 -0
  274. package/src/shapes/hexagon.js +26 -0
  275. package/src/shapes/image.js +192 -0
  276. package/src/shapes/index.js +111 -0
  277. package/src/shapes/line.js +29 -0
  278. package/src/shapes/pattern.js +90 -0
  279. package/src/shapes/pin.js +44 -0
  280. package/src/shapes/poly.js +31 -0
  281. package/src/shapes/prism.js +226 -0
  282. package/src/shapes/rect.js +35 -0
  283. package/src/shapes/renderable.js +333 -0
  284. package/src/shapes/ring.js +26 -0
  285. package/src/shapes/roundrect.js +95 -0
  286. package/src/shapes/shape.js +117 -0
  287. package/src/shapes/slice.js +26 -0
  288. package/src/shapes/sphere.js +314 -0
  289. package/src/shapes/sphere3d.js +537 -0
  290. package/src/shapes/square.js +15 -0
  291. package/src/shapes/star.js +99 -0
  292. package/src/shapes/svg.js +408 -0
  293. package/src/shapes/text.js +553 -0
  294. package/src/shapes/traceable.js +83 -0
  295. package/src/shapes/transform.js +357 -0
  296. package/src/shapes/transformable.js +172 -0
  297. package/src/shapes/triangle.js +26 -0
  298. package/src/sound/index.js +17 -0
  299. package/src/sound/sound.js +473 -0
  300. package/src/sound/synth.analyzer.js +149 -0
  301. package/src/sound/synth.effects.js +207 -0
  302. package/src/sound/synth.envelope.js +59 -0
  303. package/src/sound/synth.js +229 -0
  304. package/src/sound/synth.musical.js +160 -0
  305. package/src/sound/synth.noise.js +85 -0
  306. package/src/sound/synth.oscillators.js +293 -0
  307. package/src/state/index.js +10 -0
  308. package/src/state/state-machine.js +371 -0
  309. package/src/util/camera3d.js +438 -0
  310. package/src/util/index.js +6 -0
  311. package/src/util/isometric-camera.js +235 -0
  312. package/src/util/layout.js +317 -0
  313. package/src/util/position.js +147 -0
  314. package/src/util/tasks.js +47 -0
  315. package/src/util/zindex.js +287 -0
  316. package/src/webgl/index.js +9 -0
  317. package/src/webgl/shaders/sphere-shaders.js +994 -0
  318. package/src/webgl/webgl-renderer.js +388 -0
  319. package/tde.png +0 -0
  320. package/test/math/orbital.test.js +61 -0
  321. package/test/math/tensor.test.js +114 -0
  322. package/test/particle/emitter.test.js +204 -0
  323. package/test/particle/particle-system.test.js +310 -0
  324. package/test/particle/particle.test.js +116 -0
  325. package/test/particle/updaters.test.js +386 -0
  326. package/test/setup.js +120 -0
  327. package/test/shapes/euclidian.test.js +44 -0
  328. package/test/shapes/geometry.test.js +86 -0
  329. package/test/shapes/group.test.js +86 -0
  330. package/test/shapes/rectangle.test.js +64 -0
  331. package/test/shapes/transform.test.js +379 -0
  332. package/test/util/camera3d.test.js +428 -0
  333. package/test/util/scene3d.test.js +352 -0
  334. package/types/collision.d.ts +249 -0
  335. package/types/common.d.ts +155 -0
  336. package/types/game.d.ts +497 -0
  337. package/types/index.d.ts +309 -0
  338. package/types/io.d.ts +188 -0
  339. package/types/logger.d.ts +127 -0
  340. package/types/math.d.ts +268 -0
  341. package/types/mixins.d.ts +92 -0
  342. package/types/motion.d.ts +678 -0
  343. package/types/painter.d.ts +378 -0
  344. package/types/shapes.d.ts +864 -0
  345. package/types/sound.d.ts +672 -0
  346. package/types/state.d.ts +251 -0
  347. package/types/util.d.ts +253 -0
  348. package/vite.config.js +50 -0
  349. package/vitest.config.js +13 -0
@@ -0,0 +1,251 @@
1
+ /**
2
+ * GCanvas State Machine Types
3
+ * State management utilities for game objects.
4
+ * @module state
5
+ */
6
+
7
+ // ==========================================================================
8
+ // State Machine Configuration
9
+ // ==========================================================================
10
+
11
+ /** State transition definition */
12
+ export interface StateTransition {
13
+ /** Target state to transition to */
14
+ target?: string;
15
+ /** Guard function - transition only if returns true */
16
+ guard?: (data?: any) => boolean;
17
+ /** Action to run before transition */
18
+ action?: (data?: any) => void;
19
+ }
20
+
21
+ /** Event handlers for a state */
22
+ export interface StateEvents {
23
+ [triggerName: string]: string | StateTransition;
24
+ }
25
+
26
+ /** Individual state configuration */
27
+ export interface StateConfig {
28
+ /** Duration in seconds before auto-transitioning (optional) */
29
+ duration?: number;
30
+ /** Next state to transition to after duration (for timed states) */
31
+ next?: string;
32
+ /** Called when entering this state */
33
+ enter?: (data?: any) => void;
34
+ /** Called each frame while in this state */
35
+ update?: (dt: number) => void;
36
+ /** Called when leaving this state */
37
+ exit?: (data?: any) => void;
38
+ /** Called when a timed state completes without a 'next' state */
39
+ onComplete?: () => void;
40
+ /** Event-based transitions */
41
+ on?: StateEvents;
42
+ }
43
+
44
+ /** State definitions object */
45
+ export interface States {
46
+ [stateName: string]: StateConfig;
47
+ }
48
+
49
+ /** StateMachine constructor options */
50
+ export interface StateMachineOptions {
51
+ /** Initial state name */
52
+ initial?: string;
53
+ /** State definitions */
54
+ states?: States;
55
+ /** Context object passed to callbacks (usually `this`) */
56
+ context?: any;
57
+ }
58
+
59
+ /** Phase definition for sequence-based state machines */
60
+ export interface PhaseConfig {
61
+ /** Phase name */
62
+ name: string;
63
+ /** Phase duration in seconds */
64
+ duration: number;
65
+ /** Called when entering this phase */
66
+ enter?: () => void;
67
+ /** Called each frame during this phase */
68
+ update?: (dt: number) => void;
69
+ /** Called when leaving this phase */
70
+ exit?: () => void;
71
+ }
72
+
73
+ /** Options for StateMachine.fromSequence() */
74
+ export interface SequenceOptions {
75
+ /** Whether to loop back to first phase after last */
76
+ loop?: boolean;
77
+ /** Called when sequence completes (if not looping) */
78
+ onComplete?: () => void;
79
+ /** Context object passed to callbacks */
80
+ context?: any;
81
+ }
82
+
83
+ // ==========================================================================
84
+ // StateMachine Class
85
+ // ==========================================================================
86
+
87
+ /**
88
+ * Flexible state management for game objects.
89
+ * Manages states with enter/update/exit lifecycle callbacks.
90
+ * Supports timed transitions, sequential phases, and conditional triggers.
91
+ *
92
+ * @example
93
+ * // Basic usage
94
+ * const fsm = new StateMachine({
95
+ * initial: 'idle',
96
+ * states: {
97
+ * idle: {
98
+ * enter: () => console.log('Now idle'),
99
+ * update: (dt) => { // per-frame logic },
100
+ * exit: () => console.log('Leaving idle')
101
+ * },
102
+ * walking: {
103
+ * enter: () => player.startWalkAnimation(),
104
+ * update: (dt) => player.move(dt)
105
+ * }
106
+ * }
107
+ * });
108
+ *
109
+ * @example
110
+ * // Timed phase sequence
111
+ * const laser = new StateMachine({
112
+ * initial: 'warning',
113
+ * states: {
114
+ * warning: { duration: 0.3, next: 'charging' },
115
+ * charging: { duration: 0.2, next: 'active' },
116
+ * active: {
117
+ * duration: 0.4,
118
+ * next: 'fade',
119
+ * enter: () => { laser.canDamage = true; }
120
+ * },
121
+ * fade: {
122
+ * duration: 0.2,
123
+ * exit: () => { laser.destroy(); }
124
+ * }
125
+ * }
126
+ * });
127
+ */
128
+ export class StateMachine {
129
+ /** State definitions */
130
+ states: States;
131
+
132
+ /** Current state name */
133
+ currentState: string | null;
134
+
135
+ /** Previous state name */
136
+ previousState: string | null;
137
+
138
+ /** Time spent in current state */
139
+ stateTime: number;
140
+
141
+ /** Context passed to state callbacks */
142
+ context: any;
143
+
144
+ /** Whether the state machine is paused */
145
+ paused: boolean;
146
+
147
+ /** Global state change callback */
148
+ onStateChange: ((newState: string, previousState: string | null, data?: any) => void) | null;
149
+
150
+ constructor(config?: StateMachineOptions);
151
+
152
+ /**
153
+ * Get the current state name
154
+ */
155
+ get state(): string | null;
156
+
157
+ /**
158
+ * Get the current state configuration
159
+ */
160
+ get currentStateConfig(): StateConfig | null;
161
+
162
+ /**
163
+ * Check if currently in a specific state
164
+ */
165
+ is(stateName: string): boolean;
166
+
167
+ /**
168
+ * Check if currently in any of the given states
169
+ */
170
+ isAny(...stateNames: string[]): boolean;
171
+
172
+ /**
173
+ * Add or update a state definition
174
+ * @returns this for chaining
175
+ */
176
+ addState(name: string, config: StateConfig): this;
177
+
178
+ /**
179
+ * Remove a state definition
180
+ * @returns this for chaining
181
+ */
182
+ removeState(name: string): this;
183
+
184
+ /**
185
+ * Transition to a new state
186
+ * @param newState - State to transition to
187
+ * @param data - Optional data passed to enter callback
188
+ * @returns True if transition occurred
189
+ */
190
+ setState(newState: string, data?: any): boolean;
191
+
192
+ /**
193
+ * Attempt to transition based on a trigger/event
194
+ * @param trigger - Trigger name to check against state transitions
195
+ * @param data - Optional data passed to callbacks
196
+ * @returns True if a transition occurred
197
+ */
198
+ trigger(trigger: string, data?: any): boolean;
199
+
200
+ /**
201
+ * Update the state machine (call each frame)
202
+ * @param dt - Delta time in seconds
203
+ */
204
+ update(dt: number): void;
205
+
206
+ /**
207
+ * Get normalized progress through current state (0-1)
208
+ * Only meaningful for states with a duration
209
+ */
210
+ get progress(): number;
211
+
212
+ /**
213
+ * Get remaining time in current state
214
+ * Only meaningful for states with a duration
215
+ */
216
+ get remaining(): number;
217
+
218
+ /**
219
+ * Check if current state is a timed state
220
+ */
221
+ get isTimed(): boolean;
222
+
223
+ /**
224
+ * Pause the state machine (stops update processing)
225
+ */
226
+ pause(): void;
227
+
228
+ /**
229
+ * Resume the state machine
230
+ */
231
+ resume(): void;
232
+
233
+ /**
234
+ * Reset to initial state or specific state
235
+ * @param state - State to reset to (defaults to first defined state)
236
+ */
237
+ reset(state?: string): void;
238
+
239
+ /**
240
+ * Create a state machine from a simple phase sequence.
241
+ * Convenience method for common "phase 1 → phase 2 → phase 3" patterns.
242
+ *
243
+ * @example
244
+ * const lightning = StateMachine.fromSequence([
245
+ * { name: 'tracing', duration: 0.4, enter: () => startTrace() },
246
+ * { name: 'active', duration: 0.3, enter: () => enableDamage() },
247
+ * { name: 'fade', duration: 0.2, exit: () => destroy() }
248
+ * ]);
249
+ */
250
+ static fromSequence(phases: PhaseConfig[], options?: SequenceOptions): StateMachine;
251
+ }
@@ -0,0 +1,253 @@
1
+ /**
2
+ * GCanvas Util Module
3
+ * Utility classes and functions for layout, positioning, z-ordering, and task management.
4
+ * @module util
5
+ */
6
+
7
+ import { Point, LayoutResult } from './common';
8
+ import { Transformable } from './shapes';
9
+
10
+ // ==========================================================================
11
+ // Z-Ordered Collection
12
+ // ==========================================================================
13
+
14
+ /** Options for ZOrderedCollection */
15
+ export interface ZOrderedCollectionOptions {
16
+ /** Sort children by zIndex when rendering */
17
+ sortByZIndex?: boolean;
18
+ }
19
+
20
+ /**
21
+ * Z-ordered collection for managing child objects.
22
+ * Maintains rendering order based on zIndex property.
23
+ */
24
+ export class ZOrderedCollection {
25
+ /** Array of child objects */
26
+ children: Transformable[];
27
+
28
+ constructor(options?: ZOrderedCollectionOptions);
29
+
30
+ /**
31
+ * Add an object to the collection.
32
+ * @param object - Object to add
33
+ */
34
+ add(object: Transformable): void;
35
+
36
+ /**
37
+ * Remove an object from the collection.
38
+ * @param object - Object to remove
39
+ * @returns Whether object was found and removed
40
+ */
41
+ remove(object: Transformable): boolean;
42
+
43
+ /** Remove all objects */
44
+ clear(): void;
45
+
46
+ /**
47
+ * Get children sorted by zIndex.
48
+ * @returns Sorted array of children
49
+ */
50
+ getSortedChildren(): Transformable[];
51
+
52
+ /** Move object to front (highest z-order) */
53
+ bringToFront(object: Transformable): void;
54
+
55
+ /** Move object to back (lowest z-order) */
56
+ sendToBack(object: Transformable): void;
57
+
58
+ /** Move object forward one z-level */
59
+ bringForward(object: Transformable): void;
60
+
61
+ /** Move object backward one z-level */
62
+ sendBackward(object: Transformable): void;
63
+ }
64
+
65
+ // ==========================================================================
66
+ // Position Constants
67
+ // ==========================================================================
68
+
69
+ /**
70
+ * Position/anchor utilities with layout constants.
71
+ * Provides named constants for common anchor positions.
72
+ *
73
+ * @example
74
+ * const pos = Position.parse(Position.CENTER, canvasWidth, canvasHeight);
75
+ */
76
+ export class Position {
77
+ static readonly TOP_LEFT: string;
78
+ static readonly TOP_CENTER: string;
79
+ static readonly TOP_RIGHT: string;
80
+ static readonly CENTER_LEFT: string;
81
+ static readonly CENTER: string;
82
+ static readonly CENTER_RIGHT: string;
83
+ static readonly BOTTOM_LEFT: string;
84
+ static readonly BOTTOM_CENTER: string;
85
+ static readonly BOTTOM_RIGHT: string;
86
+
87
+ /**
88
+ * Parse a position string into coordinates.
89
+ * @param position - Position string (e.g., "center", "top-left")
90
+ * @param containerWidth - Container width
91
+ * @param containerHeight - Container height
92
+ * @param objectWidth - Optional object width for centering
93
+ * @param objectHeight - Optional object height for centering
94
+ * @returns Calculated position
95
+ */
96
+ static parse(
97
+ position: string,
98
+ containerWidth: number,
99
+ containerHeight: number,
100
+ objectWidth?: number,
101
+ objectHeight?: number
102
+ ): Point;
103
+ }
104
+
105
+ // ==========================================================================
106
+ // Task Manager
107
+ // ==========================================================================
108
+
109
+ /**
110
+ * Task manager for scheduling delayed operations.
111
+ */
112
+ export class TaskManager {
113
+ /**
114
+ * Add a task to be executed after a delay.
115
+ * @param task - Function to execute
116
+ * @param delay - Delay in seconds (default: 0)
117
+ */
118
+ add(task: () => void, delay?: number): void;
119
+
120
+ /**
121
+ * Update all tasks.
122
+ * @param dt - Delta time in seconds
123
+ */
124
+ update(dt: number): void;
125
+
126
+ /** Clear all pending tasks */
127
+ clear(): void;
128
+ }
129
+
130
+ // ==========================================================================
131
+ // Layout Functions
132
+ // ==========================================================================
133
+
134
+ /** Item with dimensions for layout calculations */
135
+ export interface LayoutItem {
136
+ width?: number;
137
+ height?: number;
138
+ x?: number;
139
+ y?: number;
140
+ }
141
+
142
+ /** Options for applyLayout */
143
+ export interface ApplyLayoutOptions {
144
+ /** X offset to apply to all positions */
145
+ offsetX?: number;
146
+ /** Y offset to apply to all positions */
147
+ offsetY?: number;
148
+ /** Transform function to apply to positions */
149
+ transform?: (pos: Point) => Point;
150
+ }
151
+
152
+ /** Options for horizontal/vertical layouts */
153
+ export interface LinearLayoutOptions {
154
+ /** Space between items (default: 10) */
155
+ spacing?: number;
156
+ /** Padding around entire layout (default: 0) */
157
+ padding?: number;
158
+ /** Alignment: "start", "center", or "end" (default: "start") */
159
+ align?: 'start' | 'center' | 'end';
160
+ /** Position items relative to their centers (default: true) */
161
+ centerItems?: boolean;
162
+ }
163
+
164
+ /** Options for tile layout */
165
+ export interface TileLayoutOptions {
166
+ /** Number of columns (default: 4) */
167
+ columns?: number;
168
+ /** Space between items (default: 10) */
169
+ spacing?: number;
170
+ /** Padding around entire layout (default: 0) */
171
+ padding?: number;
172
+ /** Position items relative to their centers (default: true) */
173
+ centerItems?: boolean;
174
+ }
175
+
176
+ /** Options for grid layout */
177
+ export interface GridLayoutOptions {
178
+ /** Number of columns */
179
+ columns?: number;
180
+ /** Number of rows */
181
+ rows?: number;
182
+ /** Fixed cell width */
183
+ cellWidth?: number;
184
+ /** Fixed cell height */
185
+ cellHeight?: number;
186
+ /** Space between cells (default: 10) */
187
+ spacing?: number;
188
+ /** Padding around entire layout (default: 0) */
189
+ padding?: number;
190
+ /** Position items relative to their centers (default: true) */
191
+ centerItems?: boolean;
192
+ }
193
+
194
+ /**
195
+ * Apply calculated positions to items.
196
+ * @param items - Array of objects to position (must have x, y properties)
197
+ * @param positions - Array of position objects from layout functions
198
+ * @param options - Options for applying positions
199
+ * @returns The items with updated positions
200
+ */
201
+ export function applyLayout<T extends LayoutItem>(
202
+ items: T[],
203
+ positions: Point[],
204
+ options?: ApplyLayoutOptions
205
+ ): T[];
206
+
207
+ /**
208
+ * Create a horizontal layout (items arranged left to right).
209
+ * @param items - Array of objects with width and height
210
+ * @param options - Layout options
211
+ * @returns Layout result with positions and dimensions
212
+ *
213
+ * @example
214
+ * const result = horizontalLayout(buttons, { spacing: 20 });
215
+ * applyLayout(buttons, result.positions);
216
+ */
217
+ export function horizontalLayout(
218
+ items: LayoutItem[],
219
+ options?: LinearLayoutOptions
220
+ ): LayoutResult;
221
+
222
+ /**
223
+ * Create a vertical layout (items arranged top to bottom).
224
+ * @param items - Array of objects with width and height
225
+ * @param options - Layout options
226
+ * @returns Layout result with positions and dimensions
227
+ */
228
+ export function verticalLayout(
229
+ items: LayoutItem[],
230
+ options?: LinearLayoutOptions
231
+ ): LayoutResult;
232
+
233
+ /**
234
+ * Create a tile layout (items in a grid with fixed columns).
235
+ * @param items - Array of objects with width and height
236
+ * @param options - Layout options
237
+ * @returns Layout result with positions and dimensions
238
+ */
239
+ export function tileLayout(
240
+ items: LayoutItem[],
241
+ options?: TileLayoutOptions
242
+ ): LayoutResult;
243
+
244
+ /**
245
+ * Create a flexible grid layout.
246
+ * @param items - Array of objects with width and height
247
+ * @param options - Layout options
248
+ * @returns Layout result with positions and dimensions
249
+ */
250
+ export function gridLayout(
251
+ items: LayoutItem[],
252
+ options?: GridLayoutOptions
253
+ ): LayoutResult;
package/vite.config.js ADDED
@@ -0,0 +1,50 @@
1
+ import { defineConfig } from "vite";
2
+ import path from "path";
3
+
4
+ const libEntry = path.resolve(__dirname, "src/index.js");
5
+
6
+ export default defineConfig(({ mode }) => {
7
+ const isDebug = mode === "debug";
8
+
9
+ return {
10
+ server: {
11
+ port: 9195,
12
+ strictPort: true, // Don't try other ports if 9195 is in use
13
+ },
14
+ build: {
15
+ lib: {
16
+ entry: libEntry,
17
+ name: "GCanvas",
18
+ formats: isDebug ? ["umd"] : ["umd", "es"],
19
+ fileName: (format) => {
20
+ if (isDebug) return "gcanvas.debug.js";
21
+ return `gcanvas.${format}.js`;
22
+ },
23
+ },
24
+ minify: isDebug ? false : "terser",
25
+ terserOptions: {
26
+ compress: true,
27
+ mangle: true,
28
+ format: {
29
+ comments: false,
30
+ },
31
+ },
32
+ outDir: "dist",
33
+ emptyOutDir: true,
34
+ rollupOptions: {
35
+ output: [
36
+ {
37
+ format: "umd",
38
+ entryFileNames: "gcanvas.umd.js",
39
+ name: "GCanvas",
40
+ globals: {},
41
+ },
42
+ {
43
+ format: "es",
44
+ entryFileNames: "gcanvas.es.js",
45
+ },
46
+ ],
47
+ },
48
+ },
49
+ };
50
+ });
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: 'jsdom',
6
+ globals: true,
7
+ setupFiles: ['./test/setup.js'],
8
+ coverage: {
9
+ provider: 'v8',
10
+ reporter: ['text', 'json', 'html'],
11
+ },
12
+ },
13
+ });