@needle-tools/engine 3.2.15-alpha → 3.4.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 +23 -0
- package/dist/needle-engine.js +44005 -36382
- package/dist/needle-engine.min.js +706 -513
- package/dist/needle-engine.umd.cjs +685 -492
- package/lib/engine/codegen/register_types.js +54 -4
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +3 -3
- package/lib/engine/engine_addressables.js +30 -9
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_element.js +1 -1
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_gameobject.d.ts +2 -1
- package/lib/engine/engine_gameobject.js +19 -0
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_input.js +10 -0
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_math.d.ts +4 -0
- package/lib/engine/engine_math.js +6 -0
- package/lib/engine/engine_math.js.map +1 -1
- package/lib/engine/engine_three_utils.js +2 -2
- package/lib/engine/engine_three_utils.js.map +1 -1
- package/lib/engine-components/Animation.js +4 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +7 -2
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/OrbitControls.js +13 -4
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/TransformGizmo.d.ts +8 -4
- package/lib/engine-components/TransformGizmo.js +62 -63
- package/lib/engine-components/TransformGizmo.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +27 -2
- package/lib/engine-components/codegen/components.js +27 -2
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/export/usdz/Extension.d.ts +4 -4
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +86 -0
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +830 -0
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -0
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +6 -3
- package/lib/engine-components/export/usdz/USDZExporter.js +34 -11
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/Animation.d.ts +15 -15
- package/lib/engine-components/export/usdz/extensions/Animation.js +24 -29
- package/lib/engine-components/export/usdz/extensions/Animation.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/DocumentExtension.d.ts +5 -0
- package/lib/engine-components/export/usdz/extensions/DocumentExtension.js +7 -0
- package/lib/engine-components/export/usdz/extensions/DocumentExtension.js.map +1 -0
- package/lib/engine-components/export/usdz/extensions/USDZText.d.ts +47 -0
- package/lib/engine-components/export/usdz/extensions/USDZText.js +114 -0
- package/lib/engine-components/export/usdz/extensions/USDZText.js.map +1 -0
- package/lib/engine-components/export/usdz/extensions/behavior/Actions.d.ts +30 -0
- package/lib/engine-components/export/usdz/extensions/behavior/Actions.js +89 -0
- package/lib/engine-components/export/usdz/extensions/behavior/Actions.js.map +1 -0
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +23 -0
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +114 -0
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js.map +1 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +96 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +421 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.d.ts +111 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js +409 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js.map +1 -0
- package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
- package/lib/engine-components/ui/BaseUIComponent.d.ts +2 -0
- package/lib/engine-components/ui/BaseUIComponent.js +6 -0
- package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
- package/lib/engine-components/ui/Button.js +9 -5
- package/lib/engine-components/ui/Button.js.map +1 -1
- package/lib/engine-components/ui/Canvas.d.ts +23 -6
- package/lib/engine-components/ui/Canvas.js +167 -34
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.d.ts +6 -0
- package/lib/engine-components/ui/EventSystem.js +4 -4
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +5 -2
- package/lib/engine-components/ui/Graphic.js +38 -7
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/Image.d.ts +1 -0
- package/lib/engine-components/ui/Image.js +14 -5
- package/lib/engine-components/ui/Image.js.map +1 -1
- package/lib/engine-components/ui/InputField.d.ts +1 -0
- package/lib/engine-components/ui/InputField.js +8 -0
- package/lib/engine-components/ui/InputField.js.map +1 -1
- package/lib/engine-components/ui/Interfaces.d.ts +19 -0
- package/lib/engine-components/ui/Interfaces.js +11 -0
- package/lib/engine-components/ui/Interfaces.js.map +1 -1
- package/lib/engine-components/ui/Layout.d.ts +65 -3
- package/lib/engine-components/ui/Layout.js +304 -3
- package/lib/engine-components/ui/Layout.js.map +1 -1
- package/lib/engine-components/ui/Outline.d.ts +7 -0
- package/lib/engine-components/ui/Outline.js +21 -0
- package/lib/engine-components/ui/Outline.js.map +1 -0
- package/lib/engine-components/ui/RectTransform.d.ts +32 -13
- package/lib/engine-components/ui/RectTransform.js +216 -56
- package/lib/engine-components/ui/RectTransform.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +13 -10
- package/lib/engine-components/ui/Text.js +177 -246
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/utils/LookAt.d.ts +13 -0
- package/lib/engine-components/utils/LookAt.js +66 -0
- package/lib/engine-components/utils/LookAt.js.map +1 -0
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +12 -3
- package/lib/engine-components/webxr/WebXRImageTracking.js +156 -24
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/plugins/vite/reload.js +13 -2
- package/src/engine/codegen/register_types.js +56 -6
- package/src/engine/engine_addressables.ts +28 -10
- package/src/engine/engine_element.ts +1 -1
- package/src/engine/engine_gameobject.ts +19 -1
- package/src/engine/engine_input.ts +11 -0
- package/src/engine/engine_math.ts +10 -0
- package/src/engine/engine_three_utils.ts +2 -2
- package/src/engine-components/Animation.ts +4 -0
- package/src/engine-components/AnimatorController.ts +7 -1
- package/src/engine-components/OrbitControls.ts +14 -6
- package/src/engine-components/TransformGizmo.ts +64 -70
- package/src/engine-components/codegen/components.ts +27 -2
- package/src/engine-components/export/usdz/Extension.ts +4 -5
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +1280 -0
- package/src/engine-components/export/usdz/USDZExporter.ts +39 -17
- package/src/engine-components/export/usdz/extensions/Animation.ts +37 -45
- package/src/engine-components/export/usdz/extensions/DocumentExtension.ts +10 -0
- package/src/engine-components/export/usdz/extensions/USDZText.ts +142 -0
- package/src/engine-components/export/usdz/extensions/behavior/Actions.ts +99 -0
- package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +181 -0
- package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +503 -0
- package/src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +459 -0
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +1 -1
- package/src/engine-components/ui/BaseUIComponent.ts +7 -1
- package/src/engine-components/ui/Button.ts +14 -9
- package/src/engine-components/ui/Canvas.ts +178 -39
- package/src/engine-components/ui/EventSystem.ts +16 -9
- package/src/engine-components/ui/Graphic.ts +46 -8
- package/src/engine-components/ui/Image.ts +13 -4
- package/src/engine-components/ui/InputField.ts +9 -1
- package/src/engine-components/ui/Interfaces.ts +39 -3
- package/src/engine-components/ui/Layout.ts +303 -4
- package/src/engine-components/ui/Outline.ts +13 -0
- package/src/engine-components/ui/RectTransform.ts +236 -68
- package/src/engine-components/ui/Text.ts +284 -265
- package/src/engine-components/utils/LookAt.ts +74 -0
- package/src/engine-components/webxr/WebXRImageTracking.ts +179 -31
- package/lib/engine-components/export/usdz/types.d.ts +0 -34
- package/lib/engine-components/export/usdz/types.js +0 -2
- package/lib/engine-components/export/usdz/types.js.map +0 -1
- package/lib/engine-components/ui/Keyboard.d.ts +0 -31
- package/lib/engine-components/ui/Keyboard.js +0 -178
- package/lib/engine-components/ui/Keyboard.js.map +0 -1
- package/src/engine-components/export/usdz/types.ts +0 -39
- package/src/engine-components/ui/Keyboard.ts +0 -204
|
@@ -2,13 +2,15 @@ import { onChange, updateRenderSettings as updateRenderSettingsRecursive } from
|
|
|
2
2
|
import { serializable } from "../../engine/engine_serialization_decorator";
|
|
3
3
|
import { FrameEvent } from "../../engine/engine_setup";
|
|
4
4
|
import { BaseUIComponent, UIRootComponent } from "./BaseUIComponent";
|
|
5
|
-
import { Mathf } from "../../engine/engine_math";
|
|
6
|
-
import * as THREE from "three";
|
|
7
|
-
import { getComponentsInChildren } from "../../engine/engine_components";
|
|
8
|
-
import { IComponent } from "../../engine/engine_types";
|
|
9
5
|
import { GameObject } from "../Component";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
6
|
+
import { Matrix4, Object3D } from "three";
|
|
7
|
+
import { RectTransform } from "./RectTransform";
|
|
8
|
+
import { ICanvas, ILayoutGroup, IRectTransform } from "./Interfaces";
|
|
9
|
+
import { Camera } from "../Camera";
|
|
10
|
+
import { EventSystem } from "./EventSystem";
|
|
11
|
+
import * as ThreeMeshUI from 'three-mesh-ui'
|
|
12
|
+
import { getParam } from "../../engine/engine_utils";
|
|
13
|
+
import { LayoutGroup } from "./Layout";
|
|
12
14
|
|
|
13
15
|
export enum RenderMode {
|
|
14
16
|
ScreenSpaceOverlay = 0,
|
|
@@ -17,7 +19,17 @@ export enum RenderMode {
|
|
|
17
19
|
Undefined = -1,
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
const debugLayout = getParam("debuguilayout");
|
|
23
|
+
|
|
24
|
+
export class Canvas extends UIRootComponent implements ICanvas {
|
|
25
|
+
|
|
26
|
+
get isCanvas() {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get screenspace(): any {
|
|
31
|
+
return this.renderMode !== RenderMode.WorldSpace;
|
|
32
|
+
}
|
|
21
33
|
|
|
22
34
|
@serializable()
|
|
23
35
|
set renderOnTop(val: boolean) {
|
|
@@ -27,8 +39,15 @@ export class Canvas extends UIRootComponent {
|
|
|
27
39
|
this._renderOnTop = val;
|
|
28
40
|
this.onRenderSettingsChanged();
|
|
29
41
|
}
|
|
30
|
-
get renderOnTop() {
|
|
31
|
-
|
|
42
|
+
get renderOnTop() {
|
|
43
|
+
if (this._renderOnTop !== undefined) return this._renderOnTop;
|
|
44
|
+
if (this.screenspace) {
|
|
45
|
+
// Render ScreenSpaceOverlay always on top
|
|
46
|
+
if (this._renderMode === RenderMode.ScreenSpaceOverlay) return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
private _renderOnTop: boolean | undefined;
|
|
32
51
|
|
|
33
52
|
@serializable()
|
|
34
53
|
set depthWrite(val: boolean) {
|
|
@@ -99,43 +118,131 @@ export class Canvas extends UIRootComponent {
|
|
|
99
118
|
this._scaleFactor = val;
|
|
100
119
|
}
|
|
101
120
|
|
|
121
|
+
@serializable(Camera)
|
|
122
|
+
worldCamera?: Camera;
|
|
123
|
+
|
|
124
|
+
@serializable()
|
|
125
|
+
planeDistance: number = -1;
|
|
126
|
+
|
|
102
127
|
awake() {
|
|
128
|
+
//@ts-ignore
|
|
103
129
|
this.shadowComponent = this.gameObject;
|
|
104
130
|
super.awake();
|
|
105
131
|
}
|
|
106
132
|
|
|
133
|
+
start() {
|
|
134
|
+
this.onUpdateRenderMode();
|
|
135
|
+
}
|
|
136
|
+
|
|
107
137
|
onEnable() {
|
|
108
138
|
super.onEnable();
|
|
109
139
|
this._updateRenderSettingsRoutine = undefined;
|
|
110
140
|
this.onRenderSettingsChanged();
|
|
141
|
+
document.addEventListener("resize", this._boundRenderSettingsChanged);
|
|
142
|
+
// We want to run AFTER all regular onBeforeRender callbacks
|
|
143
|
+
this.context.pre_render_callbacks.push(this.onBeforeRenderRoutine);
|
|
144
|
+
this.context.post_render_callbacks.push(this.onAfterRenderRoutine);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
onDisable(): void {
|
|
148
|
+
super.onDisable();
|
|
149
|
+
document.removeEventListener("resize", this._boundRenderSettingsChanged);
|
|
150
|
+
// Remove callbacks
|
|
151
|
+
const preRenderIndex = this.context.pre_render_callbacks.indexOf(this.onBeforeRenderRoutine);
|
|
152
|
+
if (preRenderIndex !== -1) {
|
|
153
|
+
this.context.pre_render_callbacks.splice(preRenderIndex, 1);
|
|
154
|
+
}
|
|
155
|
+
const postRenderIndex = this.context.post_render_callbacks.indexOf(this.onAfterRenderRoutine);
|
|
156
|
+
if (postRenderIndex !== -1) {
|
|
157
|
+
this.context.post_render_callbacks.splice(postRenderIndex, 1);
|
|
158
|
+
}
|
|
111
159
|
}
|
|
112
160
|
|
|
113
|
-
private
|
|
161
|
+
private _boundRenderSettingsChanged = this.onRenderSettingsChanged.bind(this);
|
|
162
|
+
|
|
114
163
|
private previousParent: Object3D | null = null;
|
|
164
|
+
private _lastMatrixWorld: Matrix4 | null = null;
|
|
165
|
+
private _rectTransforms: IRectTransform[] = [];
|
|
115
166
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
167
|
+
registerTransform(rt: IRectTransform) {
|
|
168
|
+
this._rectTransforms.push(rt);
|
|
169
|
+
}
|
|
170
|
+
unregisterTransform(rt: IRectTransform) {
|
|
171
|
+
const index = this._rectTransforms.indexOf(rt);
|
|
172
|
+
if (index !== -1) {
|
|
173
|
+
this._rectTransforms.splice(index, 1);
|
|
120
174
|
}
|
|
121
|
-
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private _layoutGroups: Map<Object3D, ILayoutGroup> = new Map();
|
|
178
|
+
registerLayoutGroup(group: ILayoutGroup) {
|
|
179
|
+
const obj = group.gameObject;
|
|
180
|
+
this._layoutGroups.set(obj, group)
|
|
181
|
+
}
|
|
182
|
+
unregisterLayoutGroup(group: ILayoutGroup) {
|
|
183
|
+
const obj = group.gameObject;
|
|
184
|
+
this._layoutGroups.delete(obj);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
onBeforeRenderRoutine = () => {
|
|
188
|
+
if (this.renderOnTop) {
|
|
122
189
|
// 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
190
|
this.previousParent = this.gameObject.parent;
|
|
124
191
|
this.gameObject.removeFromParent();
|
|
125
192
|
}
|
|
193
|
+
else {
|
|
194
|
+
this.onUpdateRenderMode();
|
|
195
|
+
this.handleLayoutUpdates();
|
|
196
|
+
// TODO: we might need to optimize this. This is here to make sure the TMUI text clipping matrices are correct. Ideally the text does use onBeforeRender and apply the clipping matrix there so we dont have to force update all the matrices here
|
|
197
|
+
this.shadowComponent?.updateMatrixWorld(true);
|
|
198
|
+
this.shadowComponent?.updateWorldMatrix(true, true);
|
|
199
|
+
EventSystem.ensureUpdateMeshUI(ThreeMeshUI, this.context);
|
|
200
|
+
}
|
|
126
201
|
}
|
|
127
202
|
|
|
128
|
-
|
|
203
|
+
onAfterRenderRoutine = () => {
|
|
129
204
|
if (this.renderOnTop && this.previousParent && this.context.mainCamera) {
|
|
130
205
|
this.previousParent.add(this.gameObject);
|
|
131
206
|
this.context.renderer.autoClear = false;
|
|
132
207
|
this.context.renderer.clearDepth();
|
|
208
|
+
this.onUpdateRenderMode(true);
|
|
209
|
+
this.handleLayoutUpdates();
|
|
210
|
+
this.shadowComponent?.updateMatrixWorld(true);
|
|
211
|
+
// this.handleLayoutUpdates();
|
|
212
|
+
EventSystem.ensureUpdateMeshUI(ThreeMeshUI, this.context);
|
|
133
213
|
this.context.renderer.render(this.gameObject, this.context.mainCamera);
|
|
134
214
|
this.context.renderer.autoClear = true;
|
|
135
215
|
}
|
|
216
|
+
this._lastMatrixWorld?.copy(this.gameObject.matrixWorld);
|
|
136
217
|
}
|
|
137
218
|
|
|
138
|
-
|
|
219
|
+
private handleLayoutUpdates() {
|
|
220
|
+
if (this._lastMatrixWorld === null) {
|
|
221
|
+
this._lastMatrixWorld = new Matrix4();
|
|
222
|
+
}
|
|
223
|
+
const matrixWorldChanged = !this._lastMatrixWorld.equals(this.gameObject.matrixWorld);
|
|
224
|
+
if (debugLayout && matrixWorldChanged) console.log("Canvas Layout changed", this.context.time.frameCount, this.name);
|
|
225
|
+
|
|
226
|
+
// TODO: optimize this, we should only need to update a subhierarchy of the parts where layout has changed
|
|
227
|
+
let didLog = false;
|
|
228
|
+
for (const ch of this._rectTransforms) {
|
|
229
|
+
if (matrixWorldChanged) ch.markDirty();
|
|
230
|
+
let layout = this._layoutGroups.get(ch.gameObject);
|
|
231
|
+
if(ch.isDirty && !layout){
|
|
232
|
+
layout = ch.gameObject.getComponentInParent(LayoutGroup) as LayoutGroup;
|
|
233
|
+
}
|
|
234
|
+
if (ch.isDirty || layout?.isDirty) {
|
|
235
|
+
if (debugLayout && !didLog) {
|
|
236
|
+
console.log("CANVAS UPDATE ### " + ch.name + " ##################################### " + this.context.time.frame);
|
|
237
|
+
// didLog = true;
|
|
238
|
+
}
|
|
239
|
+
layout?.updateLayout();
|
|
240
|
+
ch.updateTransform();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
applyRenderSettings() {
|
|
139
246
|
this.onRenderSettingsChanged();
|
|
140
247
|
}
|
|
141
248
|
|
|
@@ -149,7 +256,7 @@ export class Canvas extends UIRootComponent {
|
|
|
149
256
|
yield;
|
|
150
257
|
this._updateRenderSettingsRoutine = undefined;
|
|
151
258
|
if (this.shadowComponent) {
|
|
152
|
-
this.
|
|
259
|
+
this.onUpdateRenderMode();
|
|
153
260
|
// this.onWillUpdateRenderSettings();
|
|
154
261
|
updateRenderSettingsRecursive(this.shadowComponent, this);
|
|
155
262
|
for (const ch of GameObject.getComponentsInChildren(this.gameObject, BaseUIComponent)) {
|
|
@@ -159,44 +266,76 @@ export class Canvas extends UIRootComponent {
|
|
|
159
266
|
}
|
|
160
267
|
|
|
161
268
|
private _activeRenderMode: RenderMode = -1;
|
|
269
|
+
private _lastWidth: number = -1;
|
|
270
|
+
private _lastHeight: number = -1;
|
|
162
271
|
|
|
163
|
-
private get isScreenSpace(): boolean {
|
|
164
|
-
return this._activeRenderMode === RenderMode.ScreenSpaceCamera || this._activeRenderMode === RenderMode.ScreenSpaceOverlay;
|
|
165
|
-
}
|
|
166
272
|
|
|
167
|
-
private
|
|
168
|
-
if (
|
|
169
|
-
|
|
273
|
+
private onUpdateRenderMode(force: boolean = false) {
|
|
274
|
+
if (!force) {
|
|
275
|
+
if (this._renderMode === this._activeRenderMode && this._lastWidth === this.context.domWidth && this._lastHeight === this.context.domHeight) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
this._activeRenderMode = this._renderMode;
|
|
280
|
+
let camera = this.context.mainCameraComponent;
|
|
281
|
+
let planeDistance: number = camera?.farClipPlane ?? 100;
|
|
282
|
+
if (this._renderMode === RenderMode.ScreenSpaceCamera) {
|
|
283
|
+
if (this.worldCamera)
|
|
284
|
+
camera = this.worldCamera as Camera;
|
|
285
|
+
if (this.planeDistance > 0)
|
|
286
|
+
planeDistance = this.planeDistance;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
switch (this._renderMode) {
|
|
170
290
|
case RenderMode.ScreenSpaceOverlay:
|
|
171
291
|
case RenderMode.ScreenSpaceCamera:
|
|
172
|
-
|
|
173
|
-
|
|
292
|
+
this._lastWidth = this.context.domWidth;
|
|
293
|
+
this._lastHeight = this.context.domHeight;
|
|
294
|
+
|
|
295
|
+
// showBalloonWarning("Screenspace Canvas is not supported yet. Please use worldspace");
|
|
174
296
|
if (!camera) return;
|
|
297
|
+
|
|
175
298
|
const canvas = this.gameObject;
|
|
176
299
|
const camObj = camera.gameObject;
|
|
177
300
|
camObj?.add(canvas);
|
|
178
|
-
|
|
301
|
+
// we move the plane SLIGHTLY closer to be sure not to cull the canvas
|
|
302
|
+
const plane = planeDistance - .1;
|
|
179
303
|
canvas.position.x = 0;
|
|
180
304
|
canvas.position.y = 0;
|
|
181
|
-
canvas.position.z = -
|
|
305
|
+
canvas.position.z = -plane;
|
|
306
|
+
canvas.quaternion.identity();
|
|
182
307
|
|
|
183
|
-
|
|
308
|
+
const rect = this.gameObject.getComponent(RectTransform)!;
|
|
309
|
+
let hasChanged = false;
|
|
310
|
+
if (rect.sizeDelta.x !== this.context.domWidth) {
|
|
311
|
+
hasChanged = true;
|
|
312
|
+
}
|
|
313
|
+
if (rect.sizeDelta.y !== this.context.domHeight) {
|
|
314
|
+
hasChanged = true;
|
|
315
|
+
}
|
|
184
316
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
317
|
+
const vFOV = camera.fieldOfView! * Math.PI / 180;
|
|
318
|
+
const h = 2 * Math.tan(vFOV / 2) * Math.abs(plane);
|
|
319
|
+
canvas.scale.x = h / this.context.domHeight;
|
|
320
|
+
canvas.scale.y = h / this.context.domHeight;
|
|
321
|
+
// Set scale.z, otherwise small offsets in screenspace mode have different visual results based on export scale and other settings
|
|
322
|
+
canvas.scale.z = .01;
|
|
190
323
|
|
|
324
|
+
if (hasChanged) {
|
|
325
|
+
rect.sizeDelta.x = this.context.domWidth;
|
|
326
|
+
rect.sizeDelta.y = this.context.domHeight;
|
|
327
|
+
rect?.markDirty();
|
|
191
328
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
//
|
|
195
|
-
//
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
// this.context.scene.add(this.gameObject)
|
|
332
|
+
// this.gameObject.scale.multiplyScalar(.01);
|
|
333
|
+
// this.gameObject.position.set(0,0,0);
|
|
196
334
|
|
|
197
335
|
break;
|
|
198
336
|
case RenderMode.WorldSpace:
|
|
199
|
-
|
|
337
|
+
this._lastWidth = -1;
|
|
338
|
+
this._lastHeight = -1;
|
|
200
339
|
break;
|
|
201
340
|
}
|
|
202
341
|
}
|
|
@@ -7,7 +7,7 @@ import { Context } from "../../engine/engine_setup";
|
|
|
7
7
|
import { OrbitControls } from "../OrbitControls";
|
|
8
8
|
import { IPointerEventHandler, PointerEventData } from "./PointerEvents";
|
|
9
9
|
import { ObjectRaycaster, Raycaster } from "./Raycaster";
|
|
10
|
-
import { InputEvents } from "../../engine/engine_input";
|
|
10
|
+
import { InputEvents, PointerEventArgs } from "../../engine/engine_input";
|
|
11
11
|
import { Object3D } from "three";
|
|
12
12
|
import { ICanvasGroup, IGraphic } from "./Interfaces";
|
|
13
13
|
import { getParam } from "../../engine/engine_utils";
|
|
@@ -22,6 +22,12 @@ export enum EventSystemEvents {
|
|
|
22
22
|
AfterHandleInput = "AfterHandleInput",
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export declare type AfterHandleInputEvent = {
|
|
26
|
+
sender: EventSystem,
|
|
27
|
+
args: PointerEventData,
|
|
28
|
+
hasActiveUI: boolean
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
export class EventSystem extends Behaviour {
|
|
26
32
|
|
|
27
33
|
|
|
@@ -249,16 +255,16 @@ export class EventSystem extends Behaviour {
|
|
|
249
255
|
if (!hits) return;
|
|
250
256
|
this.lastPointerEvent = args;
|
|
251
257
|
|
|
252
|
-
const evt = {
|
|
258
|
+
const evt : AfterHandleInputEvent = {
|
|
253
259
|
sender: this,
|
|
254
260
|
args: args,
|
|
255
261
|
hasActiveUI: this.currentActiveMeshUIComponents.length > 0,
|
|
256
262
|
}
|
|
257
|
-
if(debug && args.isClicked)
|
|
258
|
-
showBalloonMessage("EventSystem: " +
|
|
263
|
+
if (debug && args.isClicked)
|
|
264
|
+
showBalloonMessage("EventSystem: " + args.pointerId + " - " + this.context.time.frame + " - Up:" + args.isUp + ", Down:" + args.isDown)
|
|
259
265
|
this.dispatchEvent(new CustomEvent(EventSystemEvents.BeforeHandleInput, { detail: evt }))
|
|
260
266
|
this.handleIntersections(hits, args);
|
|
261
|
-
this.dispatchEvent(new CustomEvent(EventSystemEvents.AfterHandleInput, { detail: evt }))
|
|
267
|
+
this.dispatchEvent(new CustomEvent<AfterHandleInputEvent>(EventSystemEvents.AfterHandleInput, { detail: evt }))
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
private _tempComponentsArray: Behaviour[] = [];
|
|
@@ -518,8 +524,8 @@ class MeshUIHelper {
|
|
|
518
524
|
if (currentFrame === lu.frame) return;
|
|
519
525
|
lu.frame = currentFrame;
|
|
520
526
|
let shouldUpdate = this.needsUpdate || currentFrame < 1;
|
|
521
|
-
if(lu.nextUpdate === context.time.frameCount) shouldUpdate = true;
|
|
522
|
-
if(this.needsUpdate) lu.nextUpdate = currentFrame + 3;
|
|
527
|
+
if (lu.nextUpdate === context.time.frameCount) shouldUpdate = true;
|
|
528
|
+
// if(this.needsUpdate) lu.nextUpdate = currentFrame + 3;
|
|
523
529
|
if (shouldUpdate) {
|
|
524
530
|
if (debug)
|
|
525
531
|
console.log("Update threemeshui");
|
|
@@ -564,8 +570,9 @@ class MeshUIHelper {
|
|
|
564
570
|
static findBlockInParent(elem: any): ThreeMeshUI.Block | null {
|
|
565
571
|
if (!elem) return null;
|
|
566
572
|
if (elem.isBlock) {
|
|
567
|
-
|
|
568
|
-
|
|
573
|
+
// @TODO : Replace states managements
|
|
574
|
+
// if (Object.keys(elem.states).length > 0)
|
|
575
|
+
return elem;
|
|
569
576
|
}
|
|
570
577
|
return this.findBlockInParent(elem.parent);
|
|
571
578
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IGraphic } from './Interfaces';
|
|
1
|
+
import { IGraphic, IRectTransformChangedReceiver } from './Interfaces';
|
|
2
2
|
import * as ThreeMeshUI from 'three-mesh-ui'
|
|
3
3
|
import { RGBAColor } from "../js-extensions/RGBAColor"
|
|
4
4
|
import { BaseUIComponent } from "./BaseUIComponent";
|
|
@@ -7,9 +7,17 @@ import { Color, LinearEncoding, sRGBEncoding, Texture } from 'three';
|
|
|
7
7
|
import { RectTransform } from './RectTransform';
|
|
8
8
|
import { onChange, scheduleAction } from "./Utils"
|
|
9
9
|
import { GameObject } from '../Component';
|
|
10
|
+
import SimpleStateBehavior from "three-mesh-ui/examples/behaviors/states/SimpleStateBehavior"
|
|
11
|
+
import { Outline } from './Outline';
|
|
12
|
+
import { BehaviorExtension, UsdzBehaviour } from '../../engine-components/export/usdz/extensions/behavior/Behaviour';
|
|
13
|
+
import { USDObject } from '../../engine-components/export/usdz/ThreeUSDZExporter';
|
|
10
14
|
|
|
15
|
+
const _colorStateObject: { backgroundColor: Color, backgroundOpacity: number } = {
|
|
16
|
+
backgroundColor: new Color(1, 1, 1),
|
|
17
|
+
backgroundOpacity: 1,
|
|
18
|
+
};
|
|
11
19
|
|
|
12
|
-
export class Graphic extends BaseUIComponent implements IGraphic {
|
|
20
|
+
export class Graphic extends BaseUIComponent implements IGraphic, IRectTransformChangedReceiver {
|
|
13
21
|
|
|
14
22
|
get isGraphic() { return true; }
|
|
15
23
|
|
|
@@ -26,9 +34,11 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
26
34
|
}
|
|
27
35
|
this._color.copy(col);
|
|
28
36
|
}
|
|
37
|
+
|
|
29
38
|
protected onColorChanged() {
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
_colorStateObject.backgroundColor = this._color;
|
|
40
|
+
_colorStateObject.backgroundOpacity = this._color.alpha;
|
|
41
|
+
this.uiObject?.set(_colorStateObject);
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
// used via animations
|
|
@@ -44,6 +54,9 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
44
54
|
|
|
45
55
|
|
|
46
56
|
private _rect: RectTransform | null = null;
|
|
57
|
+
|
|
58
|
+
private _stateManager : SimpleStateBehavior | null = null;
|
|
59
|
+
|
|
47
60
|
protected get rectTransform(): RectTransform {
|
|
48
61
|
if (!this._rect) {
|
|
49
62
|
this._rect = GameObject.getComponent(this.gameObject, RectTransform);
|
|
@@ -51,6 +64,11 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
51
64
|
return this._rect!;
|
|
52
65
|
}
|
|
53
66
|
|
|
67
|
+
onParentRectTransformChanged() {
|
|
68
|
+
this.uiObject?.set({ width: this.rectTransform.width, height:this.rectTransform.height })
|
|
69
|
+
this.markDirty();
|
|
70
|
+
}
|
|
71
|
+
|
|
54
72
|
__internalNewInstanceCreated(): void {
|
|
55
73
|
super.__internalNewInstanceCreated();
|
|
56
74
|
this._rect = null;
|
|
@@ -63,14 +81,21 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
63
81
|
if (this.uiObject) {
|
|
64
82
|
//@ts-ignore
|
|
65
83
|
this.uiObject.setState(state);
|
|
84
|
+
this?.markDirty();
|
|
66
85
|
}
|
|
67
86
|
}
|
|
68
87
|
|
|
69
88
|
setupState(state: object) {
|
|
70
89
|
this.makePanel();
|
|
71
90
|
if (this.uiObject) {
|
|
91
|
+
|
|
92
|
+
// @marwie : v7.x now have a concurrent state management in core mimicking html/css
|
|
93
|
+
// ie : (::firstChild::hover::disabled) where firstchild, hover and disabled are all on different channels
|
|
94
|
+
// In order to keep needle Raycaster and EventSystem intact, I added in v7 a SimpleStateBehavior, which acts as previously
|
|
95
|
+
|
|
96
|
+
if( !this._stateManager ) this._stateManager = new SimpleStateBehavior(this.uiObject);
|
|
72
97
|
//@ts-ignore
|
|
73
|
-
this.uiObject.setupState(state);
|
|
98
|
+
this.uiObject.setupState(state.state, state.attributes);
|
|
74
99
|
}
|
|
75
100
|
}
|
|
76
101
|
|
|
@@ -79,8 +104,8 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
79
104
|
if (this.uiObject) {
|
|
80
105
|
//@ts-ignore
|
|
81
106
|
this.uiObject.set(opts);
|
|
82
|
-
if (opts["backgroundColor"] !== undefined || opts["backgroundOpacity"] !== undefined)
|
|
83
|
-
|
|
107
|
+
// if (opts["backgroundColor"] !== undefined || opts["backgroundOpacity"] !== undefined)
|
|
108
|
+
// this.uiObject["updateBackgroundMaterial"]?.call(this.uiObject);
|
|
84
109
|
}
|
|
85
110
|
}
|
|
86
111
|
|
|
@@ -119,6 +144,7 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
119
144
|
offset: 1, // without a tiny offset we get z fighting
|
|
120
145
|
};
|
|
121
146
|
this.onBeforeCreate(opts);
|
|
147
|
+
this.applyEffects(opts);
|
|
122
148
|
this.onCreate(opts);
|
|
123
149
|
this.controlsChildLayout = false;
|
|
124
150
|
this._currentlyCreatingPanel = false;
|
|
@@ -133,6 +159,17 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
133
159
|
}
|
|
134
160
|
protected onAfterCreated() { }
|
|
135
161
|
|
|
162
|
+
private applyEffects(opts){
|
|
163
|
+
const outline = this.gameObject?.getComponent(Outline);
|
|
164
|
+
if (outline) {
|
|
165
|
+
if (outline.effectDistance) opts.borderWidth = Math.max(Math.abs(outline.effectDistance.x), Math.abs(outline.effectDistance.y));
|
|
166
|
+
if (outline.effectColor) {
|
|
167
|
+
opts.borderColor = outline.effectColor;
|
|
168
|
+
opts.borderOpacity = outline.effectColor.alpha;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
136
173
|
/** used internally to ensure textures assigned to UI use linear encoding */
|
|
137
174
|
static textureCache: Map<Texture, Texture> = new Map();
|
|
138
175
|
|
|
@@ -151,13 +188,14 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
151
188
|
tex = clone;
|
|
152
189
|
}
|
|
153
190
|
}
|
|
154
|
-
this.setOptions({
|
|
191
|
+
this.setOptions({ backgroundImage: tex, borderRadius: 0, backgroundOpacity: this.color.alpha, backgroundSize: "stretch" });
|
|
155
192
|
}
|
|
156
193
|
}
|
|
157
194
|
|
|
158
195
|
protected onAfterAddedToScene(): void {
|
|
159
196
|
super.onAfterAddedToScene();
|
|
160
197
|
if (this.shadowComponent) {
|
|
198
|
+
// @TODO: I think we dont even need this anymore and this leads to the offset being applied twice
|
|
161
199
|
//@ts-ignore
|
|
162
200
|
this.shadowComponent.offset = this.shadowComponent.position.z;
|
|
163
201
|
|
|
@@ -24,11 +24,15 @@ export class Image extends MaskableGraphic {
|
|
|
24
24
|
|
|
25
25
|
private _sprite?: Sprite;
|
|
26
26
|
|
|
27
|
+
@serializable()
|
|
28
|
+
private pixelsPerUnitMultiplier: number = 1;
|
|
29
|
+
|
|
27
30
|
private isBuiltinSprite() {
|
|
28
31
|
switch (this.sprite?.texture?.name) {
|
|
29
32
|
case "InputFieldBackground":
|
|
30
33
|
case "UISprite":
|
|
31
34
|
case "Background":
|
|
35
|
+
case "Knob":
|
|
32
36
|
return true;
|
|
33
37
|
}
|
|
34
38
|
// this is a hack/workaround for production builds where the name of the sprite is missing
|
|
@@ -39,12 +43,17 @@ export class Image extends MaskableGraphic {
|
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
protected onBeforeCreate(opts: any): void {
|
|
46
|
+
super.onBeforeCreate(opts);
|
|
42
47
|
if (this.isBuiltinSprite()) {
|
|
43
|
-
opts.borderRadius = 5;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
opts.borderRadius = 5 / this.pixelsPerUnitMultiplier;
|
|
49
|
+
if(this.sprite?.texture?.name === "Knob") {
|
|
50
|
+
opts.borderRadius = 999;
|
|
51
|
+
}
|
|
52
|
+
// opts.borderColor = new Color(.4, .4, .4);
|
|
53
|
+
// opts.borderOpacity = this.color.alpha;
|
|
54
|
+
// opts.borderWidth = .3;
|
|
47
55
|
}
|
|
56
|
+
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
protected onAfterCreated(): void {
|
|
@@ -13,7 +13,7 @@ const debug = getParam("debuginputfield");
|
|
|
13
13
|
|
|
14
14
|
export class InputField extends Behaviour implements IPointerEventHandler {
|
|
15
15
|
|
|
16
|
-
get text()
|
|
16
|
+
get text(): string {
|
|
17
17
|
return this.textComponent?.text ?? "";
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -148,6 +148,14 @@ export class InputField extends Behaviour implements IPointerEventHandler {
|
|
|
148
148
|
this.onEndEdit?.invoke(InputField.htmlField.value);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
// @Marwie, I can provide this fix. But the issue seems to comes from Raycaster+EventSystem
|
|
152
|
+
// As we rollout InputField, and no others elements is behind raycast,
|
|
153
|
+
// ThreeMeshUI.update is not called.
|
|
154
|
+
update() {
|
|
155
|
+
if (InputField.active === this) {
|
|
156
|
+
this.textComponent?.markDirty();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
151
159
|
|
|
152
160
|
private onInput(evt: KeyboardEvent) {
|
|
153
161
|
if (InputField.active !== this) return;
|
|
@@ -1,12 +1,48 @@
|
|
|
1
|
+
import { Behaviour } from "../Component";
|
|
1
2
|
import { IComponent } from "../../engine/engine_types";
|
|
2
3
|
|
|
4
|
+
export interface ICanvas {
|
|
5
|
+
get isCanvas(): boolean;
|
|
6
|
+
get screenspace(): boolean;
|
|
7
|
+
registerTransform(rt: IRectTransform);
|
|
8
|
+
unregisterTransform(rt: IRectTransform);
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
export interface ICanvasGroup {
|
|
4
|
-
get isCanvasGroup()
|
|
12
|
+
get isCanvasGroup(): boolean;
|
|
5
13
|
blocksRaycasts: boolean;
|
|
6
14
|
interactable: boolean;
|
|
7
15
|
}
|
|
8
16
|
|
|
9
17
|
export interface IGraphic extends IComponent {
|
|
10
|
-
get isGraphic()
|
|
18
|
+
get isGraphic(): boolean;
|
|
11
19
|
raycastTarget: boolean;
|
|
12
|
-
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface IRectTransform extends IComponent {
|
|
23
|
+
get isDirty(): boolean;
|
|
24
|
+
markDirty();
|
|
25
|
+
updateTransform();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface IRectTransformChangedReceiver {
|
|
29
|
+
onParentRectTransformChanged(comp: IRectTransform): void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ILayoutGroup extends IComponent {
|
|
33
|
+
get isLayoutGroup(): boolean;
|
|
34
|
+
get isDirty(): boolean;
|
|
35
|
+
updateLayout();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// export abstract class LayoutGroup extends Behaviour implements IRectTransformChangedReceiver, ILayoutGroup {
|
|
39
|
+
// get isLayoutGroup(): boolean {
|
|
40
|
+
// return true;
|
|
41
|
+
// }
|
|
42
|
+
// updateLayout() {
|
|
43
|
+
// throw new Error("Method not implemented.");
|
|
44
|
+
// }
|
|
45
|
+
// onParentRectTransformChanged(comp: IRectTransform): void {
|
|
46
|
+
// throw new Error("Method not implemented.");
|
|
47
|
+
// }
|
|
48
|
+
// }
|