@needle-tools/engine 3.2.15-alpha → 3.3.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 +13 -0
- package/dist/needle-engine.js +42120 -35732
- package/dist/needle-engine.min.js +687 -495
- package/dist/needle-engine.umd.cjs +689 -497
- package/lib/engine/codegen/register_types.js +4 -2
- 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 +17 -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-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 +2 -1
- package/lib/engine-components/codegen/components.js +2 -1
- package/lib/engine-components/codegen/components.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 +13 -6
- package/lib/engine-components/ui/Canvas.js +101 -37
- 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 +10 -1
- 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 +8 -0
- 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 +29 -11
- package/lib/engine-components/ui/RectTransform.js +178 -46
- 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 +7 -0
- package/lib/engine-components/utils/LookAt.js +29 -0
- package/lib/engine-components/utils/LookAt.js.map +1 -0
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +8 -0
- package/lib/engine-components/webxr/WebXRImageTracking.js +79 -3
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/engine/codegen/register_types.js +4 -2
- package/src/engine/engine_addressables.ts +28 -10
- package/src/engine/engine_element.ts +1 -1
- package/src/engine/engine_gameobject.ts +18 -1
- package/src/engine/engine_input.ts +11 -0
- package/src/engine/engine_math.ts +10 -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 +2 -1
- package/src/engine-components/ui/Button.ts +14 -9
- package/src/engine-components/ui/Canvas.ts +104 -40
- package/src/engine-components/ui/EventSystem.ts +16 -9
- package/src/engine-components/ui/Graphic.ts +44 -8
- package/src/engine-components/ui/Image.ts +10 -1
- package/src/engine-components/ui/InputField.ts +9 -1
- package/src/engine-components/ui/Interfaces.ts +12 -0
- package/src/engine-components/ui/Outline.ts +13 -0
- package/src/engine-components/ui/RectTransform.ts +203 -60
- package/src/engine-components/ui/Text.ts +284 -265
- package/src/engine-components/utils/LookAt.ts +21 -0
- package/src/engine-components/webxr/WebXRImageTracking.ts +85 -10
- 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/ui/Keyboard.ts +0 -204
|
@@ -2,13 +2,13 @@ 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 { showBalloonMessage, showBalloonWarning } from "../../engine/debug";
|
|
11
6
|
import { Object3D } from "three";
|
|
7
|
+
import { RectTransform } from "./RectTransform";
|
|
8
|
+
import { ICanvas } from "./Interfaces";
|
|
9
|
+
import { Camera } from "../Camera";
|
|
10
|
+
import { EventSystem } from "./EventSystem";
|
|
11
|
+
import * as ThreeMeshUI from 'three-mesh-ui'
|
|
12
12
|
|
|
13
13
|
export enum RenderMode {
|
|
14
14
|
ScreenSpaceOverlay = 0,
|
|
@@ -17,7 +17,11 @@ export enum RenderMode {
|
|
|
17
17
|
Undefined = -1,
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export class Canvas extends UIRootComponent {
|
|
20
|
+
export class Canvas extends UIRootComponent implements ICanvas {
|
|
21
|
+
|
|
22
|
+
get screenspace(): any {
|
|
23
|
+
return this.renderMode !== RenderMode.WorldSpace;
|
|
24
|
+
}
|
|
21
25
|
|
|
22
26
|
@serializable()
|
|
23
27
|
set renderOnTop(val: boolean) {
|
|
@@ -27,8 +31,15 @@ export class Canvas extends UIRootComponent {
|
|
|
27
31
|
this._renderOnTop = val;
|
|
28
32
|
this.onRenderSettingsChanged();
|
|
29
33
|
}
|
|
30
|
-
get renderOnTop() {
|
|
31
|
-
|
|
34
|
+
get renderOnTop() {
|
|
35
|
+
if (this._renderOnTop !== undefined) return this._renderOnTop;
|
|
36
|
+
if (this.screenspace) {
|
|
37
|
+
// Render ScreenSpaceOverlay always on top
|
|
38
|
+
if (this._renderMode === RenderMode.ScreenSpaceOverlay) return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
private _renderOnTop: boolean | undefined;
|
|
32
43
|
|
|
33
44
|
@serializable()
|
|
34
45
|
set depthWrite(val: boolean) {
|
|
@@ -99,7 +110,14 @@ export class Canvas extends UIRootComponent {
|
|
|
99
110
|
this._scaleFactor = val;
|
|
100
111
|
}
|
|
101
112
|
|
|
113
|
+
@serializable(Camera)
|
|
114
|
+
worldCamera?: Camera;
|
|
115
|
+
|
|
116
|
+
@serializable()
|
|
117
|
+
planeDistance: number = -1;
|
|
118
|
+
|
|
102
119
|
awake() {
|
|
120
|
+
//@ts-ignore
|
|
103
121
|
this.shadowComponent = this.gameObject;
|
|
104
122
|
super.awake();
|
|
105
123
|
}
|
|
@@ -108,34 +126,59 @@ export class Canvas extends UIRootComponent {
|
|
|
108
126
|
super.onEnable();
|
|
109
127
|
this._updateRenderSettingsRoutine = undefined;
|
|
110
128
|
this.onRenderSettingsChanged();
|
|
129
|
+
document.addEventListener("resize", this._boundRenderSettingsChanged);
|
|
130
|
+
// We want to run AFTER all regular onBeforeRender callbacks
|
|
131
|
+
this.context.pre_render_callbacks.push(this.onBeforeRenderRoutine);
|
|
132
|
+
this.context.post_render_callbacks.push(this.onAfterRenderRoutine);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
onDisable(): void {
|
|
136
|
+
super.onDisable();
|
|
137
|
+
document.removeEventListener("resize", this._boundRenderSettingsChanged);
|
|
138
|
+
// Remove callbacks
|
|
139
|
+
const preRenderIndex = this.context.pre_render_callbacks.indexOf(this.onBeforeRenderRoutine);
|
|
140
|
+
if (preRenderIndex !== -1) {
|
|
141
|
+
this.context.pre_render_callbacks.splice(preRenderIndex, 1);
|
|
142
|
+
}
|
|
143
|
+
const postRenderIndex = this.context.post_render_callbacks.indexOf(this.onAfterRenderRoutine);
|
|
144
|
+
if (postRenderIndex !== -1) {
|
|
145
|
+
this.context.post_render_callbacks.splice(postRenderIndex, 1);
|
|
146
|
+
}
|
|
111
147
|
}
|
|
112
148
|
|
|
113
|
-
private
|
|
149
|
+
private _boundRenderSettingsChanged = this.onRenderSettingsChanged.bind(this);
|
|
150
|
+
|
|
114
151
|
private previousParent: Object3D | null = null;
|
|
115
152
|
|
|
116
|
-
|
|
117
|
-
if (this.
|
|
118
|
-
this.previousAspect = this.context.mainCameraComponent.aspect;
|
|
119
|
-
this.updateRenderMode();
|
|
120
|
-
}
|
|
121
|
-
else if(this.renderOnTop){
|
|
153
|
+
onBeforeRenderRoutine = () => {
|
|
154
|
+
if (this.renderOnTop) {
|
|
122
155
|
// 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
156
|
this.previousParent = this.gameObject.parent;
|
|
124
157
|
this.gameObject.removeFromParent();
|
|
125
158
|
}
|
|
159
|
+
else {
|
|
160
|
+
this.onUpdateRenderMode();
|
|
161
|
+
// 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
|
|
162
|
+
this.shadowComponent?.updateMatrixWorld(true);
|
|
163
|
+
this.shadowComponent?.updateWorldMatrix(true, true);
|
|
164
|
+
EventSystem.ensureUpdateMeshUI(ThreeMeshUI, this.context);
|
|
165
|
+
}
|
|
126
166
|
}
|
|
127
167
|
|
|
128
|
-
|
|
168
|
+
onAfterRenderRoutine = () => {
|
|
129
169
|
if (this.renderOnTop && this.previousParent && this.context.mainCamera) {
|
|
130
170
|
this.previousParent.add(this.gameObject);
|
|
131
171
|
this.context.renderer.autoClear = false;
|
|
132
172
|
this.context.renderer.clearDepth();
|
|
173
|
+
this.onUpdateRenderMode(true);
|
|
174
|
+
this.shadowComponent?.updateMatrixWorld(true);
|
|
175
|
+
EventSystem.ensureUpdateMeshUI(ThreeMeshUI, this.context);
|
|
133
176
|
this.context.renderer.render(this.gameObject, this.context.mainCamera);
|
|
134
177
|
this.context.renderer.autoClear = true;
|
|
135
178
|
}
|
|
136
179
|
}
|
|
137
180
|
|
|
138
|
-
applyRenderSettings(){
|
|
181
|
+
applyRenderSettings() {
|
|
139
182
|
this.onRenderSettingsChanged();
|
|
140
183
|
}
|
|
141
184
|
|
|
@@ -149,7 +192,7 @@ export class Canvas extends UIRootComponent {
|
|
|
149
192
|
yield;
|
|
150
193
|
this._updateRenderSettingsRoutine = undefined;
|
|
151
194
|
if (this.shadowComponent) {
|
|
152
|
-
this.
|
|
195
|
+
this.onUpdateRenderMode();
|
|
153
196
|
// this.onWillUpdateRenderSettings();
|
|
154
197
|
updateRenderSettingsRecursive(this.shadowComponent, this);
|
|
155
198
|
for (const ch of GameObject.getComponentsInChildren(this.gameObject, BaseUIComponent)) {
|
|
@@ -159,44 +202,65 @@ export class Canvas extends UIRootComponent {
|
|
|
159
202
|
}
|
|
160
203
|
|
|
161
204
|
private _activeRenderMode: RenderMode = -1;
|
|
205
|
+
private _lastWidth: number = -1;
|
|
206
|
+
private _lastHeight: number = -1;
|
|
162
207
|
|
|
163
|
-
private
|
|
164
|
-
|
|
165
|
-
|
|
208
|
+
private onUpdateRenderMode(force: boolean = false) {
|
|
209
|
+
if (!force) {
|
|
210
|
+
if (this._renderMode === this._activeRenderMode && this._lastWidth === this.context.domWidth && this._lastHeight === this.context.domHeight) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
this._activeRenderMode = this._renderMode;
|
|
215
|
+
let camera = this.context.mainCameraComponent;
|
|
216
|
+
let planeDistance: number = camera?.farClipPlane ?? 100;
|
|
217
|
+
if (this._renderMode === RenderMode.ScreenSpaceCamera) {
|
|
218
|
+
if (this.worldCamera)
|
|
219
|
+
camera = this.worldCamera as Camera;
|
|
220
|
+
if (this.planeDistance > 0)
|
|
221
|
+
planeDistance = this.planeDistance;
|
|
222
|
+
}
|
|
166
223
|
|
|
167
|
-
|
|
168
|
-
if (this.renderMode === this._activeRenderMode) return;
|
|
169
|
-
switch (this.renderMode) {
|
|
224
|
+
switch (this._renderMode) {
|
|
170
225
|
case RenderMode.ScreenSpaceOverlay:
|
|
171
226
|
case RenderMode.ScreenSpaceCamera:
|
|
172
|
-
|
|
173
|
-
|
|
227
|
+
this._lastWidth = this.context.domWidth;
|
|
228
|
+
this._lastHeight = this.context.domHeight;
|
|
229
|
+
|
|
230
|
+
// showBalloonWarning("Screenspace Canvas is not supported yet. Please use worldspace");
|
|
174
231
|
if (!camera) return;
|
|
232
|
+
|
|
175
233
|
const canvas = this.gameObject;
|
|
176
234
|
const camObj = camera.gameObject;
|
|
177
235
|
camObj?.add(canvas);
|
|
178
|
-
|
|
236
|
+
// we move the plane SLIGHTLY closer to be sure not to cull the canvas
|
|
237
|
+
const plane = planeDistance - .1;
|
|
179
238
|
canvas.position.x = 0;
|
|
180
239
|
canvas.position.y = 0;
|
|
181
|
-
canvas.position.z = -
|
|
240
|
+
canvas.position.z = -plane;
|
|
241
|
+
canvas.quaternion.identity();
|
|
182
242
|
|
|
183
|
-
|
|
243
|
+
const rect = this.gameObject.getComponent(RectTransform)!;
|
|
184
244
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
245
|
+
const vFOV = camera.fieldOfView! * Math.PI / 180;
|
|
246
|
+
const h = 2 * Math.tan(vFOV / 2) * Math.abs(plane);
|
|
247
|
+
canvas.scale.x = h / this.context.domHeight;
|
|
248
|
+
canvas.scale.y = h / this.context.domHeight;
|
|
249
|
+
// Set scale.z, otherwise small offsets in screenspace mode have different visual results based on export scale and other settings
|
|
250
|
+
canvas.scale.z = .01;
|
|
251
|
+
rect.sizeDelta.x = this.context.domWidth;
|
|
252
|
+
rect.sizeDelta.y = this.context.domHeight;
|
|
253
|
+
rect?.markDirty();
|
|
190
254
|
|
|
191
|
-
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
// }
|
|
255
|
+
|
|
256
|
+
// this.context.scene.add(this.gameObject)
|
|
257
|
+
// this.gameObject.scale.multiplyScalar(.01);
|
|
258
|
+
// this.gameObject.position.set(0,0,0);
|
|
196
259
|
|
|
197
260
|
break;
|
|
198
261
|
case RenderMode.WorldSpace:
|
|
199
|
-
|
|
262
|
+
this._lastWidth = -1;
|
|
263
|
+
this._lastHeight = -1;
|
|
200
264
|
break;
|
|
201
265
|
}
|
|
202
266
|
}
|
|
@@ -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,15 @@ 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';
|
|
10
12
|
|
|
13
|
+
const _colorStateObject: { backgroundColor: Color, backgroundOpacity: number } = {
|
|
14
|
+
backgroundColor: new Color(1, 1, 1),
|
|
15
|
+
backgroundOpacity: 1,
|
|
16
|
+
};
|
|
11
17
|
|
|
12
|
-
export class Graphic extends BaseUIComponent implements IGraphic {
|
|
18
|
+
export class Graphic extends BaseUIComponent implements IGraphic, IRectTransformChangedReceiver {
|
|
13
19
|
|
|
14
20
|
get isGraphic() { return true; }
|
|
15
21
|
|
|
@@ -26,9 +32,11 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
26
32
|
}
|
|
27
33
|
this._color.copy(col);
|
|
28
34
|
}
|
|
35
|
+
|
|
29
36
|
protected onColorChanged() {
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
_colorStateObject.backgroundColor = this._color;
|
|
38
|
+
_colorStateObject.backgroundOpacity = this._color.alpha;
|
|
39
|
+
this.uiObject?.set(_colorStateObject);
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
// used via animations
|
|
@@ -44,6 +52,9 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
44
52
|
|
|
45
53
|
|
|
46
54
|
private _rect: RectTransform | null = null;
|
|
55
|
+
|
|
56
|
+
private _stateManager : SimpleStateBehavior | null = null;
|
|
57
|
+
|
|
47
58
|
protected get rectTransform(): RectTransform {
|
|
48
59
|
if (!this._rect) {
|
|
49
60
|
this._rect = GameObject.getComponent(this.gameObject, RectTransform);
|
|
@@ -51,6 +62,11 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
51
62
|
return this._rect!;
|
|
52
63
|
}
|
|
53
64
|
|
|
65
|
+
onParentRectTransformChanged() {
|
|
66
|
+
this.uiObject?.set({ width: this.rectTransform.width, height:this.rectTransform.height })
|
|
67
|
+
this.markDirty();
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
__internalNewInstanceCreated(): void {
|
|
55
71
|
super.__internalNewInstanceCreated();
|
|
56
72
|
this._rect = null;
|
|
@@ -63,14 +79,21 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
63
79
|
if (this.uiObject) {
|
|
64
80
|
//@ts-ignore
|
|
65
81
|
this.uiObject.setState(state);
|
|
82
|
+
this?.markDirty();
|
|
66
83
|
}
|
|
67
84
|
}
|
|
68
85
|
|
|
69
86
|
setupState(state: object) {
|
|
70
87
|
this.makePanel();
|
|
71
88
|
if (this.uiObject) {
|
|
89
|
+
|
|
90
|
+
// @marwie : v7.x now have a concurrent state management in core mimicking html/css
|
|
91
|
+
// ie : (::firstChild::hover::disabled) where firstchild, hover and disabled are all on different channels
|
|
92
|
+
// In order to keep needle Raycaster and EventSystem intact, I added in v7 a SimpleStateBehavior, which acts as previously
|
|
93
|
+
|
|
94
|
+
if( !this._stateManager ) this._stateManager = new SimpleStateBehavior(this.uiObject);
|
|
72
95
|
//@ts-ignore
|
|
73
|
-
this.uiObject.setupState(state);
|
|
96
|
+
this.uiObject.setupState(state.state, state.attributes);
|
|
74
97
|
}
|
|
75
98
|
}
|
|
76
99
|
|
|
@@ -79,8 +102,8 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
79
102
|
if (this.uiObject) {
|
|
80
103
|
//@ts-ignore
|
|
81
104
|
this.uiObject.set(opts);
|
|
82
|
-
if (opts["backgroundColor"] !== undefined || opts["backgroundOpacity"] !== undefined)
|
|
83
|
-
|
|
105
|
+
// if (opts["backgroundColor"] !== undefined || opts["backgroundOpacity"] !== undefined)
|
|
106
|
+
// this.uiObject["updateBackgroundMaterial"]?.call(this.uiObject);
|
|
84
107
|
}
|
|
85
108
|
}
|
|
86
109
|
|
|
@@ -119,6 +142,7 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
119
142
|
offset: 1, // without a tiny offset we get z fighting
|
|
120
143
|
};
|
|
121
144
|
this.onBeforeCreate(opts);
|
|
145
|
+
this.applyEffects(opts);
|
|
122
146
|
this.onCreate(opts);
|
|
123
147
|
this.controlsChildLayout = false;
|
|
124
148
|
this._currentlyCreatingPanel = false;
|
|
@@ -133,6 +157,17 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
133
157
|
}
|
|
134
158
|
protected onAfterCreated() { }
|
|
135
159
|
|
|
160
|
+
private applyEffects(opts){
|
|
161
|
+
const outline = this.gameObject?.getComponent(Outline);
|
|
162
|
+
if (outline) {
|
|
163
|
+
if (outline.effectDistance) opts.borderWidth = Math.max(Math.abs(outline.effectDistance.x), Math.abs(outline.effectDistance.y));
|
|
164
|
+
if (outline.effectColor) {
|
|
165
|
+
opts.borderColor = outline.effectColor;
|
|
166
|
+
opts.borderOpacity = outline.effectColor.alpha;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
136
171
|
/** used internally to ensure textures assigned to UI use linear encoding */
|
|
137
172
|
static textureCache: Map<Texture, Texture> = new Map();
|
|
138
173
|
|
|
@@ -151,13 +186,14 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
151
186
|
tex = clone;
|
|
152
187
|
}
|
|
153
188
|
}
|
|
154
|
-
this.setOptions({
|
|
189
|
+
this.setOptions({ backgroundImage: tex, borderRadius: 0, backgroundOpacity: this.color.alpha, backgroundSize: "stretch" });
|
|
155
190
|
}
|
|
156
191
|
}
|
|
157
192
|
|
|
158
193
|
protected onAfterAddedToScene(): void {
|
|
159
194
|
super.onAfterAddedToScene();
|
|
160
195
|
if (this.shadowComponent) {
|
|
196
|
+
// @TODO: I think we dont even need this anymore and this leads to the offset being applied twice
|
|
161
197
|
//@ts-ignore
|
|
162
198
|
this.shadowComponent.offset = this.shadowComponent.position.z;
|
|
163
199
|
|
|
@@ -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;
|
|
48
|
+
opts.borderRadius = 5 / this.pixelsPerUnitMultiplier;
|
|
49
|
+
if(this.sprite?.texture?.name === "Knob") {
|
|
50
|
+
opts.borderRadius = 999;
|
|
51
|
+
}
|
|
44
52
|
opts.borderColor = new Color(.4, .4, .4);
|
|
45
53
|
opts.borderOpacity = this.color.alpha;
|
|
46
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,5 +1,9 @@
|
|
|
1
1
|
import { IComponent } from "../../engine/engine_types";
|
|
2
2
|
|
|
3
|
+
export interface ICanvas {
|
|
4
|
+
get screenspace() : boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
export interface ICanvasGroup {
|
|
4
8
|
get isCanvasGroup() : boolean;
|
|
5
9
|
blocksRaycasts: boolean;
|
|
@@ -9,4 +13,12 @@ export interface ICanvasGroup {
|
|
|
9
13
|
export interface IGraphic extends IComponent {
|
|
10
14
|
get isGraphic() : boolean;
|
|
11
15
|
raycastTarget: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface IRectTransform extends IComponent {
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface IRectTransformChangedReceiver {
|
|
23
|
+
onParentRectTransformChanged(comp : IRectTransform) : void;
|
|
12
24
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RGBAColor } from "../js-extensions";
|
|
2
|
+
import { serializable } from "../../engine/engine_serialization";
|
|
3
|
+
import { Behaviour } from "../Component";
|
|
4
|
+
import { Color, Vector2 } from "three"
|
|
5
|
+
|
|
6
|
+
export class Outline extends Behaviour {
|
|
7
|
+
|
|
8
|
+
@serializable(RGBAColor)
|
|
9
|
+
effectColor?: RGBAColor;
|
|
10
|
+
|
|
11
|
+
@serializable(Vector2)
|
|
12
|
+
effectDistance?: Vector2;
|
|
13
|
+
}
|