dacha 0.18.0 → 0.18.1

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.
@@ -8,17 +8,17 @@ interface RenderData {
8
8
  }
9
9
  type TextAlign = 'left' | 'center' | 'right';
10
10
  export interface BitmapTextConfig {
11
- text: string;
12
- font: string;
13
- fontSize: number;
14
- align: TextAlign;
15
- color: string;
16
- opacity: number;
17
- blending: BlendingMode;
18
- disabled: boolean;
19
- sortingLayer: string;
20
- sortOffsetX: number;
21
- sortOffsetY: number;
11
+ text?: string;
12
+ font?: string;
13
+ fontSize?: number;
14
+ align?: TextAlign;
15
+ color?: string;
16
+ opacity?: number;
17
+ blending?: BlendingMode;
18
+ disabled?: boolean;
19
+ sortingLayer?: string;
20
+ sortOffsetX?: number;
21
+ sortOffsetY?: number;
22
22
  }
23
23
  /**
24
24
  * BitmapText component for rendering text using a bitmap font.
@@ -60,16 +60,19 @@ export class BitmapText extends Component {
60
60
  renderData;
61
61
  constructor(config) {
62
62
  super();
63
- this.text = config.text;
64
- this.font = config.font;
65
- this.fontSize = config.fontSize;
66
- this.align = config.align;
67
- this.color = config.color;
68
- this.opacity = config.opacity;
69
- this.blending = config.blending;
70
- this.disabled = config.disabled;
71
- this.sortingLayer = config.sortingLayer;
72
- this.sortOffset = { x: config.sortOffsetX, y: config.sortOffsetY };
63
+ this.text = config.text ?? 'Text';
64
+ this.font = config.font ?? '';
65
+ this.fontSize = config.fontSize ?? 10;
66
+ this.align = config.align ?? 'center';
67
+ this.color = config.color ?? '#000000';
68
+ this.opacity = config.opacity ?? 1;
69
+ this.blending = config.blending ?? 'normal';
70
+ this.disabled = config.disabled ?? false;
71
+ this.sortingLayer = config.sortingLayer ?? 'default';
72
+ this.sortOffset = {
73
+ x: config.sortOffsetX ?? 0,
74
+ y: config.sortOffsetY ?? 0,
75
+ };
73
76
  }
74
77
  }
75
78
  BitmapText.componentName = 'BitmapText';
@@ -13,20 +13,20 @@ export interface MaterialConfig {
13
13
  options: Record<string, unknown>;
14
14
  }
15
15
  export interface MeshConfig {
16
- src: string;
17
- width: number;
18
- height: number;
19
- slice: number;
20
- flipX: boolean;
21
- flipY: boolean;
22
- sortingLayer: string;
23
- sortOffsetX: number;
24
- sortOffsetY: number;
25
- color: string;
26
- blending: BlendingMode;
27
- opacity: number;
16
+ src?: string;
17
+ width?: number;
18
+ height?: number;
19
+ slice?: number;
20
+ flipX?: boolean;
21
+ flipY?: boolean;
22
+ sortingLayer?: string;
23
+ sortOffsetX?: number;
24
+ sortOffsetY?: number;
25
+ color?: string;
26
+ blending?: BlendingMode;
27
+ opacity?: number;
28
28
  material?: MaterialConfig;
29
- disabled: boolean;
29
+ disabled?: boolean;
30
30
  }
31
31
  /**
32
32
  * Mesh component for rendering 2D textures with a custom shader.
@@ -78,16 +78,19 @@ export class Mesh extends Component {
78
78
  */
