dacha 0.15.2 → 0.16.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 (169) hide show
  1. package/build/contrib/components/animatable/comparator-condition-component-value.d.ts +1 -1
  2. package/build/contrib/components/animatable/group-state.d.ts +1 -1
  3. package/build/contrib/components/animatable/index.d.ts +1 -1
  4. package/build/contrib/components/animatable/one-dimensional-props.d.ts +1 -1
  5. package/build/contrib/components/animatable/one-dimensional-props.js +1 -3
  6. package/build/contrib/components/animatable/state.d.ts +1 -1
  7. package/build/contrib/components/animatable/timeline.d.ts +2 -2
  8. package/build/contrib/components/animatable/transition.d.ts +1 -1
  9. package/build/contrib/components/animatable/two-dimensional-props.d.ts +1 -1
  10. package/build/contrib/components/animatable/two-dimensional-props.js +1 -3
  11. package/build/contrib/components/animatable/types.d.ts +9 -9
  12. package/build/contrib/components/bitmap-text/index.d.ts +36 -0
  13. package/build/contrib/components/bitmap-text/index.js +42 -0
  14. package/build/contrib/components/index.d.ts +3 -2
  15. package/build/contrib/components/index.js +3 -1
  16. package/build/contrib/components/keyboard-control/index.d.ts +6 -8
  17. package/build/contrib/components/keyboard-control/index.js +8 -2
  18. package/build/contrib/components/mouse-control/index.d.ts +3 -7
  19. package/build/contrib/components/mouse-control/index.js +4 -1
  20. package/build/contrib/components/pixi-view/index.d.ts +20 -0
  21. package/build/contrib/components/pixi-view/index.js +24 -0
  22. package/build/contrib/components/shape/index.d.ts +64 -0
  23. package/build/contrib/components/shape/index.js +60 -0
  24. package/build/contrib/components/sprite/index.d.ts +17 -6
  25. package/build/contrib/components/sprite/index.js +10 -4
  26. package/build/contrib/systems/animator/index.d.ts +1 -1
  27. package/build/contrib/systems/animator/index.js +9 -9
  28. package/build/contrib/systems/animator/substate-pickers/index.d.ts +2 -3
  29. package/build/contrib/systems/animator/substate-pickers/one-dimensional-picker.d.ts +1 -1
  30. package/build/contrib/systems/animator/substate-pickers/picker.d.ts +1 -1
  31. package/build/contrib/systems/animator/substate-pickers/two-dimensional-picker.d.ts +1 -1
  32. package/build/contrib/systems/animator/utils.d.ts +2 -2
  33. package/build/contrib/systems/animator/utils.js +0 -1
  34. package/build/contrib/systems/audio-system/index.d.ts +1 -1
  35. package/build/contrib/systems/audio-system/index.js +20 -18
  36. package/build/contrib/systems/audio-system/types.d.ts +6 -6
  37. package/build/contrib/systems/behavior-system/system.d.ts +2 -0
  38. package/build/contrib/systems/behavior-system/system.js +18 -5
  39. package/build/contrib/systems/camera-system/system.d.ts +1 -1
  40. package/build/contrib/systems/camera-system/system.js +16 -10
  41. package/build/contrib/systems/game-stats-meter/index.d.ts +1 -1
  42. package/build/contrib/systems/game-stats-meter/index.js +6 -6
  43. package/build/contrib/systems/index.d.ts +2 -2
  44. package/build/contrib/systems/index.js +1 -1
  45. package/build/contrib/systems/keyboard-control-system/index.d.ts +1 -1
  46. package/build/contrib/systems/keyboard-control-system/index.js +5 -7
  47. package/build/contrib/systems/keyboard-input-system/input-listener.d.ts +1 -1
  48. package/build/contrib/systems/mouse-control-system/index.d.ts +1 -1
  49. package/build/contrib/systems/mouse-control-system/index.js +5 -7
  50. package/build/contrib/systems/mouse-input-system/subsystems/input-subsystem/mouse-input-listener.d.ts +1 -1
  51. package/build/contrib/systems/physics-system/subsystems/collision-detection/index.d.ts +1 -1
  52. package/build/contrib/systems/physics-system/subsystems/collision-detection/index.js +17 -16
  53. package/build/contrib/systems/physics-system/subsystems/collision-detection/types.d.ts +9 -9
  54. package/build/contrib/systems/physics-system/subsystems/collision-detection/types.js +3 -0
  55. package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.d.ts +0 -1
  56. package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.js +46 -59
  57. package/build/contrib/systems/physics-system/subsystems/physics/index.d.ts +1 -1
  58. package/build/contrib/systems/physics-system/subsystems/physics/index.js +10 -14
  59. package/build/contrib/systems/renderer/builders/bitmap-text-builder/index.d.ts +8 -0
  60. package/build/contrib/systems/renderer/builders/bitmap-text-builder/index.js +115 -0
  61. package/build/contrib/systems/renderer/builders/bitmap-text-builder/utils.d.ts +2 -0
  62. package/build/contrib/systems/renderer/builders/bitmap-text-builder/utils.js +7 -0
  63. package/build/contrib/systems/renderer/builders/builder.d.ts +7 -0
  64. package/build/contrib/systems/renderer/builders/index.d.ts +5 -0
  65. package/build/contrib/systems/renderer/builders/index.js +4 -0
  66. package/build/contrib/systems/renderer/builders/pixi-view-builder/index.d.ts +8 -0
  67. package/build/contrib/systems/renderer/builders/pixi-view-builder/index.js +31 -0
  68. package/build/contrib/systems/renderer/builders/shape-builder/index.d.ts +12 -0
  69. package/build/contrib/systems/renderer/builders/shape-builder/index.js +128 -0
  70. package/build/contrib/systems/renderer/builders/shape-builder/utils.d.ts +4 -0
  71. package/build/contrib/systems/renderer/builders/shape-builder/utils.js +85 -0
  72. package/build/contrib/systems/renderer/builders/sprite-builder/index.d.ts +19 -0
  73. package/build/contrib/systems/renderer/builders/sprite-builder/index.js +166 -0
  74. package/build/contrib/systems/renderer/builders/sprite-builder/utils.d.ts +4 -0
  75. package/build/contrib/systems/renderer/builders/sprite-builder/utils.js +16 -0
  76. package/build/contrib/systems/renderer/builders/utils.d.ts +1 -0
  77. package/build/contrib/systems/renderer/builders/utils.js +4 -0
  78. package/build/contrib/systems/renderer/consts.d.ts +5 -0
  79. package/build/contrib/systems/renderer/consts.js +12 -0
  80. package/build/contrib/systems/renderer/index.d.ts +2 -0
  81. package/build/contrib/systems/renderer/index.js +2 -0
  82. package/build/contrib/systems/renderer/renderer.d.ts +31 -0
  83. package/build/contrib/systems/renderer/renderer.js +249 -0
  84. package/build/contrib/systems/renderer/service/index.d.ts +20 -0
  85. package/build/contrib/systems/renderer/service/index.js +70 -0
  86. package/build/contrib/systems/{sprite-renderer → renderer}/sort/index.d.ts +1 -3
  87. package/build/contrib/systems/{sprite-renderer → renderer}/sort/index.js +2 -4
  88. package/build/contrib/systems/renderer/sort/sort-by-layer.d.ts +2 -0
  89. package/build/contrib/systems/renderer/sort/sort-by-layer.js +13 -0
  90. package/build/contrib/systems/renderer/sort/sort-by-x-axis.d.ts +2 -0
  91. package/build/contrib/systems/renderer/sort/sort-by-x-axis.js +9 -0
  92. package/build/contrib/systems/renderer/sort/sort-by-y-axis.d.ts +2 -0
  93. package/build/contrib/systems/renderer/sort/sort-by-y-axis.js +9 -0
  94. package/build/contrib/systems/renderer/sort/types.d.ts +2 -0
  95. package/build/contrib/systems/{sprite-renderer → renderer}/sort/utils.d.ts +1 -1
  96. package/build/contrib/systems/renderer/types.d.ts +26 -0
  97. package/build/contrib/systems/renderer/types.js +1 -0
  98. package/build/contrib/systems/renderer/utils.d.ts +5 -0
  99. package/build/contrib/systems/renderer/utils.js +42 -0
  100. package/build/contrib/types/input-events.d.ts +1 -1
  101. package/build/contrib/types/view.d.ts +1 -0
  102. package/build/contrib/types/view.js +1 -0
  103. package/build/engine/actor/actor-collection.d.ts +4 -1
  104. package/build/engine/actor/actor-collection.js +4 -1
  105. package/build/engine/actor/actor-creator.d.ts +3 -3
  106. package/build/engine/actor/actor-query.d.ts +29 -0
  107. package/build/engine/actor/actor-query.js +85 -0
  108. package/build/engine/actor/actor.d.ts +3 -4
  109. package/build/engine/actor/index.d.ts +2 -0
  110. package/build/engine/actor/index.js +1 -0
  111. package/build/engine/component/component.d.ts +2 -2
  112. package/build/engine/data-lib/cache-store.d.ts +2 -1
  113. package/build/engine/data-lib/cache-store.js +7 -1
  114. package/build/engine/engine.d.ts +28 -6
  115. package/build/engine/engine.js +35 -27
  116. package/build/engine/entity/entity.d.ts +1 -1
  117. package/build/engine/event-target/event-target.d.ts +1 -1
  118. package/build/engine/math-lib/vector/ops.d.ts +4 -4
  119. package/build/engine/math-lib/vector/ops.js +2 -3
  120. package/build/engine/resource-loader/loaders/image-loader.d.ts +1 -1
  121. package/build/engine/resource-loader/loaders/index.d.ts +2 -3
  122. package/build/engine/resource-loader/loaders/json-loader.d.ts +1 -1
  123. package/build/engine/resource-loader/loaders/loader.d.ts +1 -1
  124. package/build/engine/scene/scene-manager.js +7 -1
  125. package/build/engine/template/template-collection.d.ts +2 -2
  126. package/build/engine/template/template.d.ts +2 -2
  127. package/build/index.d.ts +2 -2
  128. package/build/index.js +1 -1
  129. package/build/types/global.d.ts +20 -0
  130. package/package.json +13 -10
  131. package/build/contrib/components/light/index.d.ts +0 -20
  132. package/build/contrib/components/light/index.js +0 -18
  133. package/build/contrib/components/renderable/index.d.ts +0 -44
  134. package/build/contrib/components/renderable/index.js +0 -65
  135. package/build/contrib/components/renderable/material.d.ts +0 -16
  136. package/build/contrib/components/renderable/material.js +0 -8
  137. package/build/contrib/components/sprite/material.d.ts +0 -16
  138. package/build/contrib/components/sprite/material.js +0 -8
  139. package/build/contrib/systems/sprite-renderer/index.d.ts +0 -2
  140. package/build/contrib/systems/sprite-renderer/index.js +0 -2
  141. package/build/contrib/systems/sprite-renderer/light-subsystem/index.d.ts +0 -13
  142. package/build/contrib/systems/sprite-renderer/light-subsystem/index.js +0 -62
  143. package/build/contrib/systems/sprite-renderer/light-subsystem/light-factory.d.ts +0 -4
  144. package/build/contrib/systems/sprite-renderer/light-subsystem/light-factory.js +0 -27
  145. package/build/contrib/systems/sprite-renderer/material-factory/index.d.ts +0 -4
  146. package/build/contrib/systems/sprite-renderer/material-factory/index.js +0 -32
  147. package/build/contrib/systems/sprite-renderer/renderer.d.ts +0 -36
  148. package/build/contrib/systems/sprite-renderer/renderer.js +0 -249
  149. package/build/contrib/systems/sprite-renderer/service/index.d.ts +0 -24
  150. package/build/contrib/systems/sprite-renderer/service/index.js +0 -52
  151. package/build/contrib/systems/sprite-renderer/sort/sort-by-fit.d.ts +0 -2
  152. package/build/contrib/systems/sprite-renderer/sort/sort-by-fit.js +0 -12
  153. package/build/contrib/systems/sprite-renderer/sort/sort-by-layer.d.ts +0 -2
  154. package/build/contrib/systems/sprite-renderer/sort/sort-by-layer.js +0 -14
  155. package/build/contrib/systems/sprite-renderer/sort/sort-by-x-axis.d.ts +0 -2
  156. package/build/contrib/systems/sprite-renderer/sort/sort-by-x-axis.js +0 -15
  157. package/build/contrib/systems/sprite-renderer/sort/sort-by-y-axis.d.ts +0 -2
  158. package/build/contrib/systems/sprite-renderer/sort/sort-by-y-axis.js +0 -15
  159. package/build/contrib/systems/sprite-renderer/sort/sort-by-z-axis.d.ts +0 -2
  160. package/build/contrib/systems/sprite-renderer/sort/sort-by-z-axis.js +0 -6
  161. package/build/contrib/systems/sprite-renderer/sort/types.d.ts +0 -2
  162. package/build/contrib/systems/sprite-renderer/sprite-cropper.d.ts +0 -8
  163. package/build/contrib/systems/sprite-renderer/sprite-cropper.js +0 -30
  164. package/build/contrib/systems/sprite-renderer/types.d.ts +0 -7
  165. package/build/contrib/systems/sprite-renderer/utils.d.ts +0 -9
  166. package/build/contrib/systems/sprite-renderer/utils.js +0 -47
  167. /package/build/contrib/systems/{sprite-renderer/sort/types.js → renderer/builders/builder.js} +0 -0
  168. /package/build/contrib/systems/{sprite-renderer → renderer/sort}/types.js +0 -0
  169. /package/build/contrib/systems/{sprite-renderer → renderer}/sort/utils.js +0 -0
