nova64 0.2.6 โ†’ 0.2.7

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.
Files changed (47) hide show
  1. package/dist/examples/strider-demo-3d/fix-game.sh +0 -0
  2. package/dist/runtime/api-2d.js +1158 -0
  3. package/dist/runtime/api-3d/camera.js +73 -0
  4. package/dist/runtime/api-3d/instancing.js +180 -0
  5. package/dist/runtime/api-3d/lights.js +51 -0
  6. package/dist/runtime/api-3d/materials.js +47 -0
  7. package/dist/runtime/api-3d/models.js +84 -0
  8. package/dist/runtime/api-3d/particles.js +296 -0
  9. package/dist/runtime/api-3d/pbr.js +113 -0
  10. package/dist/runtime/api-3d/primitives.js +304 -0
  11. package/dist/runtime/api-3d/scene.js +169 -0
  12. package/dist/runtime/api-3d/transforms.js +161 -0
  13. package/dist/runtime/api-3d.js +166 -0
  14. package/dist/runtime/api-effects.js +840 -0
  15. package/dist/runtime/api-gameutils.js +476 -0
  16. package/dist/runtime/api-generative.js +610 -0
  17. package/dist/runtime/api-presets.js +85 -0
  18. package/dist/runtime/api-skybox.js +232 -0
  19. package/dist/runtime/api-sprites.js +100 -0
  20. package/dist/runtime/api-voxel.js +712 -0
  21. package/dist/runtime/api.js +201 -0
  22. package/dist/runtime/assets.js +27 -0
  23. package/dist/runtime/audio.js +114 -0
  24. package/dist/runtime/collision.js +47 -0
  25. package/dist/runtime/console.js +101 -0
  26. package/dist/runtime/editor.js +233 -0
  27. package/dist/runtime/font.js +233 -0
  28. package/dist/runtime/framebuffer.js +28 -0
  29. package/dist/runtime/fullscreen-button.js +185 -0
  30. package/dist/runtime/gpu-canvas2d.js +47 -0
  31. package/dist/runtime/gpu-threejs.js +643 -0
  32. package/dist/runtime/gpu-webgl2.js +310 -0
  33. package/dist/runtime/index.d.ts +682 -0
  34. package/dist/runtime/index.js +22 -0
  35. package/dist/runtime/input.js +225 -0
  36. package/dist/runtime/logger.js +60 -0
  37. package/dist/runtime/physics.js +101 -0
  38. package/dist/runtime/screens.js +213 -0
  39. package/dist/runtime/storage.js +38 -0
  40. package/dist/runtime/store.js +151 -0
  41. package/dist/runtime/textinput.js +68 -0
  42. package/dist/runtime/ui/buttons.js +124 -0
  43. package/dist/runtime/ui/panels.js +105 -0
  44. package/dist/runtime/ui/text.js +86 -0
  45. package/dist/runtime/ui/widgets.js +141 -0
  46. package/dist/runtime/ui.js +111 -0
  47. package/package.json +34 -32
