canvasengine 1.3.0 → 2.0.0-beta.2

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 (96) hide show
  1. package/package.json +51 -17
  2. package/src/components/Canvas.ts +134 -0
  3. package/src/components/Container.ts +46 -0
  4. package/src/components/DisplayObject.ts +458 -0
  5. package/src/components/DrawMap/index.ts +65 -0
  6. package/src/components/Graphic.ts +147 -0
  7. package/src/components/NineSliceSprite.ts +46 -0
  8. package/src/components/ParticleEmitter.ts +39 -0
  9. package/src/components/Scene.ts +6 -0
  10. package/src/components/Sprite.ts +493 -0
  11. package/src/components/Text.ts +145 -0
  12. package/src/components/Tilemap/Tile.ts +79 -0
  13. package/src/components/Tilemap/TileGroup.ts +207 -0
  14. package/src/components/Tilemap/TileLayer.ts +163 -0
  15. package/src/components/Tilemap/TileSet.ts +41 -0
  16. package/src/components/Tilemap/index.ts +80 -0
  17. package/src/components/TilingSprite.ts +39 -0
  18. package/src/components/Viewport.ts +159 -0
  19. package/src/components/index.ts +13 -0
  20. package/src/components/types/DisplayObject.ts +69 -0
  21. package/src/components/types/MouseEvent.ts +3 -0
  22. package/src/components/types/Spritesheet.ts +389 -0
  23. package/src/components/types/index.ts +4 -0
  24. package/src/directives/Drag.ts +84 -0
  25. package/src/directives/KeyboardControls.ts +922 -0
  26. package/src/directives/Scheduler.ts +101 -0
  27. package/src/directives/Sound.ts +91 -0
  28. package/src/directives/Transition.ts +45 -0
  29. package/src/directives/ViewportCull.ts +40 -0
  30. package/src/directives/ViewportFollow.ts +26 -0
  31. package/src/directives/index.ts +7 -0
  32. package/src/engine/animation.ts +113 -0
  33. package/src/engine/bootstrap.ts +19 -0
  34. package/src/engine/directive.ts +23 -0
  35. package/src/engine/reactive.ts +379 -0
  36. package/src/engine/signal.ts +138 -0
  37. package/src/engine/trigger.ts +40 -0
  38. package/src/engine/utils.ts +135 -0
  39. package/src/hooks/addContext.ts +6 -0
  40. package/src/hooks/useProps.ts +155 -0
  41. package/src/hooks/useRef.ts +21 -0
  42. package/src/index.ts +13 -0
  43. package/src/utils/Ease.ts +33 -0
  44. package/src/utils/RadialGradient.ts +86 -0
  45. package/.gitattributes +0 -22
  46. package/.npmignore +0 -163
  47. package/canvasengine-1.3.0.all.min.js +0 -21
  48. package/canvasengine.js +0 -5802
  49. package/core/DB.js +0 -24
  50. package/core/ModelServer.js +0 -348
  51. package/core/Users.js +0 -190
  52. package/core/engine-common.js +0 -952
  53. package/doc/cocoonjs.md +0 -36
  54. package/doc/doc-lang.yml +0 -43
  55. package/doc/doc-router.yml +0 -14
  56. package/doc/doc-tuto.yml +0 -9
  57. package/doc/doc.yml +0 -39
  58. package/doc/element.md +0 -37
  59. package/doc/entity.md +0 -90
  60. package/doc/extend.md +0 -47
  61. package/doc/get_started.md +0 -19
  62. package/doc/images/entity.png +0 -0
  63. package/doc/multitouch.md +0 -58
  64. package/doc/nodejs.md +0 -142
  65. package/doc/scene.md +0 -44
  66. package/doc/text.md +0 -156
  67. package/examples/server/client.html +0 -31
  68. package/examples/server/server.js +0 -16
  69. package/examples/tiled_server/client.html +0 -52
  70. package/examples/tiled_server/images/tiles_spritesheet.png +0 -0
  71. package/examples/tiled_server/server/map.json +0 -50
  72. package/examples/tiled_server/server/map.tmx +0 -16
  73. package/examples/tiled_server/server/server.js +0 -16
  74. package/extends/Animation.js +0 -910
  75. package/extends/Effect.js +0 -252
  76. package/extends/Gleed2d.js +0 -252
  77. package/extends/Hit.js +0 -1509
  78. package/extends/Input.js +0 -699
  79. package/extends/Marshal.js +0 -716
  80. package/extends/Scrolling.js +0 -388
  81. package/extends/Soundmanager2.js +0 -5466
  82. package/extends/Spritesheet.js +0 -196
  83. package/extends/Text.js +0 -366
  84. package/extends/Tiled.js +0 -403
  85. package/extends/Window.js +0 -575
  86. package/extends/gamepad.js +0 -397
  87. package/extends/socket.io.min.js +0 -2
  88. package/extends/swf/soundmanager2.swf +0 -0
  89. package/extends/swf/soundmanager2_debug.swf +0 -0
  90. package/extends/swf/soundmanager2_flash9.swf +0 -0
  91. package/extends/swf/soundmanager2_flash9_debug.swf +0 -0
  92. package/extends/swf/soundmanager2_flash_xdomain.zip +0 -0
  93. package/extends/workers/transition.js +0 -43
  94. package/index.js +0 -46
  95. package/license.txt +0 -19
  96. package/readme.md +0 -483