@@ -0,0 +1,19 @@
1
+ import { Sprite as PixiSprite, TilingSprite } from 'pixi.js';
2
+ import type { Builder } from '../builder';
3
+ import type { Actor } from '../../../../../engine/actor';
4
+ import { CacheStore } from '../../../../../engine/data-lib';
5
+ interface SpriteBuilderOptions {
6
+ imageStore: CacheStore<HTMLImageElement>;
7
+ }
8
+ export declare class SpriteBuilder implements Builder {
9
+ private imageStore;
10
+ private textureSourceMap;
11
+ private textureArrayMap;
12
+ constructor(options: SpriteBuilderOptions);
13
+ destroy(actor: Actor): void;
14
+ buildView(actor: Actor): PixiSprite | TilingSprite | undefined;
15
+ updateView(actor: Actor): void;
16
+ private updateTextureArray;
17
+ private getTextureArray;
18
+ }
19
+ export {};
@@ -0,0 +1,166 @@
1
+ import { Texture, Sprite as PixiSprite, TilingSprite, Bounds, } from 'pixi.js';
2
+ import { BLEND_MODE_MAPPING } from '../../consts';
3
+ import { Transform } from '../../../../components/transform';
4
+ import { Sprite } from '../../../../components/sprite';
5
+ import { CacheStore } from '../../../../../engine/data-lib';
6
+ import { floatEquals } from '../utils';
7
+ import { getTextureSource, getTextureArray } from './utils';
8
+ export class SpriteBuilder {
9
+ imageStore;
10
+ textureSourceMap;
11
+ textureArrayMap;
12
+ constructor(options) {
13
+ this.imageStore = options.imageStore;
14
+ this.textureSourceMap = new CacheStore();
15
+ this.textureArrayMap = new CacheStore();
16
+ }
17
+ destroy(actor) {
18
+ const sprite = actor.getComponent(Sprite);
19
+ const textureSourceKey = sprite.renderData?.textureSourceKey;
20
+ const textureArrayKey = sprite.renderData?.textureArrayKey;
21
+ if (textureSourceKey) {
22
+ this.textureSourceMap.release(textureSourceKey, true);
23
+ }
24
+ if (textureArrayKey) {
25
+ this.textureArrayMap.release(textureArrayKey, true);
26
+ }
27
+ sprite.renderData?.view.destroy();
28
+ sprite.renderData = undefined;
29
+ }
30
+ buildView(actor) {
31
+ const sprite = actor.getComponent(Sprite);
32
+ if (!sprite) {
33
+ return undefined;
34
+ }
35
+ const { offsetX, offsetY } = actor.getComponent(Transform);
36
+ const options = { anchor: 0.5 };
37
+ const view = sprite.fit === 'stretch'
38
+ ? new PixiSprite(options)
39
+ : new TilingSprite(options);
40
+ sprite.renderData = { view };
41
+ view.__dacha = {
42
+ actor,
43
+ builderKey: Sprite.componentName,
44
+ viewComponent: sprite,
45
+ bounds: new Bounds(offsetX, offsetY, offsetX, offsetY),
46
+ meta: {},
47
+ didChange: false,
48
+ };
49
+ return view;
50
+ }
51
+ updateView(actor) {
52
+ const transform = actor.getComponent(Transform);
53
+ const sprite = actor.getComponent(Sprite);
54
+ if (!sprite) {
55
+ return undefined;
56
+ }
57
+ const view = sprite.renderData.view;
58
+ const meta = view.__dacha.meta;
59
+ view.__dacha.didChange = false;
60
+ if (sprite.disabled !== meta.disabled) {
61
+ view.visible = !sprite.disabled;
62
+ meta.disabled = sprite.disabled;
63
+ view.__dacha.didChange = true;
64
+ }
65
+ if (sprite.color !== meta.color) {
66
+ view.tint = sprite.color;
67
+ meta.color = sprite.color;
68
+ view.__dacha.didChange = true;
69
+ }
70
+ if (sprite.blending !== meta.blending) {
71
+ view.blendMode = BLEND_MODE_MAPPING[sprite.blending];
72
+ meta.blending = sprite.blending;
73
+ view.__dacha.didChange = true;
74
+ }
75
+ if (sprite.opacity !== meta.opacity) {
76
+ view.alpha = sprite.opacity;
77
+ meta.opacity = sprite.opacity;
78
+ view.__dacha.didChange = true;
79
+ }
80
+ const angle = transform.rotation + sprite.rotation;
81
+ if (angle !== meta.angle) {
82
+ view.angle = angle;
83
+ meta.angle = angle;
84
+ view.__dacha.didChange = true;
85
+ }
86
+ const { offsetX, offsetY } = transform;
87
+ if (!floatEquals(offsetX, meta.offsetX) ||
88
+ !floatEquals(offsetY, meta.offsetY)) {
89
+ view.position.set(offsetX, offsetY);
90
+ meta.offsetX = offsetX;
91
+ meta.offsetY = offsetY;
92
+ view.__dacha.didChange = true;
93
+ }
94
+ if (this.imageStore.has(sprite.src) &&
95
+ (sprite.src !== meta.src || sprite.slice !== meta.slice)) {
96
+ view.label = sprite.src;
97
+ this.updateTextureArray(sprite);
98
+ meta.src = sprite.src;
99
+ meta.slice = sprite.slice;
100
+ view.__dacha.didChange = true;
101
+ }
102
+ const textureArray = this.getTextureArray(sprite);
103
+ const texture = textureArray?.[sprite.currentFrame ?? 0];
104
+ view.texture = texture ?? Texture.WHITE;
105
+ const scaleX = (sprite.flipX ? -1 : 1) * transform.scaleX;
106
+ const scaleY = (sprite.flipY ? -1 : 1) * transform.scaleY;
107
+ if (view.texture !== meta.texture ||
108
+ scaleX !== meta.scaleX ||
109
+ scaleY !== meta.scaleY ||
110
+ sprite.width !== meta.width ||
111
+ sprite.height !== meta.height) {
112
+ if (sprite.fit === 'stretch') {
113
+ view.scale.set((sprite.width / view.texture.width) * scaleX, (sprite.height / view.texture.height) * scaleY);
114
+ }
115
+ if (sprite.fit === 'repeat') {
116
+ view.setSize(sprite.width, sprite.height);
117
+ view.scale.set(scaleX, scaleY);
118
+ }
119
+ meta.texture = view.texture;
120
+ meta.scaleX = scaleX;
121
+ meta.scaleY = scaleY;
122
+ meta.width = sprite.width;
123
+ meta.height = sprite.height;
124
+ view.__dacha.didChange = true;
125
+ }
126
+ }
127
+ updateTextureArray(sprite) {
128
+ const oldTextureSourceKey = sprite.renderData.textureSourceKey;
129
+ const oldTextureArrayKey = sprite.renderData.textureArrayKey;
130
+ if (oldTextureSourceKey) {
131
+ this.textureSourceMap.release(oldTextureSourceKey, true);
132
+ }
133
+ if (oldTextureArrayKey) {
134
+ this.textureArrayMap.release(oldTextureArrayKey, true);
135
+ }
136
+ sprite.renderData.textureSourceKey = sprite.src;
137
+ sprite.renderData.textureArrayKey = `${sprite.slice}_${sprite.renderData.textureSourceKey}`;
138
+ const textureSourceKey = sprite.renderData.textureSourceKey;
139
+ const textureArrayKey = sprite.renderData.textureArrayKey;
140
+ if (this.textureArrayMap.has(textureArrayKey)) {
141
+ this.textureArrayMap.retain(textureArrayKey);
142
+ this.textureSourceMap.retain(textureSourceKey);
143
+ return;
144
+ }
145
+ if (this.textureSourceMap.has(textureSourceKey)) {
146
+ const textureSource = this.textureSourceMap.get(textureSourceKey);
147
+ const textureArray = getTextureArray(textureSource, sprite);
148
+ this.textureArrayMap.add(textureArrayKey, textureArray);
149
+ this.textureArrayMap.retain(textureArrayKey);
150
+ this.textureSourceMap.retain(textureSourceKey);
151
+ }
152
+ const image = this.imageStore.get(sprite.src);
153
+ if (!image) {
154
+ return undefined;
155
+ }
156
+ const textureSource = getTextureSource(image);
157
+ const textureArray = getTextureArray(textureSource, sprite);
158
+ this.textureSourceMap.add(textureSourceKey, textureSource);
159
+ this.textureArrayMap.add(textureArrayKey, textureArray);
160
+ this.textureArrayMap.retain(textureArrayKey);
161
+ this.textureSourceMap.retain(textureSourceKey);
162
+ }
163
+ getTextureArray(sprite) {
164
+ return this.textureArrayMap.get(sprite.renderData.textureArrayKey);
165
+ }
166
+ }
@@ -0,0 +1,4 @@
1
+ import { Texture, TextureSource } from 'pixi.js';
2
+ import { Sprite } from '../../../../components/sprite';
3
+ export declare const getTextureSource: (image: HTMLImageElement) => TextureSource;
4
+ export declare const getTextureArray: (textureSource: TextureSource, sprite: Sprite) => Texture[];
@@ -0,0 +1,16 @@
1
+ import { Texture, TextureSource, Rectangle } from 'pixi.js';
2
+ export const getTextureSource = (image) => TextureSource.from({
3
+ resource: image,
4
+ scaleMode: 'nearest',
5
+ });
6
+ export const getTextureArray = (textureSource, sprite) => {
7
+ const textures = [];
8
+ const frameWidth = Math.max(textureSource.width / sprite.slice, 1);
9
+ const frameHeight = Math.max(textureSource.height, 1);
10
+ for (let i = 0; i < sprite.slice; i += 1) {
11
+ const rectangle = new Rectangle(i * frameWidth, 0, frameWidth, frameHeight);
12
+ const texture = new Texture({ source: textureSource, frame: rectangle });
13
+ textures.push(texture);
14
+ }
15
+ return textures;
16
+ };
@@ -0,0 +1 @@
1
+ export declare const floatEquals: (a: number, b: number) => boolean;
@@ -0,0 +1,4 @@
1
+ const FLOAT_EPSILON = 1e-5;
2
+ export const floatEquals = (a, b) => {
3
+ return Math.abs(a - b) < FLOAT_EPSILON;
4
+ };
@@ -0,0 +1,5 @@
1
+ import { type BLEND_MODES } from 'pixi.js';
2
+ import { type BlendingMode } from '../../components/sprite';
3
+ import { type SortingOrder } from './types';
4
+ export declare const BLEND_MODE_MAPPING: Record<BlendingMode, BLEND_MODES>;
5
+ export declare const SORTING_ORDER_MAPPING: Record<SortingOrder, [number, number]>;
@@ -0,0 +1,12 @@
1
+ export const BLEND_MODE_MAPPING = {
2
+ normal: 'normal',
3
+ addition: 'add',
4
+ substract: 'subtract',
5
+ multiply: 'multiply',
6
+ };
7
+ export const SORTING_ORDER_MAPPING = {
8
+ bottomRight: [1, 1],
9
+ bottomLeft: [-1, 1],
10
+ topLeft: [-1, -1],
11
+ topRight: [1, -1],
12
+ };
@@ -0,0 +1,2 @@
1
+ export { Renderer } from './renderer';
2
+ export { RendererService } from './service';
@@ -0,0 +1,2 @@
1
+ export { Renderer } from './renderer';
2
+ export { RendererService } from './service';
@@ -0,0 +1,31 @@
1
+ import { WorldSystem, type WorldSystemOptions } from '../../../engine/system';
2
+ import { type Scene } from '../../../engine/scene';
3
+ export declare class Renderer extends WorldSystem {
4
+ private actorQuery?;
5
+ private viewEntries?;
6
+ private deletedActors;
7
+ private window;
8
+ private application;
9
+ private worldContainer;
10
+ private imageStore;
11
+ private builders;
12
+ private sortFn;
13
+ private templateCollection;
14
+ private backgroundColor;
15
+ private cameraService;
16
+ constructor(options: WorldSystemOptions);
17
+ onWorldLoad(): Promise<void>;
18
+ onWorldDestroy(): void;
19
+ onSceneLoad(scene: Scene): Promise<void>;
20
+ onSceneEnter(scene: Scene): void;
21
+ onSceneExit(): void;
22
+ onSceneDestroy(scene: Scene): void;
23
+ private handleActorAdd;
24
+ private handleActorRemove;
25
+ private updateCamera;
26
+ private updateViews;
27
+ private updateBounds;
28
+ private sortViews;
29
+ private clearDeletedEntries;
30
+ update(): void;
31
+ }
@@ -0,0 +1,249 @@
1
+ import { Application, Container, Color, Assets, } from 'pixi.js';
2
+ import { AddActor, RemoveActor, } from '../../../engine/events';
3
+ import { WorldSystem } from '../../../engine/system';
4
+ import { ActorQuery } from '../../../engine/actor';
5
+ import { Transform } from '../../components/transform';
6
+ import { Sprite } from '../../components/sprite';
7
+ import { Shape } from '../../components/shape';
8
+ import { PixiView } from '../../components/pixi-view';
9
+ import { BitmapText } from '../../components/bitmap-text';
10
+ import { Camera } from '../../components/camera';
11
+ import { CameraService } from '../camera-system';
12
+ import { CacheStore } from '../../../engine/data-lib';
13
+ import { getWindowNode } from '../../utils/get-window-node';
14
+ import { RendererService } from './service';
15
+ import { composeSort, createSortByLayer, sortByYAxis, sortByXAxis, } from './sort';
16
+ import { parseSortingLayers } from './sort/utils';
17
+ import { loadImage, getAllImageSources, getAllFontSources } from './utils';
18
+ import { SpriteBuilder, ShapeBuilder, PixiViewBuilder, BitmapTextBuilder, } from './builders';
19
+ import { SORTING_ORDER_MAPPING } from './consts';
20
+ export class Renderer extends WorldSystem {
21
+ actorQuery;
22
+ viewEntries;
23
+ deletedActors;
24
+ window;
25
+ application;
26
+ worldContainer;
27
+ imageStore;
28
+ builders;
29
+ sortFn;
30
+ templateCollection;
31
+ backgroundColor;
32
+ cameraService;
33
+ constructor(options) {
34
+ super();
35
+ const { globalOptions, windowNodeId, backgroundColor, templateCollection, world, } = options;
36
+ this.templateCollection = templateCollection;
37
+ this.backgroundColor = new Color(backgroundColor);
38
+ this.window = getWindowNode(windowNodeId);
39
+ const sorting = globalOptions.sorting;
40
+ const sortingOrder = SORTING_ORDER_MAPPING[sorting?.order ?? 'bottomRight'];
41
+ this.sortFn = composeSort([
42
+ createSortByLayer(parseSortingLayers(sorting?.layers)),
43
+ sortByYAxis(sortingOrder[1]),
44
+ sortByXAxis(sortingOrder[0]),
45
+ ]);
46
+ this.application = new Application();
47
+ this.worldContainer = new Container({ sortableChildren: true });
48
+ this.imageStore = new CacheStore();
49
+ this.builders = new Map();
50
+ this.builders.set(Sprite.componentName, new SpriteBuilder({ imageStore: this.imageStore }));
51
+ this.builders.set(Shape.componentName, new ShapeBuilder());
52
+ this.builders.set(PixiView.componentName, new PixiViewBuilder());
53
+ this.builders.set(BitmapText.componentName, new BitmapTextBuilder());
54
+ this.cameraService = world.getService(CameraService);
55
+ this.deletedActors = new Set();
56
+ world.addService(new RendererService({
57
+ application: this.application,
58
+ getViewEntries: () => this.viewEntries,
59
+ sortFn: this.sortFn,
60
+ }));
61
+ }
62
+ async onWorldLoad() {
63
+ await this.application.init({
64
+ autoStart: false,
65
+ resizeTo: this.window,
66
+ width: this.window.clientWidth,
67
+ height: this.window.clientHeight,
68
+ backgroundColor: this.backgroundColor.toHex(),
69
+ backgroundAlpha: this.backgroundColor.alpha,
70
+ resolution: window.devicePixelRatio,
71
+ autoDensity: true,
72
+ });
73
+ this.window.appendChild(this.application.canvas);
74
+ this.application.stage.addChild(this.worldContainer);
75
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
76
+ // @ts-ignore
77
+ window.__PIXI_DEVTOOLS__ = {
78
+ app: this.application,
79
+ };
80
+ }
81
+ onWorldDestroy() {
82
+ this.window.removeChild(this.application.canvas);
83
+ this.application.destroy();
84
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
85
+ // @ts-ignore
86
+ window.__PIXI_DEVTOOLS__ = undefined;
87
+ }
88
+ async onSceneLoad(scene) {
89
+ const allImageSources = [
90
+ ...getAllImageSources(this.templateCollection.getAll()),
91
+ ...getAllImageSources(scene.children),
92
+ ];
93
+ const uniqueImageSources = [...new Set(allImageSources)];
94
+ const images = await Promise.all(uniqueImageSources.map((src) => {
95
+ return !this.imageStore.has(src) ? loadImage(src) : undefined;
96
+ }));
97
+ uniqueImageSources.forEach((src, index) => {
98
+ if (images[index]) {
99
+ this.imageStore.add(src, images[index]);
100
+ }
101
+ });
102
+ allImageSources.forEach((src) => this.imageStore.retain(src));
103
+ const allFontSources = [
104
+ ...getAllFontSources(this.templateCollection.getAll()),
105
+ ...getAllFontSources(scene.children),
106
+ ];
107
+ const uniqueFontSources = [...new Set(allFontSources)];
108
+ await Assets.load(uniqueFontSources);
109
+ }
110
+ onSceneEnter(scene) {
111
+ this.actorQuery = new ActorQuery({
112
+ scene,
113
+ filter: (actor) => Boolean(actor.getComponent(Transform) &&
114
+ (actor.getComponent(Sprite) ||
115
+ actor.getComponent(Shape) ||
116
+ actor.getComponent(PixiView) ||
117
+ actor.getComponent(BitmapText))),
118
+ });
119
+ this.viewEntries = [];
120
+ for (const actor of this.actorQuery.getActors()) {
121
+ this.builders.forEach((builder) => {
122
+ const view = builder.buildView(actor);
123
+ if (view) {
124
+ this.viewEntries?.push(view);
125
+ this.worldContainer.addChild(view);
126
+ }
127
+ });
128
+ }
129
+ this.actorQuery.addEventListener(AddActor, this.handleActorAdd);
130
+ this.actorQuery.addEventListener(RemoveActor, this.handleActorRemove);
131
+ }
132
+ onSceneExit() {
133
+ this.actorQuery?.removeEventListener(AddActor, this.handleActorAdd);
134
+ this.actorQuery?.removeEventListener(RemoveActor, this.handleActorRemove);
135
+ this.worldContainer.removeChildren();
136
+ this.application.renderer.clear();
137
+ this.viewEntries?.forEach((entry) => {
138
+ this.builders.get(entry.__dacha.builderKey).destroy(entry.__dacha.actor);
139
+ });
140
+ this.viewEntries = undefined;
141
+ this.actorQuery?.destroy();
142
+ this.actorQuery = undefined;
143
+ }
144
+ onSceneDestroy(scene) {
145
+ const allSources = [
146
+ ...getAllImageSources(this.templateCollection.getAll()),
147
+ ...getAllImageSources(scene.children),
148
+ ];
149
+ allSources.forEach((src) => this.imageStore.release(src));
150
+ this.imageStore.cleanReleased();
151
+ }
152
+ handleActorAdd = (event) => {
153
+ const { actor } = event;
154
+ const sprite = actor.getComponent(Sprite);
155
+ if (sprite) {
156
+ const { src } = sprite;
157
+ if (this.imageStore.has(src)) {
158
+ this.imageStore.retain(src);
159
+ }
160
+ else {
161
+ void loadImage(src).then((image) => {
162
+ if (image) {
163
+ this.imageStore.add(src, image);
164
+ this.imageStore.retain(src);
165
+ }
166
+ });
167
+ }
168
+ }
169
+ const text = actor.getComponent(BitmapText);
170
+ if (text) {
171
+ Assets.load(text.font);
172
+ }
173
+ this.builders.forEach((builder) => {
174
+ const view = builder.buildView(actor);
175
+ if (view) {
176
+ this.viewEntries?.push(view);
177
+ this.worldContainer.addChild(view);
178
+ }
179
+ });
180
+ this.deletedActors.delete(actor);
181
+ };
182
+ handleActorRemove = (event) => {
183
+ const { actor } = event;
184
+ const sprite = actor.getComponent(Sprite);
185
+ if (sprite) {
186
+ this.imageStore.release(sprite.src);
187
+ }
188
+ this.deletedActors.add(actor);
189
+ };
190
+ updateCamera() {
191
+ const currentCamera = this.cameraService.getCurrentCamera();
192
+ const transform = currentCamera?.getComponent(Transform);
193
+ const camera = currentCamera?.getComponent(Camera);
194
+ const offsetX = transform?.offsetX ?? 0;
195
+ const offsetY = transform?.offsetY ?? 0;
196
+ const zoom = camera?.zoom ?? 1;
197
+ this.worldContainer.scale.set(zoom);
198
+ this.worldContainer.position.set(this.application.renderer.width / 2, this.application.renderer.height / 2);
199
+ this.worldContainer.pivot.set(offsetX, offsetY);
200
+ }
201
+ updateViews() {
202
+ this.viewEntries?.forEach((view) => {
203
+ this.builders
204
+ .get(view.__dacha.builderKey)
205
+ .updateView(view.__dacha.actor);
206
+ });
207
+ }
208
+ updateBounds() {
209
+ this.viewEntries?.forEach((view) => {
210
+ if (!view.__dacha.didChange) {
211
+ return;
212
+ }
213
+ const bounds = view.getLocalBounds();
214
+ view.__dacha.bounds.set(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY);
215
+ view.updateLocalTransform();
216
+ view.__dacha.bounds.applyMatrix(view.localTransform);
217
+ });
218
+ }
219
+ sortViews() {
220
+ this.viewEntries?.sort(this.sortFn);
221
+ this.viewEntries?.forEach((view, index) => {
222
+ view.zIndex = index;
223
+ });
224
+ }
225
+ clearDeletedEntries() {
226
+ if (this.deletedActors.size === 0) {
227
+ return;
228
+ }
229
+ this.worldContainer.removeChildren();
230
+ this.viewEntries = this.viewEntries?.filter((entry) => {
231
+ if (!this.deletedActors.has(entry.__dacha.actor)) {
232
+ this.worldContainer.addChild(entry);
233
+ return true;
234
+ }
235
+ this.builders.get(entry.__dacha.builderKey).destroy(entry.__dacha.actor);
236
+ return false;
237
+ });
238
+ this.deletedActors.clear();
239
+ }
240
+ update() {
241
+ this.clearDeletedEntries();
242
+ this.updateCamera();
243
+ this.updateViews();
244
+ this.updateBounds();
245
+ this.sortViews();
246
+ this.application.renderer.render({ container: this.application.stage });
247
+ }
248
+ }
249
+ Renderer.systemName = 'Renderer';
@@ -0,0 +1,20 @@
1
+ import { type ViewContainer, type Application } from 'pixi.js';
2
+ import { type Actor } from '../../../../engine/actor';
3
+ import { type SortFn } from '../sort';
4
+ import { type Bounds } from '../types';
5
+ interface RendererServiceOptions {
6
+ application: Application;
7
+ getViewEntries: () => ViewContainer[] | undefined;
8
+ sortFn: SortFn;
9
+ }
10
+ export declare class RendererService {
11
+ private application;
12
+ private getViewEntries;
13
+ private sortFn;
14
+ constructor({ application, getViewEntries, sortFn }: RendererServiceOptions);
15
+ getRenderingContext(): Application;
16
+ intersectsWithPoint(x: number, y: number): Actor[];
17
+ intersectsWithRectangle(minX: number, minY: number, maxX: number, maxY: number): Actor[];
18
+ getBounds(actor: Actor): Bounds;
19
+ }
20
+ export {};
@@ -0,0 +1,70 @@
1
+ import { Sprite } from '../../../components/sprite';
2
+ import { Shape } from '../../../components/shape';
3
+ import { PixiView } from '../../../components/pixi-view';
4
+ import { BitmapText } from '../../../components/bitmap-text';
5
+ import { Transform } from '../../../components/transform';
6
+ const VIEW_COMPONENTS = [Sprite, Shape, PixiView, BitmapText];
7
+ export class RendererService {
8
+ application;
9
+ getViewEntries;
10
+ sortFn;
11
+ constructor({ application, getViewEntries, sortFn }) {
12
+ this.application = application;
13
+ this.getViewEntries = getViewEntries;
14
+ this.sortFn = sortFn;
15
+ }
16
+ getRenderingContext() {
17
+ return this.application;
18
+ }
19
+ intersectsWithPoint(x, y) {
20
+ const intersects = new Set();
21
+ this.getViewEntries()?.forEach((entry) => {
22
+ const { minX, minY, maxX, maxY } = entry.__dacha.bounds;
23
+ if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
24
+ intersects.add(entry);
25
+ }
26
+ });
27
+ // TODO: Find more efficient way to return intersected objects in right order
28
+ // according to posititon and sorting layer
29
+ return Array.from(intersects)
30
+ .sort(this.sortFn)
31
+ .reverse()
32
+ .map((entry) => entry.__dacha.actor);
33
+ }
34
+ intersectsWithRectangle(minX, minY, maxX, maxY) {
35
+ const actors = new Set();
36
+ this.getViewEntries()?.forEach((entry) => {
37
+ const { x, y } = entry.position;
38
+ if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
39
+ actors.add(entry.__dacha.actor);
40
+ }
41
+ });
42
+ return Array.from(actors);
43
+ }
44
+ getBounds(actor) {
45
+ const transform = actor.getComponent(Transform);
46
+ let minX = transform.offsetX;
47
+ let minY = transform.offsetY;
48
+ let maxX = transform.offsetX;
49
+ let maxY = transform.offsetY;
50
+ VIEW_COMPONENTS.forEach((ViewComponent) => {
51
+ const viewComponent = actor.getComponent(ViewComponent);
52
+ const bounds = viewComponent?.renderData?.view.__dacha.bounds;
53
+ if (!bounds) {
54
+ return;
55
+ }
56
+ minX = Math.min(minX, bounds?.minX);
57
+ minY = Math.min(minY, bounds?.minY);
58
+ maxX = Math.max(maxX, bounds?.maxX);
59
+ maxY = Math.max(maxY, bounds?.maxY);
60
+ });
61
+ return {
62
+ minX,
63
+ minY,
64
+ maxX,
65
+ maxY,
66
+ width: maxX - minX,
67
+ height: maxY - minY,
68
+ };
69
+ }
70
+ }
@@ -2,7 +2,5 @@ import { SortFn } from './types';
2
2
  export { createSortByLayer } from './sort-by-layer';
