Skip to content

Commit c3ca721

Browse files
authored
refactor!: major breaking changes for ECS APIs (#157)
1 parent c8405ca commit c3ca721

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1165
-681
lines changed

.changeset/little-cats-appear.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@jolly-pixel/runtime": major
3+
"@jolly-pixel/engine": major
4+
---
5+
6+
Major refactoring of ECS APIs (GameInstance -> World, Actor and ActorComponent breaking, SceneEngine -> SceneManager, new Transform APIs, etc)

.claude/settings.local.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(npm run test:*)",
5+
"Bash(npx tsc:*)",
6+
"Bash(find:*)",
7+
"Bash(git mv:*)"
8+
]
9+
}
10+
}

packages/editors/model/src/ModelManipulator.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ export class ModelManipulator extends ActorComponent {
3434
});
3535

3636
this.#camera = options.camera;
37-
this.#canvas = this.actor.gameInstance.renderer.canvas;
37+
this.#canvas = this.actor.world.renderer.canvas;
3838
// @ts-ignore
39-
this.#actors = this.actor.gameInstance.tree.children.filter((node) => node.name.endsWith("Model"));
39+
this.#actors = this.actor.world.tree.children.filter((node) => node.name.endsWith("Model"));
4040
this.#raycaster = new THREE.Raycaster();
4141
this.#mouse = new THREE.Vector2();
4242
this.#dragPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
@@ -113,8 +113,8 @@ export class ModelManipulator extends ActorComponent {
113113

114114
const intersectableObjects: THREE.Object3D[] = [];
115115
this.#actors.forEach((actor) => {
116-
if (actor.threeObject.children.length > 0) {
117-
actor.threeObject.traverse((child) => {
116+
if (actor.object3D.children.length > 0) {
117+
actor.object3D.traverse((child) => {
118118
if (child instanceof THREE.Mesh) {
119119
intersectableObjects.push(child);
120120
}
@@ -135,7 +135,7 @@ export class ModelManipulator extends ActorComponent {
135135
const intersection = new THREE.Vector3();
136136
this.#raycaster.ray.intersectPlane(this.#dragPlane, intersection);
137137

138-
this.#dragOffset.copy(this.#draggedActor.threeObject.position).sub(intersection);
138+
this.#dragOffset.copy(this.#draggedActor.object3D.position).sub(intersection);
139139
}
140140
}
141141
}
@@ -147,8 +147,8 @@ export class ModelManipulator extends ActorComponent {
147147

148148
const intersectableObjects: THREE.Object3D[] = [];
149149
this.#actors.forEach((actor) => {
150-
if (actor.threeObject.children.length > 0) {
151-
actor.threeObject.traverse((child) => {
150+
if (actor.object3D.children.length > 0) {
151+
actor.object3D.traverse((child) => {
152152
if (child instanceof THREE.Mesh) {
153153
intersectableObjects.push(child);
154154
}
@@ -167,7 +167,7 @@ export class ModelManipulator extends ActorComponent {
167167
this.#canvas.style.cursor = "grabbing";
168168

169169
this.#rotationStartMouse.copy(this.#mouse);
170-
this.#rotationStartRotation = this.#draggedActor.threeObject.rotation.y;
170+
this.#rotationStartRotation = this.#draggedActor.object3D.rotation.y;
171171
}
172172
}
173173
}
@@ -181,23 +181,23 @@ export class ModelManipulator extends ActorComponent {
181181

182182
const intersection = new THREE.Vector3();
183183
if (this.#raycaster.ray.intersectPlane(this.#dragPlane, intersection)) {
184-
this.#draggedActor.threeObject.position.copy(intersection.add(this.#dragOffset));
184+
this.#draggedActor.object3D.position.copy(intersection.add(this.#dragOffset));
185185
}
186186
}
187187
else if (this.#isAltDown) {
188188
const mouseDelta = this.#mouse.x - this.#rotationStartMouse.x;
189189
const rotationSpeed = Math.PI * 2;
190190
const newRotation = this.#rotationStartRotation + (mouseDelta * rotationSpeed);
191-
this.#draggedActor.threeObject.rotation.y = newRotation;
191+
this.#draggedActor.object3D.rotation.y = newRotation;
192192
}
193193
}
194194
else if (this.#isControlDown || this.#isAltDown) {
195195
this.#raycaster.setFromCamera(this.#mouse, this.#camera);
196196

197197
const intersectableObjects: THREE.Object3D[] = [];
198198
this.#actors.forEach((actor) => {
199-
if (actor.threeObject.children.length > 0) {
200-
actor.threeObject.traverse((child) => {
199+
if (actor.object3D.children.length > 0) {
200+
actor.object3D.traverse((child) => {
201201
if (child instanceof THREE.Mesh) {
202202
intersectableObjects.push(child);
203203
}
@@ -231,7 +231,7 @@ export class ModelManipulator extends ActorComponent {
231231

232232
#findActorForObject(object: THREE.Object3D): Actor | null {
233233
for (const actor of this.#actors) {
234-
if (this.#isObjectInActor(object, actor.threeObject)) {
234+
if (this.#isObjectInActor(object, actor.object3D)) {
235235
return actor;
236236
}
237237
}

packages/editors/model/src/PlayerBehavior.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ export class PlayerBehavior extends Behavior<PlayerProperties> {
3838
}
3939

4040
awake() {
41-
this.actor.threeObject.rotateX(-Math.PI / 2);
41+
this.actor.object3D.rotateX(-Math.PI / 2);
4242

4343
this.model.animation.setClipNameRewriter((name) => name.slice(name.indexOf("|") + 1).toLowerCase());
4444
this.model.animation.play("idle_loop");
4545
this.model.animation.setFadeDuration(0.25);
4646
}
4747

4848
update() {
49-
const { input } = this.actor.gameInstance;
49+
const { input } = this.actor.world;
5050

5151
if (input.isTouchDown("primary")) {
5252
console.log("Primary touch is down!");
@@ -61,11 +61,11 @@ export class PlayerBehavior extends Behavior<PlayerProperties> {
6161
}
6262

6363
if (input.isKeyDown("ArrowUp")) {
64-
this.actor.threeObject.position.z += this.speed;
64+
this.actor.object3D.position.z += this.speed;
6565
this.model.animation.play("walk_loop");
6666
}
6767
else if (input.isKeyDown("ArrowDown")) {
68-
this.actor.threeObject.position.z -= this.speed;
68+
this.actor.object3D.position.z -= this.speed;
6969
this.model.animation.play("walk_loop");
7070
}
7171
else if (input.isMouseButtonDown("left")) {

packages/editors/model/src/index.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,55 +19,55 @@ function initRuntime() {
1919
const runtime = new Runtime(canvasHTMLElement, {
2020
includePerformanceStats: true
2121
});
22-
const { gameInstance } = runtime;
22+
const { world } = runtime;
2323

24-
const { camera } = new Actor(gameInstance, { name: "camera" })
25-
.registerComponentAndGet(
24+
const { camera } = new Actor(world, { name: "camera" })
25+
.addComponentAndGet(
2626
Camera3DControls,
2727
{ speed: 0.25, rotationSpeed: 0.50 }
2828
);
2929

3030
camera.position.set(5, 5, 5);
3131
camera.lookAt(0, 0, 0);
3232

33-
new Actor(gameInstance, { name: "tinyWitchModel" })
34-
.registerComponent(ModelRenderer, {
33+
new Actor(world, { name: "tinyWitchModel" })
34+
.addComponent(ModelRenderer, {
3535
path: "models/Tiny_Witch.obj"
3636
}, (component) => {
37-
component.actor.threeObject.position.set(-5, 0, 0);
37+
component.actor.object3D.position.set(-5, 0, 0);
3838
});
39-
// new Actor(gameInstance, { name: "tree" })
40-
// .registerComponent(ModelRenderer, {
39+
// new Actor(world, { name: "tree" })
40+
// .addComponent(ModelRenderer, {
4141
// path: "models/CommonTree_1.obj"
4242
// }, (component) => {
43-
// component.actor.threeObject.position.set(0, 0, 0);
43+
// component.actor.object3D.position.set(0, 0, 0);
4444
// });
45-
new Actor(gameInstance, { name: "player" })
46-
.registerComponent(ModelRenderer, {
45+
new Actor(world, { name: "player" })
46+
.addComponent(ModelRenderer, {
4747
path: "models/Standard.fbx"
4848
})
49-
.registerComponent(PlayerBehavior, {}, (_component) => {
49+
.addComponent(PlayerBehavior, {}, (_component) => {
5050
// console.log(component);
5151
// component.onPlayerPunch.connect(() => {
5252
// console.log("Player punched!");
5353
// });
5454
});
55-
// new Actor(gameInstance, { name: "duckModel" })
56-
// .registerComponent(ModelRenderer, {
55+
// new Actor(world, { name: "duckModel" })
56+
// .addComponent(ModelRenderer, {
5757
// path: "models/Duck.gltf"
5858
// }, (component) => {
59-
// component.actor.threeObject.position.set(-2, 0, 0);
60-
// component.actor.threeObject.rotateY(45);
59+
// component.actor.object3D.position.set(-2, 0, 0);
60+
// component.actor.object3D.rotateY(45);
6161
// });
62-
// new Actor(gameInstance, { name: "toyCarModel" })
63-
// .registerComponent(ModelRenderer, {
62+
// new Actor(world, { name: "toyCarModel" })
63+
// .addComponent(ModelRenderer, {
6464
// path: "models/ToyCar.glb"
6565
// }, (component) => {
66-
// component.actor.threeObject.position.set(0, 0.90, -4);
67-
// component.actor.threeObject.scale.set(50, 50, 50);
66+
// component.actor.object3D.position.set(0, 0.90, -4);
67+
// component.actor.object3D.scale.set(50, 50, 50);
6868
// });
6969

70-
const scene = gameInstance.scene.getSource();
70+
const scene = world.sceneManager.getSource();
7171
scene.background = null;
7272
scene.add(
7373
new THREE.GridHelper(

packages/editors/voxel-map/src/VoxelRenderer.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ export class VoxelRenderer extends ActorComponent {
4444
const { cameraActorName = "camera", ratio = 50 } = options;
4545

4646
this.ratio = ratio;
47-
const behavior = this.actor.gameInstance.scene.tree
47+
const behavior = this.actor.world.sceneManager.tree
4848
.getActor(cameraActorName)
49-
?.getBehavior(Camera3DControls);
49+
?.getComponent(Camera3DControls);
5050
if (!behavior) {
5151
throw new Error(`Unable to fetch camera behavior from actor with name <${cameraActorName}>`);
5252
}
@@ -55,7 +55,7 @@ export class VoxelRenderer extends ActorComponent {
5555
}
5656

5757
awake() {
58-
const threeScene = this.actor.gameInstance.scene.getSource();
58+
const threeScene = this.actor.world.sceneManager.getSource();
5959
threeScene.background = new THREE.Color("#e7f2ff");
6060

6161
this.plane = new THREE.Mesh(
@@ -70,19 +70,19 @@ export class VoxelRenderer extends ActorComponent {
7070
new THREE.AmbientLight(new THREE.Color("#ffffff"), 3)
7171
);
7272

73-
this.actor.registerComponent(GridRenderer, { ratio: this.ratio });
74-
this.actor.registerComponent(RollOverRenderer, void 0, (component) => {
73+
this.actor.addComponent(GridRenderer, { ratio: this.ratio });
74+
this.actor.addComponent(RollOverRenderer, void 0, (component) => {
7575
threeScene.add(component.object);
7676
});
7777

78-
createViewHelper(this.camera, this.actor.gameInstance);
78+
createViewHelper(this.camera, this.actor.world);
7979
}
8080

8181
remove(
8282
intersect: THREE.Intersection<THREE.Object3D>
8383
) {
8484
if (intersect.object !== this.plane) {
85-
this.actor.gameInstance.scene.getSource().remove(intersect.object);
85+
this.actor.world.sceneManager.getSource().remove(intersect.object);
8686
this.tree.remove(intersect.object);
8787
}
8888
}
@@ -102,20 +102,20 @@ export class VoxelRenderer extends ActorComponent {
102102
texture: textures[Math.floor(Math.random() * textures.length)]
103103
}).setPositionFromIntersection(intersect);
104104

105-
this.actor.gameInstance.scene.getSource().add(voxel);
105+
this.actor.world.sceneManager.getSource().add(voxel);
106106
this.tree.add(voxel);
107107
}
108108

109109
update() {
110-
const { input } = this.actor.gameInstance;
110+
const { input } = this.actor.world;
111111

112112
const isAnyMouseButtonsPressed = input.wasMouseButtonJustPressed("ANY");
113113
if (!isAnyMouseButtonsPressed) {
114114
return;
115115
}
116116

117117
this.raycaster.setFromCamera(
118-
this.actor.gameInstance.input.getMousePosition(),
118+
this.actor.world.input.getMousePosition(),
119119
this.camera
120120
);
121121

packages/editors/voxel-map/src/components/GridRenderer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export class GridRenderer extends ActorComponent {
8686
this.mesh = new THREE.LineSegments(geometry, material);
8787
this.mesh.computeLineDistances();
8888

89-
this.actor.threeObject.add(this.mesh);
89+
this.actor.object3D.add(this.mesh);
9090
}
9191

9292
clearMesh() {
@@ -101,7 +101,7 @@ export class GridRenderer extends ActorComponent {
101101
else {
102102
this.mesh.material.dispose();
103103
}
104-
this.actor.threeObject.remove(this.mesh);
104+
this.actor.object3D.remove(this.mesh);
105105
this.mesh = null;
106106
}
107107

packages/editors/voxel-map/src/components/OrbitCamera.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ export class OrbitCameraControls extends ActorComponent {
1717
this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
1818
this.controls = new OrbitControls(
1919
this.camera,
20-
this.actor.gameInstance.renderer.canvas
20+
this.actor.world.renderer.canvas
2121
);
2222
this.camera.position.set(0, 20, 100);
2323
this.camera.lookAt(0, 0, 0);
2424

25-
createViewHelper(this.camera, this.actor.gameInstance);
25+
createViewHelper(this.camera, this.actor.world);
2626
}
2727

2828
start() {
29-
this.actor.gameInstance.renderer.addRenderComponent(this.camera);
29+
this.actor.world.renderer.addRenderComponent(this.camera);
3030
}
3131

3232
update() {

packages/editors/voxel-map/src/components/RollOverRenderer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class RollOverRenderer extends ActorComponent {
4848
}
4949

5050
update() {
51-
const { input } = this.actor.gameInstance;
51+
const { input } = this.actor.world;
5252

5353
const isMouseMoving = input.isMouseMoving();
5454
if (!isMouseMoving) {
@@ -57,7 +57,7 @@ export class RollOverRenderer extends ActorComponent {
5757

5858
const { raycaster, camera, ratio, tree } = this.voxelRenderer;
5959
raycaster.setFromCamera(
60-
this.actor.gameInstance.input.getMousePosition(),
60+
this.actor.world.input.getMousePosition(),
6161
camera
6262
);
6363

packages/editors/voxel-map/src/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ function initRuntime() {
2222
const runtime = new Runtime(canvasHTMLElement, {
2323
includePerformanceStats: true
2424
});
25-
const { gameInstance } = runtime;
25+
const { world } = runtime;
2626

27-
new Actor(gameInstance, { name: "camera" })
28-
.registerComponent(Camera3DControls, { speed: 8, rotationSpeed: 1 }, (component) => {
27+
new Actor(world, { name: "camera" })
28+
.addComponent(Camera3DControls, { speed: 8, rotationSpeed: 1 }, (component) => {
2929
component.camera.position.set(200, 200, 400);
3030
component.camera.lookAt(0, 0, 0);
3131
});
3232

33-
new Actor(gameInstance, { name: "map" })
34-
.registerComponent(VoxelRenderer, { ratio: 16, cameraActorName: "camera" });
33+
new Actor(world, { name: "map" })
34+
.addComponent(VoxelRenderer, { ratio: 16, cameraActorName: "camera" });
3535

3636
return runtime;
3737
}

0 commit comments

Comments
 (0)