@@ -0,0 +1,169 @@
1
+ // runtime/api-3d/scene.js
2
+ // clearScene, setupScene, raycasting, stats, N64 effects
3
+
4
+ import * as THREE from 'three';
5
+ import { logger } from '../logger.js';
6
+
7
+ export function sceneModule(ctx) {
8
+ const {
9
+ scene,
10
+ camera,
11
+ renderer,
12
+ gpu,
13
+ meshes,
14
+ cartLights,
15
+ materialCache,
16
+ instancedMeshes,
17
+ lodObjects,
18
+ } = ctx;
19
+
20
+ // These come from other modules โ€” resolved at call-time via ctx
21
+ function getDisposeMaterial() {
22
+ return ctx.disposeMaterial;
23
+ }
24
+ function getRemoveLight() {
25
+ return ctx.removeLight;
26
+ }
27
+
28
+ function clearScene() {
29
+ const disposeMaterial = getDisposeMaterial();
30
+ const removeLight = getRemoveLight();
31
+
32
+ logger.info(
33
+ '๐Ÿงน Clearing 3D scene... meshes:',
34
+ meshes.size,
35
+ 'lights:',
36
+ cartLights.size,
37
+ 'materials:',
38
+ materialCache.size
39
+ );
40
+
41
+ // Dispose all cart meshes
42
+ for (const [, mesh] of meshes) {
43
+ scene.remove(mesh);
44
+ if (mesh.geometry) mesh.geometry.dispose();
45
+ if (mesh.material) {
46
+ if (Array.isArray(mesh.material)) mesh.material.forEach(disposeMaterial);
47
+ else disposeMaterial(mesh.material);
48
+ }
49
+ }
50
+ meshes.clear();
51
+
52
+ // Remove dynamic lights
53
+ cartLights.forEach((_, id) => removeLight(id));
54
+ cartLights.clear();
55
+
56
+ // Flush material cache
57
+ materialCache.forEach(disposeMaterial);
58
+ materialCache.clear();
59
+
60
+ // Remove any remaining scene children (e.g. from loadModel / direct additions)
61
+ while (scene.children.length > 0) {
62
+ const child = scene.children[0];
63
+ scene.remove(child);
64
+ if (child.geometry) child.geometry.dispose();
65
+ if (child.material) {
66
+ if (Array.isArray(child.material)) child.material.forEach(disposeMaterial);
67
+ else disposeMaterial(child.material);
68
+ }
69
+ }
70
+
71
+ // Re-add minimal default lighting so scenes aren't black
72
+ scene.add(new THREE.AmbientLight(0xffffff, 0.5));
73
+ const dir = new THREE.DirectionalLight(0xffffff, 0.8);
74
+ dir.position.set(5, 10, 7.5);
75
+ scene.add(dir);
76
+
77
+ // Reset animated mesh registry in GPU backend
78
+ if (gpu.clearAnimatedMeshes) gpu.clearAnimatedMeshes();
79
+
80
+ // Dispose instanced meshes
81
+ for (const { mesh } of instancedMeshes.values()) {
82
+ scene.remove(mesh);
83
+ mesh.geometry?.dispose();
84
+ mesh.material?.dispose();
85
+ }
86
+ instancedMeshes.clear();
87
+
88
+ // Dispose LOD objects
89
+ for (const lod of lodObjects.values()) {
90
+ scene.remove(lod);
91
+ for (const { object } of lod.levels) {
92
+ object.geometry?.dispose();
93
+ object.material?.dispose();
94
+ }
95
+ }
96
+ lodObjects.clear();
97
+
98
+ logger.info('โœ… Scene cleared completely');
99
+ }
100
+
101
+ /**
102
+ * setupScene(opts) โ€” One-call scene configuration.
103
+ * opts: { camera, light, fog, skybox, effects }
104
+ */
105
+ function setupScene(opts = {}) {
106
+ const cam = opts.camera ?? {};
107
+ ctx.setCameraPosition(cam.x ?? 0, cam.y ?? 5, cam.z ?? 10);
108
+ ctx.setCameraTarget(cam.targetX ?? 0, cam.targetY ?? 0, cam.targetZ ?? 0);
109
+ if (cam.fov) ctx.setCameraFOV(cam.fov);
110
+
111
+ const light = opts.light ?? {};
112
+ if (light.direction) {
113
+ const d = light.direction;
114
+ ctx.setLightDirection(d[0] ?? -0.3, d[1] ?? -1, d[2] ?? -0.5);
115
+ }
116
+ if (light.color !== undefined) ctx.setLightColor(light.color);
117
+ if (light.ambient !== undefined) ctx.setAmbientLight(light.ambient);
118
+
119
+ if (opts.fog && opts.fog !== false) {
120
+ ctx.setFog(opts.fog.color ?? 0x000000, opts.fog.near ?? 10, opts.fog.far ?? 50);
121
+ }
122
+
123
+ if (opts.skybox && typeof globalThis.createSpaceSkybox === 'function') {
124
+ globalThis.createSpaceSkybox(opts.skybox);
125
+ }
126
+
127
+ if (opts.effects && typeof globalThis.enableRetroEffects === 'function') {
128
+ globalThis.enableRetroEffects(typeof opts.effects === 'object' ? opts.effects : {});
129
+ }
130
+ }
131
+
132
+ function raycastFromCamera(x, y) {
133
+ const raycaster = new THREE.Raycaster();
134
+ const mouse = new THREE.Vector2(
135
+ (x / renderer.domElement.clientWidth) * 2 - 1,
136
+ -(y / renderer.domElement.clientHeight) * 2 + 1
137
+ );
138
+ raycaster.setFromCamera(mouse, camera);
139
+ const objects = Array.from(meshes.values()).filter(m => m.type === 'Mesh');
140
+ const hits = raycaster.intersectObjects(objects);
141
+ if (hits.length > 0) {
142
+ for (const [id, mesh] of meshes) {
143
+ if (mesh === hits[0].object) {
144
+ return { meshId: id, point: hits[0].point, distance: hits[0].distance };
145
+ }
146
+ }
147
+ }
148
+ return null;
149
+ }
150
+
151
+ function get3DStats() {
152
+ return gpu.getStats();
153
+ }
154
+ function enablePixelation(factor = 2) {
155
+ gpu.enablePixelation(factor);
156
+ }
157
+ function enableDithering(enabled = true) {
158
+ gpu.enableDithering(enabled);
159
+ }
160
+
161
+ return {
162
+ clearScene,
163
+ setupScene,
164
+ raycastFromCamera,
165
+ get3DStats,
166
+ enablePixelation,
167
+ enableDithering,
168
+ };
169
+ }
@@ -0,0 +1,161 @@
1
+ // runtime/api-3d/transforms.js
2
+ // Mesh position, rotation, scale, visibility, and shadow controls
3
+
4
+ import { logger } from '../logger.js';
5
+
6
+ export function transformsModule({ getMesh }) {
7
+ function setPosition(meshId, x, y, z) {
8
+ try {
9
+ const mesh = getMesh(meshId);
10
+ if (!mesh) {
11
+ logger.warn(`setPosition: mesh with id ${meshId} not found`);
12
+ return false;
13
+ }
14
+ mesh.position.set(
15
+ typeof x === 'number' ? x : 0,
16
+ typeof y === 'number' ? y : 0,
17
+ typeof z === 'number' ? z : 0
18
+ );
19
+ return true;
20
+ } catch (e) {
21
+ logger.error('setPosition failed:', e);
22
+ return false;
23
+ }
24
+ }
25
+
26
+ function setRotation(meshId, x, y, z) {
27
+ try {
28
+ const mesh = getMesh(meshId);
29
+ if (!mesh) {
30
+ logger.warn(`setRotation: mesh with id ${meshId} not found`);
31
+ return false;
32
+ }
33
+ mesh.rotation.set(
34
+ typeof x === 'number' ? x : 0,
35
+ typeof y === 'number' ? y : 0,
36
+ typeof z === 'number' ? z : 0
37
+ );
38
+ return true;
39
+ } catch (e) {
40
+ logger.error('setRotation failed:', e);
41
+ return false;
42
+ }
43
+ }
44
+
45
+ function setScale(meshId, x, y, z) {
46
+ try {
47
+ const mesh = getMesh(meshId);
48
+ if (!mesh) {
49
+ logger.warn(`setScale: mesh with id ${meshId} not found`);
50
+ return false;
51
+ }
52
+ x = typeof x === 'number' && x > 0 ? x : 1;
53
+ if (typeof y === 'undefined') {
54
+ mesh.scale.setScalar(x);
55
+ } else {
56
+ mesh.scale.set(
57
+ x,
58
+ typeof y === 'number' && y > 0 ? y : 1,
59
+ typeof z === 'number' && z > 0 ? z : 1
60
+ );
61
+ }
62
+ return true;
63
+ } catch (e) {
64
+ logger.error('setScale failed:', e);
65
+ return false;
66
+ }
67
+ }
68
+
69
+ function getPosition(meshId) {
70
+ const mesh = getMesh(meshId);
71
+ return mesh ? [mesh.position.x, mesh.position.y, mesh.position.z] : null;
72
+ }
73
+
74
+ function getRotation(meshId) {
75
+ const mesh = getMesh(meshId);
76
+ return mesh ? [mesh.rotation.x, mesh.rotation.y, mesh.rotation.z] : null;
77
+ }
78
+
79
+ function rotateMesh(meshId, dX, dY, dZ) {
80
+ try {
81
+ const mesh = getMesh(meshId);
82
+ if (!mesh) {
83
+ logger.warn(`rotateMesh: mesh with id ${meshId} not found`);
84
+ return false;
85
+ }
86
+ mesh.rotation.x += typeof dX === 'number' ? dX : 0;
87
+ mesh.rotation.y += typeof dY === 'number' ? dY : 0;
88
+ mesh.rotation.z += typeof dZ === 'number' ? dZ : 0;
89
+ return true;
90
+ } catch (e) {
91
+ logger.error('rotateMesh failed:', e);
92
+ return false;
93
+ }
94
+ }
95
+
96
+ function moveMesh(meshId, x, y, z) {
97
+ const mesh = getMesh(meshId);
98
+ if (mesh) {
99
+ mesh.position.x += x;
100
+ mesh.position.y += y;
101
+ mesh.position.z += z;
102
+ }
103
+ }
104
+
105
+ function setFlatShading(meshId, enabled = true) {
106
+ const mesh = getMesh(meshId);
107
+ if (!mesh) return false;
108
+ if (mesh.material) {
109
+ mesh.material.flatShading = enabled;
110
+ mesh.material.needsUpdate = true;
111
+ }
112
+ return true;
113
+ }
114
+
115
+ function setMeshVisible(meshId, visible) {
116
+ const mesh = getMesh(meshId);
117
+ if (!mesh) return false;
118
+ mesh.visible = visible;
119
+ return true;
120
+ }
121
+
122
+ function setMeshOpacity(meshId, opacity) {
123
+ const mesh = getMesh(meshId);
124
+ if (!mesh) return false;
125
+ if (mesh.material) {
126
+ mesh.material.transparent = opacity < 1;
127
+ mesh.material.opacity = opacity;
128
+ mesh.material.needsUpdate = true;
129
+ }
130
+ return true;
131
+ }
132
+
133
+ function setCastShadow(meshId, cast) {
134
+ const mesh = getMesh(meshId);
135
+ if (!mesh) return false;
136
+ mesh.castShadow = cast;
137
+ return true;
138
+ }
139
+
140
+ function setReceiveShadow(meshId, receive) {
141
+ const mesh = getMesh(meshId);
142
+ if (!mesh) return false;
143
+ mesh.receiveShadow = receive;
144
+ return true;
145
+ }
146
+
147
+ return {
148
+ setPosition,
149
+ setRotation,
150
+ setScale,
151
+ getPosition,
152
+ getRotation,
153
+ rotateMesh,
154
+ moveMesh,
155
+ setFlatShading,
156
+ setMeshVisible,
157
+ setMeshOpacity,
158
+ setCastShadow,
159
+ setReceiveShadow,
160
+ };
161
+ }
@@ -0,0 +1,166 @@
1
+ // runtime/api-3d.js
2
+ // Thin orchestrator โ€” delegates to runtime/api-3d/*.js sub-modules
3
+ import * as THREE from 'three';
4
+ globalThis.THREE = THREE;
5
+ import { materialsModule } from './api-3d/materials.js';
6
+ import { primitivesModule } from './api-3d/primitives.js';
7
+ import { transformsModule } from './api-3d/transforms.js';
8
+ import { cameraModule } from './api-3d/camera.js';
9
+ import { lightsModule } from './api-3d/lights.js';
10
+ import { modelsModule } from './api-3d/models.js';
11
+ import { instancingModule } from './api-3d/instancing.js';
12
+ import { pbrModule } from './api-3d/pbr.js';
13
+ import { sceneModule } from './api-3d/scene.js';
14
+ import { particlesModule } from './api-3d/particles.js';
15
+
16
+ export function threeDApi(gpu) {
17
+ if (!gpu.getScene) return { exposeTo: () => {} };
18
+
19
+ const scene = gpu.getScene();
20
+ const camera = gpu.getCamera();
21
+ const renderer = gpu.getRenderer();
22
+
23
+ // Shared state โ€” passed by reference into every sub-module
24
+ const meshes = new Map();
25
+ const mixers = new Map();
26
+ const modelAnimations = new Map();
27
+ const materialCache = new Map();
28
+ const cartLights = new Map();
29
+ const instancedMeshes = new Map();
30
+ const lodObjects = new Map();
31
+ const counters = { mesh: 0, light: 0, instance: 0, lod: 0 };
32
+
33
+ // Build context โ€” each module appends its exports so later modules can call earlier ones
34
+ const ctx = {
35
+ scene,
36
+ camera,
37
+ renderer,
38
+ gpu,
39
+ meshes,
40
+ mixers,
41
+ modelAnimations,
42
+ materialCache,
43
+ cartLights,
44
+ instancedMeshes,
45
+ lodObjects,
46
+ counters,
47
+ };
48
+
49
+ Object.assign(ctx, materialsModule(ctx));
50
+ Object.assign(ctx, primitivesModule(ctx));
51
+ Object.assign(ctx, transformsModule(ctx));
52
+ Object.assign(ctx, cameraModule(ctx));
53
+ Object.assign(ctx, lightsModule(ctx));
54
+ Object.assign(ctx, modelsModule(ctx));
55
+ Object.assign(ctx, instancingModule(ctx));
56
+ Object.assign(ctx, pbrModule(ctx));
57
+ Object.assign(ctx, particlesModule(ctx));
58
+ Object.assign(ctx, sceneModule(ctx)); // last: uses late binding to call other modules
59
+
60
+ return {
61
+ exposeTo(target) {
62
+ Object.assign(target, {
63
+ // Primitive creation
64
+ createCube: ctx.createCube,
65
+ createSphere: ctx.createSphere,
66
+ createCylinder: ctx.createCylinder,
67
+ createPlane: ctx.createPlane,
68
+ createAdvancedCube: ctx.createAdvancedCube,
69
+ createAdvancedSphere: ctx.createAdvancedSphere,
70
+ createTorus: ctx.createTorus,
71
+ createCone: ctx.createCone,
72
+ createCapsule: ctx.createCapsule,
73
+
74
+ // Mesh management
75
+ destroyMesh: ctx.destroyMesh,
76
+ removeMesh: ctx.removeMesh,
77
+
78
+ // Model and texture loading
79
+ loadModel: ctx.loadModel,
80
+ playAnimation: ctx.playAnimation,
81
+ updateAnimations: ctx.updateAnimations,
82
+ loadTexture: ctx.loadTexture,
83
+
84
+ // Transforms
85
+ setPosition: ctx.setPosition,
86
+ setRotation: ctx.setRotation,
87
+ setScale: ctx.setScale,
88
+ getPosition: ctx.getPosition,
89
+ getRotation: ctx.getRotation,
90
+ rotateMesh: ctx.rotateMesh,
91
+ moveMesh: ctx.moveMesh,
92
+
93
+ // Mesh helpers
94
+ setFlatShading: ctx.setFlatShading,
95
+ setMeshVisible: ctx.setMeshVisible,
96
+ setMeshOpacity: ctx.setMeshOpacity,
97
+ setCastShadow: ctx.setCastShadow,
98
+ setReceiveShadow: ctx.setReceiveShadow,
99
+
100
+ // Camera
101
+ setCameraPosition: ctx.setCameraPosition,
102
+ setCameraTarget: ctx.setCameraTarget,
103
+ setCameraLookAt: ctx.setCameraLookAt,
104
+ setCameraFOV: ctx.setCameraFOV,
105
+
106
+ // Scene / atmosphere
107
+ setFog: ctx.setFog,
108
+ clearFog: ctx.clearFog,
109
+ setLightDirection: ctx.setLightDirection,
110
+ setLightColor: ctx.setLightColor,
111
+ setAmbientLight: ctx.setAmbientLight,
112
+ setDirectionalLight: ctx.setDirectionalLight,
113
+ clearScene: ctx.clearScene,
114
+
115
+ // Effects
116
+ enablePixelation: ctx.enablePixelation,
117
+ enableDithering: ctx.enableDithering,
118
+
119
+ // Dynamic lights
120
+ createPointLight: ctx.createPointLight,
121
+ setPointLightPosition: ctx.setPointLightPosition,
122
+ setPointLightColor: ctx.setPointLightColor,
123
+ removeLight: ctx.removeLight,
124
+
125
+ // GPU instancing
126
+ createInstancedMesh: ctx.createInstancedMesh,
127
+ setInstanceTransform: ctx.setInstanceTransform,
128
+ setInstanceColor: ctx.setInstanceColor,
129
+ finalizeInstances: ctx.finalizeInstances,
130
+ removeInstancedMesh: ctx.removeInstancedMesh,
131
+
132
+ // LOD system
133
+ createLODMesh: ctx.createLODMesh,
134
+ setLODPosition: ctx.setLODPosition,
135
+ removeLODMesh: ctx.removeLODMesh,
136
+ updateLODs: ctx.updateLODs,
137
+
138
+ // Normal / PBR maps
139
+ loadNormalMap: ctx.loadNormalMap,
140
+ setNormalMap: ctx.setNormalMap,
141
+ setPBRMaps: ctx.setPBRMaps,
142
+ setPBRProperties: ctx.setPBRProperties,
143
+
144
+ // GPU particle system
145
+ createParticleSystem: ctx.createParticleSystem,
146
+ setParticleEmitter: ctx.setParticleEmitter,
147
+ emitParticle: ctx.emitParticle,
148
+ burstParticles: ctx.burstParticles,
149
+ updateParticles: ctx.updateParticles,
150
+ removeParticleSystem: ctx.removeParticleSystem,
151
+ getParticleStats: ctx.getParticleStats,
152
+
153
+ // Interaction / stats / convenience
154
+ raycastFromCamera: ctx.raycastFromCamera,
155
+ get3DStats: ctx.get3DStats,
156
+ setupScene: ctx.setupScene,
157
+
158
+ // Direct Three.js access for advanced users
159
+ getScene: () => scene,
160
+ getCamera: () => camera,
161
+ getRenderer: () => renderer,
162
+ getMesh: ctx.getMesh,
163
+ });
164
+ },
165
+ };
166
+ }