package/package.json CHANGED
@@ -1,18 +1,52 @@
1
- {
2
- "name": "canvasengine",
3
- "version": "1.3.0",
4
- "description": "Use a model for handling server-side events and develop a multiplayer game.",
5
- "main": "index.js",
6
- "bin": { "canvasengine": "index.js" },
7
- "author": "WebCreative5",
8
- "keywords": ["html5", "canvas", "game", "model"],
9
- "repository" : {
10
- "type": "git",
11
- "url": "https://github.com/RSamaium/CanvasEngine.git"
12
- },
13
- "license": "MIT",
14
- "dependencies": {
15
- "socket.io": "0.9.16"
16
- },
17
- "engines": { "node": "*" }
1
+ {
2
+ "name": "canvasengine",
3
+ "version": "2.0.0-beta.2",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "dependencies": {
8
+ "@barvynkoa/particle-emitter": "^0.0.1",
9
+ "@pixi/tilemap": "^5.0.1",
10
+ "@rpgjs/tiled": "^4.3.0",
11
+ "@signe/reactive": "^1.0.1",
12
+ "howler": "^2.2.4",
13
+ "package.json": "^2.0.1",
14
+ "pixi-filters": "^6.0.5",
15
+ "pixi-viewport": "^6.0.3",
16
+ "pixi.js": "^8.6.4",
17
+ "popmotion": "^11.0.5",
18
+ "rxjs": "^7.8.1",
19
+ "yoga-layout": "^2.0.1"
20
+ },
21
+ "devDependencies": {
22
+ "@types/howler": "^2.2.11"
23
+ },
24
+ "author": "Samuel Ronce",
25
+ "license": "MIT",
26
+ "homepage": "https://canvasengine.net",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/RSamaium/CanvasEngine.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/RSamaium/CanvasEngine/issues"
33
+ },
34
+ "keywords": [
35
+ "canvas",
36
+ "pixijs",
37
+ "reactive",
38
+ "html5"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "overrides": {
44
+ "revolt-fx": {
45
+ "pixi.js": "^8.6.4"
46
+ }
47
+ },
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "dev": "tsup --watch"
51
+ }
18
52
  }
