@oliversalzburg/js-utils 0.0.14 → 0.0.15

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 (151) hide show
  1. package/_site/assets/navigation.js +1 -1
  2. package/_site/assets/search.js +1 -1
  3. package/_site/classes/AbstractError.html +47 -8
  4. package/_site/classes/Canvas.html +59 -20
  5. package/_site/classes/CanvasSandbox.html +76 -0
  6. package/_site/classes/Euler.html +217 -0
  7. package/_site/classes/InternalError.html +48 -9
  8. package/_site/classes/InvalidArgumentError.html +47 -8
  9. package/_site/classes/InvalidOperationError.html +47 -8
  10. package/_site/classes/Matrix3.html +167 -0
  11. package/_site/classes/NotImplementedError.html +47 -8
  12. package/_site/classes/PermissionViolationError.html +47 -8
  13. package/_site/classes/Quaternion.html +211 -0
  14. package/_site/classes/Random.html +56 -15
  15. package/_site/classes/RenderLoop.html +58 -19
  16. package/_site/classes/ResourceConflictError.html +47 -8
  17. package/_site/classes/Transformation.html +52 -0
  18. package/_site/classes/UnexpectedNilError.html +44 -5
  19. package/_site/classes/UnknownError.html +47 -8
  20. package/_site/classes/Vector2.html +77 -38
  21. package/_site/classes/Vector3.html +201 -15
  22. package/_site/classes/Vector4.html +156 -0
  23. package/_site/favicon.ico +0 -0
  24. package/_site/functions/addVector2.html +43 -4
  25. package/_site/functions/addVector3.html +44 -0
  26. package/_site/functions/blend.html +41 -2
  27. package/_site/functions/blendAdditive.html +41 -2
  28. package/_site/functions/blendSubtractive.html +41 -2
  29. package/_site/functions/clamp.html +41 -2
  30. package/_site/functions/coalesceOnRejection.html +48 -0
  31. package/_site/functions/cosDeg.html +41 -2
  32. package/_site/functions/crossVector3.html +44 -0
  33. package/_site/functions/deg2rad.html +41 -2
  34. package/_site/functions/difference.html +41 -2
  35. package/_site/functions/distance.html +41 -2
  36. package/_site/functions/dotVector3.html +44 -0
  37. package/_site/functions/errorToJSON.html +41 -2
  38. package/_site/functions/errorToRecord.html +41 -2
  39. package/_site/functions/errorToSimpleSerializable.html +41 -2
  40. package/_site/functions/filterType.html +41 -2
  41. package/_site/functions/formatString.html +41 -2
  42. package/_site/functions/formatStringTemplate.html +41 -2
  43. package/_site/functions/fromRGB.html +41 -2
  44. package/_site/functions/fromRGBA.html +41 -2
  45. package/_site/functions/getA.html +41 -2
  46. package/_site/functions/getB.html +41 -2
  47. package/_site/functions/getDocumentElementTypeById.html +41 -2
  48. package/_site/functions/getG.html +41 -2
  49. package/_site/functions/getR.html +41 -2
  50. package/_site/functions/intersect.html +41 -2
  51. package/_site/functions/is.html +41 -2
  52. package/_site/functions/isError.html +41 -2
  53. package/_site/functions/isInteger.html +41 -2
  54. package/_site/functions/isNil.html +41 -2
  55. package/_site/functions/isqrt.html +41 -2
  56. package/_site/functions/multiplyVector2.html +43 -4
  57. package/_site/functions/multiplyVector3.html +44 -0
  58. package/_site/functions/mustExist.html +41 -2
  59. package/_site/functions/nextPalette.html +42 -2
  60. package/_site/functions/prepareAsyncContext.html +46 -0
  61. package/_site/functions/putPixel32.html +41 -2
  62. package/_site/functions/putPixel32Add.html +41 -2
  63. package/_site/functions/putPixel32Sub.html +41 -2
  64. package/_site/functions/putSubPixel32.html +41 -2
  65. package/_site/functions/rad2deg.html +41 -2
  66. package/_site/functions/randomRange.html +41 -2
  67. package/_site/functions/safeRGBComponent.html +41 -2
  68. package/_site/functions/seedFromString.html +41 -2
  69. package/_site/functions/shuffleArray.html +41 -2
  70. package/_site/functions/sinDeg.html +41 -2
  71. package/_site/functions/sleep.html +41 -2
  72. package/_site/functions/somecolor.html +41 -2
  73. package/_site/functions/subtractVector2.html +43 -4
  74. package/_site/functions/subtractVector3.html +44 -0
  75. package/_site/functions/toGrayScale.html +41 -2
  76. package/_site/functions/unknownToError.html +41 -2
  77. package/_site/index.html +41 -2
  78. package/_site/interfaces/CanvasOptions.html +42 -3
  79. package/_site/interfaces/CanvasSandboxApplication.html +60 -0
  80. package/_site/interfaces/CanvasSandboxExpectedOptions.html +48 -0
  81. package/_site/interfaces/RenderLoopOptions.html +43 -4
  82. package/_site/modules.html +59 -4
  83. package/_site/types/AnyAsyncFunction.html +41 -0
  84. package/_site/types/AnyConstructor.html +41 -2
  85. package/_site/types/AnyFunction.html +41 -2
  86. package/_site/types/ConstructorOf.html +41 -2
  87. package/_site/types/FunctionReturning.html +41 -2
  88. package/_site/types/Maybe.html +41 -2
  89. package/_site/types/Mixin.html +41 -2
  90. package/_site/types/Nil.html +41 -2
  91. package/_site/types/RenderLoopCallback.html +41 -2
  92. package/_site/types/SerializedError.html +41 -2
  93. package/_site/variables/MS_PER_FRAME_60FPS.html +42 -1
  94. package/_site/variables/PALETTES.html +41 -2
  95. package/_site/variables/TWO_PI.html +41 -2
  96. package/_site/variables/random-1.html +41 -2
  97. package/docs/assets/favicon.ico +0 -0
  98. package/lib/Async.d.ts +3 -0
  99. package/lib/Async.js +17 -0
  100. package/lib/Async.js.map +1 -0
  101. package/lib/async.d.ts +24 -0
  102. package/lib/async.js +37 -0
  103. package/lib/async.js.map +1 -0
  104. package/lib/core.d.ts +4 -0
  105. package/lib/core.js.map +1 -1
  106. package/lib/graphics/canvas-sandbox.d.ts +206 -0
  107. package/lib/graphics/canvas-sandbox.js +272 -0
  108. package/lib/graphics/canvas-sandbox.js.map +1 -0
  109. package/lib/graphics/canvas.d.ts +13 -6
  110. package/lib/graphics/canvas.js +52 -16
  111. package/lib/graphics/canvas.js.map +1 -1
  112. package/lib/graphics/core.d.ts +2 -1
  113. package/lib/graphics/core.js +2 -0
  114. package/lib/graphics/core.js.map +1 -1
  115. package/lib/graphics/index.d.ts +1 -0
  116. package/lib/graphics/index.js +1 -0
  117. package/lib/graphics/index.js.map +1 -1
  118. package/lib/graphics/render-loop.d.ts +1 -0
  119. package/lib/graphics/render-loop.js +1 -0
  120. package/lib/graphics/render-loop.js.map +1 -1
  121. package/lib/index.d.ts +1 -0
  122. package/lib/index.js +1 -0
  123. package/lib/index.js.map +1 -1
  124. package/lib/math/euler.d.ts +19 -0
  125. package/lib/math/euler.js +23 -0
  126. package/lib/math/euler.js.map +1 -0
  127. package/lib/math/index.d.ts +5 -1
  128. package/lib/math/index.js +5 -1
  129. package/lib/math/index.js.map +1 -1
  130. package/lib/math/matrix3.d.ts +218 -0
  131. package/lib/math/matrix3.js +509 -0
  132. package/lib/math/matrix3.js.map +1 -0
  133. package/lib/math/quaternion.d.ts +120 -0
  134. package/lib/math/quaternion.js +272 -0
  135. package/lib/math/quaternion.js.map +1 -0
  136. package/lib/math/transformation.d.ts +27 -0
  137. package/lib/math/transformation.js +32 -0
  138. package/lib/math/transformation.js.map +1 -0
  139. package/lib/math/vector2.d.ts +19 -19
  140. package/lib/math/vector2.js +12 -12
  141. package/lib/math/vector2.js.map +1 -1
  142. package/lib/math/vector3.d.ts +256 -3
  143. package/lib/math/vector3.js +440 -1
  144. package/lib/math/vector3.js.map +1 -1
  145. package/lib/math/vector4.d.ts +183 -0
  146. package/lib/math/vector4.js +303 -0
  147. package/lib/math/vector4.js.map +1 -0
  148. package/lib/random.d.ts +5 -1
  149. package/lib/random.js +7 -1
  150. package/lib/random.js.map +1 -1
  151. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Async.js","sourceRoot":"","sources":["../source/Async.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,OAA+B,EAC/B,OAAkC,EAClC,MAA+B,EAC/B,EAAE;IACF,OAAO,KAAK,OAAO,EAAE;SAClB,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;SAClC,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAA+B,EAAE,EAAE;IACrE,OAAO,GAAG,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,UAAmE,EACnE,EAAK,EACL,EAAE;IACF,IAAI;QACF,OAAO,MAAM,UAAU,EAAE,CAAC;KAC3B;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,EAAE,CAAC;KACX;AACH,CAAC,CAAC"}
