@thewhateverapp/tile-sdk 0.14.9 → 0.14.11
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/dist/pixi/index.d.ts +25 -4
- package/dist/pixi/index.d.ts.map +1 -1
- package/dist/pixi/index.js +27 -6
- package/dist/react/PixiGame.d.ts +41 -92
- package/dist/react/PixiGame.d.ts.map +1 -1
- package/dist/react/PixiGame.js +123 -114
- package/dist/scene/SceneFromJson.d.ts +1 -1
- package/dist/scene/SceneFromJson.d.ts.map +1 -1
- package/dist/scene/SceneFromJson.js +4 -31
- package/dist/scene/SceneRenderer.d.ts.map +1 -1
- package/dist/scene/SceneRenderer.js +94 -36
- package/dist/scene/entities/EntityGraphics.d.ts +26 -0
- package/dist/scene/entities/EntityGraphics.d.ts.map +1 -0
- package/dist/scene/entities/EntityGraphics.js +226 -0
- package/dist/scene/index.d.ts +2 -2
- package/dist/scene/index.d.ts.map +1 -1
- package/dist/scene/index.js +2 -2
- package/package.json +2 -12
- package/dist/scene/entities/EntityRenderer.d.ts +0 -14
- package/dist/scene/entities/EntityRenderer.d.ts.map +0 -1
- package/dist/scene/entities/EntityRenderer.js +0 -203
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneRenderer.d.ts","sourceRoot":"","sources":["../../src/scene/SceneRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SceneRenderer.d.ts","sourceRoot":"","sources":["../../src/scene/SceneRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAGjF,OAAO,KAAK,EAAE,WAAW,EAAU,MAAM,2BAA2B,CAAC;AAwDrE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,IAAI,EAAE,WAAW,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,kCAAkC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EAAE,SAAS,EACf,OAAO,EACP,MAAc,EACd,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,EACnB,KAAa,GACd,EAAE,kBAAkB,qBA0CpB;AAgTD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import React, { useEffect, useRef, useCallback, useMemo, useState } from 'react';
|
|
3
|
+
import * as PIXI from 'pixi.js';
|
|
3
4
|
import Matter from 'matter-js';
|
|
4
5
|
import { compileScene } from '@thewhateverapp/scene-sdk';
|
|
5
|
-
import { PixiGame, useGameLoop,
|
|
6
|
+
import { PixiGame, usePixiApp, useGameLoop, TILE_WIDTH, TILE_HEIGHT } from '../pixi/index.js';
|
|
6
7
|
import { SceneContext, createEntityState, createPlayerState, createCameraState, createInputState, createTimelineState, } from './SceneContext.js';
|
|
7
|
-
import { EntityRenderer } from './entities/EntityRenderer.js';
|
|
8
8
|
import { usePhysicsEngine } from './physics/PhysicsEngine.js';
|
|
9
9
|
import { useInputManager } from './input/InputManager.js';
|
|
10
10
|
import { useComponentRunner } from './components/ComponentRunner.js';
|
|
11
11
|
import { useTimelineExecutor } from './timeline/TimelineExecutor.js';
|
|
12
12
|
import { useCameraController } from './camera/CameraController.js';
|
|
13
|
-
import {
|
|
13
|
+
import { createEntityGraphics, updateEntityGraphics, } from './entities/EntityGraphics.js';
|
|
14
14
|
const { Body } = Matter;
|
|
15
15
|
/**
|
|
16
16
|
* Hook to track container size using ResizeObserver
|
|
@@ -66,6 +66,11 @@ export function SceneRenderer({ spec: inputSpec, onEvent, paused = false, width:
|
|
|
66
66
|
* Inner component that runs inside PixiGame context
|
|
67
67
|
*/
|
|
68
68
|
function SceneContent({ spec, onEvent, paused, width, height, debug, }) {
|
|
69
|
+
const app = usePixiApp();
|
|
70
|
+
// Pixi containers
|
|
71
|
+
const worldContainerRef = useRef(null);
|
|
72
|
+
const layerContainersRef = useRef(new Map());
|
|
73
|
+
const entityGraphicsRef = useRef(new Map());
|
|
69
74
|
// Initialize refs for all state
|
|
70
75
|
const entitiesRef = useRef(new Map());
|
|
71
76
|
const playerRef = useRef(createPlayerState());
|
|
@@ -115,14 +120,23 @@ function SceneContent({ spec, onEvent, paused, width, height, debug, }) {
|
|
|
115
120
|
tags: prefab.tags,
|
|
116
121
|
components: prefab.components,
|
|
117
122
|
};
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
const state = createEntityState(entity);
|
|
124
|
+
entitiesRef.current.set(id, state);
|
|
125
|
+
// Create graphics for the new entity
|
|
126
|
+
const layerContainer = layerContainersRef.current.get(entity.layer);
|
|
127
|
+
if (layerContainer) {
|
|
128
|
+
const graphics = createEntityGraphics(state, debug);
|
|
129
|
+
entityGraphicsRef.current.set(id, graphics);
|
|
130
|
+
layerContainer.addChild(graphics.container);
|
|
131
|
+
}
|
|
132
|
+
}, [spec.prefabs, debug]);
|
|
120
133
|
// Destroy entity
|
|
121
134
|
const destroyEntity = useCallback((id) => {
|
|
122
135
|
const entity = entitiesRef.current.get(id);
|
|
123
136
|
if (entity) {
|
|
124
137
|
entity.destroyed = true;
|
|
125
138
|
// Body cleanup happens in physics engine
|
|
139
|
+
// Graphics cleanup happens in render loop
|
|
126
140
|
}
|
|
127
141
|
}, []);
|
|
128
142
|
// Respawn player at checkpoint
|
|
@@ -173,6 +187,35 @@ function SceneContent({ spec, onEvent, paused, width, height, debug, }) {
|
|
|
173
187
|
bpm,
|
|
174
188
|
startTime: startTimeRef.current,
|
|
175
189
|
}), [spec, layers, bpm, emitEvent, getEntity, spawnEntity, destroyEntity, respawnPlayer]);
|
|
190
|
+
// Initialize pixi containers
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (!app)
|
|
193
|
+
return;
|
|
194
|
+
// Create world container
|
|
195
|
+
const worldContainer = new PIXI.Container();
|
|
196
|
+
worldContainer.sortableChildren = true;
|
|
197
|
+
app.stage.addChild(worldContainer);
|
|
198
|
+
worldContainerRef.current = worldContainer;
|
|
199
|
+
// Create layer containers
|
|
200
|
+
const layerContainers = new Map();
|
|
201
|
+
layers.forEach((layer, index) => {
|
|
202
|
+
const container = new PIXI.Container();
|
|
203
|
+
container.zIndex = index;
|
|
204
|
+
worldContainer.addChild(container);
|
|
205
|
+
layerContainers.set(layer, container);
|
|
206
|
+
});
|
|
207
|
+
layerContainersRef.current = layerContainers;
|
|
208
|
+
return () => {
|
|
209
|
+
// Cleanup
|
|
210
|
+
entityGraphicsRef.current.forEach((graphics) => {
|
|
211
|
+
graphics.container.destroy({ children: true });
|
|
212
|
+
});
|
|
213
|
+
entityGraphicsRef.current.clear();
|
|
214
|
+
layerContainersRef.current.clear();
|
|
215
|
+
worldContainer.destroy({ children: true });
|
|
216
|
+
worldContainerRef.current = null;
|
|
217
|
+
};
|
|
218
|
+
}, [app, layers]);
|
|
176
219
|
// Initialize entities from spec
|
|
177
220
|
useEffect(() => {
|
|
178
221
|
const entityMap = new Map();
|
|
@@ -191,7 +234,20 @@ function SceneContent({ spec, onEvent, paused, width, height, debug, }) {
|
|
|
191
234
|
// Reset start time
|
|
192
235
|
startTimeRef.current = Date.now();
|
|
193
236
|
timelineRef.current = createTimelineState();
|
|
194
|
-
|
|
237
|
+
// Create graphics for all entities
|
|
238
|
+
entityGraphicsRef.current.forEach((graphics) => {
|
|
239
|
+
graphics.container.destroy({ children: true });
|
|
240
|
+
});
|
|
241
|
+
entityGraphicsRef.current.clear();
|
|
242
|
+
for (const [id, state] of entityMap) {
|
|
243
|
+
const layerContainer = layerContainersRef.current.get(state.entity.layer);
|
|
244
|
+
if (layerContainer) {
|
|
245
|
+
const graphics = createEntityGraphics(state, debug);
|
|
246
|
+
entityGraphicsRef.current.set(id, graphics);
|
|
247
|
+
layerContainer.addChild(graphics.container);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}, [spec, debug]);
|
|
195
251
|
// Initialize physics engine
|
|
196
252
|
usePhysicsEngine(contextValue, width, height);
|
|
197
253
|
// Initialize input handling
|
|
@@ -202,7 +258,7 @@ function SceneContent({ spec, onEvent, paused, width, height, debug, }) {
|
|
|
202
258
|
useTimelineExecutor(contextValue);
|
|
203
259
|
// Update camera
|
|
204
260
|
useCameraController(contextValue, width, height);
|
|
205
|
-
// Main game loop
|
|
261
|
+
// Main game loop - update graphics positions
|
|
206
262
|
useGameLoop((delta) => {
|
|
207
263
|
if (paused)
|
|
208
264
|
return;
|
|
@@ -217,37 +273,39 @@ function SceneContent({ spec, onEvent, paused, width, height, debug, }) {
|
|
|
217
273
|
timelineRef.current.elapsedMs = now - startTimeRef.current;
|
|
218
274
|
timelineRef.current.currentBeat = (timelineRef.current.elapsedMs / 1000) * (bpm / 60);
|
|
219
275
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
276
|
+
// Update camera position
|
|
277
|
+
if (worldContainerRef.current) {
|
|
278
|
+
const camera = cameraRef.current;
|
|
279
|
+
worldContainerRef.current.x = -camera.x + width / 2;
|
|
280
|
+
worldContainerRef.current.y = -camera.y + height / 2;
|
|
281
|
+
worldContainerRef.current.scale.set(camera.zoom);
|
|
282
|
+
}
|
|
283
|
+
// Update entity graphics
|
|
284
|
+
for (const [id, state] of entitiesRef.current) {
|
|
285
|
+
const graphics = entityGraphicsRef.current.get(id);
|
|
286
|
+
if (!graphics)
|
|
287
|
+
continue;
|
|
288
|
+
if (state.destroyed || !state.visible) {
|
|
289
|
+
// Remove destroyed/hidden entities
|
|
290
|
+
if (graphics.container.parent) {
|
|
291
|
+
graphics.container.parent.removeChild(graphics.container);
|
|
292
|
+
}
|
|
293
|
+
if (state.destroyed) {
|
|
294
|
+
graphics.container.destroy({ children: true });
|
|
295
|
+
entityGraphicsRef.current.delete(id);
|
|
296
|
+
entitiesRef.current.delete(id);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
graphics.container.visible = false;
|
|
300
|
+
}
|
|
301
|
+
continue;
|
|
240
302
|
}
|
|
303
|
+
graphics.container.visible = true;
|
|
304
|
+
updateEntityGraphics(graphics, state);
|
|
241
305
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const zB = b.entity.render?.zIndex ?? 0;
|
|
246
|
-
return zA - zB;
|
|
247
|
-
});
|
|
248
|
-
return result;
|
|
249
|
-
}, [entities, layer]);
|
|
250
|
-
return (React.createElement(React.Fragment, null, layerEntities.map((state) => (React.createElement(EntityRenderer, { key: state.entity.id, state: state, debug: debug })))));
|
|
306
|
+
}, !paused);
|
|
307
|
+
// Provide context for hooks that need it
|
|
308
|
+
return (React.createElement(SceneContext.Provider, { value: contextValue }, null));
|
|
251
309
|
}
|
|
252
310
|
// Re-export useScene for convenience
|
|
253
311
|
import { useScene } from './SceneContext.js';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EntityGraphics - Imperative pixi.js graphics creation for entities
|
|
3
|
+
*
|
|
4
|
+
* This module creates and updates pixi objects directly without React reconciler.
|
|
5
|
+
*/
|
|
6
|
+
import * as PIXI from 'pixi.js';
|
|
7
|
+
import type { EntityState } from '../SceneContext.js';
|
|
8
|
+
/**
|
|
9
|
+
* Container for entity graphics
|
|
10
|
+
*/
|
|
11
|
+
export interface EntityGraphics {
|
|
12
|
+
container: PIXI.Container;
|
|
13
|
+
graphics: PIXI.Graphics | null;
|
|
14
|
+
text: PIXI.Text | null;
|
|
15
|
+
sprite: PIXI.Sprite | null;
|
|
16
|
+
debugGraphics: PIXI.Graphics | null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create pixi graphics for an entity
|
|
20
|
+
*/
|
|
21
|
+
export declare function createEntityGraphics(state: EntityState, debug?: boolean): EntityGraphics;
|
|
22
|
+
/**
|
|
23
|
+
* Update entity graphics position and state
|
|
24
|
+
*/
|
|
25
|
+
export declare function updateEntityGraphics(entityGraphics: EntityGraphics, state: EntityState): void;
|
|
26
|
+
//# sourceMappingURL=EntityGraphics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityGraphics.d.ts","sourceRoot":"","sources":["../../../src/scene/entities/EntityGraphics.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAWtD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC;IAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;CACrC;AASD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,GAAE,OAAe,GAAG,cAAc,CA8F/F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAoB7F"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* EntityGraphics - Imperative pixi.js graphics creation for entities
|
|
4
|
+
*
|
|
5
|
+
* This module creates and updates pixi objects directly without React reconciler.
|
|
6
|
+
*/
|
|
7
|
+
import * as PIXI from 'pixi.js';
|
|
8
|
+
/**
|
|
9
|
+
* Parse hex color string to number
|
|
10
|
+
*/
|
|
11
|
+
function parseColor(color) {
|
|
12
|
+
return parseInt(color.replace('#', ''), 16);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create pixi graphics for an entity
|
|
16
|
+
*/
|
|
17
|
+
export function createEntityGraphics(state, debug = false) {
|
|
18
|
+
const container = new PIXI.Container();
|
|
19
|
+
let graphics = null;
|
|
20
|
+
let text = null;
|
|
21
|
+
let sprite = null;
|
|
22
|
+
let debugGraphics = null;
|
|
23
|
+
const { entity } = state;
|
|
24
|
+
const kind = entity.kind;
|
|
25
|
+
// Parse colors
|
|
26
|
+
const fillColor = parseColor(state.fill ?? entity.render?.fill ?? '#ffffff');
|
|
27
|
+
const strokeColor = entity.render?.stroke ? parseColor(entity.render.stroke) : undefined;
|
|
28
|
+
const strokeWidth = entity.render?.strokeWidth ?? 0;
|
|
29
|
+
switch (kind) {
|
|
30
|
+
case 'rect': {
|
|
31
|
+
const geom = entity.geom;
|
|
32
|
+
graphics = new PIXI.Graphics();
|
|
33
|
+
drawRect(graphics, geom, fillColor, strokeColor, strokeWidth);
|
|
34
|
+
container.addChild(graphics);
|
|
35
|
+
if (debug) {
|
|
36
|
+
debugGraphics = new PIXI.Graphics();
|
|
37
|
+
drawDebugBounds(debugGraphics, geom);
|
|
38
|
+
container.addChild(debugGraphics);
|
|
39
|
+
}
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case 'circle': {
|
|
43
|
+
const geom = entity.geom;
|
|
44
|
+
graphics = new PIXI.Graphics();
|
|
45
|
+
drawCircle(graphics, geom, fillColor, strokeColor, strokeWidth);
|
|
46
|
+
container.addChild(graphics);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case 'poly': {
|
|
50
|
+
const geom = entity.geom;
|
|
51
|
+
graphics = new PIXI.Graphics();
|
|
52
|
+
drawPoly(graphics, geom, fillColor, strokeColor, strokeWidth);
|
|
53
|
+
container.addChild(graphics);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case 'line': {
|
|
57
|
+
const geom = entity.geom;
|
|
58
|
+
graphics = new PIXI.Graphics();
|
|
59
|
+
drawLine(graphics, geom, strokeColor ?? fillColor);
|
|
60
|
+
container.addChild(graphics);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case 'text': {
|
|
64
|
+
const geom = entity.geom;
|
|
65
|
+
text = createTextElement(geom, fillColor);
|
|
66
|
+
container.addChild(text);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case 'sprite': {
|
|
70
|
+
const geom = entity.geom;
|
|
71
|
+
// For now, draw a placeholder since we don't have texture loading
|
|
72
|
+
graphics = new PIXI.Graphics();
|
|
73
|
+
drawSpritePlaceholder(graphics, geom);
|
|
74
|
+
container.addChild(graphics);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case 'emitter': {
|
|
78
|
+
const geom = entity.geom;
|
|
79
|
+
graphics = new PIXI.Graphics();
|
|
80
|
+
drawEmitterMarker(graphics, fillColor);
|
|
81
|
+
container.addChild(graphics);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case 'group':
|
|
85
|
+
// Groups are just containers
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
console.warn(`Unknown entity kind: ${kind}`);
|
|
89
|
+
}
|
|
90
|
+
// Set initial position
|
|
91
|
+
container.x = state.x;
|
|
92
|
+
container.y = state.y;
|
|
93
|
+
container.rotation = state.rotation;
|
|
94
|
+
container.scale.set(state.scaleX, state.scaleY);
|
|
95
|
+
container.alpha = state.alpha;
|
|
96
|
+
return { container, graphics, text, sprite, debugGraphics };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Update entity graphics position and state
|
|
100
|
+
*/
|
|
101
|
+
export function updateEntityGraphics(entityGraphics, state) {
|
|
102
|
+
const { container, graphics } = entityGraphics;
|
|
103
|
+
// Update transform
|
|
104
|
+
container.x = state.x;
|
|
105
|
+
container.y = state.y;
|
|
106
|
+
container.rotation = state.rotation;
|
|
107
|
+
container.scale.set(state.scaleX, state.scaleY);
|
|
108
|
+
container.alpha = state.alpha;
|
|
109
|
+
// If fill color changed, redraw (for dynamic color changes)
|
|
110
|
+
if (graphics && state.entity.kind === 'rect') {
|
|
111
|
+
const geom = state.entity.geom;
|
|
112
|
+
const fillColor = parseColor(state.fill ?? state.entity.render?.fill ?? '#ffffff');
|
|
113
|
+
const strokeColor = state.entity.render?.stroke ? parseColor(state.entity.render.stroke) : undefined;
|
|
114
|
+
const strokeWidth = state.entity.render?.strokeWidth ?? 0;
|
|
115
|
+
graphics.clear();
|
|
116
|
+
drawRect(graphics, geom, fillColor, strokeColor, strokeWidth);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Draw a rectangle
|
|
121
|
+
*/
|
|
122
|
+
function drawRect(g, geom, fillColor, strokeColor, strokeWidth = 0) {
|
|
123
|
+
if (strokeColor !== undefined && strokeWidth > 0) {
|
|
124
|
+
g.lineStyle(strokeWidth, strokeColor);
|
|
125
|
+
}
|
|
126
|
+
g.beginFill(fillColor);
|
|
127
|
+
const anchorX = geom.w / 2;
|
|
128
|
+
const anchorY = geom.h / 2;
|
|
129
|
+
if (geom.cornerRadius && geom.cornerRadius > 0) {
|
|
130
|
+
g.drawRoundedRect(-anchorX, -anchorY, geom.w, geom.h, geom.cornerRadius);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
g.drawRect(-anchorX, -anchorY, geom.w, geom.h);
|
|
134
|
+
}
|
|
135
|
+
g.endFill();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Draw a circle
|
|
139
|
+
*/
|
|
140
|
+
function drawCircle(g, geom, fillColor, strokeColor, strokeWidth = 0) {
|
|
141
|
+
if (strokeColor !== undefined && strokeWidth > 0) {
|
|
142
|
+
g.lineStyle(strokeWidth, strokeColor);
|
|
143
|
+
}
|
|
144
|
+
g.beginFill(fillColor);
|
|
145
|
+
g.drawCircle(0, 0, geom.r);
|
|
146
|
+
g.endFill();
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Draw a polygon
|
|
150
|
+
*/
|
|
151
|
+
function drawPoly(g, geom, fillColor, strokeColor, strokeWidth = 0) {
|
|
152
|
+
if (strokeColor !== undefined && strokeWidth > 0) {
|
|
153
|
+
g.lineStyle(strokeWidth, strokeColor);
|
|
154
|
+
}
|
|
155
|
+
g.beginFill(fillColor);
|
|
156
|
+
const points = geom.points;
|
|
157
|
+
if (points.length < 3)
|
|
158
|
+
return;
|
|
159
|
+
g.moveTo(points[0][0], points[0][1]);
|
|
160
|
+
for (let i = 1; i < points.length; i++) {
|
|
161
|
+
g.lineTo(points[i][0], points[i][1]);
|
|
162
|
+
}
|
|
163
|
+
g.closePath();
|
|
164
|
+
g.endFill();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Draw a line
|
|
168
|
+
*/
|
|
169
|
+
function drawLine(g, geom, strokeColor) {
|
|
170
|
+
g.lineStyle(geom.lineWidth ?? 2, strokeColor);
|
|
171
|
+
const points = geom.points;
|
|
172
|
+
if (points.length < 2)
|
|
173
|
+
return;
|
|
174
|
+
g.moveTo(points[0][0], points[0][1]);
|
|
175
|
+
for (let i = 1; i < points.length; i++) {
|
|
176
|
+
g.lineTo(points[i][0], points[i][1]);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Create a text element
|
|
181
|
+
*/
|
|
182
|
+
function createTextElement(geom, fillColor) {
|
|
183
|
+
const style = new PIXI.TextStyle({
|
|
184
|
+
fontFamily: geom.fontFamily ?? 'Arial',
|
|
185
|
+
fontSize: geom.fontSize ?? 16,
|
|
186
|
+
fontWeight: (geom.fontWeight ?? 'normal'),
|
|
187
|
+
fill: fillColor,
|
|
188
|
+
align: (geom.align ?? 'center'),
|
|
189
|
+
});
|
|
190
|
+
const text = new PIXI.Text(geom.text, style);
|
|
191
|
+
text.anchor.set(0.5, 0.5);
|
|
192
|
+
return text;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Draw sprite placeholder (for missing sprites)
|
|
196
|
+
*/
|
|
197
|
+
function drawSpritePlaceholder(g, geom) {
|
|
198
|
+
const w = geom.w ?? 32;
|
|
199
|
+
const h = geom.h ?? 32;
|
|
200
|
+
g.beginFill(0x888888);
|
|
201
|
+
g.drawRect(-w / 2, -h / 2, w, h);
|
|
202
|
+
g.endFill();
|
|
203
|
+
// Draw X to indicate missing sprite
|
|
204
|
+
g.lineStyle(2, 0xff0000);
|
|
205
|
+
g.moveTo(-w / 2, -h / 2);
|
|
206
|
+
g.lineTo(w / 2, h / 2);
|
|
207
|
+
g.moveTo(w / 2, -h / 2);
|
|
208
|
+
g.lineTo(-w / 2, h / 2);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Draw emitter marker
|
|
212
|
+
*/
|
|
213
|
+
function drawEmitterMarker(g, fillColor) {
|
|
214
|
+
g.beginFill(fillColor, 0.3);
|
|
215
|
+
g.drawCircle(0, 0, 10);
|
|
216
|
+
g.endFill();
|
|
217
|
+
g.lineStyle(1, fillColor);
|
|
218
|
+
g.drawCircle(0, 0, 15);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Draw debug bounds
|
|
222
|
+
*/
|
|
223
|
+
function drawDebugBounds(g, geom) {
|
|
224
|
+
g.lineStyle(1, 0x00ff00, 0.5);
|
|
225
|
+
g.drawRect(-geom.w / 2, -geom.h / 2, geom.w, geom.h);
|
|
226
|
+
}
|
package/dist/scene/index.d.ts
CHANGED
|
@@ -32,8 +32,8 @@ export { SceneRenderer, useScene } from './SceneRenderer.js';
|
|
|
32
32
|
export type { SceneRendererProps } from './SceneRenderer.js';
|
|
33
33
|
export { SceneContext, createEntityState, createPlayerState, createCameraState, createInputState, createTimelineState, } from './SceneContext.js';
|
|
34
34
|
export type { SceneContextValue, EntityState, PlayerState, CameraState, InputState, TimelineState, ActiveTween, } from './SceneContext.js';
|
|
35
|
-
export {
|
|
36
|
-
export type {
|
|
35
|
+
export { createEntityGraphics, updateEntityGraphics, } from './entities/EntityGraphics.js';
|
|
36
|
+
export type { EntityGraphics } from './entities/EntityGraphics.js';
|
|
37
37
|
export { usePhysicsEngine, applyImpulse, setVelocity, } from './physics/PhysicsEngine.js';
|
|
38
38
|
export { useInputManager, isJumpPressed, isKeyPressed, isTouching, } from './input/InputManager.js';
|
|
39
39
|
export { useComponentRunner, registerComponent, } from './components/ComponentRunner.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scene/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scene/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACZ,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,UAAU,GACX,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,SAAS,GACV,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/scene/index.js
CHANGED
|
@@ -33,8 +33,8 @@ export { SceneFromJson } from './SceneFromJson.js';
|
|
|
33
33
|
export { SceneRenderer, useScene } from './SceneRenderer.js';
|
|
34
34
|
// Context and types
|
|
35
35
|
export { SceneContext, createEntityState, createPlayerState, createCameraState, createInputState, createTimelineState, } from './SceneContext.js';
|
|
36
|
-
// Entity
|
|
37
|
-
export {
|
|
36
|
+
// Entity graphics (imperative pixi creation)
|
|
37
|
+
export { createEntityGraphics, updateEntityGraphics, } from './entities/EntityGraphics.js';
|
|
38
38
|
// Physics
|
|
39
39
|
export { usePhysicsEngine, applyImpulse, setVelocity, } from './physics/PhysicsEngine.js';
|
|
40
40
|
// Input
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thewhateverapp/tile-sdk",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.11",
|
|
4
4
|
"description": "SDK for building interactive tiles on The Whatever App platform",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -70,24 +70,14 @@
|
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"react": "^18.0.0",
|
|
73
|
-
"
|
|
74
|
-
"pixi.js": "^7.0.0",
|
|
75
|
-
"@pixi/filter-glow": "^5.0.0"
|
|
73
|
+
"pixi.js": "^7.0.0"
|
|
76
74
|
},
|
|
77
75
|
"peerDependenciesMeta": {
|
|
78
|
-
"@pixi/react": {
|
|
79
|
-
"optional": true
|
|
80
|
-
},
|
|
81
76
|
"pixi.js": {
|
|
82
77
|
"optional": true
|
|
83
|
-
},
|
|
84
|
-
"@pixi/filter-glow": {
|
|
85
|
-
"optional": true
|
|
86
78
|
}
|
|
87
79
|
},
|
|
88
80
|
"devDependencies": {
|
|
89
|
-
"@pixi/filter-glow": "^5.0.0",
|
|
90
|
-
"@pixi/react": "^7.1.2",
|
|
91
81
|
"@types/matter-js": "^0.19.0",
|
|
92
82
|
"@types/node": "^20.0.0",
|
|
93
83
|
"@types/react": "^18.2.48",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { EntityState } from '../SceneContext.js';
|
|
3
|
-
/**
|
|
4
|
-
* Props for EntityRenderer
|
|
5
|
-
*/
|
|
6
|
-
export interface EntityRendererProps {
|
|
7
|
-
state: EntityState;
|
|
8
|
-
debug?: boolean;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Renders a single entity based on its kind
|
|
12
|
-
*/
|
|
13
|
-
export declare function EntityRenderer({ state, debug }: EntityRendererProps): React.JSX.Element | null;
|
|
14
|
-
//# sourceMappingURL=EntityRenderer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EntityRenderer.d.ts","sourceRoot":"","sources":["../../../src/scene/entities/EntityRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAWtD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAa,EAAE,EAAE,mBAAmB,4BAyG3E"}
|