@needle-tools/engine 3.1.0-alpha.2 → 3.2.0-alpha
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/CHANGELOG.md +14 -0
- package/dist/needle-engine.js +9024 -8814
- package/dist/needle-engine.min.js +264 -264
- package/dist/needle-engine.umd.cjs +266 -266
- package/lib/engine/codegen/register_types.js +2 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_overlay.js +2 -0
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_context_registry.d.ts +2 -0
- package/lib/engine/engine_context_registry.js +3 -0
- package/lib/engine/engine_context_registry.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +2 -0
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_license.js +1 -1
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_lightdata.js +1 -1
- package/lib/engine/engine_lightdata.js.map +1 -1
- package/lib/engine/engine_networking_auto.d.ts +3 -3
- package/lib/engine/engine_networking_auto.js +7 -3
- package/lib/engine/engine_networking_auto.js.map +1 -1
- package/lib/engine/engine_rendererdata.d.ts +1 -0
- package/lib/engine/engine_rendererdata.js +39 -15
- package/lib/engine/engine_rendererdata.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js +10 -1
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +14 -11
- package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_progressive.js +11 -4
- package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -1
- package/lib/engine/extensions/extensions.js +4 -0
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +1 -0
- package/lib/engine-components/AudioSource.js +6 -3
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/Camera.js +1 -1
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +5 -0
- package/lib/engine-components/Renderer.js +64 -17
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RendererLightmap.d.ts +1 -2
- package/lib/engine-components/RendererLightmap.js +8 -10
- package/lib/engine-components/RendererLightmap.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.d.ts +32 -0
- package/lib/engine-components/SceneSwitcher.js +228 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -0
- package/lib/engine-components/ScreenCapture.js +1 -0
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +2 -0
- package/lib/engine-components/VideoPlayer.js +7 -3
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/XRFlag.js +3 -0
- package/lib/engine-components/XRFlag.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.js +0 -2
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.js +9 -3
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/engine/codegen/register_types.js +2 -0
- package/src/engine/debug/debug_overlay.ts +1 -0
- package/src/engine/engine_context_registry.ts +3 -0
- package/src/engine/engine_gltf_builtin_components.ts +3 -0
- package/src/engine/engine_license.ts +1 -1
- package/src/engine/engine_lightdata.ts +1 -1
- package/src/engine/engine_networking_auto.ts +13 -6
- package/src/engine/engine_rendererdata.ts +35 -16
- package/src/engine/engine_serialization_builtin_serializer.ts +10 -1
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +15 -13
- package/src/engine/extensions/NEEDLE_lightmaps.ts +3 -2
- package/src/engine/extensions/NEEDLE_progressive.ts +9 -3
- package/src/engine/extensions/extensions.ts +6 -0
- package/src/engine-components/AudioSource.ts +6 -3
- package/src/engine-components/Camera.ts +1 -1
- package/src/engine-components/Component.ts +0 -1
- package/src/engine-components/Renderer.ts +69 -20
- package/src/engine-components/RendererLightmap.ts +7 -11
- package/src/engine-components/SceneSwitcher.ts +224 -0
- package/src/engine-components/ScreenCapture.ts +1 -0
- package/src/engine-components/VideoPlayer.ts +16 -11
- package/src/engine-components/XRFlag.ts +3 -0
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/timeline/PlayableDirector.ts +0 -1
- package/src/engine-components/timeline/TimelineTracks.ts +9 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-alpha",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in",
|
|
5
5
|
"main": "dist/needle-engine.umd.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -119,6 +119,7 @@ import { RGBAColor } from "../../engine-components/js-extensions/RGBAColor";
|
|
|
119
119
|
import { Rigidbody } from "../../engine-components/RigidBody";
|
|
120
120
|
import { RotationBySpeedModule } from "../../engine-components/ParticleSystemModules";
|
|
121
121
|
import { RotationOverLifetimeModule } from "../../engine-components/ParticleSystemModules";
|
|
122
|
+
import { SceneSwitcher } from "../../engine-components/SceneSwitcher";
|
|
122
123
|
import { ScreenCapture } from "../../engine-components/ScreenCapture";
|
|
123
124
|
import { ScreenSpaceAmbientOcclusion } from "../../engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion";
|
|
124
125
|
import { ShadowCatcher } from "../../engine-components/ShadowCatcher";
|
|
@@ -303,6 +304,7 @@ TypeStore.add("RGBAColor", RGBAColor);
|
|
|
303
304
|
TypeStore.add("Rigidbody", Rigidbody);
|
|
304
305
|
TypeStore.add("RotationBySpeedModule", RotationBySpeedModule);
|
|
305
306
|
TypeStore.add("RotationOverLifetimeModule", RotationOverLifetimeModule);
|
|
307
|
+
TypeStore.add("SceneSwitcher", SceneSwitcher);
|
|
306
308
|
TypeStore.add("ScreenCapture", ScreenCapture);
|
|
307
309
|
TypeStore.add("ScreenSpaceAmbientOcclusion", ScreenSpaceAmbientOcclusion);
|
|
308
310
|
TypeStore.add("ShadowCatcher", ShadowCatcher);
|
|
@@ -24,6 +24,7 @@ export function getErrorCount() {
|
|
|
24
24
|
export function makeErrorsVisibleForDevelopment() {
|
|
25
25
|
if (hide) return;
|
|
26
26
|
const isLocal = isLocalNetwork();
|
|
27
|
+
if(debug) console.log("Is this a local network?", isLocal);
|
|
27
28
|
if (isLocal) {
|
|
28
29
|
if (debug)
|
|
29
30
|
console.log(window.location.hostname);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { IContext } from "./engine_types";
|
|
2
2
|
|
|
3
3
|
export enum ContextEvent {
|
|
4
|
+
/** called when the context is registered to the registry, the context is not fully initialized at this point */
|
|
5
|
+
ContextRegistered = "ContextRegistered",
|
|
4
6
|
ContextCreated = "ContextCreated",
|
|
5
7
|
ContextDestroyed = "ContextDestroyed",
|
|
6
8
|
MissingCamera = "MissingCamera",
|
|
@@ -26,6 +28,7 @@ export class ContextRegistry {
|
|
|
26
28
|
|
|
27
29
|
static register(ctx: IContext) {
|
|
28
30
|
this.Registered.push(ctx);
|
|
31
|
+
this.dispatchCallback(ContextEvent.ContextRegistered, ctx);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
static unregister(ctx: IContext) {
|
|
@@ -50,6 +50,9 @@ export async function createBuiltinComponents(context: Context, gltfId: SourceId
|
|
|
50
50
|
idProvider = new InstantiateIdProvider(seed as number);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
const idEnd = gltfId.indexOf("?");
|
|
54
|
+
gltfId = idEnd === -1 ? gltfId : gltfId.substring(0, idEnd);
|
|
55
|
+
|
|
53
56
|
const serializationContext = new SerializationContext(gltf.scene);
|
|
54
57
|
serializationContext.gltfId = gltfId;
|
|
55
58
|
serializationContext.context = context;
|
|
@@ -33,7 +33,7 @@ export class LightDataRegistry implements ILightDataRegistry {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
registerTexture(sourceId: SourceIdentifier, type: LightmapType, tex: Texture, index: number) {
|
|
36
|
-
if (debugLightmap) console.log("Registering ", LightmapType[type], tex
|
|
36
|
+
if (debugLightmap) console.log("Registering ", LightmapType[type] + " \"" + sourceId + "\"", tex);
|
|
37
37
|
if (!this._lightmaps.has(sourceId))
|
|
38
38
|
this._lightmaps.set(sourceId, new Map());
|
|
39
39
|
const map = this._lightmaps.get(sourceId);
|
|
@@ -200,21 +200,28 @@ export declare type SyncFieldOptions = {
|
|
|
200
200
|
onPropertyChanged: Function,
|
|
201
201
|
};
|
|
202
202
|
|
|
203
|
+
export declare type FieldChangedCallbackFn = (newValue: any, previousValue: any) => void | boolean;
|
|
204
|
+
|
|
203
205
|
/**
|
|
204
206
|
* Decorate a field to be automatically networked synced
|
|
205
|
-
* @param onFieldChanged name of a callback function that will be called when the field is changed.
|
|
206
|
-
*
|
|
207
|
+
* @param onFieldChanged name of a callback function that will be called when the field is changed.
|
|
208
|
+
* You can also pass in a function like so: syncField(myClass.prototype.myFunctionToBeCalled)
|
|
209
|
+
* This function may return false to prevent notifyChanged from being called
|
|
207
210
|
* (for example a networked color is sent as a number and may be converted to a color in the receiver again)
|
|
208
|
-
*
|
|
209
211
|
* Parameters: (newValue, previousValue)
|
|
210
|
-
* @returns
|
|
211
212
|
*/
|
|
212
|
-
export const syncField = function
|
|
213
|
+
export const syncField = function(onFieldChanged: string | FieldChangedCallbackFn) {
|
|
213
214
|
|
|
214
215
|
return function (target: any, propertyKey: string) {
|
|
215
216
|
|
|
216
217
|
let syncer: ComponentPropertiesSyncer | null = null;
|
|
217
|
-
|
|
218
|
+
|
|
219
|
+
let fn: Function | undefined = undefined;
|
|
220
|
+
if (typeof onFieldChanged === "string")
|
|
221
|
+
fn = target[onFieldChanged];
|
|
222
|
+
else if (typeof onFieldChanged === "function") {
|
|
223
|
+
fn = onFieldChanged;
|
|
224
|
+
}
|
|
218
225
|
|
|
219
226
|
const t = target;
|
|
220
227
|
const internalAwake = t.__internalAwake;
|
|
@@ -36,7 +36,8 @@ export class RendererData {
|
|
|
36
36
|
this.context.pre_update_callbacks.push(this.preUpdate.bind(this))
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
private
|
|
39
|
+
private _currentReflectionId?: SourceIdentifier;
|
|
40
|
+
private sceneLightSettings?: Map<SourceIdentifier, SceneLightSettings>;
|
|
40
41
|
|
|
41
42
|
private preUpdate() {
|
|
42
43
|
const time = this.context.time;
|
|
@@ -53,14 +54,26 @@ export class RendererData {
|
|
|
53
54
|
|
|
54
55
|
get environmentIntensity(): number {
|
|
55
56
|
if (!this.sceneLightSettings) return 1;
|
|
56
|
-
|
|
57
|
+
if (!this._currentReflectionId) return 1;
|
|
58
|
+
const settings = this.sceneLightSettings.get(this._currentReflectionId);
|
|
59
|
+
if(settings)
|
|
60
|
+
return settings.ambientIntensity;// * Math.PI * .5;
|
|
61
|
+
return 1;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
registerSceneLightSettings(sceneLightSettings: SceneLightSettings) {
|
|
60
|
-
|
|
65
|
+
const sourceId = sceneLightSettings.sourceId;
|
|
66
|
+
if(!sourceId){
|
|
67
|
+
console.error("Missing source id for scene light settings, can not register:", sceneLightSettings);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (debug) console.log("Register lighting settings", sceneLightSettings?.sourceId, sceneLightSettings);
|
|
71
|
+
if (!this.sceneLightSettings) this.sceneLightSettings = new Map();
|
|
72
|
+
this.sceneLightSettings.set(sourceId, sceneLightSettings);
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
registerReflection(sourceId: SourceIdentifier, reflectionTexture: Texture) {
|
|
76
|
+
if (debug) console.log("Register reflection", sourceId, reflectionTexture);
|
|
64
77
|
const h = new LightData(this.context, reflectionTexture, 1);
|
|
65
78
|
this._lighting[sourceId] = h;
|
|
66
79
|
}
|
|
@@ -70,16 +83,21 @@ export class RendererData {
|
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
enableReflection(sourceId: SourceIdentifier) {
|
|
86
|
+
const previousId = this._currentReflectionId;
|
|
87
|
+
this._currentReflectionId = sourceId;
|
|
88
|
+
const settings = this.sceneLightSettings?.get(sourceId);
|
|
89
|
+
|
|
73
90
|
if (debug) {
|
|
74
|
-
console.log(
|
|
91
|
+
console.log("Enable reflection", sourceId, settings ? AmbientMode[settings.ambientMode] : "Unknown ambient mode");
|
|
75
92
|
}
|
|
76
93
|
|
|
77
|
-
switch (
|
|
94
|
+
switch (settings?.ambientMode) {
|
|
78
95
|
case AmbientMode.Skybox:
|
|
79
96
|
case AmbientMode.Custom:
|
|
80
97
|
// only set environment reflection when ambient mode is skybox or custom
|
|
81
98
|
const existing = this.getReflection(sourceId);
|
|
82
99
|
if (existing && existing.Source) {
|
|
100
|
+
if (debug) console.log("Setting environment reflection", existing.Source);
|
|
83
101
|
const scene = this.context.scene;
|
|
84
102
|
const tex = existing.Source;
|
|
85
103
|
tex.encoding = sRGBEncoding;
|
|
@@ -87,29 +105,30 @@ export class RendererData {
|
|
|
87
105
|
scene.environment = tex;
|
|
88
106
|
return;
|
|
89
107
|
}
|
|
108
|
+
else if (debug) console.warn("Could not find reflection for source", sourceId);
|
|
90
109
|
break;
|
|
91
110
|
}
|
|
92
111
|
|
|
93
|
-
if (
|
|
94
|
-
switch (
|
|
112
|
+
if (settings?.environmentReflectionSource === DefaultReflectionMode.Custom) {
|
|
113
|
+
switch (settings?.ambientMode) {
|
|
95
114
|
case AmbientMode.Trilight:
|
|
96
|
-
if (
|
|
97
|
-
const colors =
|
|
115
|
+
if (settings.ambientTrilight) {
|
|
116
|
+
const colors = settings.ambientTrilight;
|
|
98
117
|
const tex = createTrilightTexture(colors[0], colors[1], colors[2], 64, 64);
|
|
99
118
|
tex.encoding = sRGBEncoding;
|
|
100
119
|
tex.mapping = EquirectangularReflectionMapping;
|
|
101
120
|
this.context.scene.environment = tex;
|
|
102
121
|
}
|
|
103
|
-
else console.error("Missing ambient trilight",
|
|
122
|
+
else console.error("Missing ambient trilight", settings.sourceId);
|
|
104
123
|
return;
|
|
105
124
|
case AmbientMode.Flat:
|
|
106
|
-
if (
|
|
107
|
-
const tex = createFlatTexture(
|
|
125
|
+
if (settings.ambientLight) {
|
|
126
|
+
const tex = createFlatTexture(settings.ambientLight, 64);
|
|
108
127
|
tex.encoding = sRGBEncoding;
|
|
109
128
|
tex.mapping = EquirectangularReflectionMapping;
|
|
110
129
|
this.context.scene.environment = tex;
|
|
111
130
|
}
|
|
112
|
-
else console.error("Missing ambientlight",
|
|
131
|
+
else console.error("Missing ambientlight", settings.sourceId);
|
|
113
132
|
return;
|
|
114
133
|
default:
|
|
115
134
|
return;
|
|
@@ -124,7 +143,7 @@ export class RendererData {
|
|
|
124
143
|
|
|
125
144
|
async getSceneLightingData(sourceId: SourceIdentifier): Promise<SphericalHarmonicsData> {
|
|
126
145
|
if (debug)
|
|
127
|
-
console.log("GET SCENE LIGHT DATA");
|
|
146
|
+
console.log("GET SCENE LIGHT DATA", sourceId);
|
|
128
147
|
|
|
129
148
|
// const existing = this.getReflection(sourceId);
|
|
130
149
|
// const sh = existing?.getSphericalHarmonicsArray(this.sceneLightSettings?.ambientIntensity ?? 1);
|
|
@@ -140,7 +159,7 @@ export class RendererData {
|
|
|
140
159
|
const ex = this.getReflection(sourceId);
|
|
141
160
|
if (ex) {
|
|
142
161
|
clearInterval(interval);
|
|
143
|
-
res(ex.getSphericalHarmonicsArray(this.
|
|
162
|
+
res(ex.getSphericalHarmonicsArray(this.environmentIntensity ?? 1)!);
|
|
144
163
|
}
|
|
145
164
|
}, 10);
|
|
146
165
|
});
|
|
@@ -181,7 +200,7 @@ export class LightData {
|
|
|
181
200
|
const reflection = this._source;
|
|
182
201
|
let rt: THREE.WebGLCubeRenderTarget | null = null;
|
|
183
202
|
if (reflection) {
|
|
184
|
-
if (debug) console.log("GENERATING LIGHT PROBE", reflection);
|
|
203
|
+
if (debug) console.log("GENERATING LIGHT PROBE", reflection, this.Source);
|
|
185
204
|
const size = Math.min(reflection.image.width, 512);
|
|
186
205
|
const target = new WebGLCubeRenderTarget(size);
|
|
187
206
|
rt = target.fromEquirectangularTexture(this._context.renderer, reflection);
|
|
@@ -240,7 +240,16 @@ class EventListSerializer extends TypeSerializer {
|
|
|
240
240
|
}
|
|
241
241
|
const hasMethod = call.method?.length > 0;
|
|
242
242
|
if (target && hasMethod) {
|
|
243
|
-
const printWarningMethodNotFound = () =>
|
|
243
|
+
const printWarningMethodNotFound = () => {
|
|
244
|
+
const uppercaseMethodName = call.method[0].toLowerCase() + call.method.slice(1);
|
|
245
|
+
if (typeof target[uppercaseMethodName] === "function") {
|
|
246
|
+
console.warn(`Could not find method ${call.method} on object ${target.name}. Please rename ${call.method} to ${uppercaseMethodName}?`, target, typeof target[call.method]);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
console.warn(`Could not find method ${call.method} on object ${target.name}`, target, typeof target[call.method]);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
244
253
|
const method = target[call.method];
|
|
245
254
|
if (typeof method !== "function") {
|
|
246
255
|
let foundMethod = false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AmbientLight, Color, HemisphereLight } from "three";
|
|
1
|
+
import { AmbientLight, Color, HemisphereLight, Object3D } from "three";
|
|
2
2
|
import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader";
|
|
3
3
|
import { SourceIdentifier } from "../engine_types";
|
|
4
4
|
import { Behaviour, GameObject } from "../../engine-components/Component";
|
|
@@ -42,9 +42,12 @@ export class NEEDLE_lighting_settings implements GLTFLoaderPlugin {
|
|
|
42
42
|
const ext: LightingSettings = extensions[EXTENSION_NAME];
|
|
43
43
|
if (ext) {
|
|
44
44
|
if (debug)
|
|
45
|
-
console.log(ext);
|
|
45
|
+
console.log("Apply \"" + this.name + "\", src: \"" + this.sourceId + "\"", ext);
|
|
46
46
|
// add a component to the root of the scene
|
|
47
|
-
const
|
|
47
|
+
const lightSettings = new Object3D();
|
|
48
|
+
lightSettings.name = "Needle LightSettings";
|
|
49
|
+
_result.scene.add(lightSettings);
|
|
50
|
+
const settings = GameObject.addNewComponent(lightSettings, SceneLightSettings, false);
|
|
48
51
|
settings.sourceId = this.sourceId;
|
|
49
52
|
settings.ambientIntensity = ext.ambientIntensity;
|
|
50
53
|
settings.ambientLight = new Color().fromArray(ext.ambientLight);
|
|
@@ -98,12 +101,11 @@ export class SceneLightSettings extends Behaviour {
|
|
|
98
101
|
|
|
99
102
|
onEnable() {
|
|
100
103
|
const isActive = this.context.mainCameraComponent?.sourceId === this.sourceId;
|
|
101
|
-
if (debug)
|
|
102
|
-
console.log("Enable scene lighting", this.sourceId, isActive, this, this.context.mainCameraComponent?.sourceId);
|
|
104
|
+
if (debug) console.log("Enable scene lighting", this.sourceId, isActive, this, this.context.mainCameraComponent?.sourceId);
|
|
103
105
|
if (!isActive) {
|
|
104
|
-
if(debug) console.warn("This is
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
if(debug) console.warn("This environment light is not active??!", this.context.mainCameraComponent?.sourceId)
|
|
107
|
+
this.enabled = false;
|
|
108
|
+
return;
|
|
107
109
|
}
|
|
108
110
|
if (this.ambientMode == AmbientMode.Flat) {
|
|
109
111
|
if (this.ambientLight && !this._ambientLightObj) {
|
|
@@ -130,19 +132,19 @@ export class SceneLightSettings extends Behaviour {
|
|
|
130
132
|
if (!this._lightProbeObj) {
|
|
131
133
|
if (this.sourceId) {
|
|
132
134
|
this.context.rendererData.getSceneLightingData(this.sourceId).then(data => {
|
|
133
|
-
if (debug)
|
|
134
|
-
console.log(data);
|
|
135
135
|
if (!data) return;
|
|
136
136
|
this._lightProbeObj = data.lightProbe;
|
|
137
137
|
if (this.enabled && !this.destroyed && this._lightProbeObj) {
|
|
138
|
-
|
|
138
|
+
if (debug)
|
|
139
|
+
console.log("Add", this.sourceId, data);
|
|
140
|
+
this.gameObject.add(this._lightProbeObj);
|
|
139
141
|
}
|
|
140
142
|
});
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
145
|
else {
|
|
144
146
|
if (this.enabled && this.destroyed && this._lightProbeObj) {
|
|
145
|
-
this.
|
|
147
|
+
this.gameObject.add(this._lightProbeObj);
|
|
146
148
|
}
|
|
147
149
|
}
|
|
148
150
|
}
|
|
@@ -154,7 +156,7 @@ export class SceneLightSettings extends Behaviour {
|
|
|
154
156
|
|
|
155
157
|
onDisable() {
|
|
156
158
|
if (debug)
|
|
157
|
-
console.log("
|
|
159
|
+
console.log("Disable envlight:", this.sourceId, this);
|
|
158
160
|
if (this._lightProbeObj) this._lightProbeObj.removeFromParent();
|
|
159
161
|
if(this._ambientLightObj) this._ambientLightObj.removeFromParent();
|
|
160
162
|
if (this.sourceId)
|
|
@@ -58,6 +58,7 @@ export class NEEDLE_lightmaps implements GLTFLoaderPlugin {
|
|
|
58
58
|
console.log(ext);
|
|
59
59
|
|
|
60
60
|
return new Promise(async (res, _rej) => {
|
|
61
|
+
|
|
61
62
|
const dependencies: Array<Promise<any>> = [];
|
|
62
63
|
for (const entry of arr) {
|
|
63
64
|
if (entry.pointer) {
|
|
@@ -70,10 +71,10 @@ export class NEEDLE_lightmaps implements GLTFLoaderPlugin {
|
|
|
70
71
|
// TODO this is most likely wrong for floating point textures
|
|
71
72
|
if (entry.type !== LightmapType.Lightmap)
|
|
72
73
|
tex.encoding = sRGBEncoding;
|
|
73
|
-
else
|
|
74
|
+
else
|
|
74
75
|
tex.encoding = LinearEncoding;
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
|
|
77
78
|
// Dont flip skybox textures anymore - previously we exported them flipped when baking in Unity but now we allow to pass through export without re-baking exisitng skybox textures if they use default values. So we expect textures to be NOT flipped anymore
|
|
78
79
|
// if (entry.type === LightmapType.Skybox) {
|
|
79
80
|
// if (tex.type == FloatType || tex.type == HalfFloatType)
|
|
@@ -138,10 +138,16 @@ export class NEEDLE_progressive implements GLTFLoaderPlugin {
|
|
|
138
138
|
}
|
|
139
139
|
const resolveKey = uri + "_" + progressiveInfo.guid;
|
|
140
140
|
if (this.resolved[resolveKey]) {
|
|
141
|
-
if (debug) console.log("Texture has already been loaded: " + resolveKey, material.name, slot, current.name);
|
|
142
141
|
let res = this.resolved[resolveKey];
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
// check if the texture has been disposed or not
|
|
143
|
+
if (res.image && res.image.data) {
|
|
144
|
+
if (debug) console.log("Texture has already been loaded: " + resolveKey, material.name, slot, current.name, res);
|
|
145
|
+
res = this.copySettings(current, res);
|
|
146
|
+
return res;
|
|
147
|
+
}
|
|
148
|
+
else if (res) {
|
|
149
|
+
if(debug) console.log("Texture has been disposed, will load again: " + resolveKey, material.name, slot, current.name, res);
|
|
150
|
+
}
|
|
145
151
|
}
|
|
146
152
|
|
|
147
153
|
const info = this.onProgressiveLoadStart(context, source, uri, material, slot);
|
|
@@ -51,6 +51,12 @@ class PointerResolver {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export function registerExtensions(loader: GLTFLoader, context: Context, sourceId: SourceIdentifier) {
|
|
54
|
+
|
|
55
|
+
// Make sure to remove any url parameters from the sourceId (because the source id in the renderer does not have a ?v=xxx so it will not be able to register the resolved lightmap otherwise)
|
|
56
|
+
const idEnd = sourceId.lastIndexOf("?");
|
|
57
|
+
if (idEnd >= 0) sourceId = sourceId.substring(0, idEnd);
|
|
58
|
+
|
|
59
|
+
|
|
54
60
|
loader.register(p => new NEEDLE_gameobject_data(p));
|
|
55
61
|
loader.register(p => new NEEDLE_persistent_assets(p));
|
|
56
62
|
loader.register(p => new NEEDLE_lightmaps(p, context.lightmaps, sourceId));
|
|
@@ -143,6 +143,7 @@ export class AudioSource extends Behaviour {
|
|
|
143
143
|
@serializable()
|
|
144
144
|
rollOffMode: AudioRolloffMode = 0;
|
|
145
145
|
|
|
146
|
+
playInBackground: boolean = true;
|
|
146
147
|
|
|
147
148
|
private _loop: boolean = false;
|
|
148
149
|
private sound: THREE.PositionalAudio | null = null;
|
|
@@ -196,9 +197,11 @@ export class AudioSource extends Behaviour {
|
|
|
196
197
|
private onVisibilityChanged = () => {
|
|
197
198
|
switch (document.visibilityState) {
|
|
198
199
|
case "hidden":
|
|
199
|
-
this.
|
|
200
|
-
|
|
201
|
-
this.
|
|
200
|
+
if (this.playInBackground === false) {
|
|
201
|
+
this.wasPlaying = this.isPlaying;
|
|
202
|
+
if (this.isPlaying) {
|
|
203
|
+
this.pause();
|
|
204
|
+
}
|
|
202
205
|
}
|
|
203
206
|
break;
|
|
204
207
|
case "visible":
|
|
@@ -390,7 +390,7 @@ class CameraSkybox {
|
|
|
390
390
|
enable() {
|
|
391
391
|
this._skybox = this.context.lightmaps.tryGetSkybox(this._camera.sourceId) as THREE.Texture;
|
|
392
392
|
if (!this._skybox) {
|
|
393
|
-
console.warn("Failed to load/find skybox texture", this);
|
|
393
|
+
console.warn("Failed to load/find skybox texture", this._camera.sourceId, this.context.lightmaps);
|
|
394
394
|
}
|
|
395
395
|
else if (this.context.scene.background !== this._skybox) {
|
|
396
396
|
if (debug)
|
|
@@ -9,7 +9,6 @@ import { syncDestroy, syncInstantiate } from "../engine/engine_networking_instan
|
|
|
9
9
|
import { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap, UIDProvider, Collision, ICollider } from "../engine/engine_types";
|
|
10
10
|
import { addNewComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, moveComponentInstance, removeComponent } from "../engine/engine_components";
|
|
11
11
|
import { findByGuid, destroy, InstantiateOptions, instantiate, HideFlags, foreachComponent, markAsInstancedRendered, isActiveInHierarchy, isActiveSelf, isUsingInstancing, setActive, isDestroyed } from "../engine/engine_gameobject";
|
|
12
|
-
import { resolveUrl } from "../engine/engine_utils";
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
// export interface ISerializationCallbackReceiver {
|
|
@@ -59,6 +59,18 @@ class SharedMaterialArray implements ISharedMaterials {
|
|
|
59
59
|
private _indexMapMaxIndex?: number;
|
|
60
60
|
private _indexMap?: Map<number, number>;
|
|
61
61
|
|
|
62
|
+
private _changed: boolean = false;
|
|
63
|
+
get changed(): boolean {
|
|
64
|
+
return this._changed;
|
|
65
|
+
}
|
|
66
|
+
set changed(value: boolean) {
|
|
67
|
+
if (value === true) {
|
|
68
|
+
if (debugRenderer)
|
|
69
|
+
console.warn("SharedMaterials have changed: " + this._renderer.name, this);
|
|
70
|
+
}
|
|
71
|
+
this._changed = value;
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
is(renderer: Renderer) {
|
|
63
75
|
return this._renderer === renderer;
|
|
64
76
|
}
|
|
@@ -131,7 +143,12 @@ class SharedMaterialArray implements ISharedMaterials {
|
|
|
131
143
|
if (typeof key === "string")
|
|
132
144
|
setMaterial(value, Number.parseInt(key));
|
|
133
145
|
// console.log(target, key, value);
|
|
134
|
-
|
|
146
|
+
if (Reflect.set(target, key, value)) {
|
|
147
|
+
if (value instanceof Material)
|
|
148
|
+
target.changed = true;
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
135
152
|
}
|
|
136
153
|
});
|
|
137
154
|
}
|
|
@@ -141,6 +158,13 @@ class SharedMaterialArray implements ISharedMaterials {
|
|
|
141
158
|
return this._targets.length;
|
|
142
159
|
}
|
|
143
160
|
|
|
161
|
+
// iterator to support: for(const mat of sharedMaterials)
|
|
162
|
+
*[Symbol.iterator]() {
|
|
163
|
+
for (let i = 0; i < this.length; i++) {
|
|
164
|
+
yield this.getMaterial(i);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
144
168
|
private resolveIndex(index: number): number {
|
|
145
169
|
const map = this._indexMap;
|
|
146
170
|
// if we have a index map it means that some materials were missing
|
|
@@ -157,6 +181,7 @@ class SharedMaterialArray implements ISharedMaterials {
|
|
|
157
181
|
const target = this._targets[index];
|
|
158
182
|
if (!target || target["material"] === undefined) return;
|
|
159
183
|
target["material"] = mat;
|
|
184
|
+
this.changed = true;
|
|
160
185
|
}
|
|
161
186
|
|
|
162
187
|
private getMaterial(index: number) {
|
|
@@ -231,7 +256,10 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
231
256
|
}
|
|
232
257
|
|
|
233
258
|
set sharedMaterial(mat: THREE.Material) {
|
|
259
|
+
const cur = this.sharedMaterials[0];
|
|
260
|
+
if (cur === mat) return;
|
|
234
261
|
this.sharedMaterials[0] = mat;
|
|
262
|
+
this.applyLightmapping();
|
|
235
263
|
}
|
|
236
264
|
|
|
237
265
|
/**@deprecated please use sharedMaterial */
|
|
@@ -241,7 +269,7 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
241
269
|
|
|
242
270
|
/**@deprecated please use sharedMaterial */
|
|
243
271
|
set material(mat: THREE.Material) {
|
|
244
|
-
this.
|
|
272
|
+
this.sharedMaterial = mat;
|
|
245
273
|
}
|
|
246
274
|
|
|
247
275
|
private _sharedMaterials!: SharedMaterialArray;
|
|
@@ -323,7 +351,6 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
323
351
|
|
|
324
352
|
this._reflectionProbe = null;
|
|
325
353
|
|
|
326
|
-
const type = this.gameObject.type;
|
|
327
354
|
if (this.isMultiMaterialObject(this.gameObject)) {
|
|
328
355
|
for (const child of this.gameObject.children) {
|
|
329
356
|
this.context.addBeforeRenderListener(child, this.onBeforeRenderThree.bind(this));
|
|
@@ -359,20 +386,39 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
359
386
|
this.context.addBeforeRenderListener(this.gameObject, this.onBeforeRenderThree.bind(this));
|
|
360
387
|
}
|
|
361
388
|
|
|
389
|
+
this.applyLightmapping();
|
|
390
|
+
|
|
391
|
+
if (showWireframe) {
|
|
392
|
+
for (let i = 0; i < this.sharedMaterials.length; i++) {
|
|
393
|
+
const mat: any = this.sharedMaterials[i];
|
|
394
|
+
if (mat) {
|
|
395
|
+
mat.wireframe = true;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
private applyLightmapping() {
|
|
362
403
|
if (this.lightmapIndex >= 0) {
|
|
404
|
+
const type = this.gameObject.type;
|
|
405
|
+
|
|
363
406
|
// use the override lightmap if its not undefined
|
|
364
407
|
const tex = this._lightmapTextureOverride !== undefined
|
|
365
408
|
? this._lightmapTextureOverride
|
|
366
409
|
: this.context.lightmaps.tryGetLightmap(this.sourceId, this.lightmapIndex);
|
|
367
410
|
if (tex) {
|
|
368
|
-
|
|
369
|
-
|
|
411
|
+
if (!this._lightmaps)
|
|
412
|
+
this._lightmaps = [];
|
|
370
413
|
|
|
371
414
|
if (type === "Mesh") {
|
|
372
415
|
const mat = this.gameObject["material"];
|
|
373
416
|
if (!mat?.isMeshBasicMaterial) {
|
|
374
|
-
|
|
375
|
-
|
|
417
|
+
if (this._lightmaps.length <= 0) {
|
|
418
|
+
const rm = new RendererLightmap(this.gameObject, this.context);
|
|
419
|
+
this._lightmaps.push(rm);
|
|
420
|
+
}
|
|
421
|
+
const rm = this._lightmaps[0];
|
|
376
422
|
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex, debugLightmap);
|
|
377
423
|
}
|
|
378
424
|
else {
|
|
@@ -383,10 +429,16 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
383
429
|
// for multi materials we need to loop through children
|
|
384
430
|
// and then we add a lightmap renderer component to each of them
|
|
385
431
|
else if (this.isMultiMaterialObject(this.gameObject) && this.sharedMaterials.length > 0) {
|
|
386
|
-
for (
|
|
432
|
+
for (let i = 0; i < this.gameObject.children.length; i++) {
|
|
433
|
+
const child = this.gameObject.children[i];
|
|
387
434
|
if (!child["material"]?.isMeshBasicMaterial) {
|
|
388
|
-
|
|
389
|
-
this._lightmaps.
|
|
435
|
+
let rm: RendererLightmap | undefined = undefined;
|
|
436
|
+
if (i >= this._lightmaps.length) {
|
|
437
|
+
rm = new RendererLightmap(child as GameObject, this.context);
|
|
438
|
+
this._lightmaps.push(rm);
|
|
439
|
+
}
|
|
440
|
+
else
|
|
441
|
+
rm = this._lightmaps[i];
|
|
390
442
|
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex, debugLightmap);
|
|
391
443
|
// onBeforeRender is not called when the renderer is on a group
|
|
392
444
|
// this is an issue we probably also need to handle for custom shaders
|
|
@@ -396,16 +448,8 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
396
448
|
}
|
|
397
449
|
}
|
|
398
450
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
if (showWireframe) {
|
|
404
|
-
for (let i = 0; i < this.sharedMaterials.length; i++) {
|
|
405
|
-
const mat: any = this.sharedMaterials[i];
|
|
406
|
-
if (mat) {
|
|
407
|
-
mat.wireframe = true;
|
|
408
|
-
}
|
|
451
|
+
else {
|
|
452
|
+
if (debug) console.warn("Lightmap not found", this.sourceId, this.lightmapIndex);
|
|
409
453
|
}
|
|
410
454
|
}
|
|
411
455
|
|
|
@@ -518,6 +562,11 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
518
562
|
else {
|
|
519
563
|
this.applySettings(this.gameObject);
|
|
520
564
|
}
|
|
565
|
+
|
|
566
|
+
if (this.sharedMaterials.changed) {
|
|
567
|
+
this.sharedMaterials.changed = false;
|
|
568
|
+
this.applyLightmapping();
|
|
569
|
+
}
|
|
521
570
|
|
|
522
571
|
if (this.handles?.length) {
|
|
523
572
|
// if (this.name === "Darbouka")
|