3
3
  export { sortByXAxis } from './sort-by-x-axis';
4
4
  export { sortByYAxis } from './sort-by-y-axis';
5
- export { sortByZAxis } from './sort-by-z-axis';
6
- export { sortByFit } from './sort-by-fit';
7
- export declare const composeSort: (sortFns: Array<SortFn>) => SortFn;
5
+ export declare const composeSort: (sortFns: SortFn[]) => SortFn;
8
6
  export type { SortFn };
@@ -1,12 +1,10 @@
1
1
  export { createSortByLayer } from './sort-by-layer';
2
2
  export { sortByXAxis } from './sort-by-x-axis';
3
3
  export { sortByYAxis } from './sort-by-y-axis';
4
- export { sortByZAxis } from './sort-by-z-axis';
5
- export { sortByFit } from './sort-by-fit';
6
4
  export const composeSort = (sortFns) => (a, b) => {
7
5
  let result = 0;
8
- for (let i = 0; i < sortFns.length; i += 1) {
9
- result = sortFns[i](a, b);
6
+ for (const sortFn of sortFns) {
7
+ result = sortFn(a, b);
10
8
  if (result !== 0) {
11
9
  return result;
12
10
  }
@@ -0,0 +1,2 @@
1
+ import type { SortFn } from './types';
2
+ export declare const createSortByLayer: (sortingLayers: string[]) => SortFn;
@@ -0,0 +1,13 @@
1
+ export const createSortByLayer = (sortingLayers) => {
2
+ const sortingLayer = sortingLayers.reduce((storage, layer, index) => {
3
+ storage[layer] = index;
4
+ return storage;
5
+ }, {});
6
+ return (a, b) => {
7
+ const aComponent = a.__dacha.viewComponent;
8
+ const bComponent = b.__dacha.viewComponent;
9
+ const aSortingLayerOrder = sortingLayer[aComponent.sortingLayer];
10
+ const bSortingLayerOrder = sortingLayer[bComponent.sortingLayer];
11
+ return aSortingLayerOrder - bSortingLayerOrder;
12
+ };
13
+ };
@@ -0,0 +1,2 @@
1
+ import type { SortFn } from './types';
2
+ export declare const sortByXAxis: (direction?: number) => SortFn;