package/lib/async.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { AnyAsyncFunction, FunctionReturning } from "./core.js";
2
+ /**
3
+ * Wraps the given asynchronous function in a new function that will ignore any outcome of
4
+ * the context as it resolves.
5
+ *
6
+ * This can be useful when providing asynchonous event handler to `.addEventlistener()`,
7
+ * which only expects synchronous functions.
8
+ * @param context The asynchronous function to exectute.
9
+ * @returns A function returning nothing.
10
+ * @group Async
11
+ */
12
+ export declare const prepareAsyncContext: (context: AnyAsyncFunction) => (() => void);
13
+ /**
14
+ * Executes an asynchronous function and resolves with an alternative result
15
+ * in case the function failed.
16
+ * @param executable The asynchronous function to execute.
17
+ * @param to The result we want to return when the function errors.
18
+ * @template {unknown} TExecutableReturn The return type of the function.
19
+ * @template {unknown} TCoalesce The type of the object to coalesce to.
20
+ * @returns Whatever the function resolved to, or the provided replacement,
21
+ * in case the function failed.
22
+ * @group Async
23
+ */
24
+ export declare const coalesceOnRejection: <TExecutableReturn, TCoalesce>(executable: FunctionReturning<Promise<TExecutableReturn>>, to: TCoalesce) => Promise<TExecutableReturn | TCoalesce>;
package/lib/async.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Wraps the given asynchronous function in a new function that will ignore any outcome of
3
+ * the context as it resolves.
4
+ *
5
+ * This can be useful when providing asynchonous event handler to `.addEventlistener()`,
6
+ * which only expects synchronous functions.
7
+ * @param context The asynchronous function to exectute.
8
+ * @returns A function returning nothing.
9
+ * @group Async
10
+ */
11
+ export const prepareAsyncContext = (context) => {
12
+ return () => {
13
+ void context()
14
+ .then(() => undefined)
15
+ .catch(() => undefined);
16
+ };
17
+ };
18
+ /**
19
+ * Executes an asynchronous function and resolves with an alternative result
20
+ * in case the function failed.
21
+ * @param executable The asynchronous function to execute.
22
+ * @param to The result we want to return when the function errors.
23
+ * @template {unknown} TExecutableReturn The return type of the function.
24
+ * @template {unknown} TCoalesce The type of the object to coalesce to.
25
+ * @returns Whatever the function resolved to, or the provided replacement,
26
+ * in case the function failed.
27
+ * @group Async
28
+ */
29
+ export const coalesceOnRejection = async (executable, to) => {
30
+ try {
31
+ return await executable();
32
+ }
33
+ catch (error) {
34
+ return to;
35
+ }
36
+ };
37
+ //# sourceMappingURL=async.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.js","sourceRoot":"","sources":["../source/async.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAyB,EAAgB,EAAE;IAC7E,OAAO,GAAG,EAAE;QACV,KAAK,OAAO,EAAE;aACX,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;aACrB,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,UAAyD,EACzD,EAAa,EACb,EAAE;IACF,IAAI;QACF,OAAO,MAAM,UAAU,EAAE,CAAC;KAC3B;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,EAAE,CAAC;KACX;AACH,CAAC,CAAC"}
package/lib/core.d.ts CHANGED
@@ -6,6 +6,10 @@ export type ConstructorOf<T = Record<string, unknown>> = new (...args: Array<any
6
6
  * Describes literally any function.
7
7
  */
8
8
  export type AnyFunction = (...args: Array<any>) => any;
9
+ /**
10
+ * Describes literally any asynchronous function.
11
+ */
12
+ export type AnyAsyncFunction = (...args: Array<any>) => Promise<any>;
9
13
  /**
10
14
  * Any constructor
11
15
  */
package/lib/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../source/core.ts"],"names":[],"mappings":"AAAA,uDAAuD;AA4BvD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,IAAY,EAAU,EAAE;IAC1E,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../source/core.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAiCvD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,IAAY,EAAU,EAAE;IAC1E,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC"}
@@ -0,0 +1,206 @@
1
+ /// <reference types="@types/web" />
2
+ import { Random } from "../random.js";
3
+ import { Canvas } from "./canvas.js";
4
+ import { RenderLoop } from "./render-loop.js";
5
+ /**
6
+ * The options your application has to accept so it can interact with the {@linkcode CanvasSandbox}.
7
+ * @group Graphics
8
+ */
9
+ export interface CanvasSandboxExpectedOptions {
10
+ /**
11
+ * Should your application run in dark mode?
12
+ * You can ignore this setting and produce any colored output you want,
13
+ * but the setting will be toggeled by the sandbox according to the user's
14
+ * browser/OS preference.
15
+ */
16
+ darkMode: boolean;
17
+ /**
18
+ * The seed for the PRNG.
19
+ */
20
+ seed: string;
21
+ }
22
+ /**
23
+ * Describes an application running inside the {@linkcode CanvasSandbox}.
24
+ * @template {CanvasSandboxExpectedOptions} TApplicationOptions The type of the options object
25
+ * with which the application is constructed.
26
+ * @group Graphics
27
+ */
28
+ export interface CanvasSandboxApplication<TApplicationOptions extends CanvasSandboxExpectedOptions> {
29
+ /**
30
+ * The options with which the application was constructed.
31
+ */
32
+ options: TApplicationOptions;
33
+ /**
34
+ * The PRNG used in this application.
35
+ */
36
+ random: Random;
37
+ /**
38
+ * Is the application currently paused?
39
+ * Should be get/set, but can also be ignored, if the feature isn't used.
40
+ */
41
+ paused: boolean;
42
+ /**
43
+ * Request the application to draw a new frame.
44
+ * @param delta How many milliseconds passed since the last frame draw.
45
+ * @param timestamp The current timestamp.
46
+ */
47
+ onDraw(delta: number, timestamp: number): void;
48
+ /**
49
+ * Reconfigure the application with the given options and restart it.
50
+ * @param canvas The canvas to use.
51
+ * @param options The new options to use.
52
+ */
53
+ reconfigure(canvas: Canvas, options: Partial<TApplicationOptions>): void;
54
+ /**
55
+ * Start the application.
56
+ */
57
+ start(): void;
58
+ }
59
+ /**
60
+ * The {@linkcode CanvasSandbox} provides a scaffold to quickly perform experiments
61
+ * with a {@linkcode !HTMLCanvasElement} in a document. Common functionality for such
62
+ * experiments is implemented in the sandbox already.
63
+ * @example
64
+ * ```ts
65
+ * import { Random, seedFromString } from "@oliversalzburg/js-utils/lib/random.js";
66
+ * import { Canvas } from "@oliversalzburg/js-utils/lib/graphics/canvas.js";
67
+ * import { getDocumentElementTypeById } from "@oliversalzburg/js-utils/lib/dom/core.js";
68
+ * import { CanvasSandbox } from "@oliversalzburg/js-utils/lib/graphics/canvas-sandbox.js";
69
+ *
70
+ * interface ApplicationOptions {
71
+ * seed: string;
72
+ * somethingElse: number;
73
+ * }
74
+ *
75
+ * class Application {
76
+ * canvas: Canvas;
77
+ * options: ApplicationOptions;
78
+ * random: Random;
79
+ *
80
+ * constructor(canvas:Canvas, options: ApplicationOptions) {
81
+ * this.canvas = canvas;
82
+ * this.options = options;
83
+ * this.random = new Random(seedFromString(options.seed));
84
+ * }
85
+ *
86
+ * reconfigure(canvas:Canvas, options: Partial<ApplicationOptions>) {
87
+ * this.canvas = canvas;
88
+ * this.options = { ...this.options, ...options };
89
+ * this.random = new Random(seedFromString(options.seed));
90
+ * }
91
+ *
92
+ * onDraw(delta:number, timestamp:number) {
93
+ * // draw something on `this.canvas`
94
+ * }
95
+ *
96
+ * start() {}
97
+ * }
98
+ *
99
+ * const canvasNode = getDocumentElementTypeById(document, "main", HTMLCanvasElement);
100
+ * const canvasSandbox = new CanvasSandbox(
101
+ * window,
102
+ * canvasNode,
103
+ * Application,
104
+ * {seed: "foo", somethingElse: 12345}
105
+ * );
106
+ * canvasSandbox.run();
107
+ * ```
108
+ * ```html
109
+ * <!doctype html>
110
+ * <html>
111
+ * <head>
112
+ * <meta charset="UTF-8" />
113
+ * <link rel="stylesheet" href="main.css" />
114
+ * </head>
115
+ *
116
+ * <body>
117
+ * <canvas id="main" class="darkMode" width="512" height="512"></canvas>
118
+ * </body>
119
+ * <script src="main.ts" type="module"></script>
120
+ * </html>
121
+ * ```
122
+ * ```css
123
+ * html,
124
+ * body {
125
+ * height: 100%;
126
+ * width: 100%;
127
+ * padding: 0;
128
+ * margin: 0;
129
+ * background-color: #808080;
130
+ * }
131
+ *
132
+ * body {
133
+ * transition: background-color 1s ease-in-out;
134
+ * }
135
+ * body.darkMode {
136
+ * background-color: #211f1f;
137
+ * }
138
+ * body.lightMode {
139
+ * background-color: #ebdcdc;
140
+ * }
141
+ *
142
+ * #main {
143
+ * display: block;
144
+ * position: absolute;
145
+ * margin: auto;
146
+ * top: 0;
147
+ * left: 0;
148
+ * right: 0;
149
+ * bottom: 0;
150
+ *
151
+ * filter: drop-shadow(10px 10px 4px rgba(0, 0, 0, 0.5));
152
+ * transition: all 1s;
153
+ * }
154
+ * ```
155
+ * @template {CanvasSandboxExpectedOptions} TApplicationOptions The type of the options
156
+ * the application in the sandbox will be constructed with.
157
+ * @group Graphics
158
+ */
159
+ export declare class CanvasSandbox<TApplicationOptions extends CanvasSandboxExpectedOptions> {
160
+ #private;
161
+ /**
162
+ * The window the sandbox is running in.
163
+ */
164
+ readonly window: Window;
165
+ /**
166
+ * The document the sandbox is interacting with.
167
+ */
168
+ readonly document: Document;
169
+ /**
170
+ * The application running inside the sandbox.
171
+ */
172
+ readonly application: CanvasSandboxApplication<TApplicationOptions>;
173
+ /**
174
+ * The canvas node that we're drawing into.
175
+ */
176
+ readonly canvasNode: HTMLCanvasElement;
177
+ /**
178
+ * Our convenience canvas wrapper, which we provide to the application
179
+ * to render to.
180
+ */
181
+ readonly canvas: Canvas;
182
+ /**
183
+ * The render loop we use to control frame rendering.
184
+ */
185
+ readonly renderLoop: RenderLoop;
186
+ /**
187
+ * Construct a new {@linkcode CanvasSandbox}.
188
+ * @param window The window we're running inside.
189
+ * @param canvasNode The canvas node we're drawing to.
190
+ * @param Application The application that is going to run in the sandbox.
191
+ * @param options The options that the application should be constructed with.
192
+ */
193
+ constructor(window: Window, canvasNode: HTMLCanvasElement, Application: new (canvas: Canvas, options: TApplicationOptions) => CanvasSandboxApplication<TApplicationOptions>, options: TApplicationOptions);
194
+ /**
195
+ * Run the sandbox.
196
+ */
197
+ run(): void;
198
+ /**
199
+ * Switch the sandbox to dark mode.
200
+ */
201
+ toDarkMode(): void;
202
+ /**
203
+ * Switch the sandbox to light mode.
204
+ */
205
+ toLightMode(): void;
206
+ }
@@ -0,0 +1,272 @@
1
+ import { prepareAsyncContext } from "../async.js";
2
+ import { Canvas } from "./canvas.js";
3
+ import { nextPalette } from "./core.js";
4
+ import { RenderLoop } from "./render-loop.js";
5
+ /**
6
+ * The {@linkcode CanvasSandbox} provides a scaffold to quickly perform experiments
7
+ * with a {@linkcode !HTMLCanvasElement} in a document. Common functionality for such
8
+ * experiments is implemented in the sandbox already.
9
+ * @example
10
+ * ```ts
11
+ * import { Random, seedFromString } from "@oliversalzburg/js-utils/lib/random.js";
12
+ * import { Canvas } from "@oliversalzburg/js-utils/lib/graphics/canvas.js";
13
+ * import { getDocumentElementTypeById } from "@oliversalzburg/js-utils/lib/dom/core.js";
14
+ * import { CanvasSandbox } from "@oliversalzburg/js-utils/lib/graphics/canvas-sandbox.js";
15
+ *
16
+ * interface ApplicationOptions {
17
+ * seed: string;
18
+ * somethingElse: number;
19
+ * }
20
+ *
21
+ * class Application {
22
+ * canvas: Canvas;
23
+ * options: ApplicationOptions;
24
+ * random: Random;
25
+ *
26
+ * constructor(canvas:Canvas, options: ApplicationOptions) {
27
+ * this.canvas = canvas;
28
+ * this.options = options;
29
+ * this.random = new Random(seedFromString(options.seed));
30
+ * }
31
+ *
32
+ * reconfigure(canvas:Canvas, options: Partial<ApplicationOptions>) {
33
+ * this.canvas = canvas;
34
+ * this.options = { ...this.options, ...options };
35
+ * this.random = new Random(seedFromString(options.seed));
36
+ * }
37
+ *
38
+ * onDraw(delta:number, timestamp:number) {
39
+ * // draw something on `this.canvas`
40
+ * }
41
+ *
42
+ * start() {}
43
+ * }
44
+ *
45
+ * const canvasNode = getDocumentElementTypeById(document, "main", HTMLCanvasElement);
46
+ * const canvasSandbox = new CanvasSandbox(
47
+ * window,
48
+ * canvasNode,
49
+ * Application,
50
+ * {seed: "foo", somethingElse: 12345}
51
+ * );
52
+ * canvasSandbox.run();
53
+ * ```
54
+ * ```html
55
+ * <!doctype html>
56
+ * <html>
57
+ * <head>
58
+ * <meta charset="UTF-8" />
59
+ * <link rel="stylesheet" href="main.css" />
60
+ * </head>
61
+ *
62
+ * <body>
63
+ * <canvas id="main" class="darkMode" width="512" height="512"></canvas>
64
+ * </body>
65
+ * <script src="main.ts" type="module"></script>
66
+ * </html>
67
+ * ```
68
+ * ```css
69
+ * html,
70
+ * body {
71
+ * height: 100%;
72
+ * width: 100%;
73
+ * padding: 0;
74
+ * margin: 0;
75
+ * background-color: #808080;
76
+ * }
77
+ *
78
+ * body {
79
+ * transition: background-color 1s ease-in-out;
80
+ * }
81
+ * body.darkMode {
82
+ * background-color: #211f1f;
83
+ * }
84
+ * body.lightMode {
85
+ * background-color: #ebdcdc;
86
+ * }
87
+ *
88
+ * #main {
89
+ * display: block;
90
+ * position: absolute;
91
+ * margin: auto;
92
+ * top: 0;
93
+ * left: 0;
94
+ * right: 0;
95
+ * bottom: 0;
96
+ *
97
+ * filter: drop-shadow(10px 10px 4px rgba(0, 0, 0, 0.5));
98
+ * transition: all 1s;
99
+ * }
100
+ * ```
101
+ * @template {CanvasSandboxExpectedOptions} TApplicationOptions The type of the options
102
+ * the application in the sandbox will be constructed with.
103
+ * @group Graphics
104
+ */
105
+ export class CanvasSandbox {
106
+ /**
107
+ * The window the sandbox is running in.
108
+ */
109
+ window;
110
+ /**
111
+ * The document the sandbox is interacting with.
112
+ */
113
+ document;
114
+ /**
115
+ * The application running inside the sandbox.
116
+ */
117
+ application;
118
+ /**
119
+ * The canvas node that we're drawing into.
120
+ */
121
+ canvasNode;
122
+ /**
123
+ * Our convenience canvas wrapper, which we provide to the application
124
+ * to render to.
125
+ */
126
+ canvas;
127
+ /**
128
+ * The render loop we use to control frame rendering.
129
+ */
130
+ renderLoop;
131
+ /**
132
+ * The handle that keeps track of debouncing of `resize` events.
133
+ */
134
+ #resizeDebounce = null;
135
+ /**
136
+ * Construct a new {@linkcode CanvasSandbox}.
137
+ * @param window The window we're running inside.
138
+ * @param canvasNode The canvas node we're drawing to.
139
+ * @param Application The application that is going to run in the sandbox.
140
+ * @param options The options that the application should be constructed with.
141
+ */
142
+ constructor(window, canvasNode, Application, options) {
143
+ this.window = window;
144
+ this.document = window.document;
145
+ this.canvasNode = canvasNode;
146
+ this.canvas = new Canvas(canvasNode);
147
+ this.application = new Application(this.canvas, options);
148
+ const applicationOnDraw = this.application.onDraw.bind(this.application);
149
+ this.renderLoop = new RenderLoop(applicationOnDraw, this.canvas, { drawFps: true });
150
+ this.#hookWindow();
151
+ this.#hookBody();
152
+ this.#hookCanvas();
153
+ const systemPrefersDarkMode = this.window.matchMedia("(prefers-color-scheme: dark)").matches;
154
+ if (systemPrefersDarkMode) {
155
+ this.toDarkMode();
156
+ }
157
+ else {
158
+ this.toLightMode();
159
+ }
160
+ }
161
+ /**
162
+ * Run the sandbox.
163
+ */
164
+ run() {
165
+ this.application.start();
166
+ this.renderLoop.unblock();
167
+ }
168
+ /**
169
+ * Create event listeners on the document `body`.
170
+ */
171
+ #hookBody() {
172
+ this.document.body.addEventListener("click", prepareAsyncContext(async (event) => {
173
+ if (event.defaultPrevented) {
174
+ return;
175
+ }
176
+ if (!this.document.fullscreenEnabled) {
177
+ return;
178
+ }
179
+ if (!this.document.fullscreenElement) {
180
+ await this.canvasNode.requestFullscreen();
181
+ }
182
+ }));
183
+ this.document.body.addEventListener("keyup", event => {
184
+ switch (event.keyCode) {
185
+ case 13:
186
+ // Enter
187
+ nextPalette();
188
+ this.#reconfigureApplication({
189
+ seed: this.application.random.next().toString(),
190
+ });
191
+ this.application.reconfigure(this.canvas, {
192
+ seed: this.application.random.next().toString(),
193
+ });
194
+ this.application.start();
195
+ break;
196
+ case 32:
197
+ // Space
198
+ this.application.paused = !this.application.paused;
199
+ break;
200
+ }
201
+ });
202
+ }
203
+ /**
204
+ * Reconfigures, and then restarts, the application.
205
+ * @param options The new options for the application.
206
+ */
207
+ #reconfigureApplication(options = {}) {
208
+ this.application.reconfigure(this.canvas, options);
209
+ this.application.start();
210
+ }
211
+ /**
212
+ * Create event listeners on the canvas node in the document.
213
+ */
214
+ #hookCanvas() {
215
+ this.canvasNode.addEventListener("click", prepareAsyncContext(async (event) => {
216
+ if (this.document.fullscreenElement) {
217
+ await document.exitFullscreen();
218
+ return;
219
+ }
220
+ nextPalette();
221
+ this.#reconfigureApplication({
222
+ seed: this.application.random.next().toString(),
223
+ });
224
+ event.preventDefault();
225
+ }));
226
+ }
227
+ /**
228
+ * Create event listeners on the window we're running in.
229
+ */
230
+ #hookWindow() {
231
+ this.window
232
+ .matchMedia("(prefers-color-scheme: dark)")
233
+ .addEventListener("change", ({ matches }) => {
234
+ if (matches) {
235
+ this.toDarkMode();
236
+ }
237
+ else {
238
+ this.toLightMode();
239
+ }
240
+ });
241
+ this.window.addEventListener("resize", event => {
242
+ if (this.#resizeDebounce !== null) {
243
+ this.window.clearTimeout(this.#resizeDebounce);
244
+ }
245
+ this.#resizeDebounce = this.window.setTimeout(() => {
246
+ this.#reconfigureApplication();
247
+ this.canvas.refreshCanvasNode();
248
+ }, 1000);
249
+ });
250
+ }
251
+ /**
252
+ * Switch the sandbox to dark mode.
253
+ */
254
+ toDarkMode() {
255
+ this.#reconfigureApplication({
256
+ darkMode: true,
257
+ });
258
+ document.body.classList.add("darkMode");
259
+ document.body.classList.remove("lightMode");
260
+ }
261
+ /**
262
+ * Switch the sandbox to light mode.
263
+ */
264
+ toLightMode() {
265
+ this.#reconfigureApplication({
266
+ darkMode: false,
267
+ });
268
+ document.body.classList.add("lightMode");
269
+ document.body.classList.remove("darkMode");
270
+ }
271
+ }
272
+ //# sourceMappingURL=canvas-sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-sandbox.js","sourceRoot":"","sources":["../../source/graphics/canvas-sandbox.ts"],"names":[],"mappings":"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"}
@@ -24,17 +24,20 @@ export declare class Canvas {
24
24
  */
25
25
  readonly canvasDom: HTMLCanvasElement;
26
26
  /**
27
- * The width of the canvas.
27
+ * Retrieves the width of the canvas.
28
+ * @returns The width of the canvas.
28
29
  */
29
- readonly width: number;
30
+ get width(): number;
30
31
  /**
31
- * The height of the canvas.
32
+ * Retrieves the height of the canvas.
33
+ * @returns The height of the canvas.
32
34
  */
33
- readonly height: number;
35
+ get height(): number;
34
36
  /**
35
- * The {@linkcode !OffscreenCanvasRenderingContext2D} we're using to draw to the canvas.
37
+ * Retrieves the rendering context of the canvas.
38
+ * @returns The rendering context of the canvas.
36
39
  */
37
- readonly context: OffscreenCanvasRenderingContext2D;
40
+ get context(): OffscreenCanvasRenderingContext2D;
38
41
  /**
39
42
  * Our back buffer.
40
43
  */
@@ -49,6 +52,10 @@ export declare class Canvas {
49
52
  * @param options The configuration for this canvas.
50
53
  */
51
54
  constructor(canvas: HTMLCanvasElement, options?: Partial<CanvasOptions>);
55
+ /**
56
+ * Recreate internal buffers in reaction to a change in our target {@linkcode !HTMLCanvasElement}.
57
+ */
58
+ refreshCanvasNode(): void;
52
59
  /**
53
60
  * Draws the back buffer onto the canvas.
54
61
  */