@needle-tools/engine 4.2.0 → 4.2.2
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 +6 -0
- package/dist/needle-engine.bundle.js +6564 -6521
- package/dist/needle-engine.bundle.light.js +6561 -6518
- package/dist/needle-engine.bundle.light.min.js +134 -130
- package/dist/needle-engine.bundle.light.umd.cjs +130 -126
- package/dist/needle-engine.bundle.min.js +134 -130
- package/dist/needle-engine.bundle.umd.cjs +131 -127
- package/dist/needle-engine.d.ts +9 -9
- package/lib/engine/engine_input.d.ts +14 -2
- package/lib/engine/engine_input.js +41 -6
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +16 -3
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_types.d.ts +5 -0
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
- package/lib/engine-components/Duplicatable.js +2 -2
- package/lib/engine-components/Duplicatable.js.map +1 -1
- package/lib/engine-components/EventTrigger.d.ts +2 -0
- package/lib/engine-components/EventTrigger.js +12 -0
- package/lib/engine-components/EventTrigger.js.map +1 -1
- package/lib/engine-components/Renderer.js +5 -0
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/ScreenCapture.js +2 -2
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +0 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js +2 -2
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +19 -11
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +7 -2
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +33 -11
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.d.ts +1 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js +5 -2
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js.map +1 -1
- package/lib/engine-components/ui/Button.js +3 -3
- package/lib/engine-components/ui/Button.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.d.ts +6 -10
- package/lib/engine-components/ui/EventSystem.js +35 -52
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/InputField.d.ts +3 -1
- package/lib/engine-components/ui/InputField.js +8 -0
- package/lib/engine-components/ui/InputField.js.map +1 -1
- package/lib/engine-components/utils/OpenURL.js +2 -2
- package/lib/engine-components/utils/OpenURL.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.js +5 -1
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/engine_input.ts +47 -9
- package/src/engine/engine_serialization_core.ts +13 -4
- package/src/engine/engine_types.ts +5 -0
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
- package/src/engine-components/Duplicatable.ts +2 -2
- package/src/engine-components/EventTrigger.ts +14 -0
- package/src/engine-components/Renderer.ts +5 -0
- package/src/engine-components/ScreenCapture.ts +2 -2
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +0 -1
- package/src/engine-components/export/usdz/USDZExporter.ts +2 -2
- package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +17 -11
- package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +41 -23
- package/src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +5 -2
- package/src/engine-components/ui/Button.ts +3 -3
- package/src/engine-components/ui/EventSystem.ts +45 -62
- package/src/engine-components/ui/InputField.ts +9 -1
- package/src/engine-components/utils/OpenURL.ts +2 -2
- package/src/engine-components/webxr/WebXRImageTracking.ts +5 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { serializable } from "../engine/engine_serialization.js";
|
|
2
|
+
import { EventSystem } from "./api.js";
|
|
2
3
|
import { Behaviour } from "./Component.js"
|
|
3
4
|
import { EventList } from "./EventList.js";
|
|
4
5
|
import { EventType } from "./EventType.js"
|
|
@@ -33,6 +34,13 @@ export class EventTrigger extends Behaviour implements IPointerEventHandler {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
private hasTrigger(type: EventType) {
|
|
38
|
+
return this.triggers?.some(t => t.eventID === type) ?? false;
|
|
39
|
+
}
|
|
40
|
+
private shouldChangeCursor() {
|
|
41
|
+
return this.hasTrigger(EventType.PointerClick) || this.hasTrigger(EventType.PointerDown) || this.hasTrigger(EventType.PointerUp);
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
/** @internal */
|
|
37
45
|
onPointerClick(_: PointerEventData) {
|
|
38
46
|
this.invoke(EventType.PointerClick);
|
|
@@ -40,11 +48,17 @@ export class EventTrigger extends Behaviour implements IPointerEventHandler {
|
|
|
40
48
|
|
|
41
49
|
/** @internal */
|
|
42
50
|
onPointerEnter(_: PointerEventData) {
|
|
51
|
+
if (this.shouldChangeCursor()) {
|
|
52
|
+
this.context.input.setCursor("pointer");
|
|
53
|
+
}
|
|
43
54
|
this.invoke(EventType.PointerEnter);
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
/** @internal */
|
|
47
58
|
onPointerExit(_: PointerEventData) {
|
|
59
|
+
if (this.shouldChangeCursor()) {
|
|
60
|
+
this.context.input.unsetCursor("pointer");
|
|
61
|
+
}
|
|
48
62
|
this.invoke(EventType.PointerExit);
|
|
49
63
|
}
|
|
50
64
|
|
|
@@ -716,6 +716,11 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
716
716
|
const factor = this.hasLightmap ? Math.PI : 1;
|
|
717
717
|
const environmentIntensity = this.context.mainCameraComponent?.environmentIntensity ?? 1;
|
|
718
718
|
material.envMapIntensity = Math.max(0, environmentIntensity * this.context.sceneLighting.environmentIntensity / factor);
|
|
719
|
+
|
|
720
|
+
// since three 163 we need to set the envMap to the scene envMap if it is not set
|
|
721
|
+
// otherwise the envmapIntensity has no effect: https://github.com/mrdoob/three.js/pull/27903
|
|
722
|
+
// internal issue: https://linear.app/needle/issue/NE-6363
|
|
723
|
+
if (!material.envMap) material.envMap = this.context.scene.environment;
|
|
719
724
|
}
|
|
720
725
|
|
|
721
726
|
if (this._lightmaps) {
|
|
@@ -88,13 +88,13 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
88
88
|
onPointerEnter() {
|
|
89
89
|
if (this.context.connection.allowEditing == false) return;
|
|
90
90
|
if (!this.allowStartOnClick) return;
|
|
91
|
-
this.context.input.
|
|
91
|
+
this.context.input.setCursor("pointer");
|
|
92
92
|
}
|
|
93
93
|
/** @internal */
|
|
94
94
|
onPointerExit() {
|
|
95
95
|
if (this.context.connection.allowEditing == false) return;
|
|
96
96
|
if (!this.allowStartOnClick) return;
|
|
97
|
-
this.context.input.
|
|
97
|
+
this.context.input.unsetCursor("pointer");
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/** @internal */
|
|
@@ -1966,7 +1966,6 @@ function buildMaterial( material: MeshBasicMaterial, textures: TextureMap, quick
|
|
|
1966
1966
|
|
|
1967
1967
|
const materialName = getMaterialName(material);
|
|
1968
1968
|
|
|
1969
|
-
console.log(material);
|
|
1970
1969
|
// Special case: occluder material
|
|
1971
1970
|
// Supported on iOS 18+ and visionOS 1+
|
|
1972
1971
|
const isShadowCatcherMaterial =
|
|
@@ -403,7 +403,7 @@ export class USDZExporter extends Behaviour {
|
|
|
403
403
|
if (this.autoExportAnimations) {
|
|
404
404
|
implicitBehaviors.push(...registerAnimatorsImplictly(objectToExport, animExt));
|
|
405
405
|
}
|
|
406
|
-
const audioExt =
|
|
406
|
+
const audioExt = extensions.find(ext => ext.extensionName === "Audio");
|
|
407
407
|
if (audioExt && this.autoExportAudioSources)
|
|
408
408
|
implicitBehaviors.push(...registerAudioSourcesImplictly(objectToExport, audioExt as AudioExtension));
|
|
409
409
|
|
|
@@ -454,7 +454,7 @@ export class USDZExporter extends Behaviour {
|
|
|
454
454
|
});
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
-
const behaviorExt =
|
|
457
|
+
const behaviorExt = extensions.find(ext => ext.extensionName === "Behaviour") as BehaviorExtension | undefined;
|
|
458
458
|
if (this.interactive && behaviorExt && objectsToDisableAtSceneStart.length > 0) {
|
|
459
459
|
behaviorExt.addBehavior(disableObjectsAtStart(objectsToDisableAtSceneStart));
|
|
460
460
|
}
|
|
@@ -120,19 +120,21 @@ export class BehaviorExtension implements IUSDExporterExtension {
|
|
|
120
120
|
if (actionModel.tokenId === "StartAnimation") {
|
|
121
121
|
playAnimationActions.add(actionModel);
|
|
122
122
|
}
|
|
123
|
+
let actionType = actionModel.tokenId;
|
|
124
|
+
if (actionModel.type !== undefined) actionType += ":" + actionModel.type;
|
|
123
125
|
const affected = actionModel.affectedObjects;
|
|
124
126
|
if (affected) {
|
|
125
127
|
if (Array.isArray(affected)) {
|
|
126
128
|
for (const a of affected) {
|
|
127
129
|
actionTargets.add(a as Target);
|
|
128
130
|
//@ts-ignore
|
|
129
|
-
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${actionModel.id}[${actionModel.id}] -- ${
|
|
131
|
+
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${actionModel.id}[${actionModel.id}\n${actionType}] -- ${actionType} --> ${a.uuid}(("${a.displayName || a.name || a.uuid}"))\n`;
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
134
|
else if (typeof affected === "object") {
|
|
133
135
|
actionTargets.add(affected as Target);
|
|
134
136
|
//@ts-ignore
|
|
135
|
-
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${actionModel.id}[${actionModel.id}] -- ${
|
|
137
|
+
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${actionModel.id}[${actionModel.id}\n${actionType}] -- ${actionType} --> ${affected.uuid}(("${affected.displayName || affected.name || affected.uuid}"))\n`;
|
|
136
138
|
}
|
|
137
139
|
else if (typeof affected === "string") {
|
|
138
140
|
actionTargets.add({uuid: affected} as any as Target);
|
|
@@ -144,7 +146,7 @@ export class BehaviorExtension implements IUSDExporterExtension {
|
|
|
144
146
|
if (typeof xform === "object") {
|
|
145
147
|
actionTargets.add(xform as Target);
|
|
146
148
|
//@ts-ignore
|
|
147
|
-
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${actionModel.id}[${actionModel.id}] -- ${
|
|
149
|
+
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${actionModel.id}[${actionModel.id}\n${actionType}] -- ${actionType} --> ${xform.uuid}(("${xform.displayName || xform.name || xform.uuid}"))\n`;
|
|
148
150
|
}
|
|
149
151
|
else if (typeof xform === "string") {
|
|
150
152
|
actionTargets.add({uuid: xform} as any as Target);
|
|
@@ -159,19 +161,21 @@ export class BehaviorExtension implements IUSDExporterExtension {
|
|
|
159
161
|
collectTrigger(t, action);
|
|
160
162
|
}
|
|
161
163
|
else if (trigger instanceof TriggerModel) {
|
|
164
|
+
let triggerType = trigger.tokenId;
|
|
165
|
+
if (trigger.type !== undefined) triggerType += ":" + trigger.type;
|
|
162
166
|
if (typeof trigger.targetId === "object") {
|
|
163
167
|
triggerSources.add(trigger.targetId as Target);
|
|
164
168
|
//@ts-ignore
|
|
165
|
-
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${trigger.targetId.uuid}(("${trigger.targetId.displayName}")) --> ${trigger.id}[${trigger.id}]\n`;
|
|
169
|
+
if (createMermaidGraphForDebugging) mermaidGraphTopLevel += `${trigger.targetId.uuid}(("${trigger.targetId.displayName}")) --> ${trigger.id}[${trigger.id}\n${triggerType}]\n`;
|
|
166
170
|
}
|
|
167
171
|
//@ts-ignore
|
|
168
|
-
if (createMermaidGraphForDebugging) mermaidGraph += `${trigger.id}((${trigger.id})) -- ${
|
|
172
|
+
if (createMermaidGraphForDebugging) mermaidGraph += `${trigger.id}((${trigger.id})) -- ${triggerType} --> ${action.id}[${action.tokenId || action.id}]\n`;
|
|
169
173
|
}
|
|
170
174
|
}
|
|
171
175
|
|
|
172
176
|
// collect all targets of all triggers and actions
|
|
173
177
|
for (const beh of this.behaviours) {
|
|
174
|
-
if (createMermaidGraphForDebugging) mermaidGraph += `subgraph
|
|
178
|
+
if (createMermaidGraphForDebugging) mermaidGraph += `subgraph ${beh.id}\n`;
|
|
175
179
|
collectAction(beh.action);
|
|
176
180
|
collectTrigger(beh.trigger, beh.action);
|
|
177
181
|
if (createMermaidGraphForDebugging) mermaidGraph += `end\n`;
|
|
@@ -180,10 +184,12 @@ export class BehaviorExtension implements IUSDExporterExtension {
|
|
|
180
184
|
|
|
181
185
|
if (createMermaidGraphForDebugging) {
|
|
182
186
|
console.log("All USDZ behaviours", this.behaviours);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
if (this.behaviours.length) {
|
|
188
|
+
console.warn("The Mermaid graph can be pasted into https://massive-mermaid.glitch.me/ or https://mermaid.live/edit. It should be in your clipboard already!");
|
|
189
|
+
console.log(mermaidGraph);
|
|
190
|
+
// copy to clipboard, can be pasted into https://massive-mermaid.glitch.me/ or https://mermaid.live/edit
|
|
191
|
+
navigator.clipboard.writeText(mermaidGraph);
|
|
192
|
+
}
|
|
187
193
|
}
|
|
188
194
|
|
|
189
195
|
{
|
|
@@ -212,7 +218,7 @@ export class BehaviorExtension implements IUSDExporterExtension {
|
|
|
212
218
|
}
|
|
213
219
|
}
|
|
214
220
|
|
|
215
|
-
if (createMermaidGraphForDebugging) {
|
|
221
|
+
if (createMermaidGraphForDebugging && playAnimationActions.size) {
|
|
216
222
|
console.log(animationsGraph);
|
|
217
223
|
}
|
|
218
224
|
|
|
@@ -17,7 +17,7 @@ import { makeNameSafeForUSD,USDDocument, USDObject, USDZExporterContext } from "
|
|
|
17
17
|
import { AnimationExtension, RegisteredAnimationInfo, type UsdzAnimation } from "../Animation.js";
|
|
18
18
|
import { AudioExtension } from "./AudioExtension.js";
|
|
19
19
|
import type { BehaviorExtension, UsdzBehaviour } from "./Behaviour.js";
|
|
20
|
-
import { ActionBuilder, ActionModel, BehaviorModel, EmphasizeActionMotionType,type IBehaviorElement, Target, TriggerBuilder } from "./BehavioursBuilder.js";
|
|
20
|
+
import { ActionBuilder, ActionModel, BehaviorModel, EmphasizeActionMotionType,GroupActionModel,type IBehaviorElement, Target, TriggerBuilder } from "./BehavioursBuilder.js";
|
|
21
21
|
|
|
22
22
|
const debug = getParam("debugusdzbehaviours");
|
|
23
23
|
|
|
@@ -203,10 +203,10 @@ export class ChangeMaterialOnClick extends Behaviour implements IPointerClickHan
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
onPointerEnter(_args: PointerEventData) {
|
|
206
|
-
this.context.input.
|
|
206
|
+
this.context.input.setCursor("pointer");
|
|
207
207
|
}
|
|
208
208
|
onPointerExit(_: PointerEventData) {
|
|
209
|
-
this.context.input.
|
|
209
|
+
this.context.input.unsetCursor("pointer");
|
|
210
210
|
}
|
|
211
211
|
onPointerClick(args: PointerEventData) {
|
|
212
212
|
args.use();
|
|
@@ -251,7 +251,8 @@ export class ChangeMaterialOnClick extends Behaviour implements IPointerClickHan
|
|
|
251
251
|
private targetModels!: USDObject[];
|
|
252
252
|
|
|
253
253
|
private static _materialTriggersPerId: { [key: string]: ChangeMaterialOnClick[] } = {}
|
|
254
|
-
|
|
254
|
+
private static _startHiddenBehaviour: BehaviorModel | null = null;
|
|
255
|
+
private static _parallelStartHiddenActions: USDObject[] = [];
|
|
255
256
|
|
|
256
257
|
async beforeCreateDocument(_ext: BehaviorExtension, _context) {
|
|
257
258
|
this.targetModels = [];
|
|
@@ -309,23 +310,25 @@ export class ChangeMaterialOnClick extends Behaviour implements IPointerClickHan
|
|
|
309
310
|
}
|
|
310
311
|
|
|
311
312
|
private createAndAttachBehaviors(ext: BehaviorExtension, myVariants: Array<USDObject>, otherVariants: Array<USDObject>) {
|
|
312
|
-
const start: ActionModel[] = [];
|
|
313
313
|
const select: ActionModel[] = [];
|
|
314
314
|
|
|
315
315
|
const fadeDuration = Math.max(0, this.fadeDuration);
|
|
316
316
|
|
|
317
317
|
select.push(ActionBuilder.fadeAction([...this.targetModels, ...otherVariants], fadeDuration, false));
|
|
318
|
-
start.push(ActionBuilder.fadeAction(myVariants, fadeDuration, false));
|
|
319
318
|
select.push(ActionBuilder.fadeAction(myVariants, fadeDuration, true));
|
|
320
319
|
|
|
321
320
|
ext.addBehavior(new BehaviorModel("Select_" + this.selfModel.name,
|
|
322
321
|
TriggerBuilder.tapTrigger(this.selfModel),
|
|
323
322
|
ActionBuilder.parallel(...select))
|
|
324
323
|
);
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
324
|
+
ChangeMaterialOnClick._parallelStartHiddenActions.push(...myVariants);
|
|
325
|
+
if (!ChangeMaterialOnClick._startHiddenBehaviour) {
|
|
326
|
+
ChangeMaterialOnClick._startHiddenBehaviour =
|
|
327
|
+
new BehaviorModel("StartHidden_" + this.selfModel.name,
|
|
328
|
+
TriggerBuilder.sceneStartTrigger(),
|
|
329
|
+
ActionBuilder.fadeAction(ChangeMaterialOnClick._parallelStartHiddenActions, fadeDuration, false));
|
|
330
|
+
ext.addBehavior(ChangeMaterialOnClick._startHiddenBehaviour);
|
|
331
|
+
}
|
|
329
332
|
}
|
|
330
333
|
|
|
331
334
|
private static getMaterialName(material: Material) {
|
|
@@ -526,9 +529,9 @@ export class SetActiveOnClick extends Behaviour implements IPointerClickHandler,
|
|
|
526
529
|
sequence.push(ActionBuilder.fadeAction(selfModel, 0, false));
|
|
527
530
|
sequence.push(ActionBuilder.fadeAction(this.targetModel, 0, targetState));
|
|
528
531
|
|
|
529
|
-
ext.addBehavior(new BehaviorModel("Toggle_" + selfModel.name + "
|
|
532
|
+
ext.addBehavior(new BehaviorModel("Toggle_" + selfModel.name + "_ToggleTo" + (targetState ? "On" : "Off"),
|
|
530
533
|
TriggerBuilder.tapTrigger(selfModel),
|
|
531
|
-
ActionBuilder.parallel(...sequence)
|
|
534
|
+
sequence.length > 1 ? ActionBuilder.parallel(...sequence) : sequence[0],
|
|
532
535
|
));
|
|
533
536
|
}
|
|
534
537
|
// We have a toggleModel, so we need to set up two sequences:
|
|
@@ -540,7 +543,7 @@ export class SetActiveOnClick extends Behaviour implements IPointerClickHandler,
|
|
|
540
543
|
toggleSequence.push(ActionBuilder.fadeAction(this.toggleModel, 0, true));
|
|
541
544
|
toggleSequence.push(ActionBuilder.fadeAction(this.targetModel, 0, targetState));
|
|
542
545
|
|
|
543
|
-
ext.addBehavior(new BehaviorModel("Toggle_" + selfModel.name + "
|
|
546
|
+
ext.addBehavior(new BehaviorModel("Toggle_" + selfModel.name + "_ToggleTo" + (targetState ? "On" : "Off"),
|
|
544
547
|
TriggerBuilder.tapTrigger(selfModel),
|
|
545
548
|
ActionBuilder.parallel(...toggleSequence)
|
|
546
549
|
));
|
|
@@ -550,7 +553,7 @@ export class SetActiveOnClick extends Behaviour implements IPointerClickHandler,
|
|
|
550
553
|
reverseSequence.push(ActionBuilder.fadeAction(selfModel, 0, true));
|
|
551
554
|
reverseSequence.push(ActionBuilder.fadeAction(this.targetModel, 0, !targetState));
|
|
552
555
|
|
|
553
|
-
ext.addBehavior(new BehaviorModel("Toggle_" + selfModel.name + "
|
|
556
|
+
ext.addBehavior(new BehaviorModel("Toggle_" + selfModel.name + "_ToggleTo" + (!targetState ? "On" : "Off"),
|
|
554
557
|
TriggerBuilder.tapTrigger(this.toggleModel),
|
|
555
558
|
ActionBuilder.parallel(...reverseSequence)
|
|
556
559
|
));
|
|
@@ -565,10 +568,7 @@ export class SetActiveOnClick extends Behaviour implements IPointerClickHandler,
|
|
|
565
568
|
if (this.toggleModel)
|
|
566
569
|
objectsToHide.push(this.toggleModel);
|
|
567
570
|
|
|
568
|
-
|
|
569
|
-
TriggerBuilder.sceneStartTrigger(),
|
|
570
|
-
ActionBuilder.fadeAction(objectsToHide, 0, false)
|
|
571
|
-
));
|
|
571
|
+
HideOnStart.add(objectsToHide, ext);
|
|
572
572
|
}
|
|
573
573
|
}
|
|
574
574
|
|
|
@@ -595,6 +595,27 @@ export class SetActiveOnClick extends Behaviour implements IPointerClickHandler,
|
|
|
595
595
|
*/
|
|
596
596
|
export class HideOnStart extends Behaviour implements UsdzBehaviour {
|
|
597
597
|
|
|
598
|
+
private static _fadeBehaviour?: BehaviorModel;
|
|
599
|
+
private static _fadeObjects: Array<USDObject | Object3D> = [];
|
|
600
|
+
|
|
601
|
+
static add(target: Target, ext: BehaviorExtension) {
|
|
602
|
+
const arr = Array.isArray(target) ? target : [target];
|
|
603
|
+
for (const entry of arr) {
|
|
604
|
+
if (!HideOnStart._fadeObjects.includes(entry)) {
|
|
605
|
+
console.log("adding hide on start", entry);
|
|
606
|
+
HideOnStart._fadeObjects.push(entry);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
if (HideOnStart._fadeBehaviour === undefined) {
|
|
610
|
+
HideOnStart._fadeBehaviour = new BehaviorModel("HideOnStart",
|
|
611
|
+
TriggerBuilder.sceneStartTrigger(),
|
|
612
|
+
//@ts-ignore
|
|
613
|
+
ActionBuilder.fadeAction(HideOnStart._fadeObjects, 0, false)
|
|
614
|
+
);
|
|
615
|
+
ext.addBehavior(HideOnStart._fadeBehaviour);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
598
619
|
start() {
|
|
599
620
|
GameObject.setActive(this.gameObject, false);
|
|
600
621
|
}
|
|
@@ -603,10 +624,7 @@ export class HideOnStart extends Behaviour implements UsdzBehaviour {
|
|
|
603
624
|
if (model.uuid === this.gameObject.uuid) {
|
|
604
625
|
// we only want to mark the object as HideOnStart if it's still hidden
|
|
605
626
|
if (!this.wasVisible) {
|
|
606
|
-
|
|
607
|
-
TriggerBuilder.sceneStartTrigger(),
|
|
608
|
-
ActionBuilder.fadeAction(model, 0, false)
|
|
609
|
-
));
|
|
627
|
+
HideOnStart.add(model, ext);
|
|
610
628
|
}
|
|
611
629
|
}
|
|
612
630
|
}
|
|
@@ -752,7 +770,7 @@ export class PlayAudioOnClick extends Behaviour implements IPointerClickHandler,
|
|
|
752
770
|
// automatically play audio on start too if the referenced AudioSource has playOnAwake enabled
|
|
753
771
|
if (this.target && this.target.playOnAwake && this.target.enabled) {
|
|
754
772
|
if (anyChildHasGeometry && this.trigger === "tap") {
|
|
755
|
-
//
|
|
773
|
+
// WORKAROUND Currently (20240509) we MUST not emit this behaviour if we're also expecting the tap trigger to work.
|
|
756
774
|
// Seems to be a regression in QuickLook... audio clips can't be stopped anymore as soon as they start playing.
|
|
757
775
|
console.warn("USDZExport: Audio sources that are played on tap can't also auto-play at scene start due to a QuickLook bug.");
|
|
758
776
|
}
|
|
@@ -199,11 +199,14 @@ function addInputTargetComponent(model: USDObject, options: { direct: boolean, i
|
|
|
199
199
|
|
|
200
200
|
export class TriggerBuilder {
|
|
201
201
|
|
|
202
|
+
private static __sceneStartTrigger?: TriggerModel;
|
|
203
|
+
|
|
202
204
|
static sceneStartTrigger(): TriggerModel {
|
|
203
|
-
|
|
204
|
-
trigger
|
|
205
|
+
if (this.__sceneStartTrigger !== undefined) return this.__sceneStartTrigger;
|
|
206
|
+
const trigger = new TriggerModel(undefined, "SceneStart");
|
|
205
207
|
trigger.tokenId = "SceneTransition";
|
|
206
208
|
trigger.type = "enter";
|
|
209
|
+
this.__sceneStartTrigger = trigger;
|
|
207
210
|
return trigger;
|
|
208
211
|
}
|
|
209
212
|
|
|
@@ -90,7 +90,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
90
90
|
else if (this.transition === Transition.ColorTint && this.colors) {
|
|
91
91
|
this._image?.setState("hovered");
|
|
92
92
|
}
|
|
93
|
-
if (canSetCursor) this.context.input.
|
|
93
|
+
if (canSetCursor) this.context.input.setCursor("pointer");
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
onPointerExit() {
|
|
@@ -107,7 +107,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
107
107
|
else if (this.transition === Transition.ColorTint && this.colors) {
|
|
108
108
|
this._image?.setState("normal");
|
|
109
109
|
}
|
|
110
|
-
this.context.input.
|
|
110
|
+
this.context.input.unsetCursor("pointer");
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
onPointerDown(_) {
|
|
@@ -211,7 +211,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
onDestroy(): void {
|
|
214
|
-
if (this._isHovered) this.context.input.
|
|
214
|
+
if (this._isHovered) this.context.input.unsetCursor("pointer");
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
private _requestedAnimatorTrigger?: string;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { type Intersection, Mesh,Object3D } from "three";
|
|
1
|
+
import { type Intersection, Mesh, Object3D } from "three";
|
|
2
2
|
|
|
3
3
|
import { isDevEnvironment, showBalloonMessage } from "../../engine/debug/index.js";
|
|
4
|
-
import { type InputEventNames, InputEvents, NEPointerEvent, NEPointerEventIntersection,PointerType } from "../../engine/engine_input.js";
|
|
4
|
+
import { type InputEventNames, InputEvents, NEPointerEvent, NEPointerEventIntersection, PointerType } from "../../engine/engine_input.js";
|
|
5
|
+
import { onInitialized } from "../../engine/engine_lifecycle_api.js";
|
|
5
6
|
import { Mathf } from "../../engine/engine_math.js";
|
|
6
7
|
import { RaycastOptions, type RaycastTestObjectReturnType } from "../../engine/engine_physics.js";
|
|
7
8
|
import { Context } from "../../engine/engine_setup.js";
|
|
8
|
-
import type
|
|
9
|
+
import { HideFlags, type IComponent } from "../../engine/engine_types.js";
|
|
9
10
|
import { getParam } from "../../engine/engine_utils.js";
|
|
10
11
|
import { Behaviour, GameObject } from "../Component.js";
|
|
11
12
|
import { $shadowDomOwner } from "./BaseUIComponent.js";
|
|
@@ -30,47 +31,15 @@ export declare type AfterHandleInputEvent = {
|
|
|
30
31
|
|
|
31
32
|
declare type IComponentCanMaybeReceiveEvents = IPointerEventHandler & IComponent & { interactable?: boolean };
|
|
32
33
|
|
|
34
|
+
onInitialized((ctx) => {
|
|
35
|
+
EventSystem.createIfNoneExists(ctx);
|
|
36
|
+
})
|
|
37
|
+
|
|
33
38
|
/**
|
|
34
39
|
* @category User Interface
|
|
35
40
|
* @group Components
|
|
36
41
|
*/
|
|
37
42
|
export class EventSystem extends Behaviour {
|
|
38
|
-
private static _eventSystemMap = new Map<Context, EventSystem[]>();
|
|
39
|
-
|
|
40
|
-
static didSearchEventSystem: boolean = false;
|
|
41
|
-
static createIfNoneExists(context: Context) {
|
|
42
|
-
if (!this.didSearchEventSystem) {
|
|
43
|
-
this.didSearchEventSystem = true;
|
|
44
|
-
if (EventSystem.systems.length <= 0) {
|
|
45
|
-
EventSystem.systems.push(...GameObject.findObjectsOfType(EventSystem, context));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
for (const sys of EventSystem.systems) {
|
|
49
|
-
if (sys.context === context) return; // exists
|
|
50
|
-
}
|
|
51
|
-
const go = new Object3D();
|
|
52
|
-
GameObject.addComponent(go, EventSystem);
|
|
53
|
-
context.scene.add(go);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
static get systems(): EventSystem[] {
|
|
57
|
-
const context = Context.Current;
|
|
58
|
-
if (!this._eventSystemMap.has(context)) {
|
|
59
|
-
this._eventSystemMap.set(context, []);
|
|
60
|
-
}
|
|
61
|
-
return this._eventSystemMap.get(context)!;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
static get(ctx: Context): EventSystem | null {
|
|
65
|
-
const systems = this._eventSystemMap.get(ctx);
|
|
66
|
-
if (systems && systems.length > 0) return systems[0];
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
static get instance(): EventSystem | null {
|
|
71
|
-
return this.systems[0];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
43
|
//@ts-ignore
|
|
75
44
|
static ensureUpdateMeshUI(instance, context: Context, force: boolean = false) {
|
|
76
45
|
MeshUIHelper.update(instance, context, force);
|
|
@@ -79,32 +48,22 @@ export class EventSystem extends Behaviour {
|
|
|
79
48
|
MeshUIHelper.markDirty();
|
|
80
49
|
}
|
|
81
50
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
EventSystem.systems.push(this);
|
|
51
|
+
static createIfNoneExists(context: Context) {
|
|
52
|
+
if (!context.scene.getComponent(EventSystem)) {
|
|
53
|
+
context.scene.addComponent(EventSystem);
|
|
54
|
+
}
|
|
87
55
|
}
|
|
88
56
|
|
|
89
|
-
get
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
onDestroy(): void {
|
|
93
|
-
EventSystem.systems.splice(EventSystem.systems.indexOf(this), 1);
|
|
57
|
+
static get(ctx: Context): EventSystem | null {
|
|
58
|
+
this.createIfNoneExists(ctx);
|
|
59
|
+
return ctx.scene.getComponent(EventSystem);
|
|
94
60
|
}
|
|
95
61
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const res = GameObject.findObjectOfType(Raycaster, this.context);
|
|
99
|
-
if (!res) {
|
|
100
|
-
const rc = GameObject.addComponent(this.context.scene, ObjectRaycaster);
|
|
101
|
-
this.raycaster.push(rc);
|
|
102
|
-
if (isDevEnvironment() || debug)
|
|
103
|
-
console.warn("Added an ObjectRaycaster to the scene because no raycaster was found.");
|
|
104
|
-
}
|
|
105
|
-
}
|
|
62
|
+
static get instance(): EventSystem | null {
|
|
63
|
+
return this.get(Context.Current);
|
|
106
64
|
}
|
|
107
65
|
|
|
66
|
+
private readonly raycaster: Raycaster[] = [];
|
|
108
67
|
register(rc: Raycaster) {
|
|
109
68
|
if (rc && this.raycaster && !this.raycaster.includes(rc))
|
|
110
69
|
this.raycaster?.push(rc);
|
|
@@ -116,6 +75,23 @@ export class EventSystem extends Behaviour {
|
|
|
116
75
|
}
|
|
117
76
|
}
|
|
118
77
|
|
|
78
|
+
get hasActiveUI() { return this.currentActiveMeshUIComponents.length > 0; }
|
|
79
|
+
get isHoveringObjects() { return this.hoveredByID.size > 0; }
|
|
80
|
+
|
|
81
|
+
awake(): void {
|
|
82
|
+
// We only want ONE eventsystem on the root scene
|
|
83
|
+
// as long as this component is not implemented in core we need to check this here
|
|
84
|
+
if (this.gameObject as Object3D !== this.context.scene) {
|
|
85
|
+
this.enabled = false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
start() {
|
|
90
|
+
if (!this.context.scene.getComponent(Raycaster)) {
|
|
91
|
+
this.context.scene.addComponent(ObjectRaycaster);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
119
95
|
onEnable(): void {
|
|
120
96
|
this.context.input.addEventListener(InputEvents.PointerDown, this.onPointerEvent);
|
|
121
97
|
this.context.input.addEventListener(InputEvents.PointerUp, this.onPointerEvent);
|
|
@@ -183,7 +159,6 @@ export class EventSystem extends Behaviour {
|
|
|
183
159
|
options.screenPoint = this.context.input.getPointerPositionRC(pointerEvent.pointerId)!;
|
|
184
160
|
}
|
|
185
161
|
|
|
186
|
-
|
|
187
162
|
const hits = this.performRaycast(options) as Array<NEPointerEventIntersection>;
|
|
188
163
|
if (hits) {
|
|
189
164
|
for (const hit of hits) {
|
|
@@ -242,6 +217,14 @@ export class EventSystem extends Behaviour {
|
|
|
242
217
|
// TODO: this implementation below should be removed and we should regularly raycast objects in the scene unless marked as "do not raycast"
|
|
243
218
|
// with the introduction of the mesh-bvh based raycasting the performance impact should be greatly reduced. But this needs further testing
|
|
244
219
|
|
|
220
|
+
const raycasterOnObject = obj && "getComponent" in obj ? obj.getComponent(Raycaster) : null;
|
|
221
|
+
if (raycasterOnObject && raycasterOnObject != this._currentlyActiveRaycaster) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
// if (this._currentPointerEventName == "pointermove") {
|
|
225
|
+
// console.log(this.context.time.frame, obj.name, obj.type, obj.guid)
|
|
226
|
+
// }
|
|
227
|
+
|
|
245
228
|
// check if this object is actually a UI shadow hierarchy object
|
|
246
229
|
let uiOwner: Object3D | null = null;
|
|
247
230
|
const isUI = isUIObject(obj);
|
|
@@ -450,7 +433,7 @@ export class EventSystem extends Behaviour {
|
|
|
450
433
|
isShadow = true;
|
|
451
434
|
}
|
|
452
435
|
}
|
|
453
|
-
|
|
436
|
+
|
|
454
437
|
// adding this to have a way for allowing to receive events on TMUI elements without shadow hierarchy
|
|
455
438
|
// if(parent["needle:use_eventsystem"] == true){
|
|
456
439
|
// // if use_eventsystem is true, we want to handle the event
|
|
@@ -671,7 +654,7 @@ export class EventSystem extends Behaviour {
|
|
|
671
654
|
comp[symbol] = state;
|
|
672
655
|
return true;
|
|
673
656
|
}
|
|
674
|
-
else
|
|
657
|
+
else {
|
|
675
658
|
if (!state || !state.includes(pointerId)) return false;
|
|
676
659
|
const i = state.indexOf(pointerId);
|
|
677
660
|
if (i !== -1) {
|
|
@@ -3,7 +3,7 @@ import { FrameEvent } from "../../engine/engine_setup.js";
|
|
|
3
3
|
import { DeviceUtilities, getParam } from "../../engine/engine_utils.js";
|
|
4
4
|
import { Behaviour, GameObject } from "../Component.js";
|
|
5
5
|
import { EventList } from "../EventList.js";
|
|
6
|
-
import { type IPointerEventHandler } from "./PointerEvents.js";
|
|
6
|
+
import { type IPointerEventHandler,PointerEventData } from "./PointerEvents.js";
|
|
7
7
|
import { Text } from "./Text.js";
|
|
8
8
|
import { tryGetUIComponent } from "./Utils.js";
|
|
9
9
|
|
|
@@ -113,6 +113,14 @@ export class InputField extends Behaviour implements IPointerEventHandler {
|
|
|
113
113
|
this.onDeselected();
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
onPointerEnter(_args: PointerEventData) {
|
|
117
|
+
const canSetCursor = _args.event.pointerType === "mouse" && _args.button === 0;
|
|
118
|
+
if(canSetCursor) this.context.input.setCursor("text");
|
|
119
|
+
}
|
|
120
|
+
onPointerExit(_args: PointerEventData) {
|
|
121
|
+
this.context.input.unsetCursor("text")
|
|
122
|
+
}
|
|
123
|
+
|
|
116
124
|
onPointerClick(_args) {
|
|
117
125
|
if (debug) console.log("CLICK", _args, InputField.active);
|
|
118
126
|
InputField.activeTime = this.context.time.time;
|
|
@@ -91,12 +91,12 @@ export class OpenURL extends Behaviour implements IPointerClickHandler {
|
|
|
91
91
|
/** @internal */
|
|
92
92
|
onPointerEnter(args) {
|
|
93
93
|
if (!args.used && this.clickable)
|
|
94
|
-
this.context.input.
|
|
94
|
+
this.context.input.setCursor("pointer");
|
|
95
95
|
}
|
|
96
96
|
/** @internal */
|
|
97
97
|
onPointerExit() {
|
|
98
98
|
if (this.clickable)
|
|
99
|
-
this.context.input.
|
|
99
|
+
this.context.input.unsetCursor("pointer");
|
|
100
100
|
}
|
|
101
101
|
/** @internal */
|
|
102
102
|
onPointerClick(args: PointerEventData) {
|
|
@@ -160,9 +160,13 @@ class ImageTrackingExtension implements IUSDExporterExtension {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
onAfterHierarchy(_context: USDZExporterContext, writer: USDWriter) {
|
|
163
|
+
const iOSVersion = DeviceUtilities.getiOSVersion();
|
|
164
|
+
const majorVersion = iOSVersion ? parseInt(iOSVersion.split(".")[0]) : 18;
|
|
165
|
+
const workaroundForFB16119331 = majorVersion >= 18;
|
|
166
|
+
const multiplier = workaroundForFB16119331 ? 1 : 100;
|
|
163
167
|
writer.beginBlock(`def Preliminary_ReferenceImage "AnchoringReferenceImage"`);
|
|
164
168
|
writer.appendLine(`uniform asset image = @image_tracking/` + this.filename + `@`);
|
|
165
|
-
writer.appendLine(`uniform double physicalWidth = ` + (this.widthInMeters *
|
|
169
|
+
writer.appendLine(`uniform double physicalWidth = ` + (this.widthInMeters * multiplier).toFixed(8));
|
|
166
170
|
writer.closeBlock();
|
|
167
171
|
}
|
|
168
172
|
|