79
79
  constructor(config) {
80
80
  super();
81
- this.src = config.src;
82
- this.width = config.width;
83
- this.height = config.height;
84
- this.slice = config.slice;
81
+ this.src = config.src ?? '';
82
+ this.width = config.width ?? 10;
83
+ this.height = config.height ?? 10;
84
+ this.slice = config.slice ?? 1;
85
85
  this.currentFrame = 0;
86
- this.flipX = config.flipX;
87
- this.flipY = config.flipY;
88
- this.disabled = config.disabled;
89
- this.sortingLayer = config.sortingLayer;
90
- this.sortOffset = { x: config.sortOffsetX, y: config.sortOffsetY };
86
+ this.flipX = config.flipX ?? false;
87
+ this.flipY = config.flipY ?? false;
88
+ this.disabled = config.disabled ?? false;
89
+ this.sortingLayer = config.sortingLayer ?? 'default';
90
+ this.sortOffset = {
91
+ x: config.sortOffsetX ?? 0,
92
+ y: config.sortOffsetY ?? 0,
93
+ };
91
94
  this.color = config.color ?? '#ffffff';
92
95
  this.blending = config.blending ?? 'normal';
93
96
  this.opacity = config.opacity ?? 1;
@@ -5,10 +5,10 @@ interface RenderData {
5
5
  view: ViewContainer;
6
6
  }
7
7
  export interface PixiViewConfig {
8
- createView: () => ViewContainer;
9
- sortingLayer: string;
10
- sortOffsetX: number;
11
- sortOffsetY: number;
8
+ createView?: () => ViewContainer;
9
+ sortingLayer?: string;
10
+ sortOffsetX?: number;
11
+ sortOffsetY?: number;
12
12
  }
13
13
  /**
14
14
  * PixiView component for rendering a view.
@@ -41,7 +41,7 @@ export interface PixiViewConfig {
41
41
  */
42
42
  export declare class PixiView extends Component {
43
43
  /** Function to create a custom pixi.js view */
44
- createView: () => ViewContainer;
44
+ createView?: () => ViewContainer;
45
45
  /** Sorting layer of the pixi view */
46
46
  sortingLayer: string;
47
47
  /** Center point of the pixi view */
@@ -45,8 +45,11 @@ export class PixiView extends Component {
45
45
  constructor(config) {
46
46
  super();
47
47
  this.createView = config.createView;
48
- this.sortingLayer = config.sortingLayer;
49
- this.sortOffset = { x: config.sortOffsetX, y: config.sortOffsetY };
48
+ this.sortingLayer = config.sortingLayer ?? 'default';
49
+ this.sortOffset = {
50
+ x: config.sortOffsetX ?? 0,
51
+ y: config.sortOffsetY ?? 0,
52
+ };
50
53
  }
51
54
  /** Get the pixi.js view. It's only available after the actor with this component is added to a scene */
52
55
  get view() {
@@ -9,45 +9,29 @@ interface RenderData {
9
9
  export type ShapeType = 'rectangle' | 'roundRectangle' | 'circle' | 'ellipse' | 'line';
10
10
  export interface BaseShapeConfig {
11
11
  strokeColor?: string;
12
- strokeWidth: number;
13
- strokeAlignment: number;
14
- pixelLine: boolean;
12
+ strokeWidth?: number;
13
+ strokeAlignment?: number;
14
+ pixelLine?: boolean;
15
15
  fill?: string;
16
- opacity: number;
17
- blending: BlendingMode;
18
- disabled: boolean;
19
- sortingLayer: string;
20
- sortOffsetX: number;
21
- sortOffsetY: number;
22
- }
23
- export interface RectangleShapeConfig extends BaseShapeConfig {
24
- type: 'rectangle';
25
- sizeX: number;
26
- sizeY: number;
16
+ opacity?: number;
17
+ blending?: BlendingMode;
18
+ disabled?: boolean;
19
+ sortingLayer?: string;
20
+ sortOffsetX?: number;
21
+ sortOffsetY?: number;
27
22
  }
28
- export interface RoundRectangleShapeConfig extends BaseShapeConfig {
29
- type: 'roundRectangle';
30
- sizeX: number;
31
- sizeY: number;
32
- radius: number;
33
- }
34
- export interface CircleShapeConfig extends BaseShapeConfig {
35
- type: 'circle';
36
- radius: number;
37
- }
38
- export interface EllipseShapeConfig extends BaseShapeConfig {
39
- type: 'ellipse';
40
- radiusX: number;
41
- radiusY: number;
42
- }
43
- export interface LineShapeConfig extends BaseShapeConfig {
44
- type: 'line';
45
- point1X: number;
46
- point1Y: number;
47
- point2X: number;
48
- point2Y: number;
23
+ export interface ShapeConfig extends BaseShapeConfig {
24
+ type?: ShapeType;
25
+ sizeX?: number;
26
+ sizeY?: number;
27
+ radius?: number;
28
+ radiusX?: number;
29
+ radiusY?: number;
30
+ point1X?: number;
31
+ point1Y?: number;
32
+ point2X?: number;
33
+ point2Y?: number;
49
34
  }
50
- export type ShapeConfig = RectangleShapeConfig | RoundRectangleShapeConfig | CircleShapeConfig | EllipseShapeConfig | LineShapeConfig;
51
35
  export interface RectangleShapeGeometry {
52
36
  type: 'rectangle';
53
37
  size: Point;
@@ -71,47 +71,51 @@ export class Shape extends Component {
71
71
  */
72
72
  constructor(config) {
73
73
  super();
74
- this.strokeColor = config.strokeColor;
75
- this.strokeWidth = config.strokeWidth;
76
- this.strokeAlignment = config.strokeAlignment;
77
- this.pixelLine = config.pixelLine;
78
- this.fill = config.fill;
79
- this.opacity = config.opacity;
80
- this.blending = config.blending;
81
- this.disabled = config.disabled;
82
- this.sortingLayer = config.sortingLayer;
83
- this.sortOffset = { x: config.sortOffsetX, y: config.sortOffsetY };
84
- switch (config.type) {
74
+ this.strokeColor = config.strokeColor ?? '#ffffff';
75
+ this.strokeWidth = config.strokeWidth ?? 0;
76
+ this.strokeAlignment = config.strokeAlignment ?? 0.5;
77
+ this.pixelLine = config.pixelLine ?? false;
78
+ this.fill = config.fill ?? '#ffffff';
79
+ this.opacity = config.opacity ?? 1;
80
+ this.blending = config.blending ?? 'normal';
81
+ this.disabled = config.disabled ?? false;
82
+ this.sortingLayer = config.sortingLayer ?? 'default';
83
+ this.sortOffset = {
84
+ x: config.sortOffsetX ?? 0,
85
+ y: config.sortOffsetY ?? 0,
86
+ };
87
+ const type = config.type ?? 'rectangle';
88
+ switch (type) {
85
89
  case 'rectangle':
86
90
  this.geometry = {
87
- type: config.type,
88
- size: { x: config.sizeX, y: config.sizeY },
91
+ type,
92
+ size: { x: config.sizeX ?? 10, y: config.sizeY ?? 10 },
89
93
  };
90
94
  break;
91
95
  case 'roundRectangle':
92
96
  this.geometry = {
93
- type: config.type,
94
- size: { x: config.sizeX, y: config.sizeY },
95
- radius: config.radius,
97
+ type,
98
+ size: { x: config.sizeX ?? 10, y: config.sizeY ?? 10 },
99
+ radius: config.radius ?? 2,
96
100
  };
97
101
  break;
98
102
  case 'circle':
99
103
  this.geometry = {
100
- type: config.type,
101
- radius: config.radius,
104
+ type,
105
+ radius: config.radius ?? 5,
102
106
  };
103
107
  break;
104
108
  case 'ellipse':
105
109
  this.geometry = {
106
- type: config.type,
107
- radius: { x: config.radiusX, y: config.radiusY },
110
+ type,
111
+ radius: { x: config.radiusX ?? 5, y: config.radiusY ?? 5 },
108
112
  };
109
113
  break;
110
114
  case 'line':
111
115
  this.geometry = {
112
- type: config.type,
113
- point1: { x: config.point1X, y: config.point1Y },
114
- point2: { x: config.point2X, y: config.point2Y },
116
+ type,
117
+ point1: { x: config.point1X ?? -5, y: config.point1Y ?? 0 },
118
+ point2: { x: config.point2X ?? 5, y: config.point2Y ?? 0 },
115
119
  };
116
120
  }
117
121
  }
@@ -10,20 +10,22 @@ interface RenderData {
10
10
  type FitType = 'stretch' | 'repeat';
11
11
  export { type BlendingMode } from '../../types/view';
12
12
  export interface SpriteConfig {
13
- src: string;
14
- width: number;
15
- height: number;
16
- slice: number;
17
- flipX: boolean;
18
- flipY: boolean;
19
- sortingLayer: string;
20
- sortOffsetX: number;
21
- sortOffsetY: number;
22
- fit: FitType;
23
- color: string;
24
- blending: BlendingMode;
25
- opacity: number;
26
- disabled: boolean;
13
+ src?: string;
14
+ width?: number;
15
+ height?: number;
16
+ slice?: number;
17
+ flipX?: boolean;
18
+ flipY?: boolean;
19
+ sortingLayer?: string;
20
+ sortOffsetX?: number;
21
+ sortOffsetY?: number;
22
+ textureOffsetX?: number;
23
+ textureOffsetY?: number;
24
+ fit?: FitType;
25
+ color?: string;
26
+ blending?: BlendingMode;
27
+ opacity?: number;
28
+ disabled?: boolean;
27
29
  }
28
30
  /**
29
31
  * Sprite component for rendering 2D textures.
@@ -80,6 +82,12 @@ export declare class Sprite extends Component {
80
82
  sortingLayer: string;
81
83
  /** Center point for sorting calculations */
82
84
  sortOffset: Point;
85
+ /**
86
+ * Texture sampling offset in pixels. Only applies to `fit: 'repeat'`
87
+ * With flipX/flipY the tile is mirrored, so a positive offset scrolls in
88
+ * the mirrored direction.
89
+ */
90
+ textureOffset: Point;
83
91
  /** Current frame to render */
84
92
  currentFrame?: number;
85
93
  /** How the texture should fit within the sprite bounds */
@@ -54,6 +54,12 @@ export class Sprite extends Component {
54
54
  sortingLayer;
55
55
  /** Center point for sorting calculations */
56
56
  sortOffset;
57
+ /**
58
+ * Texture sampling offset in pixels. Only applies to `fit: 'repeat'`
59
+ * With flipX/flipY the tile is mirrored, so a positive offset scrolls in
60
+ * the mirrored direction.
61
+ */
62
+ textureOffset;
57
63
  /** Current frame to render */
58
64
  currentFrame;
59
65
  /** How the texture should fit within the sprite bounds */
@@ -73,17 +79,24 @@ export class Sprite extends Component {
73
79
  */
74
80
  constructor(config) {
75
81
  super();
76
- this.src = config.src;
77
- this.width = config.width;
78
- this.height = config.height;
79
- this.slice = config.slice;
82
+ this.src = config.src ?? '';
83
+ this.width = config.width ?? 10;
84
+ this.height = config.height ?? 10;
85
+ this.slice = config.slice ?? 1;
80
86
  this.currentFrame = 0;
81
- this.flipX = config.flipX;
82
- this.flipY = config.flipY;
83
- this.disabled = config.disabled;
84
- this.sortingLayer = config.sortingLayer;
85
- this.sortOffset = { x: config.sortOffsetX, y: config.sortOffsetY };
86
- this.fit = config.fit;
87
+ this.flipX = config.flipX ?? false;
88
+ this.flipY = config.flipY ?? false;
89
+ this.disabled = config.disabled ?? false;
90
+ this.sortingLayer = config.sortingLayer ?? 'default';
91
+ this.sortOffset = {
92
+ x: config.sortOffsetX ?? 0,
93
+ y: config.sortOffsetY ?? 0,
94
+ };
95
+ this.textureOffset = {
96
+ x: config.textureOffsetX ?? 0,
97
+ y: config.textureOffsetY ?? 0,
98
+ };
99
+ this.fit = config.fit ?? 'stretch';
87
100
  this.color = config.color ?? '#ffffff';
88
101
  this.blending = config.blending ?? 'normal';
89
102
  this.opacity = config.opacity ?? 1;
@@ -16,7 +16,6 @@ export declare class MeshBuilder implements Builder<Mesh> {
16
16
  destroy(mesh: Mesh): void;
17
17
  buildView(mesh: Mesh, actor: Actor): PixiMesh;
18
18
  updateView(mesh: Mesh): void;
19
- private updateGeometry;
20
19
  private updateTexture;
21
20
  }
22
21
  export {};
@@ -75,26 +75,6 @@ export class MeshBuilder {
75
75
  }
76
76
  this.materialSystem.updateShader(mesh);
77
77
  }
78
- updateGeometry(mesh) {
79
- const view = mesh.renderData.view;
80
- const texture = view.texture;
81
- const geometry = view.geometry;
82
- const uvs = texture?.uvs;
83
- if (!uvs) {
84
- return;
85
- }
86
- const uvAttr = geometry.getAttribute('aUV');
87
- const uvBuffer = uvAttr.buffer.data;
88
- uvBuffer[0] = uvs.x0;
89
- uvBuffer[1] = uvs.y0;
90
- uvBuffer[2] = uvs.x1;
91
- uvBuffer[3] = uvs.y1;
92
- uvBuffer[4] = uvs.x2;
93
- uvBuffer[5] = uvs.y2;
94
- uvBuffer[6] = uvs.x3;
95
- uvBuffer[7] = uvs.y3;
96
- uvAttr.buffer.update();
97
- }
98
78
  updateTexture(mesh) {
99
79
  const view = mesh.renderData.view;
100
80
  const meta = view.__dacha.meta;
@@ -109,6 +89,5 @@ export class MeshBuilder {
109
89
  const texture = textureArray?.[mesh.currentFrame];
110
90
  view.texture = texture ?? Texture.WHITE;
111
91
  meta.currentFrame = mesh.currentFrame;
112
- this.updateGeometry(mesh);
113
92
  }
114
93
  }
@@ -1,3 +1,4 @@
1
+ import { Graphics } from 'pixi.js';
1
2
  import { PixiView } from '../../../../components/pixi-view';
2
3
  export class PixiViewBuilder {
3
4
  destroy(pixiView) {
@@ -5,7 +6,7 @@ export class PixiViewBuilder {
5
6
  pixiView.renderData = undefined;
6
7
  }
7
8
  buildView(pixiView, actor) {
8
- const view = pixiView.createView();
9
+ const view = pixiView.createView ? pixiView.createView() : new Graphics();
9
10
  pixiView.renderData = { view };
10
11
  view.__dacha = {
11
12
  actor,
@@ -78,5 +78,13 @@ export class SpriteBuilder {
78
78
  meta.width = sprite.width;
79
79
  meta.height = sprite.height;
80
80
  }
81
+ if (sprite.fit === 'repeat') {
82
+ if (sprite.textureOffset.x !== meta.textureOffsetX ||
83
+ sprite.textureOffset.y !== meta.textureOffsetY) {
84
+ view.tilePosition.set(sprite.textureOffset.x, sprite.textureOffset.y);
85
+ meta.textureOffsetX = sprite.textureOffset.x;
86
+ meta.textureOffsetY = sprite.textureOffset.y;
87
+ }
88
+ }
81
89
  }
82
90
  }
@@ -1,2 +1,2 @@
1
1
  export declare const DEFAULT_VERTEX_SHADER = "\n precision mediump float;\n\n attribute vec2 aPosition;\n attribute vec2 aUV;\n\n uniform mat3 uProjectionMatrix;\n uniform mat3 uWorldTransformMatrix;\n uniform mat3 uTransformMatrix;\n\n varying vec2 vUV;\n\n void main() {\n vUV = aUV;\n\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n vec3 pos = mvp * vec3(aPosition, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n }\n";
2
- export declare const DEFAULT_FRAGMENT_SHADER = "\n precision mediump float;\n\n varying vec2 vUV;\n\n uniform sampler2D uSampler;\n uniform vec3 uTint;\n uniform float uAlpha;\n\n void main() {\n vec4 color = texture2D(uSampler, vUV);\n color.rgb *= uTint;\n color *= uAlpha;\n gl_FragColor = color;\n }\n";
2
+ export declare const DEFAULT_FRAGMENT_SHADER = "\n precision mediump float;\n\n varying vec2 vUV;\n\n uniform sampler2D uSampler;\n uniform vec2 uUVOffset;\n uniform vec2 uUVScale;\n uniform vec3 uTint;\n uniform float uAlpha;\n\n void main() {\n vec4 color = texture2D(uSampler, uUVOffset + vUV * uUVScale);\n color.rgb *= uTint;\n color *= uAlpha;\n gl_FragColor = color;\n }\n";
@@ -24,11 +24,13 @@ export const DEFAULT_FRAGMENT_SHADER = `
24
24
  varying vec2 vUV;
25
25
 
26
26
  uniform sampler2D uSampler;
27
+ uniform vec2 uUVOffset;
28
+ uniform vec2 uUVScale;
27
29
  uniform vec3 uTint;
28
30
  uniform float uAlpha;
29
31
 
30
32
  void main() {
31
- vec4 color = texture2D(uSampler, vUV);
33
+ vec4 color = texture2D(uSampler, uUVOffset + vUV * uUVScale);
32
34
  color.rgb *= uTint;
33
35
  color *= uAlpha;
34
36
  gl_FragColor = color;
@@ -35,7 +35,9 @@ export class MaterialSystem {
35
35
  uTime: { value: 0.0, type: 'f32' },
36
36
  uTint: { value: [1.0, 1.0, 1.0], type: 'vec3<f32>' },
37
37
  uAlpha: { value: 1.0, type: 'f32' },
38
- uTextureSize: { value: [0.0, 0.0], type: 'vec2<f32>' },
38
+ uFrameSize: { value: [0.0, 0.0], type: 'vec2<f32>' },
39
+ uUVOffset: { value: [0.0, 0.0], type: 'vec2<f32>' },
40
+ uUVScale: { value: [1.0, 1.0], type: 'vec2<f32>' },
39
41
  ...(config && builder?.uniforms?.(config.options)),
40
42
  },
41
43
  },
@@ -78,10 +80,14 @@ export class MaterialSystem {
78
80
  .setValue(tint)
79
81
  .toRgbArray([]);
80
82
  }
81
- view.shader.resources.uniformsGroup.uniforms.uTextureSize[0] =
82
- view.texture.source.width;
83
- view.shader.resources.uniformsGroup.uniforms.uTextureSize[1] =
84
- view.texture.source.height;
83
+ if (meta.materialTexture !== view.texture) {
84
+ meta.materialTexture = view.texture;
85
+ const { uvs, frame } = view.texture;
86
+ const uniforms = view.shader.resources.uniformsGroup.uniforms;
87
+ uniforms.uUVOffset = [uvs.x0, uvs.y0];
88
+ uniforms.uUVScale = [uvs.x1 - uvs.x0, uvs.y2 - uvs.y0];
89
+ uniforms.uFrameSize = [frame.width, frame.height];
90
+ }
85
91
  if (!material || !builder) {
86
92
  return;
87
93
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dacha",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "main": "./build/index.js",
5
5
  "types": "./build/index.d.ts",
6
6
  "exports": {