@directivegames/genesys.sdk 4.0.2 → 4.1.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/dist/src/core/tools/new-project.js +1 -0
- package/dist/src/dependencies.js +1 -1
- package/dist/src/templates/scripts/genesys/migrate-scenes-and-prefabs.js +179 -0
- package/dist/src/templates/scripts/genesys/post-install.js +10 -2
- package/dist/src/templates/src/templates/firstPerson/src/game.js +1 -1
- package/dist/src/templates/src/templates/firstPerson/src/player.js +8 -13
- package/dist/src/templates/src/templates/fps/src/game.js +1 -1
- package/dist/src/templates/src/templates/fps/src/player.js +8 -12
- package/dist/src/templates/src/templates/fps/src/weapon.js +30 -38
- package/dist/src/templates/src/templates/freeCamera/src/game.js +1 -1
- package/dist/src/templates/src/templates/freeCamera/src/player.js +6 -11
- package/dist/src/templates/src/templates/sideScroller/src/game.js +2 -3
- package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +17 -17
- package/dist/src/templates/src/templates/sideScroller/src/player.js +12 -17
- package/dist/src/templates/src/templates/thirdPerson/src/game.js +1 -1
- package/dist/src/templates/src/templates/thirdPerson/src/player.js +13 -18
- package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +1 -1
- package/dist/src/templates/src/templates/vehicle/src/game.js +2 -2
- package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +8 -9
- package/dist/src/templates/src/templates/vehicle/src/player.js +13 -18
- package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +11 -12
- package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +2 -2
- package/dist/src/templates/src/templates/vr-game/src/game.js +5 -5
- package/package.json +2 -2
- package/src/templates/scripts/genesys/migrate-scenes-and-prefabs.ts +212 -0
- package/src/templates/scripts/genesys/post-install.ts +11 -2
- package/src/templates/src/templates/firstPerson/src/game.ts +1 -1
- package/src/templates/src/templates/firstPerson/src/player.ts +10 -14
- package/src/templates/src/templates/fps/src/game.ts +1 -1
- package/src/templates/src/templates/fps/src/player.ts +10 -13
- package/src/templates/src/templates/fps/src/weapon.ts +31 -38
- package/src/templates/src/templates/freeCamera/src/game.ts +1 -1
- package/src/templates/src/templates/freeCamera/src/player.ts +7 -12
- package/src/templates/src/templates/sideScroller/src/game.ts +2 -3
- package/src/templates/src/templates/sideScroller/src/level-generator.ts +21 -21
- package/src/templates/src/templates/sideScroller/src/player.ts +15 -17
- package/src/templates/src/templates/thirdPerson/src/game.ts +1 -1
- package/src/templates/src/templates/thirdPerson/src/player.ts +16 -19
- package/src/templates/src/templates/vehicle/src/base-vehicle.ts +1 -1
- package/src/templates/src/templates/vehicle/src/game.ts +2 -2
- package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +8 -10
- package/src/templates/src/templates/vehicle/src/player.ts +16 -19
- package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +11 -13
- package/src/templates/src/templates/vehicle/src/ui-hints.ts +2 -2
- package/src/templates/src/templates/vr-game/src/game.ts +5 -5
|
@@ -24,7 +24,7 @@ export class BaseVehicle extends ENGINE.Pawn {
|
|
|
24
24
|
}
|
|
25
25
|
setupCamera() {
|
|
26
26
|
// create a follow component for smooth camera movement
|
|
27
|
-
const followComponent =
|
|
27
|
+
const followComponent = ENGINE.FollowComponent.create({
|
|
28
28
|
positionOffset: new THREE.Vector3(0, 4, 10),
|
|
29
29
|
positionDamping: 0.02,
|
|
30
30
|
lookAtOffset: new THREE.Vector3(0, 0, 0),
|
|
@@ -14,12 +14,12 @@ class MyGame extends ENGINE.BaseGameLoop {
|
|
|
14
14
|
// default spawn location
|
|
15
15
|
const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
|
|
16
16
|
// create the pawn
|
|
17
|
-
this.pawn =
|
|
17
|
+
this.pawn = VehiclePlayer.create({ position });
|
|
18
18
|
// create the controller and possess the pawn
|
|
19
19
|
this.controller = new ENGINE.PlayerController();
|
|
20
20
|
this.controller.possess(this.pawn);
|
|
21
21
|
// create UI hints
|
|
22
|
-
const uiHints =
|
|
22
|
+
const uiHints = UIHints.create();
|
|
23
23
|
// add all actors to the world
|
|
24
24
|
this.world.addActors(this.pawn, this.controller, uiHints);
|
|
25
25
|
}
|
|
@@ -22,9 +22,10 @@ import { BaseVehicle } from './base-vehicle.js';
|
|
|
22
22
|
*
|
|
23
23
|
*/
|
|
24
24
|
let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
|
|
25
|
-
constructor(
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
26
27
|
// the root component is only used for collision and physics simulation
|
|
27
|
-
const rootComponent =
|
|
28
|
+
const rootComponent = ENGINE.MeshComponent.create({
|
|
28
29
|
geometry: new THREE.BoxGeometry(2.77, 1.79, 5.75),
|
|
29
30
|
material: new THREE.MeshStandardMaterial({
|
|
30
31
|
color: 0x4444FF,
|
|
@@ -41,10 +42,10 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
|
|
|
41
42
|
},
|
|
42
43
|
});
|
|
43
44
|
rootComponent.name = 'root';
|
|
44
|
-
|
|
45
|
+
this.setRootComponent(rootComponent, true);
|
|
45
46
|
// mark the component as transient, this prevents all the components from being saved since we're recreating them in code
|
|
46
47
|
rootComponent.setTransient(true);
|
|
47
|
-
const chassisComponent =
|
|
48
|
+
const chassisComponent = ENGINE.GLTFMeshComponent.create({
|
|
48
49
|
modelUrl: '@project/assets/models/cyberTruck/chassis.glb',
|
|
49
50
|
position: new THREE.Vector3(0, 0, -0.75),
|
|
50
51
|
material: new THREE.MeshStandardMaterial({
|
|
@@ -61,7 +62,7 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
|
|
|
61
62
|
rootComponent.add(chassisComponent);
|
|
62
63
|
const wheelMeshes = [];
|
|
63
64
|
for (let i = 0; i < 4; i++) {
|
|
64
|
-
const wheelComponent =
|
|
65
|
+
const wheelComponent = ENGINE.GLTFMeshComponent.create({
|
|
65
66
|
modelUrl: '@project/assets/models/cyberTruck/wheel.glb',
|
|
66
67
|
material: new THREE.MeshStandardMaterial({
|
|
67
68
|
color: 0x44FF44,
|
|
@@ -78,8 +79,7 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
|
|
|
78
79
|
}
|
|
79
80
|
rootComponent.add(...wheelMeshes);
|
|
80
81
|
const vehicleMovementComponent = MeshVehicle_1.createVehicleMovementComponent();
|
|
81
|
-
|
|
82
|
-
super(options);
|
|
82
|
+
this.movementComponent = vehicleMovementComponent;
|
|
83
83
|
const wheelComponents = this.getComponents(ENGINE.GLTFMeshComponent).filter(component => component.name.startsWith('wheel_'));
|
|
84
84
|
vehicleMovementComponent.onWheelUpdated.add((component, wheelIndex, wheelState) => {
|
|
85
85
|
// The first mesh component is the chassis component, so we need to skip it
|
|
@@ -108,8 +108,7 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
|
|
|
108
108
|
const sideFrictionStiffness = 2;
|
|
109
109
|
const frictionSlip = 50;
|
|
110
110
|
// Create vehicle movement component
|
|
111
|
-
const vehicleMovement =
|
|
112
|
-
...ENGINE.BasePawnMovementComponent.DEFAULT_OPTIONS,
|
|
111
|
+
const vehicleMovement = ENGINE.VehicleMovementComponent.create({
|
|
113
112
|
createWheelMeshes: false,
|
|
114
113
|
maxEnginePower: 100,
|
|
115
114
|
maxBrakeForce: 1.5,
|
|
@@ -18,14 +18,15 @@ import { BaseVehicle } from './base-vehicle.js';
|
|
|
18
18
|
*/
|
|
19
19
|
let VehiclePlayer = class VehiclePlayer extends ENGINE.ThirdPersonCharacterPawn {
|
|
20
20
|
// Omit all the options that are created internally
|
|
21
|
-
constructor(
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
22
23
|
// simple camera component - contains a perspective camera by default
|
|
23
24
|
const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, 0.1, 1000);
|
|
24
25
|
// set camera position for third person view
|
|
25
26
|
camera.position.set(0, ENGINE.CHARACTER_HEIGHT * 1.3, ENGINE.CHARACTER_HEIGHT * 2);
|
|
26
27
|
camera.lookAt(0, 0, 0);
|
|
27
28
|
// use capsule root component for collision
|
|
28
|
-
const rootComponent =
|
|
29
|
+
const rootComponent = ENGINE.MeshComponent.create({
|
|
29
30
|
geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
|
|
30
31
|
material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW, visible: false, transparent: true, opacity: 0.5 }),
|
|
31
32
|
physicsOptions: {
|
|
@@ -35,25 +36,19 @@ let VehiclePlayer = class VehiclePlayer extends ENGINE.ThirdPersonCharacterPawn
|
|
|
35
36
|
collisionProfile: ENGINE.DefaultCollisionProfile.Character,
|
|
36
37
|
},
|
|
37
38
|
});
|
|
39
|
+
this.setRootComponent(rootComponent, true);
|
|
40
|
+
this.rootComponent.add(camera);
|
|
38
41
|
// use third person movement mechanics
|
|
39
|
-
const movementComponent =
|
|
40
|
-
...ENGINE.CharacterMovementComponent.DEFAULT_OPTIONS,
|
|
42
|
+
const movementComponent = ENGINE.CharacterMovementComponent.create({
|
|
41
43
|
movementType: ENGINE.CharacterMovementType.ThirdPerson,
|
|
42
44
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
enableDirectionalLightFollowing: true,
|
|
51
|
-
modelUrl: '@engine/assets/character/mannequinG.glb',
|
|
52
|
-
configUrl: '@engine/assets/character/config/mannequin-anim.json',
|
|
53
|
-
meshPosition: new THREE.Vector3(0, -ENGINE.CHARACTER_HEIGHT / 2, 0),
|
|
54
|
-
meshRotation: new THREE.Euler(0, Math.PI, 0),
|
|
55
|
-
meshScale: new THREE.Vector3(1, 1, 1),
|
|
56
|
-
});
|
|
45
|
+
this.movementComponent = movementComponent;
|
|
46
|
+
// Character model settings
|
|
47
|
+
this.enableDirectionalLightFollowing = true;
|
|
48
|
+
this.configUrl = '@engine/assets/character/config/mannequin-anim.json';
|
|
49
|
+
this.meshComponent.position.copy(new THREE.Vector3(0, -ENGINE.CHARACTER_HEIGHT / 2, 0));
|
|
50
|
+
this.meshComponent.rotation.copy(new THREE.Euler(0, Math.PI, 0));
|
|
51
|
+
rootComponent.add(this.meshComponent);
|
|
57
52
|
// set the pawn to be transient so it's never saved in the level
|
|
58
53
|
this.setTransient(true);
|
|
59
54
|
}
|
|
@@ -21,9 +21,10 @@ import { BaseVehicle } from './base-vehicle.js';
|
|
|
21
21
|
*/
|
|
22
22
|
let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseVehicle {
|
|
23
23
|
tailLightComponents = [];
|
|
24
|
-
constructor(
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
25
26
|
// Create chassis mesh
|
|
26
|
-
const rootComponent =
|
|
27
|
+
const rootComponent = ENGINE.MeshComponent.create({
|
|
27
28
|
geometry: new THREE.BoxGeometry(2, 1, 4),
|
|
28
29
|
material: new THREE.MeshStandardMaterial({
|
|
29
30
|
color: 0x4444FF,
|
|
@@ -40,11 +41,10 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
40
41
|
rootComponent.name = 'chassis';
|
|
41
42
|
// mark the component as transient, this prevents all the components from being saved since we're recreating them in code
|
|
42
43
|
rootComponent.setTransient(true);
|
|
43
|
-
|
|
44
|
+
this.setRootComponent(rootComponent, true);
|
|
44
45
|
// create decorative meshes
|
|
45
46
|
PrimitiveVehicle_1.createDecorativeMeshes(rootComponent);
|
|
46
|
-
|
|
47
|
-
super(options);
|
|
47
|
+
this.movementComponent = PrimitiveVehicle_1.createVehicleMovementComponent();
|
|
48
48
|
this.tailLightComponents = this.getComponents(ENGINE.MeshComponent)
|
|
49
49
|
.filter((component) => component.name.includes('_taillight'));
|
|
50
50
|
}
|
|
@@ -72,7 +72,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
72
72
|
}
|
|
73
73
|
static createDecorativeMeshes(rootComponent) {
|
|
74
74
|
// Add windshield
|
|
75
|
-
const windshieldComponent =
|
|
75
|
+
const windshieldComponent = ENGINE.MeshComponent.create({
|
|
76
76
|
geometry: new THREE.BoxGeometry(1.8, 1.8, 0.1),
|
|
77
77
|
material: new THREE.MeshStandardMaterial({
|
|
78
78
|
color: 0x87CEEB,
|
|
@@ -90,7 +90,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
90
90
|
windshieldComponent.name = 'windshield';
|
|
91
91
|
rootComponent.add(windshieldComponent);
|
|
92
92
|
// Add left headlight
|
|
93
|
-
const leftHeadlightComponent =
|
|
93
|
+
const leftHeadlightComponent = ENGINE.MeshComponent.create({
|
|
94
94
|
geometry: new THREE.CylinderGeometry(0.15, 0.15, 0.1, 8),
|
|
95
95
|
material: new THREE.MeshStandardMaterial({
|
|
96
96
|
color: 0xFFFFFF,
|
|
@@ -106,7 +106,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
106
106
|
leftHeadlightComponent.name = 'left_headlight';
|
|
107
107
|
rootComponent.add(leftHeadlightComponent);
|
|
108
108
|
// Add right headlight
|
|
109
|
-
const rightHeadlightComponent =
|
|
109
|
+
const rightHeadlightComponent = ENGINE.MeshComponent.create({
|
|
110
110
|
geometry: new THREE.CylinderGeometry(0.15, 0.15, 0.1, 8),
|
|
111
111
|
material: new THREE.MeshStandardMaterial({
|
|
112
112
|
color: 0xFFFFFF,
|
|
@@ -127,7 +127,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
127
127
|
emissive: 0x440000,
|
|
128
128
|
emissiveIntensity: 0.2,
|
|
129
129
|
});
|
|
130
|
-
const leftTaillightComponent =
|
|
130
|
+
const leftTaillightComponent = ENGINE.MeshComponent.create({
|
|
131
131
|
geometry: new THREE.CylinderGeometry(0.1, 0.1, 0.1, 8),
|
|
132
132
|
material: leftTaillightMaterial,
|
|
133
133
|
physicsOptions: {
|
|
@@ -144,7 +144,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
144
144
|
emissive: 0x440000,
|
|
145
145
|
emissiveIntensity: 0.2,
|
|
146
146
|
});
|
|
147
|
-
const rightTaillightComponent =
|
|
147
|
+
const rightTaillightComponent = ENGINE.MeshComponent.create({
|
|
148
148
|
geometry: new THREE.CylinderGeometry(0.1, 0.1, 0.1, 8),
|
|
149
149
|
material: rightTaillightMaterial,
|
|
150
150
|
physicsOptions: {
|
|
@@ -171,7 +171,6 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
171
171
|
const sideFrictionStiffness = 2;
|
|
172
172
|
const frictionSlip = 8;
|
|
173
173
|
const options = {
|
|
174
|
-
...ENGINE.BasePawnMovementComponent.DEFAULT_OPTIONS,
|
|
175
174
|
maxEnginePower: 35,
|
|
176
175
|
maxSteeringAngle: Math.PI / 6, // 30 degrees
|
|
177
176
|
maxBrakeForce: 1,
|
|
@@ -250,7 +249,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
|
|
|
250
249
|
},
|
|
251
250
|
],
|
|
252
251
|
};
|
|
253
|
-
return
|
|
252
|
+
return ENGINE.VehicleMovementComponent.create(options);
|
|
254
253
|
}
|
|
255
254
|
};
|
|
256
255
|
PrimitiveVehicle = PrimitiveVehicle_1 = __decorate([
|
|
@@ -10,8 +10,8 @@ import * as ENGINE from '@directivegames/genesys.js';
|
|
|
10
10
|
*/
|
|
11
11
|
let UIHints = class UIHints extends ENGINE.Actor {
|
|
12
12
|
uiElement = null;
|
|
13
|
-
constructor(
|
|
14
|
-
super(
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
15
|
this.setTransient(true); // Don't save this UI element to the level
|
|
16
16
|
}
|
|
17
17
|
async doBeginPlay() {
|
|
@@ -22,7 +22,7 @@ class MyGame extends ENGINE.BaseGameLoop {
|
|
|
22
22
|
// Disable tone mapping for VR because it breaks VR
|
|
23
23
|
this.world.postProcessManager.disablePasses(ENGINE.PostProcessPass.ToneMapping);
|
|
24
24
|
// create the vr pawn
|
|
25
|
-
this.pawn =
|
|
25
|
+
this.pawn = ENGINE.VRPawn.create({
|
|
26
26
|
position: new THREE.Vector3(0, 0, 0),
|
|
27
27
|
movementComponent: null,
|
|
28
28
|
camera: new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR),
|
|
@@ -38,10 +38,10 @@ class MyGame extends ENGINE.BaseGameLoop {
|
|
|
38
38
|
// create the controller and possess the pawn
|
|
39
39
|
this.controller = new ENGINE.PlayerController();
|
|
40
40
|
this.controller.possess(this.pawn);
|
|
41
|
-
this.pawn.addComponent(
|
|
42
|
-
this.pawn.addComponent(
|
|
43
|
-
this.pawn.addComponent(
|
|
44
|
-
this.pawn.addComponent(
|
|
41
|
+
this.pawn.addComponent(ENGINE.VRGrabComponent.create());
|
|
42
|
+
this.pawn.addComponent(ENGINE.VRSnapTurnComponent.create({ angleDeg: this.pawn.getSnapTurnAngleDegrees() }));
|
|
43
|
+
this.pawn.addComponent(ENGINE.VRInteractComponent.create({ button: ENGINE.XRButton.Trigger }));
|
|
44
|
+
this.pawn.addComponent(ENGINE.VRTeleportComponent.create({ maxDistance: 15 }));
|
|
45
45
|
// add both to the world
|
|
46
46
|
this.world.addActors(this.pawn, this.controller);
|
|
47
47
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directivegames/genesys.sdk",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Genesys SDK - A development toolkit for game development",
|
|
5
5
|
"author": "Directive Games",
|
|
6
6
|
"main": "index.js",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
111
|
"dependencies": {
|
|
112
|
-
"@directivegames/genesys.js": "^4.0.
|
|
112
|
+
"@directivegames/genesys.js": "^4.0.3",
|
|
113
113
|
"@electron/rebuild": "^4.0.1",
|
|
114
114
|
"@emotion/react": "^11.14.0",
|
|
115
115
|
"@emotion/styled": "^11.14.0",
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import * as ENGINE from '@directivegames/genesys.js';
|
|
5
|
+
|
|
6
|
+
import { getProjectRoot } from './common.js';
|
|
7
|
+
import { mockBrowserEnvironment } from './mock.js';
|
|
8
|
+
import { StorageProvider } from './storageProvider.js';
|
|
9
|
+
|
|
10
|
+
// Import game module to register game classes (tsx compiles TypeScript on the fly)
|
|
11
|
+
import '../../src/game.js';
|
|
12
|
+
|
|
13
|
+
// Set up browser environment for Node.js (provides document, window, etc.)
|
|
14
|
+
mockBrowserEnvironment();
|
|
15
|
+
|
|
16
|
+
// Set up storage provider for file operations
|
|
17
|
+
const storageProvider = new StorageProvider();
|
|
18
|
+
ENGINE.projectContext({ project: 'local-project', storageProvider: storageProvider });
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
interface FileInfo {
|
|
22
|
+
path: string;
|
|
23
|
+
type: 'scene' | 'prefab';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const defaultWorldOptions = {
|
|
27
|
+
rendererDomElement: document.createElement('div'),
|
|
28
|
+
gameContainer: document.createElement('div'),
|
|
29
|
+
backgroundColor: 0x2E2E2E,
|
|
30
|
+
physicsOptions: {
|
|
31
|
+
engine: ENGINE.PhysicsEngine.Rapier,
|
|
32
|
+
gravity: ENGINE.MathHelpers.makeVector({ up: -9.81 }),
|
|
33
|
+
},
|
|
34
|
+
navigationOptions: {
|
|
35
|
+
engine: ENGINE.NavigationEngine.RecastNavigation,
|
|
36
|
+
},
|
|
37
|
+
useManifold: true
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function findScenesAndPrefabs(dir: string, files: FileInfo[] = []): FileInfo[] {
|
|
41
|
+
const entries = fs.readdirSync(dir);
|
|
42
|
+
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const fullPath = path.join(dir, entry);
|
|
45
|
+
const stat = fs.statSync(fullPath);
|
|
46
|
+
|
|
47
|
+
if (stat.isDirectory()) {
|
|
48
|
+
// Skip common directories that shouldn't be processed
|
|
49
|
+
if (entry === 'node_modules' || entry === 'dist' || entry === '.git' || entry === '.engine') {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
findScenesAndPrefabs(fullPath, files);
|
|
53
|
+
} else if (entry.endsWith('.genesys-scene')) {
|
|
54
|
+
files.push({ path: fullPath, type: 'scene' });
|
|
55
|
+
} else if (entry.endsWith('.prefab.json')) {
|
|
56
|
+
files.push({ path: fullPath, type: 'prefab' });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return files;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function migrateSceneFile(filePath: string, relativePath: string): Promise<boolean> {
|
|
64
|
+
// Read the file content
|
|
65
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
66
|
+
const data = JSON.parse(content);
|
|
67
|
+
|
|
68
|
+
// Create a world and load into it
|
|
69
|
+
const world = new ENGINE.World(defaultWorldOptions);
|
|
70
|
+
|
|
71
|
+
if (ENGINE.isLegacyData(data)) {
|
|
72
|
+
// Use WorldSerializer for legacy data
|
|
73
|
+
await ENGINE.WorldSerializer.loadWorld(world, data);
|
|
74
|
+
} else {
|
|
75
|
+
// Use Loader for new format
|
|
76
|
+
const loader = new ENGINE.Loader();
|
|
77
|
+
await loader.loadToInstanceAsync(data, world);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Dump the world
|
|
81
|
+
const dumper = new ENGINE.Dumper();
|
|
82
|
+
const newData = dumper.dump(world);
|
|
83
|
+
|
|
84
|
+
// Write back to file
|
|
85
|
+
const newContent = JSON.stringify(newData, null, 2);
|
|
86
|
+
fs.writeFileSync(filePath, newContent, 'utf-8');
|
|
87
|
+
|
|
88
|
+
console.log(`✅ ${relativePath}`);
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function migratePrefabFile(filePath: string, relativePath: string): Promise<boolean> {
|
|
93
|
+
// Read the file content
|
|
94
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
95
|
+
const data = JSON.parse(content);
|
|
96
|
+
|
|
97
|
+
let instance: any;
|
|
98
|
+
|
|
99
|
+
if (ENGINE.isLegacyData(data)) {
|
|
100
|
+
// Use WorldSerializer for legacy data
|
|
101
|
+
console.log(`🔍 Migrating legacy prefab: ${relativePath}`);
|
|
102
|
+
instance = await ENGINE.WorldSerializer.loadActor(data);
|
|
103
|
+
console.log(`✅ ${relativePath}`);
|
|
104
|
+
} else {
|
|
105
|
+
// Use Loader for new format
|
|
106
|
+
const loader = new ENGINE.Loader();
|
|
107
|
+
instance = await loader.loadAsync(data);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!instance) {
|
|
111
|
+
console.log(`⚠️ ${relativePath}: Loaded instance is null, skipping`);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Dump using Dumper
|
|
116
|
+
const dumper = new ENGINE.Dumper();
|
|
117
|
+
const newData = dumper.dump(instance);
|
|
118
|
+
|
|
119
|
+
// Write back to file
|
|
120
|
+
const newContent = JSON.stringify(newData, null, 2);
|
|
121
|
+
fs.writeFileSync(filePath, newContent, 'utf-8');
|
|
122
|
+
|
|
123
|
+
console.log(`✅ ${relativePath}`);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function migrateFile(fileInfo: FileInfo): Promise<boolean> {
|
|
128
|
+
const { path: filePath, type } = fileInfo;
|
|
129
|
+
const relativePath = path.relative(getProjectRoot(), filePath);
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
if (type === 'scene') {
|
|
133
|
+
return await migrateSceneFile(filePath, relativePath);
|
|
134
|
+
} else {
|
|
135
|
+
return await migratePrefabFile(filePath, relativePath);
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error(`❌ ${relativePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
139
|
+
return false;
|
|
140
|
+
} finally {
|
|
141
|
+
console.log('');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function main() {
|
|
146
|
+
// Game classes are registered via the top-level import of dist/src/game.js
|
|
147
|
+
// Make sure to run `pnpm build` first!
|
|
148
|
+
|
|
149
|
+
const projectRoot = getProjectRoot();
|
|
150
|
+
const assetsFolder = path.join(projectRoot, 'assets');
|
|
151
|
+
console.log(`📁 Scanning for scene and prefab files in: ${assetsFolder}\n`);
|
|
152
|
+
|
|
153
|
+
// Find all scene and prefab files in the assets folder
|
|
154
|
+
const files = findScenesAndPrefabs(assetsFolder);
|
|
155
|
+
|
|
156
|
+
if (files.length === 0) {
|
|
157
|
+
console.log('⚠️ No scene or prefab files found.');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const prefabFiles = files.filter(f => f.type === 'prefab');
|
|
162
|
+
const sceneFiles = files.filter(f => f.type === 'scene');
|
|
163
|
+
console.log(`Found ${files.length} files to migrate:`);
|
|
164
|
+
console.log(` - ${prefabFiles.length} prefab file(s)`);
|
|
165
|
+
console.log(` - ${sceneFiles.length} scene file(s)\n`);
|
|
166
|
+
|
|
167
|
+
let successCount = 0;
|
|
168
|
+
let failCount = 0;
|
|
169
|
+
|
|
170
|
+
// Migrate prefabs first
|
|
171
|
+
if (prefabFiles.length > 0) {
|
|
172
|
+
console.log('📦 Migrating prefabs...\n');
|
|
173
|
+
for (const fileInfo of prefabFiles) {
|
|
174
|
+
const success = await migrateFile(fileInfo);
|
|
175
|
+
if (success) {
|
|
176
|
+
successCount++;
|
|
177
|
+
} else {
|
|
178
|
+
failCount++;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Then migrate scenes
|
|
184
|
+
if (sceneFiles.length > 0) {
|
|
185
|
+
console.log('\n🌍 Migrating scenes...\n');
|
|
186
|
+
for (const fileInfo of sceneFiles) {
|
|
187
|
+
const success = await migrateFile(fileInfo);
|
|
188
|
+
if (success) {
|
|
189
|
+
successCount++;
|
|
190
|
+
} else {
|
|
191
|
+
failCount++;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
197
|
+
console.log('Migration Summary:');
|
|
198
|
+
console.log(` Total files: ${files.length}`);
|
|
199
|
+
console.log(` Successful: ${successCount}`);
|
|
200
|
+
console.log(` Failed: ${failCount}`);
|
|
201
|
+
console.log(`${'='.repeat(60)}`);
|
|
202
|
+
|
|
203
|
+
if (failCount > 0) {
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
main().catch((error) => {
|
|
209
|
+
console.error('Unexpected error:', error);
|
|
210
|
+
console.error('Stack trace:', error.stack);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
});
|
|
@@ -17,14 +17,23 @@ async function main() {
|
|
|
17
17
|
|
|
18
18
|
const foldersToCopy: string[] = [
|
|
19
19
|
'games/examples',
|
|
20
|
-
'src'
|
|
21
|
-
'docs',
|
|
20
|
+
'src'
|
|
22
21
|
];
|
|
23
22
|
for (const folder of foldersToCopy) {
|
|
24
23
|
const engineFolderPath = path.join(engineInstallFolder, folder);
|
|
25
24
|
const localFolderPath = path.join(copiedEngineFolder, folder);
|
|
26
25
|
fs.cpSync(engineFolderPath, localFolderPath, { recursive: true });
|
|
27
26
|
}
|
|
27
|
+
|
|
28
|
+
// copy all *.md files
|
|
29
|
+
const files = fs.readdirSync(engineInstallFolder);
|
|
30
|
+
for (const file of files) {
|
|
31
|
+
if (file.endsWith('.md')) {
|
|
32
|
+
const engineFilePath = path.join(engineInstallFolder, file);
|
|
33
|
+
const localFilePath = path.join(copiedEngineFolder, file);
|
|
34
|
+
fs.copyFileSync(engineFilePath, localFilePath);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
main();
|
|
@@ -19,7 +19,7 @@ class FirstPersonGame extends ENGINE.BaseGameLoop {
|
|
|
19
19
|
const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
|
|
20
20
|
|
|
21
21
|
// now create the pawn
|
|
22
|
-
this.pawn =
|
|
22
|
+
this.pawn = FirstPersonPlayer.create({ position });
|
|
23
23
|
|
|
24
24
|
// create the controller and possess the pawn
|
|
25
25
|
this.controller = new ENGINE.PlayerController();
|
|
@@ -18,16 +18,17 @@ export interface FirstPersonPlayerOptions extends ENGINE.PawnOptions {
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
@ENGINE.GameClass()
|
|
21
|
-
export class FirstPersonPlayer extends ENGINE.Pawn
|
|
21
|
+
export class FirstPersonPlayer extends ENGINE.Pawn {
|
|
22
22
|
// No need to provide rootComponent, movementComponent and camera, they are created internally
|
|
23
|
-
constructor(
|
|
23
|
+
constructor() {
|
|
24
|
+
super();
|
|
24
25
|
// simple camera component - contains a perspective camera by default
|
|
25
26
|
const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR);
|
|
26
27
|
// set proper camera height for first person view
|
|
27
28
|
camera.position.set(0, ENGINE.CHARACTER_HEIGHT * 0.4, 0);
|
|
28
29
|
|
|
29
30
|
// use a simple capsule geometry as the root component
|
|
30
|
-
const rootComponent =
|
|
31
|
+
const rootComponent = ENGINE.MeshComponent.create({
|
|
31
32
|
geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
|
|
32
33
|
material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW }),
|
|
33
34
|
physicsOptions: {
|
|
@@ -40,22 +41,17 @@ export class FirstPersonPlayer extends ENGINE.Pawn<FirstPersonPlayerOptions> {
|
|
|
40
41
|
});
|
|
41
42
|
// hide the mesh in first person view
|
|
42
43
|
rootComponent.getMesh().visible = false;
|
|
44
|
+
this.setRootComponent(rootComponent, true);
|
|
45
|
+
|
|
46
|
+
this.rootComponent.add(camera);
|
|
43
47
|
|
|
44
48
|
// create the movement component
|
|
45
|
-
const movementComponent =
|
|
46
|
-
...ENGINE.CharacterMovementComponent.DEFAULT_OPTIONS,
|
|
49
|
+
const movementComponent = ENGINE.CharacterMovementComponent.create({
|
|
47
50
|
movementType: ENGINE.CharacterMovementType.FirstPerson,
|
|
48
51
|
});
|
|
52
|
+
this.movementComponent = movementComponent;
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
super({
|
|
52
|
-
...options,
|
|
53
|
-
rootComponent,
|
|
54
|
-
movementComponent,
|
|
55
|
-
// make sure the directional light follows the player for consistent shadows
|
|
56
|
-
enableDirectionalLightFollowing: true,
|
|
57
|
-
camera,
|
|
58
|
-
});
|
|
54
|
+
this.enableDirectionalLightFollowing = true;
|
|
59
55
|
|
|
60
56
|
// set the pawn to be transient so it's never saved in the level
|
|
61
57
|
this.setTransient(true);
|
|
@@ -19,7 +19,7 @@ class MyGame extends ENGINE.BaseGameLoop {
|
|
|
19
19
|
const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
|
|
20
20
|
|
|
21
21
|
// now create the pawn
|
|
22
|
-
this.pawn =
|
|
22
|
+
this.pawn = FPSPlayer.create({ position });
|
|
23
23
|
|
|
24
24
|
// create the controller and possess the pawn
|
|
25
25
|
this.controller = new ENGINE.PlayerController();
|
|
@@ -21,9 +21,10 @@ export interface FPSPlayerOptions extends ENGINE.PawnOptions {
|
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
23
|
@ENGINE.GameClass()
|
|
24
|
-
export class FPSPlayer extends ENGINE.Pawn
|
|
24
|
+
export class FPSPlayer extends ENGINE.Pawn {
|
|
25
25
|
// No need to provide rootComponent, movementComponent and camera, they are created internally
|
|
26
|
-
constructor(
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
27
28
|
// simple camera component - contains a perspective camera by default
|
|
28
29
|
const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR);
|
|
29
30
|
// set proper camera height for first person view
|
|
@@ -34,7 +35,7 @@ export class FPSPlayer extends ENGINE.Pawn<FPSPlayerOptions> {
|
|
|
34
35
|
camera.add(weapon);
|
|
35
36
|
|
|
36
37
|
// use a simple capsule geometry as the root component
|
|
37
|
-
const rootComponent =
|
|
38
|
+
const rootComponent = ENGINE.MeshComponent.create({
|
|
38
39
|
geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
|
|
39
40
|
material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW }),
|
|
40
41
|
physicsOptions: {
|
|
@@ -47,21 +48,17 @@ export class FPSPlayer extends ENGINE.Pawn<FPSPlayerOptions> {
|
|
|
47
48
|
});
|
|
48
49
|
// hide the mesh in first person view
|
|
49
50
|
rootComponent.getMesh().visible = false;
|
|
51
|
+
this.setRootComponent(rootComponent, true);
|
|
52
|
+
this.rootComponent.add(camera);
|
|
50
53
|
|
|
51
54
|
// create the movement component
|
|
52
|
-
const movementComponent =
|
|
53
|
-
...ENGINE.CharacterMovementComponent.DEFAULT_OPTIONS,
|
|
55
|
+
const movementComponent = ENGINE.CharacterMovementComponent.create({
|
|
54
56
|
movementType: ENGINE.CharacterMovementType.FirstPerson,
|
|
55
57
|
});
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
movementComponent,
|
|
61
|
-
// make sure the directional light follows the player for consistent shadows
|
|
62
|
-
enableDirectionalLightFollowing: true,
|
|
63
|
-
camera
|
|
64
|
-
});
|
|
59
|
+
this.movementComponent = movementComponent;
|
|
60
|
+
|
|
61
|
+
this.enableDirectionalLightFollowing = true;
|
|
65
62
|
|
|
66
63
|
// set the pawn to be transient so it's never saved in the level
|
|
67
64
|
this.setTransient(true);
|