@@ -0,0 +1,134 @@
1
+ import { effect, Signal, signal } from "@signe/reactive";
2
+ import { Container, autoDetectRenderer } from "pixi.js";
3
+ import { loadYoga } from "yoga-layout";
4
+ import { Props, createComponent, registerComponent, Element } from "../engine/reactive";
5
+ import { useProps } from "../hooks/useProps";
6
+ import { ComponentInstance, DisplayObject } from "./DisplayObject";
7
+ import { ComponentFunction } from "../engine/signal";
8
+ import { SignalOrPrimitive } from "./types";
9
+ import { Size } from "./types/DisplayObject";
10
+ import { Scheduler, Tick } from "../directives/Scheduler";
11
+
12
+ interface CanvasElement extends Element<ComponentInstance> {
13
+ render: (rootElement: HTMLElement) => void;
14
+ directives: {
15
+ tick: Scheduler
16
+ };
17
+ propObservables: {
18
+ tick: Signal<Tick>
19
+ };
20
+ }
21
+
22
+ registerComponent("Canvas", class Canvas extends DisplayObject(Container) {});
23
+
24
+ export interface CanvasProps extends Props {
25
+ cursorStyles?: () => any;
26
+ width?: SignalOrPrimitive<Size>;
27
+ height?: SignalOrPrimitive<Size>;
28
+ canvasEl?: HTMLElement;
29
+ selector?: string;
30
+ isRoot?: boolean;
31
+ tick?: any;
32
+ class?: SignalOrPrimitive<string>;
33
+ }
34
+
35
+ export const Canvas: ComponentFunction<CanvasProps> = async (props = {}) => {
36
+ let { cursorStyles, width, height, class: className } = useProps(props);
37
+ const Yoga = await loadYoga();
38
+
39
+ if (!props.width) width = signal<Size>(800)
40
+ if (!props.height) height = signal<Size>(600)
41
+
42
+ const renderer = await autoDetectRenderer({
43
+ ...props,
44
+ width: width?.(),
45
+ height: height?.(),
46
+ });
47
+
48
+ const canvasSize = signal({
49
+ width: renderer.width,
50
+ height: renderer.height,
51
+ });
52
+
53
+ props.isRoot = true;
54
+ const options: CanvasProps = {
55
+ ...props,
56
+ context: {
57
+ Yoga,
58
+ renderer,
59
+ canvasSize,
60
+ },
61
+ width: width?.(),
62
+ height: height?.(),
63
+ };
64
+
65
+ if (!props.tick) {
66
+ options.context!.tick = options.tick = signal({
67
+ timestamp: 0,
68
+ deltaTime: 0,
69
+ frame: 0,
70
+ deltaRatio: 1,
71
+ });
72
+ }
73
+ const canvasElement = createComponent("Canvas", options) as CanvasElement;
74
+
75
+ canvasElement.render = (rootElement: HTMLElement) => {
76
+ const canvasEl = renderer.view.canvas as HTMLCanvasElement;
77
+
78
+ (globalThis as any).__PIXI_STAGE__ = canvasElement.componentInstance;
79
+ (globalThis as any).__PIXI_RENDERER__ = renderer;
80
+
81
+ if (props.tickStart !== false) canvasElement.directives.tick.start()
82
+
83
+ effect(() => {
84
+ canvasElement.propObservables!.tick();
85
+ renderer.render(canvasElement.componentInstance as any);
86
+ });
87
+
88
+ if (cursorStyles) {
89
+ effect(() => {
90
+ renderer.events.cursorStyles = cursorStyles();
91
+ });
92
+ }
93
+
94
+ if (className) {
95
+ effect(() => {
96
+ canvasEl.classList.add(className());
97
+ });
98
+ }
99
+
100
+ const resizeCanvas = async () => {
101
+ let w, h;
102
+ if (width?.() === "100%" && height?.() === "100%") {
103
+ const parent = canvasEl.parentElement;
104
+ w = parent ? parent.clientWidth : window.innerWidth;
105
+ h = parent ? parent.clientHeight : window.innerHeight;
106
+ } else {
107
+ w = width?.() ?? canvasEl.offsetWidth;
108
+ h = height?.() ?? canvasEl.offsetHeight;
109
+ }
110
+ renderer.resize(w, h);
111
+ canvasSize.set({ width: w, height: h });
112
+ canvasElement.componentInstance.setWidth(w)
113
+ canvasElement.componentInstance.setHeight(h)
114
+ };
115
+
116
+ // Listen for window resize events
117
+ window.addEventListener("resize", resizeCanvas);
118
+
119
+ // Check if a canvas already exists in the rootElement
120
+ const existingCanvas = rootElement.querySelector('canvas');
121
+ if (existingCanvas) {
122
+ // If it exists, replace it with the new canvas
123
+ rootElement.replaceChild(canvasEl, existingCanvas);
124
+ } else {
125
+ // If it doesn't exist, append the new canvas
126
+ rootElement.appendChild(canvasEl);
127
+ }
128
+
129
+ // Initial resize
130
+ resizeCanvas();
131
+ };
132
+
133
+ return canvasElement;
134
+ };
@@ -0,0 +1,46 @@
1
+ import { Container as PixiContainer } from "pixi.js";
2
+ import { createComponent, registerComponent } from "../engine/reactive";
3
+ import { DisplayObject } from "./DisplayObject";
4
+ import { ComponentFunction } from "../engine/signal";
5
+ import { DisplayObjectProps } from "./types/DisplayObject";
6
+ import { setObservablePoint } from "../engine/utils";
7
+
8
+ interface ContainerProps extends DisplayObjectProps {
9
+ sortableChildren?: boolean;
10
+ }
11
+
12
+ export class CanvasContainer extends DisplayObject(PixiContainer) {
13
+ isCustomAnchor = true;
14
+
15
+ onUpdate(props) {
16
+ if (props.anchor) {
17
+ setObservablePoint(this._anchorPoints, props.anchor);
18
+ props.pivot = [
19
+ this.getWidth() * this._anchorPoints.x,
20
+ this.getHeight() * this._anchorPoints.y
21
+ ]
22
+ }
23
+ super.onUpdate(props);
24
+ if (props.sortableChildren != undefined) {
25
+ this.sortableChildren = props.sortableChildren;
26
+ }
27
+ }
28
+ onMount(args) {
29
+ super.onMount(args);
30
+ const { componentInstance, props } = args;
31
+ const { pixiChildren } = props;
32
+ if (pixiChildren) {
33
+ pixiChildren.forEach((child) => {
34
+ componentInstance.addChild(child);
35
+ });
36
+ }
37
+ }
38
+ }
39
+
40
+ export interface CanvasContainer extends DisplayObjectProps {}
41
+
42
+ registerComponent("Container", CanvasContainer);
43
+
44
+ export const Container: ComponentFunction<ContainerProps> = (props) => {
45
+ return createComponent("Container", props);
46
+ };
@@ -0,0 +1,458 @@
1
+ import { Node } from "yoga-layout";
2
+ import { Element, isElement, Props } from "../engine/reactive";
3
+ import { setObservablePoint } from "../engine/utils";
4
+ import type {
5
+ AlignContent,
6
+ EdgeSize,
7
+ FlexDirection,
8
+ Size,
9
+ } from "./types/DisplayObject";
10
+ import { effect, Signal, signal } from "@signe/reactive";
11
+ import { DropShadowFilter } from "pixi-filters";
12
+ import { BlurFilter, ObservablePoint } from "pixi.js";
13
+
14
+ export interface ComponentInstance extends PixiMixins.ContainerOptions {
15
+ id?: string;
16
+ children?: ComponentInstance[];
17
+ onInit?(props: Props): void;
18
+ onUpdate?(props: Props): void;
19
+ onDestroy?(parent: Element): void;
20
+ onMount?(context: Element, index?: number): void;
21
+ setWidth(width: number): void;
22
+ setHeight(height: number): void;
23
+ }
24
+
25
+ export const EVENTS = [
26
+ "added",
27
+ "childAdded",
28
+ "childRemoved",
29
+ "click",
30
+ "clickcapture",
31
+ "destroyed",
32
+ "globalmousemove",
33
+ "globalpointermove",
34
+ "globaltouchmove",
35
+ "mousedown",
36
+ "mousedowncapture",
37
+ "mouseenter",
38
+ "mouseentercapture",
39
+ "mouseleave",
40
+ "mouseleavecapture",
41
+ "mousemove",
42
+ "mousemovecapture",
43
+ "mouseout",
44
+ "mouseoutcapture",
45
+ "mouseover",
46
+ "mouseovercapture",
47
+ "mouseup",
48
+ "mouseupcapture",
49
+ "mouseupoutside",
50
+ "mouseupoutsidecapture",
51
+ "pointercancel",
52
+ "pointercancelcapture",
53
+ "pointerdown",
54
+ "pointerdowncapture",
55
+ "pointerenter",
56
+ "pointerentercapture",
57
+ "pointerleave",
58
+ "pointerleavecapture",
59
+ "pointermove",
60
+ "pointermovecapture",
61
+ "pointerout",
62
+ "pointeroutcapture",
63
+ "pointerover",
64
+ "pointerovercapture",
65
+ "pointertap",
66
+ "pointertapcapture",
67
+ "pointerup",
68
+ "pointerupcapture",
69
+ "pointerupoutside",
70
+ "pointerupoutsidecapture",
71
+ "removed",
72
+ "rightclick",
73
+ "rightclickcapture",
74
+ "rightdown",
75
+ "rightdowncapture",
76
+ "rightup",
77
+ "rightupcapture",
78
+ "rightupoutside",
79
+ "rightupoutsidecapture",
80
+ "tap",
81
+ "tapcapture",
82
+ "touchcancel",
83
+ "touchcancelcapture",
84
+ "touchend",
85
+ "touchendcapture",
86
+ "touchendoutside",
87
+ "touchendoutsidecapture",
88
+ "touchmove",
89
+ "touchmovecapture",
90
+ "touchstart",
91
+ "touchstartcapture",
92
+ "wheel",
93
+ "wheelcapture",
94
+ ];
95
+
96
+ export function DisplayObject(extendClass) {
97
+ return class DisplayObject extends extendClass {
98
+ #canvasContext: {
99
+ [key: string]: any;
100
+ } | null = null;
101
+ isFlex: boolean = false;
102
+ fullProps: Props = {};
103
+ isMounted: boolean = false;
104
+ _anchorPoints = new ObservablePoint(
105
+ { _onUpdate: () => {} },
106
+ 0,
107
+ 0
108
+ );
109
+ isCustomAnchor: boolean = false;
110
+ displayWidth = signal(0);
111
+ displayHeight = signal(0);
112
+ overrideProps: string[] = [];
113
+ node: Node;
114
+
115
+ get yoga() {
116
+ return this.#canvasContext?.Yoga;
117
+ }
118
+
119
+ get deltaRatio() {
120
+ return this.#canvasContext?.scheduler?.tick.value.deltaRatio;
121
+ }
122
+
123
+ onInit(props) {
124
+ this._id = props.id;
125
+ for (let event of EVENTS) {
126
+ if (props[event] && !this.overrideProps.includes(event)) {
127
+ this.eventMode = "static";
128
+ this.on(event, props[event]);
129
+ }
130
+ }
131
+ }
132
+
133
+ onMount({ parent, props }: Element<DisplayObject>, index?: number) {
134
+ this.#canvasContext = props.context;
135
+ this.node = this.yoga.Node.create();
136
+ if (parent) {
137
+ const instance = parent.componentInstance as DisplayObject;
138
+ if (index === undefined) {
139
+ instance.addChild(this);
140
+ } else {
141
+ instance.addChildAt(this, index);
142
+ }
143
+ if (instance.layer) this.parentLayer = instance.layer;
144
+ this.isMounted = true;
145
+ this.effectSize(props.width, props.height);
146
+ this.onUpdate(props);
147
+ this.parent.node.insertChild(
148
+ this.node,
149
+ this.parent.node.getChildCount()
150
+ );
151
+ if (parent.props.flexDirection) {
152
+ this.parent.node.calculateLayout();
153
+ for (let child of this.parent.children) {
154
+ const { left, top } = child.getComputedLayout();
155
+ child.x = left;
156
+ child.y = top;
157
+ }
158
+ }
159
+
160
+ }
161
+ }
162
+
163
+ effectSize(width: Size, height: Size) {
164
+ const handleSize = (
165
+ size: Size,
166
+ setter: (value: number) => void,
167
+ parentSize: Signal<number>
168
+ ) => {
169
+ if (typeof size === "string" && size.endsWith("%")) {
170
+ effect(() => {
171
+ setter(parentSize() * (parseInt(size) / 100));
172
+ if (this.isFlex) {
173
+ this.#applyFlexLayout();
174
+ }
175
+ });
176
+ } else {
177
+ setter(+size);
178
+ }
179
+ };
180
+
181
+ if (width != undefined)
182
+ handleSize(width, this.setWidth.bind(this), this.parent.displayWidth);
183
+ if (height != undefined)
184
+ handleSize(
185
+ height,
186
+ this.setHeight.bind(this),
187
+ this.parent.displayHeight
188
+ );
189
+ }
190
+
191
+ #applyFlexLayout() {
192
+ this.calculateLayout();
193
+ for (let child of this.children) {
194
+ const { left, top } = child.node.getComputedLayout();
195
+ child.x = left;
196
+ child.y = top;
197
+ }
198
+ }
199
+
200
+ #flexRender(props) {
201
+ if (!this.parent) return;
202
+ if (props.flexDirection || props.justifyContent) {
203
+ this.isFlex = true;
204
+ this.#applyFlexLayout();
205
+ }
206
+ }
207
+
208
+ onUpdate(props) {
209
+ this.fullProps = {
210
+ ...this.fullProps,
211
+ ...props,
212
+ };
213
+
214
+ if (!this.#canvasContext || !this.parent) return;
215
+ if (props.x !== undefined) this.setX(props.x);
216
+ if (props.y !== undefined) this.setY(props.y);
217
+ if (props.scale !== undefined)
218
+ setObservablePoint(this.scale, props.scale);
219
+ if (props.anchor !== undefined && !this.isCustomAnchor) {
220
+ setObservablePoint(this.anchor, props.anchor);
221
+ }
222
+ if (props.skew !== undefined) setObservablePoint(this.skew, props.skew);
223
+ if (props.tint) this.tint = props.tint;
224
+ if (props.rotation !== undefined) this.rotation = props.rotation;
225
+ if (props.angle !== undefined) this.angle = props.angle;
226
+ if (props.zIndex !== undefined) this.zIndex = props.zIndex;
227
+ if (props.roundPixels !== undefined) this.roundPixels = props.roundPixels;
228
+ if (props.cursor) this.cursor = props.cursor;
229
+ if (props.visible !== undefined) this.visible = props.visible;
230
+ if (props.alpha !== undefined) this.alpha = props.alpha;
231
+ if (props.pivot) setObservablePoint(this.pivot, props.pivot);
232
+ if (props.flexDirection) this.setFlexDirection(props.flexDirection);
233
+ if (props.flexWrap) this.setFlexWrap(props.flexWrap);
234
+ if (props.justifyContent) this.setJustifyContent(props.justifyContent);
235
+ if (props.alignItems) this.setAlignItems(props.alignItems);
236
+ if (props.alignContent) this.setAlignContent(props.alignContent);
237
+ if (props.alignSelf) this.setAlignSelf(props.alignSelf);
238
+ if (props.margin) this.setMargin(props.margin);
239
+ if (props.padding) this.setPadding(props.padding);
240
+ if (props.gap) this.setGap(props.gap);
241
+ if (props.border) this.setBorder(props.border);
242
+ if (props.positionType) this.setPositionType(props.positionType);
243
+ if (props.filters) this.filters = props.filters;
244
+ if (props.maskOf) {
245
+ if (isElement(props.maskOf)) {
246
+ props.maskOf.componentInstance.mask = this;
247
+ }
248
+ }
249
+ if (props.blendMode) this.blendMode = props.blendMode;
250
+ if (props.filterArea) this.filterArea = props.filterArea;
251
+ const currentFilters = this.filters || [];
252
+
253
+ if (props.shadow) {
254
+ let dropShadowFilter = currentFilters.find(
255
+ (filter) => filter instanceof DropShadowFilter
256
+ );
257
+ if (!dropShadowFilter) {
258
+ dropShadowFilter = new DropShadowFilter();
259
+ currentFilters.push(dropShadowFilter);
260
+ }
261
+ Object.assign(dropShadowFilter, props.shadow);
262
+ }
263
+
264
+ if (props.blur) {
265
+ let blurFilter = currentFilters.find(
266
+ (filter) => filter instanceof BlurFilter
267
+ );
268
+ if (!blurFilter) {
269
+ const options =
270
+ typeof props.blur === "number"
271
+ ? {
272
+ strength: props.blur,
273
+ }
274
+ : props.blur;
275
+ blurFilter = new BlurFilter(options);
276
+ currentFilters.push(blurFilter);
277
+ }
278
+ Object.assign(blurFilter, props.blur);
279
+ }
280
+
281
+ this.filters = currentFilters;
282
+
283
+ this.#flexRender(props);
284
+ }
285
+
286
+ onDestroy() {
287
+ super.destroy();
288
+ this.node?.freeRecursive();
289
+ }
290
+
291
+ getComputedLayout() {
292
+ return this.node.getComputedLayout();
293
+ }
294
+
295
+ applyComputedLayout() {
296
+ const layout = this.getComputedLayout();
297
+ this.x = layout.left;
298
+ this.y = layout.top;
299
+ }
300
+
301
+ calculateLayout() {
302
+ this.node.calculateLayout();
303
+ }
304
+
305
+ setFlexDirection(direction: FlexDirection) {
306
+ const mapping = {
307
+ row: this.yoga.FLEX_DIRECTION_ROW,
308
+ column: this.yoga.FLEX_DIRECTION_COLUMN,
309
+ "row-reverse": this.yoga.FLEX_DIRECTION_ROW_REVERSE,
310
+ "column-reverse": this.yoga.FLEX_DIRECTION_COLUMN_REVERSE,
311
+ };
312
+ this.node.setFlexDirection(mapping[direction]);
313
+ }
314
+
315
+ setFlexWrap(wrap: "wrap" | "nowrap" | "wrap-reverse") {
316
+ const mapping = {
317
+ wrap: this.yoga.WRAP_WRAP,
318
+ nowrap: this.yoga.WRAP_NO_WRAP,
319
+ "wrap-reverse": this.yoga.WRAP_WRAP_REVERSE,
320
+ };
321
+ this.node.setFlexWrap(mapping[wrap]);
322
+ }
323
+
324
+ #setAlign(methodName: string, align: AlignContent) {
325
+ const mapping = {
326
+ auto: this.yoga.ALIGN_AUTO,
327
+ "flex-start": this.yoga.ALIGN_FLEX_START,
328
+ "flex-end": this.yoga.ALIGN_FLEX_END,
329
+ center: this.yoga.ALIGN_CENTER,
330
+ stretch: this.yoga.ALIGN_STRETCH,
331
+ baseline: this.yoga.ALIGN_BASELINE,
332
+ "space-between": this.yoga.ALIGN_SPACE_BETWEEN,
333
+ "space-around": this.yoga.ALIGN_SPACE_AROUND,
334
+ };
335
+ const method = (this.node as any)[methodName].bind(this.node);
336
+ method(mapping[align]);
337
+ }
338
+
339
+ setAlignContent(align: AlignContent) {
340
+ this.#setAlign("setAlignContent", align);
341
+ }
342
+
343
+ setAlignSelf(align: AlignContent) {
344
+ this.#setAlign("setAlignSelf", align);
345
+ }
346
+
347
+ setAlignItems(align: AlignContent) {
348
+ this.#setAlign("setAlignItems", align);
349
+ }
350
+
351
+ setJustifyContent(
352
+ justifyContent:
353
+ | "flex-start"
354
+ | "flex-end"
355
+ | "center"
356
+ | "space-between"
357
+ | "space-around"
358
+ ) {
359
+ const mapping = {
360
+ "flex-start": this.yoga.JUSTIFY_FLEX_START,
361
+ "flex-end": this.yoga.JUSTIFY_FLEX_END,
362
+ center: this.yoga.JUSTIFY_CENTER,
363
+ "space-between": this.yoga.JUSTIFY_SPACE_BETWEEN,
364
+ "space-around": this.yoga.JUSTIFY_SPACE_AROUND,
365
+ };
366
+ this.node.setJustifyContent(mapping[justifyContent]);
367
+ }
368
+
369
+ #setEdgeSize(methodName: string, size: EdgeSize) {
370
+ const method = (this.node as any)[methodName].bind(this.node);
371
+ if (size instanceof Array) {
372
+ if (size.length === 2) {
373
+ method(this.yoga.EDGE_VERTICAL, size[0]);
374
+ method(this.yoga.EDGE_HORIZONTAL, size[1]);
375
+ } else if (size.length === 4) {
376
+ method(this.yoga.EDGE_TOP, size[0]);
377
+ method(this.yoga.EDGE_RIGHT, size[1]);
378
+ method(this.yoga.EDGE_BOTTOM, size[2]);
379
+ method(this.yoga.EDGE_LEFT, size[3]);
380
+ }
381
+ } else {
382
+ method(this.yoga.EDGE_ALL, size);
383
+ }
384
+ }
385
+
386
+ setPosition(position: EdgeSize) {
387
+ this.#setEdgeSize("setPosition", position);
388
+ }
389
+
390
+ setX(x: number) {
391
+ x = x + this.getWidth() * this._anchorPoints.x;
392
+ if (!this.parent.isFlex) {
393
+ this.x = x;
394
+ }
395
+ this.node.setPosition(this.yoga.EDGE_LEFT, x);
396
+ }
397
+
398
+ setY(y: number) {
399
+ y = y + this.getHeight() * this._anchorPoints.y;
400
+ if (!this.parent.isFlex) {
401
+ this.y = y;
402
+ }
403
+ this.node.setPosition(this.yoga.EDGE_TOP, y);
404
+ }
405
+
406
+ setPadding(padding: EdgeSize) {
407
+ this.#setEdgeSize("setPadding", padding);
408
+ }
409
+
410
+ setMargin(margin: EdgeSize) {
411
+ this.#setEdgeSize("setMargin", margin);
412
+ }
413
+
414
+ setGap(gap: EdgeSize) {
415
+ this.node.setGap(this.yoga.GAP_ALL, +gap);
416
+ }
417
+
418
+ setBorder(border: EdgeSize) {
419
+ this.#setEdgeSize("setBorder", border);
420
+ }
421
+
422
+ setPositionType(positionType: "relative" | "absolute") {
423
+ const mapping = {
424
+ relative: this.yoga.POSITION_TYPE_RELATIVE,
425
+ absolute: this.yoga.POSITION_TYPE_ABSOLUTE,
426
+ };
427
+ this.node.setPositionType(mapping[positionType]);
428
+ }
429
+
430
+ calculateBounds() {
431
+ super.calculateBounds();
432
+ if (!this._geometry) return;
433
+ const bounds = this._geometry.bounds;
434
+ const width = Math.abs(bounds.minX - bounds.maxX);
435
+ const height = Math.abs(bounds.minY - bounds.maxY);
436
+ // this.node.setWidth(width);
437
+ // this.node.setHeight(height);
438
+ }
439
+
440
+ setWidth(width: number) {
441
+ this.displayWidth.set(width);
442
+ this.node?.setWidth(width);
443
+ }
444
+
445
+ setHeight(height: number) {
446
+ this.displayHeight.set(height);
447
+ this.node?.setHeight(height);
448
+ }
449
+
450
+ getWidth() {
451
+ return this.displayWidth();
452
+ }
453
+
454
+ getHeight() {
455
+ return this.displayHeight();
456
+ }
457
+ };
458
+ }