@needle-tools/engine 2.67.6-pre → 2.67.8-pre
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 +5787 -5768
- package/dist/needle-engine.umd.cjs +83 -83
- package/lib/engine/engine_context.d.ts +170 -0
- package/lib/engine/engine_context.js +855 -0
- package/lib/engine/engine_context.js.map +1 -0
- package/lib/engine/engine_mainloop_utils.js +4 -1
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_setup.d.ts +1 -166
- package/lib/engine/engine_setup.js +2 -839
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_time.d.ts +2 -0
- package/lib/engine/engine_time.js +4 -1
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/ui/Canvas.d.ts +4 -1
- package/lib/engine-components/ui/Canvas.js +17 -1
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.js +1 -2
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Text.js +4 -0
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/ui/Utils.js +6 -4
- package/lib/engine-components/ui/Utils.js.map +1 -1
- package/package.json +1 -1
- package/plugins/vite/drop.js +1 -0
- package/plugins/vite/editor-connection.js +1 -1
- package/plugins/vite/poster.js +1 -1
- package/plugins/vite/reload.js +1 -1
- package/src/engine/engine_context.ts +957 -0
- package/src/engine/engine_mainloop_utils.ts +4 -2
- package/src/engine/engine_setup.ts +2 -941
- package/src/engine/engine_time.ts +4 -1
- package/src/engine-components/AnimatorController.ts +2 -2
- package/src/engine-components/postprocessing/Volume.ts +213 -213
- package/src/engine-components/ui/Canvas.ts +19 -1
- package/src/engine-components/ui/EventSystem.ts +1 -2
- package/src/engine-components/ui/Text.ts +3 -0
- package/src/engine-components/ui/Utils.ts +6 -4
|
@@ -20,11 +20,13 @@ export class Time {
|
|
|
20
20
|
|
|
21
21
|
get frameCount() { return this.frame; }
|
|
22
22
|
get smoothedFps() { return this._smoothedFps; }
|
|
23
|
+
get smoothedDeltaTime() { return 1 / this._smoothedFps; }
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
private clock = new Clock();
|
|
26
27
|
|
|
27
28
|
private _smoothedFps: number = 0;
|
|
29
|
+
private _smoothedDeltaTime: number = 0;
|
|
28
30
|
private _fpsSamples: number[] = [];
|
|
29
31
|
private _fpsSampleIndex: number = 0;
|
|
30
32
|
|
|
@@ -47,6 +49,7 @@ export class Time {
|
|
|
47
49
|
let sum = 0;
|
|
48
50
|
for (let i = 0; i < this._fpsSamples.length; i++)
|
|
49
51
|
sum += this._fpsSamples[i];
|
|
50
|
-
this.
|
|
52
|
+
this._smoothedDeltaTime = sum / this._fpsSamples.length;
|
|
53
|
+
this._smoothedFps = 1 / this._smoothedDeltaTime;
|
|
51
54
|
}
|
|
52
55
|
}
|
|
@@ -432,9 +432,9 @@ export class AnimatorController {
|
|
|
432
432
|
case AnimatorConditionMode.IfNot:
|
|
433
433
|
return param.value === false;
|
|
434
434
|
case AnimatorConditionMode.Greater:
|
|
435
|
-
return param.value > cond.threshold;
|
|
435
|
+
return param.value as number > cond.threshold;
|
|
436
436
|
case AnimatorConditionMode.Less:
|
|
437
|
-
return param.value < cond.threshold;
|
|
437
|
+
return param.value as number < cond.threshold;
|
|
438
438
|
case AnimatorConditionMode.Equals:
|
|
439
439
|
return param.value === cond.threshold;
|
|
440
440
|
case AnimatorConditionMode.NotEqual:
|
|
@@ -1,213 +1,213 @@
|
|
|
1
|
-
import { Behaviour, GameObject } from "../Component";
|
|
2
|
-
import { serializeable } from "../../engine/engine_serialization_decorator";
|
|
3
|
-
import { getParam } from "../../engine/engine_utils";
|
|
4
|
-
import { VolumeProfile } from "./VolumeProfile";
|
|
5
|
-
import { EditorModification, IEditorModification as IEditorModificationReceiver } from "../../engine/engine_editor-sync";
|
|
6
|
-
import { PostProcessingHandler } from "./PostProcessingHandler";
|
|
7
|
-
import { PostProcessingEffect } from "./PostProcessingEffect";
|
|
8
|
-
import { VolumeParameter } from "./VolumeParameter";
|
|
9
|
-
import { getEditorModificationCache } from "../../engine/engine_editor-sync";
|
|
10
|
-
import { isDevEnvironment } from "../../engine/debug";
|
|
11
|
-
import { EffectComposer } from "postprocessing";
|
|
12
|
-
|
|
13
|
-
const debug = getParam("debugpost");
|
|
14
|
-
|
|
15
|
-
export class Volume extends Behaviour implements IEditorModificationReceiver {
|
|
16
|
-
|
|
17
|
-
@serializeable(VolumeProfile)
|
|
18
|
-
sharedProfile?: VolumeProfile;
|
|
19
|
-
|
|
20
|
-
private _postprocessing?: PostProcessingHandler;
|
|
21
|
-
private _effects: PostProcessingEffect[] = [];
|
|
22
|
-
|
|
23
|
-
awake() {
|
|
24
|
-
// ensure the profile is initialized
|
|
25
|
-
this.sharedProfile?.init();
|
|
26
|
-
|
|
27
|
-
if (debug) {
|
|
28
|
-
console.log(this);
|
|
29
|
-
console.log("Press P to toggle post processing");
|
|
30
|
-
window.addEventListener("keydown", (e) => {
|
|
31
|
-
if (e.key === "p") {
|
|
32
|
-
console.log("Toggle volume: " + this.name, !this.enabled);
|
|
33
|
-
this.enabled = !this.enabled;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
onDisable() {
|
|
40
|
-
this._postprocessing?.unapply();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
onBeforeRender(): void {
|
|
44
|
-
if (!this.context.isInXR) {
|
|
45
|
-
|
|
46
|
-
if (this.context.composer && (this.context.composer instanceof EffectComposer) === false) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Wait for the first frame to be rendered before creating because then we know we have a camera (issue 135)
|
|
51
|
-
if (this.context.mainCamera) {
|
|
52
|
-
if (!this._postprocessing || !this._postprocessing.isActive) {
|
|
53
|
-
this.apply();
|
|
54
|
-
// TODO: remove this workaround for postprocessing rendering not working correctly when applied for the first time
|
|
55
|
-
this.apply();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (this.context.composer) {
|
|
60
|
-
this.context.composer.setRenderer(this.context.renderer);
|
|
61
|
-
this.context.composer.setMainScene(this.context.scene);
|
|
62
|
-
if (this.context.mainCamera)
|
|
63
|
-
this.context.composer.setMainCamera(this.context.mainCamera);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
onDestroy(): void {
|
|
69
|
-
this._postprocessing?.dispose();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private _lastApplyTime?: number;
|
|
73
|
-
private _rapidApplyCount = 0;
|
|
74
|
-
|
|
75
|
-
private apply() {
|
|
76
|
-
if (debug) console.log("Apply PostProcessing", this, this.context.mainCamera?.name);
|
|
77
|
-
|
|
78
|
-
if (isDevEnvironment()) {
|
|
79
|
-
if (this._lastApplyTime !== undefined && Date.now() - this._lastApplyTime < 100) {
|
|
80
|
-
this._rapidApplyCount++;
|
|
81
|
-
if (this._rapidApplyCount === 5)
|
|
82
|
-
console.warn("Detected rapid post processing modifications - this might be a bug", this);
|
|
83
|
-
}
|
|
84
|
-
this._lastApplyTime = Date.now();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
this.unapply();
|
|
89
|
-
|
|
90
|
-
this._effects.length = 0;
|
|
91
|
-
// get from profile
|
|
92
|
-
if (this.sharedProfile?.components) {
|
|
93
|
-
this._effects.push(...this.sharedProfile.components);
|
|
94
|
-
}
|
|
95
|
-
// get additional effects
|
|
96
|
-
const additionalComponents = this.gameObject.getComponentsInChildren(PostProcessingEffect);
|
|
97
|
-
if (debug && additionalComponents?.length)
|
|
98
|
-
console.log("Additional", additionalComponents);
|
|
99
|
-
if (additionalComponents) {
|
|
100
|
-
for (const comp of additionalComponents) {
|
|
101
|
-
if (comp.active) this._effects.push(comp);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (this._effects.length > 0) {
|
|
106
|
-
if (!this._postprocessing)
|
|
107
|
-
this._postprocessing = new PostProcessingHandler(this.context);
|
|
108
|
-
this._postprocessing.apply(this._effects);
|
|
109
|
-
this._applyPostQueue();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private unapply() {
|
|
115
|
-
this._postprocessing?.unapply();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
private _applyPostQueue() {
|
|
120
|
-
if (this._modificationQueue) {
|
|
121
|
-
for (const entry of this._modificationQueue.values()) this.onEditorModification(entry);
|
|
122
|
-
this._modificationQueue.clear();
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/** called from needle editor sync package if its active */
|
|
127
|
-
onEditorModification(modification: EditorModification): void | boolean | undefined {
|
|
128
|
-
|
|
129
|
-
if (modification.propertyName.startsWith("postprocessing.")) {
|
|
130
|
-
|
|
131
|
-
if (!this._postprocessing) {
|
|
132
|
-
if (!this._modificationQueue) this._modificationQueue = new Map<string, EditorModification>();
|
|
133
|
-
this._modificationQueue.set(modification.propertyName, modification);
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (!this._effects?.length) return;
|
|
138
|
-
const path = modification.propertyName.split(".");
|
|
139
|
-
if (path.length === 3 || path.length === 4) {
|
|
140
|
-
const componentName = path[1];
|
|
141
|
-
const propertyName = path[2];
|
|
142
|
-
for (const comp of this._effects) {
|
|
143
|
-
if (comp.typeName?.toLowerCase() === componentName.toLowerCase()) {
|
|
144
|
-
|
|
145
|
-
if (propertyName === "active") {
|
|
146
|
-
comp.active = modification.value;
|
|
147
|
-
this.scheduleRecreate();
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// cache the volume parameters
|
|
152
|
-
if (!effectVolumeProperties.has(componentName)) {
|
|
153
|
-
const volumeParameterKeys = new Array<string>();
|
|
154
|
-
effectVolumeProperties.set(componentName, volumeParameterKeys);
|
|
155
|
-
const keys = Object.keys(comp);
|
|
156
|
-
for (const key of keys) {
|
|
157
|
-
const prop = comp[key];
|
|
158
|
-
if (prop instanceof VolumeParameter) {
|
|
159
|
-
volumeParameterKeys.push(key);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (effectVolumeProperties.has(componentName)) {
|
|
165
|
-
const paramName = propertyName.toLowerCase();
|
|
166
|
-
const volumeParameterKeys = effectVolumeProperties.get(componentName)!;
|
|
167
|
-
for (const key of volumeParameterKeys) {
|
|
168
|
-
if (key.toLowerCase() === paramName) {
|
|
169
|
-
const prop = comp[key] as VolumeParameter;
|
|
170
|
-
if (prop instanceof VolumeParameter) {
|
|
171
|
-
const isActiveStateChange = path.length === 4 && path[3] === "active";
|
|
172
|
-
if (isActiveStateChange) {
|
|
173
|
-
prop.overrideState = modification.value;
|
|
174
|
-
this.scheduleRecreate();
|
|
175
|
-
}
|
|
176
|
-
else if (prop && prop.value !== undefined) {
|
|
177
|
-
prop.value = modification.value;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
console.warn("Unknown modification", propertyName);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
private _modificationQueue?: Map<string, EditorModification>;
|
|
197
|
-
|
|
198
|
-
private _recreateId: number = -1;
|
|
199
|
-
private scheduleRecreate() {
|
|
200
|
-
// When the editor modifications come in with changed active effects we want/need to re-create the effects
|
|
201
|
-
// We defer it slightly because multiple active changes could be made and we dont want to recreate the full effect stack multiple times
|
|
202
|
-
const id = ++this._recreateId;
|
|
203
|
-
setTimeout(() => {
|
|
204
|
-
if (id !== this._recreateId) return;
|
|
205
|
-
this.onDisable();
|
|
206
|
-
this.onEnable();
|
|
207
|
-
}, 200);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/** cached VolumeParameter keys per object */
|
|
213
|
-
const effectVolumeProperties: Map<string, string[]> = new Map<string, string[]>();
|
|
1
|
+
import { Behaviour, GameObject } from "../Component";
|
|
2
|
+
import { serializeable } from "../../engine/engine_serialization_decorator";
|
|
3
|
+
import { getParam } from "../../engine/engine_utils";
|
|
4
|
+
import { VolumeProfile } from "./VolumeProfile";
|
|
5
|
+
import { EditorModification, IEditorModification as IEditorModificationReceiver } from "../../engine/engine_editor-sync";
|
|
6
|
+
import { PostProcessingHandler } from "./PostProcessingHandler";
|
|
7
|
+
import { PostProcessingEffect } from "./PostProcessingEffect";
|
|
8
|
+
import { VolumeParameter } from "./VolumeParameter";
|
|
9
|
+
import { getEditorModificationCache } from "../../engine/engine_editor-sync";
|
|
10
|
+
import { isDevEnvironment } from "../../engine/debug";
|
|
11
|
+
import { EffectComposer } from "postprocessing";
|
|
12
|
+
|
|
13
|
+
const debug = getParam("debugpost");
|
|
14
|
+
|
|
15
|
+
export class Volume extends Behaviour implements IEditorModificationReceiver {
|
|
16
|
+
|
|
17
|
+
@serializeable(VolumeProfile)
|
|
18
|
+
sharedProfile?: VolumeProfile;
|
|
19
|
+
|
|
20
|
+
private _postprocessing?: PostProcessingHandler;
|
|
21
|
+
private _effects: PostProcessingEffect[] = [];
|
|
22
|
+
|
|
23
|
+
awake() {
|
|
24
|
+
// ensure the profile is initialized
|
|
25
|
+
this.sharedProfile?.init();
|
|
26
|
+
|
|
27
|
+
if (debug) {
|
|
28
|
+
console.log(this);
|
|
29
|
+
console.log("Press P to toggle post processing");
|
|
30
|
+
window.addEventListener("keydown", (e) => {
|
|
31
|
+
if (e.key === "p") {
|
|
32
|
+
console.log("Toggle volume: " + this.name, !this.enabled);
|
|
33
|
+
this.enabled = !this.enabled;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
onDisable() {
|
|
40
|
+
this._postprocessing?.unapply();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onBeforeRender(): void {
|
|
44
|
+
if (!this.context.isInXR) {
|
|
45
|
+
|
|
46
|
+
if (this.context.composer && (this.context.composer instanceof EffectComposer) === false) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Wait for the first frame to be rendered before creating because then we know we have a camera (issue 135)
|
|
51
|
+
if (this.context.mainCamera) {
|
|
52
|
+
if (!this._postprocessing || !this._postprocessing.isActive) {
|
|
53
|
+
this.apply();
|
|
54
|
+
// TODO: remove this workaround for postprocessing rendering not working correctly when applied for the first time
|
|
55
|
+
this.apply();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (this.context.composer) {
|
|
60
|
+
this.context.composer.setRenderer(this.context.renderer);
|
|
61
|
+
this.context.composer.setMainScene(this.context.scene);
|
|
62
|
+
if (this.context.mainCamera)
|
|
63
|
+
this.context.composer.setMainCamera(this.context.mainCamera);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
onDestroy(): void {
|
|
69
|
+
this._postprocessing?.dispose();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private _lastApplyTime?: number;
|
|
73
|
+
private _rapidApplyCount = 0;
|
|
74
|
+
|
|
75
|
+
private apply() {
|
|
76
|
+
if (debug) console.log("Apply PostProcessing", this, this.context.mainCamera?.name);
|
|
77
|
+
|
|
78
|
+
if (isDevEnvironment()) {
|
|
79
|
+
if (this._lastApplyTime !== undefined && Date.now() - this._lastApplyTime < 100) {
|
|
80
|
+
this._rapidApplyCount++;
|
|
81
|
+
if (this._rapidApplyCount === 5)
|
|
82
|
+
console.warn("Detected rapid post processing modifications - this might be a bug", this);
|
|
83
|
+
}
|
|
84
|
+
this._lastApplyTime = Date.now();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
this.unapply();
|
|
89
|
+
|
|
90
|
+
this._effects.length = 0;
|
|
91
|
+
// get from profile
|
|
92
|
+
if (this.sharedProfile?.components) {
|
|
93
|
+
this._effects.push(...this.sharedProfile.components);
|
|
94
|
+
}
|
|
95
|
+
// get additional effects
|
|
96
|
+
const additionalComponents = this.gameObject.getComponentsInChildren(PostProcessingEffect);
|
|
97
|
+
if (debug && additionalComponents?.length)
|
|
98
|
+
console.log("Additional", additionalComponents);
|
|
99
|
+
if (additionalComponents) {
|
|
100
|
+
for (const comp of additionalComponents) {
|
|
101
|
+
if (comp.active) this._effects.push(comp);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (this._effects.length > 0) {
|
|
106
|
+
if (!this._postprocessing)
|
|
107
|
+
this._postprocessing = new PostProcessingHandler(this.context);
|
|
108
|
+
this._postprocessing.apply(this._effects);
|
|
109
|
+
this._applyPostQueue();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private unapply() {
|
|
115
|
+
this._postprocessing?.unapply();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
private _applyPostQueue() {
|
|
120
|
+
if (this._modificationQueue) {
|
|
121
|
+
for (const entry of this._modificationQueue.values()) this.onEditorModification(entry);
|
|
122
|
+
this._modificationQueue.clear();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** called from needle editor sync package if its active */
|
|
127
|
+
onEditorModification(modification: EditorModification): void | boolean | undefined {
|
|
128
|
+
|
|
129
|
+
if (modification.propertyName.startsWith("postprocessing.")) {
|
|
130
|
+
|
|
131
|
+
if (!this._postprocessing) {
|
|
132
|
+
if (!this._modificationQueue) this._modificationQueue = new Map<string, EditorModification>();
|
|
133
|
+
this._modificationQueue.set(modification.propertyName, modification);
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!this._effects?.length) return;
|
|
138
|
+
const path = modification.propertyName.split(".");
|
|
139
|
+
if (path.length === 3 || path.length === 4) {
|
|
140
|
+
const componentName = path[1];
|
|
141
|
+
const propertyName = path[2];
|
|
142
|
+
for (const comp of this._effects) {
|
|
143
|
+
if (comp.typeName?.toLowerCase() === componentName.toLowerCase()) {
|
|
144
|
+
|
|
145
|
+
if (propertyName === "active") {
|
|
146
|
+
comp.active = modification.value;
|
|
147
|
+
this.scheduleRecreate();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// cache the volume parameters
|
|
152
|
+
if (!effectVolumeProperties.has(componentName)) {
|
|
153
|
+
const volumeParameterKeys = new Array<string>();
|
|
154
|
+
effectVolumeProperties.set(componentName, volumeParameterKeys);
|
|
155
|
+
const keys = Object.keys(comp);
|
|
156
|
+
for (const key of keys) {
|
|
157
|
+
const prop = comp[key];
|
|
158
|
+
if (prop instanceof VolumeParameter) {
|
|
159
|
+
volumeParameterKeys.push(key);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (effectVolumeProperties.has(componentName)) {
|
|
165
|
+
const paramName = propertyName.toLowerCase();
|
|
166
|
+
const volumeParameterKeys = effectVolumeProperties.get(componentName)!;
|
|
167
|
+
for (const key of volumeParameterKeys) {
|
|
168
|
+
if (key.toLowerCase() === paramName) {
|
|
169
|
+
const prop = comp[key] as VolumeParameter;
|
|
170
|
+
if (prop instanceof VolumeParameter) {
|
|
171
|
+
const isActiveStateChange = path.length === 4 && path[3] === "active";
|
|
172
|
+
if (isActiveStateChange) {
|
|
173
|
+
prop.overrideState = modification.value;
|
|
174
|
+
this.scheduleRecreate();
|
|
175
|
+
}
|
|
176
|
+
else if (prop && prop.value !== undefined) {
|
|
177
|
+
prop.value = modification.value;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.warn("Unknown modification", propertyName);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private _modificationQueue?: Map<string, EditorModification>;
|
|
197
|
+
|
|
198
|
+
private _recreateId: number = -1;
|
|
199
|
+
private scheduleRecreate() {
|
|
200
|
+
// When the editor modifications come in with changed active effects we want/need to re-create the effects
|
|
201
|
+
// We defer it slightly because multiple active changes could be made and we dont want to recreate the full effect stack multiple times
|
|
202
|
+
const id = ++this._recreateId;
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
if (id !== this._recreateId) return;
|
|
205
|
+
this.onDisable();
|
|
206
|
+
this.onEnable();
|
|
207
|
+
}, 200);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** cached VolumeParameter keys per object */
|
|
213
|
+
const effectVolumeProperties: Map<string, string[]> = new Map<string, string[]>();
|
|
@@ -8,11 +8,13 @@ import { getComponentsInChildren } from "../../engine/engine_components";
|
|
|
8
8
|
import { IComponent } from "../../engine/engine_types";
|
|
9
9
|
import { GameObject } from "../Component";
|
|
10
10
|
import { showBalloonMessage, showBalloonWarning } from "../../engine/debug";
|
|
11
|
+
import { Object3D } from "three";
|
|
11
12
|
|
|
12
13
|
export enum RenderMode {
|
|
13
14
|
ScreenSpaceOverlay = 0,
|
|
14
15
|
ScreenSpaceCamera = 1,
|
|
15
16
|
WorldSpace = 2,
|
|
17
|
+
Undefined = -1,
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export class Canvas extends UIRootComponent {
|
|
@@ -74,7 +76,7 @@ export class Canvas extends UIRootComponent {
|
|
|
74
76
|
this._renderMode = val;
|
|
75
77
|
this.onRenderSettingsChanged();
|
|
76
78
|
}
|
|
77
|
-
private _renderMode: RenderMode =
|
|
79
|
+
private _renderMode: RenderMode = RenderMode.Undefined;
|
|
78
80
|
|
|
79
81
|
private _rootCanvas!: Canvas;
|
|
80
82
|
|
|
@@ -109,12 +111,28 @@ export class Canvas extends UIRootComponent {
|
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
private previousAspect: number = -1;
|
|
114
|
+
private previousParent: Object3D | null = null;
|
|
112
115
|
|
|
113
116
|
onBeforeRender() {
|
|
114
117
|
if (this.isScreenSpace && this.context.mainCameraComponent && this.context.mainCameraComponent.aspect !== this.previousAspect) {
|
|
115
118
|
this.previousAspect = this.context.mainCameraComponent.aspect;
|
|
116
119
|
this.updateRenderMode();
|
|
117
120
|
}
|
|
121
|
+
else if(this.renderOnTop){
|
|
122
|
+
// This is just a test but in reality it should be combined with all world canvases with render on top in one render pass
|
|
123
|
+
this.previousParent = this.gameObject.parent;
|
|
124
|
+
this.gameObject.removeFromParent();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
onAfterRender(): void {
|
|
129
|
+
if (this.renderOnTop && this.previousParent && this.context.mainCamera) {
|
|
130
|
+
this.previousParent.add(this.gameObject);
|
|
131
|
+
this.context.renderer.autoClear = false;
|
|
132
|
+
this.context.renderer.clearDepth();
|
|
133
|
+
this.context.renderer.render(this.gameObject, this.context.mainCamera);
|
|
134
|
+
this.context.renderer.autoClear = true;
|
|
135
|
+
}
|
|
118
136
|
}
|
|
119
137
|
|
|
120
138
|
applyRenderSettings(){
|
|
@@ -382,8 +382,7 @@ export class EventSystem extends Behaviour {
|
|
|
382
382
|
const actualGo = parent[$shadowDomOwner].gameObject;
|
|
383
383
|
if (actualGo) {
|
|
384
384
|
const res = UIRaycastUtils.isInteractable(actualGo, this.out);
|
|
385
|
-
|
|
386
|
-
if (!res) return this.out.canvasGroup?.interactable ?? false;
|
|
385
|
+
if (!res) return false;
|
|
387
386
|
canvasGroup = this.out.canvasGroup ?? null;
|
|
388
387
|
|
|
389
388
|
const handled = this.handleMeshUIIntersection(object, pressedOrClicked);
|
|
@@ -214,6 +214,9 @@ export class Text extends Graphic {
|
|
|
214
214
|
|
|
215
215
|
this.getAlignment(opts, isTextIntermediate);
|
|
216
216
|
const block = rt.createNewBlock(opts);
|
|
217
|
+
// The text block should never write depth to avoid z-fighting
|
|
218
|
+
const mat = block["backgroundMaterial"];
|
|
219
|
+
if(mat) mat.depthWrite = false;
|
|
217
220
|
if (content) {
|
|
218
221
|
if (Array.isArray(content)) {
|
|
219
222
|
block.add(...content);
|
|
@@ -34,11 +34,13 @@ export function updateRenderSettings(shadowComponent: THREE.Object3D, settings:
|
|
|
34
34
|
// console.log(shadowComponent)
|
|
35
35
|
const mat = shadowComponent["material"];
|
|
36
36
|
if (mat?.isMaterial === true) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const parent = shadowComponent.parent;
|
|
38
|
+
if (parent && parent["isText"] === true) {
|
|
39
|
+
// console.log(shadowComponent, shadowComponent.name);
|
|
40
|
+
}
|
|
41
|
+
// mat.depthTest = !settings.renderOnTop ?? true;
|
|
42
|
+
// mat.depthWrite = settings.depthWrite ?? false;
|
|
40
43
|
mat.side = (settings.doubleSided ?? true) ? DoubleSide : FrontSide;
|
|
41
|
-
mat.depthWrite = settings.depthWrite ?? false;
|
|
42
44
|
mat.shadowSide = settings.doubleSided ? DoubleSide : FrontSide;
|
|
43
45
|
shadowComponent.castShadow = settings.castShadows ? settings.castShadows : false;
|
|
44
46
|
shadowComponent.receiveShadow = settings.receiveShadows ? settings.receiveShadows : false;
|