@energy8platform/game-engine 0.8.0 → 0.9.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/README.md +178 -68
- package/dist/core.cjs.js +12 -1
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.d.ts +6 -0
- package/dist/core.esm.js +12 -1
- package/dist/core.esm.js.map +1 -1
- package/dist/index.cjs.js +12 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.esm.js +12 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/react.cjs.js +470 -0
- package/dist/react.cjs.js.map +1 -0
- package/dist/react.d.ts +871 -0
- package/dist/react.esm.js +455 -0
- package/dist/react.esm.js.map +1 -0
- package/dist/vite.cjs.js +5 -0
- package/dist/vite.cjs.js.map +1 -1
- package/dist/vite.esm.js +5 -0
- package/dist/vite.esm.js.map +1 -1
- package/package.json +25 -3
- package/src/core/GameApplication.ts +1 -0
- package/src/core/SceneManager.ts +13 -1
- package/src/react/EngineContext.ts +26 -0
- package/src/react/ReactScene.ts +88 -0
- package/src/react/applyProps.ts +107 -0
- package/src/react/catalogue.ts +17 -0
- package/src/react/createPixiRoot.ts +31 -0
- package/src/react/extendAll.ts +51 -0
- package/src/react/hooks.ts +46 -0
- package/src/react/index.ts +23 -0
- package/src/react/reconciler.ts +169 -0
- package/src/types.ts +3 -0
- package/src/vite/index.ts +5 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import type { ReactElement } from 'react';
|
|
3
|
+
import { Scene } from '../core/Scene';
|
|
4
|
+
import { createPixiRoot } from './createPixiRoot';
|
|
5
|
+
import type { PixiRoot } from './createPixiRoot';
|
|
6
|
+
import { EngineContext } from './EngineContext';
|
|
7
|
+
import type { EngineContextValue } from './EngineContext';
|
|
8
|
+
import type { GameApplication } from '../core/GameApplication';
|
|
9
|
+
import { Orientation } from '../types';
|
|
10
|
+
|
|
11
|
+
export abstract class ReactScene extends Scene {
|
|
12
|
+
private _pixiRoot: PixiRoot | null = null;
|
|
13
|
+
private _contextValue: EngineContextValue | null = null;
|
|
14
|
+
|
|
15
|
+
/** Subclasses implement this to return their React element tree. */
|
|
16
|
+
abstract render(): ReactElement;
|
|
17
|
+
|
|
18
|
+
/** Access the GameApplication instance. */
|
|
19
|
+
protected getApp(): GameApplication {
|
|
20
|
+
const app = (this as any).__engineApp;
|
|
21
|
+
if (!app) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
'[ReactScene] No GameApplication reference. ' +
|
|
24
|
+
'Ensure this scene is managed by SceneManager (not instantiated manually).',
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return app;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override async onEnter(data?: unknown): Promise<void> {
|
|
31
|
+
const app = this.getApp();
|
|
32
|
+
|
|
33
|
+
this._contextValue = {
|
|
34
|
+
app,
|
|
35
|
+
sdk: app.sdk,
|
|
36
|
+
audio: app.audio,
|
|
37
|
+
input: app.input,
|
|
38
|
+
viewport: app.viewport,
|
|
39
|
+
gameConfig: app.gameConfig,
|
|
40
|
+
screen: {
|
|
41
|
+
width: app.viewport.width,
|
|
42
|
+
height: app.viewport.height,
|
|
43
|
+
scale: app.viewport.scale,
|
|
44
|
+
},
|
|
45
|
+
isPortrait: app.viewport.orientation === Orientation.PORTRAIT,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
this._pixiRoot = createPixiRoot(this.container);
|
|
49
|
+
this._mountReactTree();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override async onExit(): Promise<void> {
|
|
53
|
+
this._pixiRoot?.unmount();
|
|
54
|
+
this._pixiRoot = null;
|
|
55
|
+
this._contextValue = null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override onResize(width: number, height: number): void {
|
|
59
|
+
if (!this._contextValue) return;
|
|
60
|
+
const app = this.getApp();
|
|
61
|
+
|
|
62
|
+
this._contextValue = {
|
|
63
|
+
...this._contextValue,
|
|
64
|
+
screen: { width, height, scale: app.viewport.scale },
|
|
65
|
+
isPortrait: height > width,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
this._mountReactTree();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
override onDestroy(): void {
|
|
72
|
+
this._pixiRoot?.unmount();
|
|
73
|
+
this._pixiRoot = null;
|
|
74
|
+
this._contextValue = null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private _mountReactTree(): void {
|
|
78
|
+
if (!this._pixiRoot || !this._contextValue) return;
|
|
79
|
+
|
|
80
|
+
this._pixiRoot.render(
|
|
81
|
+
createElement(
|
|
82
|
+
EngineContext.Provider,
|
|
83
|
+
{ value: this._contextValue },
|
|
84
|
+
this.render(),
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const RESERVED = new Set(['children', 'key', 'ref']);
|
|
2
|
+
|
|
3
|
+
const REACT_TO_PIXI_EVENTS: Record<string, string> = {
|
|
4
|
+
onClick: 'onclick',
|
|
5
|
+
onPointerDown: 'onpointerdown',
|
|
6
|
+
onPointerUp: 'onpointerup',
|
|
7
|
+
onPointerMove: 'onpointermove',
|
|
8
|
+
onPointerOver: 'onpointerover',
|
|
9
|
+
onPointerOut: 'onpointerout',
|
|
10
|
+
onPointerEnter: 'onpointerenter',
|
|
11
|
+
onPointerLeave: 'onpointerleave',
|
|
12
|
+
onPointerCancel: 'onpointercancel',
|
|
13
|
+
onPointerTap: 'onpointertap',
|
|
14
|
+
onPointerUpOutside: 'onpointerupoutside',
|
|
15
|
+
onMouseDown: 'onmousedown',
|
|
16
|
+
onMouseUp: 'onmouseup',
|
|
17
|
+
onMouseMove: 'onmousemove',
|
|
18
|
+
onMouseOver: 'onmouseover',
|
|
19
|
+
onMouseOut: 'onmouseout',
|
|
20
|
+
onMouseEnter: 'onmouseenter',
|
|
21
|
+
onMouseLeave: 'onmouseleave',
|
|
22
|
+
onMouseUpOutside: 'onmouseupoutside',
|
|
23
|
+
onTouchStart: 'ontouchstart',
|
|
24
|
+
onTouchEnd: 'ontouchend',
|
|
25
|
+
onTouchMove: 'ontouchmove',
|
|
26
|
+
onTouchCancel: 'ontouchcancel',
|
|
27
|
+
onTouchEndOutside: 'ontouchendoutside',
|
|
28
|
+
onWheel: 'onwheel',
|
|
29
|
+
onRightClick: 'onrightclick',
|
|
30
|
+
onRightDown: 'onrightdown',
|
|
31
|
+
onRightUp: 'onrightup',
|
|
32
|
+
onRightUpOutside: 'onrightupoutside',
|
|
33
|
+
onTap: 'ontap',
|
|
34
|
+
onGlobalpointermove: 'onglobalpointermove',
|
|
35
|
+
onGlobalmousemove: 'onglobalmousemove',
|
|
36
|
+
onGlobaltouchmove: 'onglobaltouchmove',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export function isEventProp(key: string): boolean {
|
|
40
|
+
return key in REACT_TO_PIXI_EVENTS;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function hasEventProps(props: Record<string, any>): boolean {
|
|
44
|
+
for (const key in props) {
|
|
45
|
+
if (isEventProp(key)) return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function setNestedValue(target: any, path: string[], value: any): void {
|
|
51
|
+
let obj = target;
|
|
52
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
53
|
+
obj = obj[path[i]];
|
|
54
|
+
if (obj == null) return;
|
|
55
|
+
}
|
|
56
|
+
obj[path[path.length - 1]] = value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function applyProps(
|
|
60
|
+
instance: any,
|
|
61
|
+
newProps: Record<string, any>,
|
|
62
|
+
oldProps: Record<string, any> = {},
|
|
63
|
+
): void {
|
|
64
|
+
// Remove old props not in newProps
|
|
65
|
+
for (const key in oldProps) {
|
|
66
|
+
if (RESERVED.has(key) || key in newProps) continue;
|
|
67
|
+
|
|
68
|
+
const pixiEvent = REACT_TO_PIXI_EVENTS[key];
|
|
69
|
+
if (pixiEvent) {
|
|
70
|
+
instance[pixiEvent] = null;
|
|
71
|
+
} else if (key === 'draw') {
|
|
72
|
+
// no-op: can't un-draw
|
|
73
|
+
} else if (key.includes('-')) {
|
|
74
|
+
// Nested property reset not trivially possible, skip
|
|
75
|
+
} else {
|
|
76
|
+
try {
|
|
77
|
+
instance[key] = undefined;
|
|
78
|
+
} catch {
|
|
79
|
+
// read-only or non-configurable
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Apply new props
|
|
85
|
+
for (const key in newProps) {
|
|
86
|
+
if (RESERVED.has(key)) continue;
|
|
87
|
+
|
|
88
|
+
const value = newProps[key];
|
|
89
|
+
const pixiEvent = REACT_TO_PIXI_EVENTS[key];
|
|
90
|
+
|
|
91
|
+
if (pixiEvent) {
|
|
92
|
+
instance[pixiEvent] = value;
|
|
93
|
+
} else if (key === 'draw' && typeof value === 'function') {
|
|
94
|
+
instance.clear?.();
|
|
95
|
+
value(instance);
|
|
96
|
+
} else if (key.includes('-')) {
|
|
97
|
+
const parts = key.split('-');
|
|
98
|
+
setNestedValue(instance, parts, value);
|
|
99
|
+
} else {
|
|
100
|
+
try {
|
|
101
|
+
instance[key] = value;
|
|
102
|
+
} catch {
|
|
103
|
+
// read-only property
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Mutable catalogue: PascalCase name -> PixiJS constructor */
|
|
2
|
+
export const catalogue: Record<string, any> = {};
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Register PixiJS classes for use as JSX elements.
|
|
6
|
+
* Keys must be PascalCase; JSX uses the camelCase equivalent.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { Container, Sprite, Text } from 'pixi.js';
|
|
11
|
+
* extend({ Container, Sprite, Text });
|
|
12
|
+
* // Now <container>, <sprite>, <text> work in JSX
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function extend(components: Record<string, any>): void {
|
|
16
|
+
Object.assign(catalogue, components);
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ConcurrentRoot } from 'react-reconciler/constants';
|
|
2
|
+
import type { Container } from 'pixi.js';
|
|
3
|
+
import type { ReactElement } from 'react';
|
|
4
|
+
import { reconciler } from './reconciler';
|
|
5
|
+
|
|
6
|
+
export interface PixiRoot {
|
|
7
|
+
render(element: ReactElement): void;
|
|
8
|
+
unmount(): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function createPixiRoot(container: Container): PixiRoot {
|
|
12
|
+
const fiberRoot = reconciler.createContainer(
|
|
13
|
+
container, // containerInfo
|
|
14
|
+
ConcurrentRoot, // tag
|
|
15
|
+
null, // hydrationCallbacks
|
|
16
|
+
false, // isStrictMode
|
|
17
|
+
null, // concurrentUpdatesByDefaultOverride
|
|
18
|
+
'', // identifierPrefix
|
|
19
|
+
(err: Error) => console.error('[PixiRoot]', err),
|
|
20
|
+
null, // transitionCallbacks
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
render(element: ReactElement) {
|
|
25
|
+
reconciler.updateContainer(element, fiberRoot, null, () => {});
|
|
26
|
+
},
|
|
27
|
+
unmount() {
|
|
28
|
+
reconciler.updateContainer(null, fiberRoot, null, () => {});
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Container,
|
|
3
|
+
Sprite,
|
|
4
|
+
Graphics,
|
|
5
|
+
Text,
|
|
6
|
+
AnimatedSprite,
|
|
7
|
+
NineSliceSprite,
|
|
8
|
+
TilingSprite,
|
|
9
|
+
Mesh,
|
|
10
|
+
MeshPlane,
|
|
11
|
+
MeshRope,
|
|
12
|
+
MeshSimple,
|
|
13
|
+
BitmapText,
|
|
14
|
+
HTMLText,
|
|
15
|
+
} from 'pixi.js';
|
|
16
|
+
import { extend } from './catalogue';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Register all standard PixiJS display objects for JSX use.
|
|
20
|
+
* Call once at app startup before rendering any React scenes.
|
|
21
|
+
*/
|
|
22
|
+
export function extendPixiElements(): void {
|
|
23
|
+
extend({
|
|
24
|
+
Container,
|
|
25
|
+
Sprite,
|
|
26
|
+
Graphics,
|
|
27
|
+
Text,
|
|
28
|
+
AnimatedSprite,
|
|
29
|
+
NineSliceSprite,
|
|
30
|
+
TilingSprite,
|
|
31
|
+
Mesh,
|
|
32
|
+
MeshPlane,
|
|
33
|
+
MeshRope,
|
|
34
|
+
MeshSimple,
|
|
35
|
+
BitmapText,
|
|
36
|
+
HTMLText,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Register @pixi/layout components for JSX use.
|
|
42
|
+
* Pass the dynamically imported module:
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* const layout = await import('@pixi/layout/components');
|
|
46
|
+
* extendLayoutElements(layout);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function extendLayoutElements(layoutModule: Record<string, any>): void {
|
|
50
|
+
extend(layoutModule);
|
|
51
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useEngine } from './EngineContext';
|
|
3
|
+
import type { CasinoGameSDK, SessionData, GameConfigData } from '@energy8platform/game-sdk';
|
|
4
|
+
import type { AudioManager } from '../audio/AudioManager';
|
|
5
|
+
import type { InputManager } from '../input/InputManager';
|
|
6
|
+
|
|
7
|
+
export function useSDK(): CasinoGameSDK | null {
|
|
8
|
+
return useEngine().sdk;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useAudio(): AudioManager {
|
|
12
|
+
return useEngine().audio;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function useInput(): InputManager {
|
|
16
|
+
return useEngine().input;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useViewport(): { width: number; height: number; scale: number; isPortrait: boolean } {
|
|
20
|
+
const { screen, isPortrait } = useEngine();
|
|
21
|
+
return { ...screen, isPortrait };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useBalance(): number {
|
|
25
|
+
const { sdk } = useEngine();
|
|
26
|
+
const [balance, setBalance] = useState(sdk?.balance ?? 0);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!sdk) return;
|
|
30
|
+
const handler = (data: { balance: number }) => setBalance(data.balance);
|
|
31
|
+
sdk.on('balanceUpdate', handler);
|
|
32
|
+
return () => {
|
|
33
|
+
sdk.off('balanceUpdate', handler);
|
|
34
|
+
};
|
|
35
|
+
}, [sdk]);
|
|
36
|
+
|
|
37
|
+
return balance;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function useSession(): SessionData | null {
|
|
41
|
+
return useEngine().app.session;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function useGameConfig<T = GameConfigData>(): T | null {
|
|
45
|
+
return useEngine().gameConfig as T | null;
|
|
46
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Core
|
|
2
|
+
export { createPixiRoot } from './createPixiRoot';
|
|
3
|
+
export type { PixiRoot } from './createPixiRoot';
|
|
4
|
+
|
|
5
|
+
// Catalogue
|
|
6
|
+
export { extend } from './catalogue';
|
|
7
|
+
export { extendPixiElements, extendLayoutElements } from './extendAll';
|
|
8
|
+
|
|
9
|
+
// Scene
|
|
10
|
+
export { ReactScene } from './ReactScene';
|
|
11
|
+
|
|
12
|
+
// Context & Hooks
|
|
13
|
+
export { EngineContext, useEngine } from './EngineContext';
|
|
14
|
+
export type { EngineContextValue } from './EngineContext';
|
|
15
|
+
export {
|
|
16
|
+
useSDK,
|
|
17
|
+
useAudio,
|
|
18
|
+
useInput,
|
|
19
|
+
useViewport,
|
|
20
|
+
useBalance,
|
|
21
|
+
useSession,
|
|
22
|
+
useGameConfig,
|
|
23
|
+
} from './hooks';
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import Reconciler from 'react-reconciler';
|
|
2
|
+
import { DefaultEventPriority } from 'react-reconciler/constants';
|
|
3
|
+
import { Container } from 'pixi.js';
|
|
4
|
+
import { catalogue } from './catalogue';
|
|
5
|
+
import { applyProps, hasEventProps } from './applyProps';
|
|
6
|
+
|
|
7
|
+
function toPascalCase(str: string): string {
|
|
8
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const hostConfig: Reconciler.HostConfig<
|
|
12
|
+
string, // Type
|
|
13
|
+
Record<string, any>, // Props
|
|
14
|
+
Container, // Container
|
|
15
|
+
any, // Instance
|
|
16
|
+
any, // TextInstance
|
|
17
|
+
any, // SuspenseInstance
|
|
18
|
+
any, // HydratableInstance
|
|
19
|
+
any, // PublicInstance
|
|
20
|
+
any, // HostContext
|
|
21
|
+
any, // UpdatePayload
|
|
22
|
+
any, // ChildSet
|
|
23
|
+
any, // TimeoutHandle
|
|
24
|
+
any // NoTimeout
|
|
25
|
+
> = {
|
|
26
|
+
isPrimaryRenderer: false,
|
|
27
|
+
supportsMutation: true,
|
|
28
|
+
supportsPersistence: false,
|
|
29
|
+
supportsHydration: false,
|
|
30
|
+
|
|
31
|
+
createInstance(type, props) {
|
|
32
|
+
const name = toPascalCase(type);
|
|
33
|
+
const Ctor = catalogue[name];
|
|
34
|
+
if (!Ctor) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`[PixiReconciler] Unknown element "<${type}>". ` +
|
|
37
|
+
`Call extend({ ${name} }) before rendering.`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const instance = new Ctor();
|
|
41
|
+
applyProps(instance, props);
|
|
42
|
+
|
|
43
|
+
// Enable interactivity if any event prop is present
|
|
44
|
+
if (hasEventProps(props) && instance.eventMode === 'auto') {
|
|
45
|
+
instance.eventMode = 'static';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return instance;
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
createTextInstance() {
|
|
52
|
+
throw new Error(
|
|
53
|
+
'[PixiReconciler] Text strings are not supported. Use a <text> element.',
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
appendInitialChild(parent, child) {
|
|
58
|
+
if (child instanceof Container) parent.addChild(child);
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
appendChild(parent, child) {
|
|
62
|
+
if (child instanceof Container) parent.addChild(child);
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
appendChildToContainer(container, child) {
|
|
66
|
+
if (child instanceof Container) container.addChild(child);
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
removeChild(parent, child) {
|
|
70
|
+
if (child instanceof Container) {
|
|
71
|
+
parent.removeChild(child);
|
|
72
|
+
child.destroy({ children: true });
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
removeChildFromContainer(container, child) {
|
|
77
|
+
if (child instanceof Container) {
|
|
78
|
+
container.removeChild(child);
|
|
79
|
+
child.destroy({ children: true });
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
insertBefore(parent, child, beforeChild) {
|
|
84
|
+
if (child instanceof Container && beforeChild instanceof Container) {
|
|
85
|
+
if (child.parent) child.parent.removeChild(child);
|
|
86
|
+
const index = parent.getChildIndex(beforeChild);
|
|
87
|
+
parent.addChildAt(child, index);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
insertInContainerBefore(container, child, beforeChild) {
|
|
92
|
+
if (child instanceof Container && beforeChild instanceof Container) {
|
|
93
|
+
if (child.parent) child.parent.removeChild(child);
|
|
94
|
+
const index = container.getChildIndex(beforeChild);
|
|
95
|
+
container.addChildAt(child, index);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
commitUpdate(instance, _updatePayload, _type, oldProps, newProps) {
|
|
100
|
+
applyProps(instance, newProps, oldProps);
|
|
101
|
+
|
|
102
|
+
if (hasEventProps(newProps) && instance.eventMode === 'auto') {
|
|
103
|
+
instance.eventMode = 'static';
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
finalizeInitialChildren() {
|
|
108
|
+
return false;
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
prepareUpdate() {
|
|
112
|
+
return true;
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
shouldSetTextContent() {
|
|
116
|
+
return false;
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
getRootHostContext() {
|
|
120
|
+
return null;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
getChildHostContext(parentHostContext: any) {
|
|
124
|
+
return parentHostContext;
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
getPublicInstance(instance: any) {
|
|
128
|
+
return instance;
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
prepareForCommit() {
|
|
132
|
+
return null;
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
resetAfterCommit() {},
|
|
136
|
+
|
|
137
|
+
preparePortalMount() {},
|
|
138
|
+
|
|
139
|
+
scheduleTimeout: setTimeout,
|
|
140
|
+
cancelTimeout: clearTimeout,
|
|
141
|
+
noTimeout: -1,
|
|
142
|
+
|
|
143
|
+
getCurrentEventPriority() {
|
|
144
|
+
return DefaultEventPriority;
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
hideInstance(instance) {
|
|
148
|
+
instance.visible = false;
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
unhideInstance(instance) {
|
|
152
|
+
instance.visible = true;
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
hideTextInstance() {},
|
|
156
|
+
unhideTextInstance() {},
|
|
157
|
+
|
|
158
|
+
clearContainer() {},
|
|
159
|
+
|
|
160
|
+
detachDeletedInstance() {},
|
|
161
|
+
|
|
162
|
+
prepareScopeUpdate() {},
|
|
163
|
+
getInstanceFromNode() { return null; },
|
|
164
|
+
getInstanceFromScope() { return null; },
|
|
165
|
+
beforeActiveInstanceBlur() {},
|
|
166
|
+
afterActiveInstanceBlur() {},
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export const reconciler = Reconciler(hostConfig);
|
package/src/types.ts
CHANGED
|
@@ -150,6 +150,9 @@ export interface IScene {
|
|
|
150
150
|
/** Root display container for this scene */
|
|
151
151
|
readonly container: Container;
|
|
152
152
|
|
|
153
|
+
/** @internal GameApplication reference — set by SceneManager */
|
|
154
|
+
__engineApp?: any;
|
|
155
|
+
|
|
153
156
|
/** Called when the scene is entered */
|
|
154
157
|
onEnter?(data?: unknown): Promise<void> | void;
|
|
155
158
|
|
package/src/vite/index.ts
CHANGED
|
@@ -149,6 +149,9 @@ export function defineGameConfig(config: GameConfig = {}): UserConfig {
|
|
|
149
149
|
'@pixi/ui',
|
|
150
150
|
'yoga-layout',
|
|
151
151
|
'yoga-layout/load',
|
|
152
|
+
'react',
|
|
153
|
+
'react-dom',
|
|
154
|
+
'react-reconciler',
|
|
152
155
|
],
|
|
153
156
|
...userVite.resolve,
|
|
154
157
|
},
|
|
@@ -160,6 +163,8 @@ export function defineGameConfig(config: GameConfig = {}): UserConfig {
|
|
|
160
163
|
'@pixi/layout/components',
|
|
161
164
|
'@pixi/ui',
|
|
162
165
|
'yoga-layout/load',
|
|
166
|
+
'react',
|
|
167
|
+
'react-dom',
|
|
163
168
|
],
|
|
164
169
|
exclude: [
|
|
165
170
|
'yoga-layout',
|