@energy8platform/game-engine 0.3.0 → 0.4.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.
package/src/ui/Panel.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { Container, Graphics, NineSliceSprite, Texture } from 'pixi.js';
1
+ import { Container, NineSliceSprite, Texture } from 'pixi.js';
2
+ import { LayoutContainer } from '@pixi/layout/components';
3
+ import type { LayoutStyles } from '@pixi/layout';
2
4
 
3
5
  export interface PanelConfig {
4
6
  /** Width */
@@ -24,7 +26,10 @@ export interface PanelConfig {
24
26
  }
25
27
 
26
28
  /**
27
- * Background panel that can use either Graphics or 9-slice sprite.
29
+ * Background panel powered by `@pixi/layout` LayoutContainer.
30
+ *
31
+ * Supports both Graphics-based (color + border) and 9-slice sprite backgrounds.
32
+ * Children added to `content` participate in flexbox layout automatically.
28
33
  *
29
34
  * @example
30
35
  * ```ts
@@ -39,87 +44,79 @@ export interface PanelConfig {
39
44
  * });
40
45
  * ```
41
46
  */
42
- export class Panel extends Container {
43
- private _bg: Graphics | NineSliceSprite;
44
- private _content: Container;
45
- private _config: Required<
47
+ export class Panel extends LayoutContainer {
48
+ private _panelConfig: Required<
46
49
  Pick<PanelConfig, 'width' | 'height' | 'padding' | 'backgroundAlpha'>
47
50
  > & PanelConfig;
48
51
 
49
52
  constructor(config: PanelConfig = {}) {
50
- super();
51
-
52
- this._config = {
53
- width: 400,
54
- height: 300,
55
- padding: 16,
56
- backgroundAlpha: 1,
53
+ const resolvedConfig = {
54
+ width: config.width ?? 400,
55
+ height: config.height ?? 300,
56
+ padding: config.padding ?? 16,
57
+ backgroundAlpha: config.backgroundAlpha ?? 1,
57
58
  ...config,
58
59
  };
59
60
 
60
- // Create background
61
+ // If using a 9-slice texture, pass it as a custom background
62
+ let customBackground: Container | undefined;
61
63
  if (config.nineSliceTexture) {
62
64
  const texture =
63
65
  typeof config.nineSliceTexture === 'string'
64
66
  ? Texture.from(config.nineSliceTexture)
65
67
  : config.nineSliceTexture;
66
-
67
68
  const [left, top, right, bottom] = config.nineSliceBorders ?? [10, 10, 10, 10];
68
-
69
- this._bg = new NineSliceSprite({
69
+ const nineSlice = new NineSliceSprite({
70
70
  texture,
71
71
  leftWidth: left,
72
72
  topHeight: top,
73
73
  rightWidth: right,
74
74
  bottomHeight: bottom,
75
75
  });
76
- (this._bg as NineSliceSprite).width = this._config.width;
77
- (this._bg as NineSliceSprite).height = this._config.height;
78
- } else {
79
- this._bg = new Graphics();
80
- this.drawGraphicsBg();
76
+ nineSlice.width = resolvedConfig.width;
77
+ nineSlice.height = resolvedConfig.height;
78
+ nineSlice.alpha = resolvedConfig.backgroundAlpha;
79
+ customBackground = nineSlice;
81
80
  }
82
81
 
83
- this._bg.alpha = this._config.backgroundAlpha;
84
- this.addChild(this._bg);
82
+ super(customBackground ? { background: customBackground } : undefined);
85
83
 
86
- // Content container with padding
87
- this._content = new Container();
88
- this._content.x = this._config.padding;
89
- this._content.y = this._config.padding;
90
- this.addChild(this._content);
91
- }
84
+ this._panelConfig = resolvedConfig;
92
85
 
93
- /** Content container — add children here */
94
- get content(): Container {
95
- return this._content;
96
- }
86
+ // Apply layout styles
87
+ const layoutStyles: LayoutStyles = {
88
+ width: resolvedConfig.width,
89
+ height: resolvedConfig.height,
90
+ padding: resolvedConfig.padding,
91
+ flexDirection: 'column',
92
+ };
97
93
 
98
- /** Resize the panel */
99
- setSize(width: number, height: number): void {
100
- this._config.width = width;
101
- this._config.height = height;
94
+ // Graphics-based background via layout styles
95
+ if (!config.nineSliceTexture) {
96
+ layoutStyles.backgroundColor = config.backgroundColor ?? 0x1a1a2e;
97
+ layoutStyles.borderRadius = config.borderRadius ?? 0;
98
+ if (config.borderColor !== undefined && config.borderWidth) {
99
+ layoutStyles.borderColor = config.borderColor;
100
+ layoutStyles.borderWidth = config.borderWidth;
101
+ }
102
+ }
103
+
104
+ this.layout = layoutStyles;
102
105
 
103
- if (this._bg instanceof Graphics) {
104
- this.drawGraphicsBg();
105
- } else {
106
- this._bg.width = width;
107
- this._bg.height = height;
106
+ if (!config.nineSliceTexture) {
107
+ this.background.alpha = resolvedConfig.backgroundAlpha;
108
108
  }
109
109
  }
110
110
 
111
- private drawGraphicsBg(): void {
112
- const bg = this._bg as Graphics;
113
- const {
114
- width, height, backgroundColor, borderRadius, borderColor, borderWidth,
115
- } = this._config;
116
-
117
- bg.clear();
118
- bg.roundRect(0, 0, width!, height!, borderRadius ?? 0).fill(backgroundColor ?? 0x1a1a2e);
111
+ /** Access the content container (children added here participate in layout) */
112
+ get content(): Container {
113
+ return this.overflowContainer;
114
+ }
119
115
 
120
- if (borderColor !== undefined && borderWidth) {
121
- bg.roundRect(0, 0, width!, height!, borderRadius ?? 0)
122
- .stroke({ color: borderColor, width: borderWidth });
123
- }
116
+ /** Resize the panel */
117
+ setSize(width: number, height: number): void {
118
+ this._panelConfig.width = width;
119
+ this._panelConfig.height = height;
120
+ this._layout?.setStyle({ width, height });
124
121
  }
125
122
  }
@@ -1,4 +1,6 @@
1
1
  import { Container, Graphics } from 'pixi.js';
2
+ import { ProgressBar as PixiProgressBar } from '@pixi/ui';
3
+ import type { ProgressBarOptions } from '@pixi/ui';
2
4
 
3
5
  export interface ProgressBarConfig {
4
6
  width?: number;
@@ -14,8 +16,16 @@ export interface ProgressBarConfig {
14
16
  animationSpeed?: number;
15
17
  }
16
18
 
19
+ function makeBarGraphics(
20
+ w: number, h: number, radius: number, color: number,
21
+ ): Graphics {
22
+ return new Graphics().roundRect(0, 0, w, h, radius).fill(color);
23
+ }
24
+
17
25
  /**
18
- * Horizontal progress bar with optional smooth fill animation.
26
+ * Horizontal progress bar powered by `@pixi/ui` ProgressBar.
27
+ *
28
+ * Provides optional smooth animated fill via per-frame `update()`.
19
29
  *
20
30
  * @example
21
31
  * ```ts
@@ -25,9 +35,8 @@ export interface ProgressBarConfig {
25
35
  * ```
26
36
  */
27
37
  export class ProgressBar extends Container {
28
- private _track: Graphics;
29
- private _fill: Graphics;
30
- private _border: Graphics;
38
+ private _bar: PixiProgressBar;
39
+ private _borderGfx: Graphics;
31
40
  private _config: Required<ProgressBarConfig>;
32
41
  private _progress = 0;
33
42
  private _displayedProgress = 0;
@@ -36,26 +45,45 @@ export class ProgressBar extends Container {
36
45
  super();
37
46
 
38
47
  this._config = {
39
- width: 300,
40
- height: 16,
41
- borderRadius: 8,
42
- fillColor: 0xffd700,
43
- trackColor: 0x333333,
44
- borderColor: 0x555555,
45
- borderWidth: 1,
46
- animated: true,
47
- animationSpeed: 0.1,
48
- ...config,
48
+ width: config.width ?? 300,
49
+ height: config.height ?? 16,
50
+ borderRadius: config.borderRadius ?? 8,
51
+ fillColor: config.fillColor ?? 0xffd700,
52
+ trackColor: config.trackColor ?? 0x333333,
53
+ borderColor: config.borderColor ?? 0x555555,
54
+ borderWidth: config.borderWidth ?? 1,
55
+ animated: config.animated ?? true,
56
+ animationSpeed: config.animationSpeed ?? 0.1,
49
57
  };
50
58
 
51
- this._track = new Graphics();
52
- this._fill = new Graphics();
53
- this._border = new Graphics();
59
+ const { width, height, borderRadius, fillColor, trackColor, borderColor, borderWidth } = this._config;
54
60
 
55
- this.addChild(this._track, this._fill, this._border);
56
- this.drawTrack();
57
- this.drawBorder();
58
- this.drawFill(0);
61
+ const bgGraphics = makeBarGraphics(width, height, borderRadius, trackColor);
62
+ const fillGraphics = makeBarGraphics(width - borderWidth * 2, height - borderWidth * 2, Math.max(0, borderRadius - 1), fillColor);
63
+
64
+ const options: ProgressBarOptions = {
65
+ bg: bgGraphics,
66
+ fill: fillGraphics,
67
+ fillPaddings: {
68
+ top: borderWidth,
69
+ right: borderWidth,
70
+ bottom: borderWidth,
71
+ left: borderWidth,
72
+ },
73
+ progress: 0,
74
+ };
75
+
76
+ this._bar = new PixiProgressBar(options);
77
+ this.addChild(this._bar);
78
+
79
+ // Border overlay
80
+ this._borderGfx = new Graphics();
81
+ if (borderColor !== undefined && borderWidth > 0) {
82
+ this._borderGfx
83
+ .roundRect(0, 0, width, height, borderRadius)
84
+ .stroke({ color: borderColor, width: borderWidth });
85
+ }
86
+ this.addChild(this._borderGfx);
59
87
  }
60
88
 
61
89
  /** Get/set progress (0..1) */
@@ -67,14 +95,14 @@ export class ProgressBar extends Container {
67
95
  this._progress = Math.max(0, Math.min(1, value));
68
96
  if (!this._config.animated) {
69
97
  this._displayedProgress = this._progress;
70
- this.drawFill(this._displayedProgress);
98
+ this._bar.progress = this._displayedProgress * 100;
71
99
  }
72
100
  }
73
101
 
74
102
  /**
75
103
  * Call each frame if animated is true.
76
104
  */
77
- update(dt: number): void {
105
+ update(_dt: number): void {
78
106
  if (!this._config.animated) return;
79
107
  if (Math.abs(this._displayedProgress - this._progress) < 0.001) {
80
108
  this._displayedProgress = this._progress;
@@ -83,39 +111,6 @@ export class ProgressBar extends Container {
83
111
 
84
112
  this._displayedProgress +=
85
113
  (this._progress - this._displayedProgress) * this._config.animationSpeed;
86
- this.drawFill(this._displayedProgress);
87
- }
88
-
89
- private drawTrack(): void {
90
- const { width, height, borderRadius, trackColor } = this._config;
91
- this._track.clear();
92
- this._track.roundRect(0, 0, width, height, borderRadius).fill(trackColor);
93
- }
94
-
95
- private drawBorder(): void {
96
- const { width, height, borderRadius, borderColor, borderWidth } = this._config;
97
- this._border.clear();
98
- this._border
99
- .roundRect(0, 0, width, height, borderRadius)
100
- .stroke({ color: borderColor, width: borderWidth });
101
- }
102
-
103
- private drawFill(progress: number): void {
104
- const { width, height, borderRadius, fillColor, borderWidth } = this._config;
105
- const innerWidth = width - borderWidth * 2;
106
- const innerHeight = height - borderWidth * 2;
107
- const fillWidth = Math.max(0, innerWidth * progress);
108
-
109
- this._fill.clear();
110
- if (fillWidth > 0) {
111
- this._fill.x = borderWidth;
112
- this._fill.y = borderWidth;
113
- this._fill.roundRect(0, 0, fillWidth, innerHeight, borderRadius - 1).fill(fillColor);
114
-
115
- // Highlight
116
- this._fill
117
- .roundRect(0, 0, fillWidth, innerHeight * 0.4, borderRadius - 1)
118
- .fill({ color: 0xffffff, alpha: 0.15 });
119
- }
114
+ this._bar.progress = this._displayedProgress * 100;
120
115
  }
121
116
  }