@needle-tools/engine 3.5.5-alpha.1 → 3.5.7-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 +17 -0
- package/dist/needle-engine.js +14494 -14367
- package/dist/needle-engine.light.js +82420 -0
- package/dist/needle-engine.light.min.js +5057 -0
- package/dist/needle-engine.light.umd.cjs +5057 -0
- package/dist/needle-engine.min.js +331 -329
- package/dist/needle-engine.umd.cjs +327 -325
- package/lib/engine/engine_addressables.js +2 -2
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_components.d.ts +2 -2
- package/lib/engine/engine_components.js +7 -2
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +6 -3
- package/lib/engine/engine_networking.js +57 -30
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine-components/Component.d.ts +3 -0
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/SyncedRoom.d.ts +3 -0
- package/lib/engine-components/SyncedRoom.js +10 -6
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +5 -3
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js +2 -1
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/USDZText.d.ts +10 -3
- package/lib/engine-components/export/usdz/extensions/USDZText.js +88 -8
- package/lib/engine-components/export/usdz/extensions/USDZText.js.map +1 -1
- package/lib/engine-components/js-extensions/Object3D.js +4 -1
- package/lib/engine-components/js-extensions/Object3D.js.map +1 -1
- package/lib/engine-components/ui/Button.js +10 -0
- package/lib/engine-components/ui/Button.js.map +1 -1
- package/lib/engine-components/ui/Canvas.js +3 -2
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/CanvasGroup.js +5 -5
- package/lib/engine-components/ui/CanvasGroup.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +3 -0
- package/lib/engine-components/ui/Graphic.js +19 -5
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/Interfaces.d.ts +4 -1
- package/lib/engine-components/ui/Interfaces.js.map +1 -1
- package/lib/engine-components/ui/RectTransform.d.ts +3 -1
- package/lib/engine-components/ui/RectTransform.js +22 -22
- package/lib/engine-components/ui/RectTransform.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +3 -1
- package/lib/engine-components/ui/Text.js +6 -0
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.js +1 -2
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/engine/engine_addressables.ts +1 -1
- package/src/engine/engine_components.ts +7 -2
- package/src/engine/engine_networking.ts +65 -34
- package/src/engine-components/Component.ts +3 -1
- package/src/engine-components/ParticleSystemModules.ts +1483 -1483
- package/src/engine-components/SyncedRoom.ts +11 -9
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +9 -6
- package/src/engine-components/export/usdz/USDZExporter.ts +2 -1
- package/src/engine-components/export/usdz/extensions/USDZText.ts +99 -11
- package/src/engine-components/js-extensions/Object3D.ts +5 -1
- package/src/engine-components/ui/Button.ts +5 -0
- package/src/engine-components/ui/Canvas.ts +3 -2
- package/src/engine-components/ui/CanvasGroup.ts +7 -6
- package/src/engine-components/ui/Graphic.ts +27 -15
- package/src/engine-components/ui/Interfaces.ts +5 -1
- package/src/engine-components/ui/RectTransform.ts +32 -28
- package/src/engine-components/ui/Text.ts +9 -4
- package/src/engine-components/webxr/WebXR.ts +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Behaviour } from "./Component";
|
|
2
2
|
import * as utils from "../engine/engine_utils"
|
|
3
3
|
import { serializable } from "../engine/engine_serialization_decorator";
|
|
4
|
+
import { getParam } from "../engine/engine_utils";
|
|
4
5
|
|
|
5
6
|
const viewParamName = "view";
|
|
6
7
|
const debug = utils.getParam("debugsyncedroom");
|
|
@@ -40,7 +41,9 @@ export class SyncedRoom extends Behaviour {
|
|
|
40
41
|
this.context.connection.joinRoom(viewId, true);
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
// If setup to join a random room
|
|
45
|
+
if (this.joinRandomRoom || getParam(this.urlParameterName))
|
|
46
|
+
this.tryJoinRoom();
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
onDisable(): void {
|
|
@@ -48,6 +51,13 @@ export class SyncedRoom extends Behaviour {
|
|
|
48
51
|
this.context.connection.leaveRoom(this.roomName);
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
/** Will generate a random room name, set it as an URL parameter and attempt to join the room */
|
|
55
|
+
tryJoinRandomRoom() {
|
|
56
|
+
this.setRandomRoomUrlParameter();
|
|
57
|
+
this.tryJoinRoom();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Try to join the currently set roomName */
|
|
51
61
|
tryJoinRoom(call: number = 0): boolean {
|
|
52
62
|
if (call === undefined) call = 0;
|
|
53
63
|
let hasRoomParameter = false;
|
|
@@ -78,12 +88,6 @@ export class SyncedRoom extends Behaviour {
|
|
|
78
88
|
return false;
|
|
79
89
|
}
|
|
80
90
|
|
|
81
|
-
if (!this.roomName || this.roomName.length <= 0) {
|
|
82
|
-
if (debug)
|
|
83
|
-
console.error("Missing room name on \"" + this.name + "\". Make sure this is correctly configured in Unity", this.context.connection.isDebugEnabled ? this : "");
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
91
|
if (!this.context.connection.isConnected) {
|
|
88
92
|
this.context.connection.connect();
|
|
89
93
|
}
|
|
@@ -157,8 +161,6 @@ export class SyncedRoom extends Behaviour {
|
|
|
157
161
|
urlParams.set(viewParamName, this.context.connection.currentRoomViewId);
|
|
158
162
|
return window.location.origin + window.location.pathname + "?" + urlParams.toString();
|
|
159
163
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
164
|
return null;
|
|
163
165
|
}
|
|
164
166
|
}
|
|
@@ -661,12 +661,6 @@ function addResources( object, context: USDZExporterContext ) {
|
|
|
661
661
|
|
|
662
662
|
}
|
|
663
663
|
|
|
664
|
-
if ( ! ( material.uuid in context.materials ) ) {
|
|
665
|
-
|
|
666
|
-
context.materials[ material.uuid ] = material;
|
|
667
|
-
|
|
668
|
-
}
|
|
669
|
-
|
|
670
664
|
} else {
|
|
671
665
|
|
|
672
666
|
console.warn( 'THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)', name );
|
|
@@ -675,6 +669,15 @@ function addResources( object, context: USDZExporterContext ) {
|
|
|
675
669
|
|
|
676
670
|
}
|
|
677
671
|
|
|
672
|
+
if( material ) {
|
|
673
|
+
|
|
674
|
+
if ( ! ( material.uuid in context.materials ) ) {
|
|
675
|
+
|
|
676
|
+
context.materials[ material.uuid ] = material;
|
|
677
|
+
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
678
681
|
for ( const ch of object.children ) {
|
|
679
682
|
|
|
680
683
|
addResources( ch, context );
|
|
@@ -15,6 +15,7 @@ import { WebARSessionRoot } from "../../webxr/WebARSessionRoot";
|
|
|
15
15
|
import { hasProLicense } from "../../../engine/engine_license";
|
|
16
16
|
import { BehaviorExtension } from "./extensions/behavior/Behaviour";
|
|
17
17
|
import { AudioExtension } from "./extensions/behavior/AudioExtension";
|
|
18
|
+
import { TextExtension } from "./extensions/USDZText";
|
|
18
19
|
|
|
19
20
|
const debug = getParam("debugusdz");
|
|
20
21
|
|
|
@@ -66,7 +67,6 @@ export class USDZExporter extends Behaviour {
|
|
|
66
67
|
private webARSessionRoot: WebARSessionRoot | undefined;
|
|
67
68
|
|
|
68
69
|
start() {
|
|
69
|
-
console.log(this.customUsdzFile);
|
|
70
70
|
if (debug) {
|
|
71
71
|
console.log(this);
|
|
72
72
|
console.log("Debug USDZ, press 't' to export")
|
|
@@ -97,6 +97,7 @@ export class USDZExporter extends Behaviour {
|
|
|
97
97
|
if (this.interactive) {
|
|
98
98
|
this.extensions.push(new BehaviorExtension());
|
|
99
99
|
this.extensions.push(new AudioExtension());
|
|
100
|
+
this.extensions.push(new TextExtension());
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { IUSDExporterExtension } from "../Extension";
|
|
1
2
|
import { IBehaviorElement } from "../extensions/behavior/BehavioursBuilder";
|
|
2
|
-
import { USDDocument, USDWriter } from "../ThreeUSDZExporter";
|
|
3
|
+
import { USDDocument, USDObject, USDWriter, USDZExporterContext } from "../ThreeUSDZExporter";
|
|
4
|
+
import { GameObject } from "../../../Component";
|
|
5
|
+
import { Text } from "../../../ui/Text"
|
|
6
|
+
import { RectTransform } from "../../../ui/RectTransform";
|
|
7
|
+
import { Color, Material, Matrix4, MeshStandardMaterial, Object3D, Vector3 } from "three";
|
|
8
|
+
import { TextAnchor } from "../../../ui/Text";
|
|
3
9
|
|
|
4
10
|
|
|
5
11
|
export enum TextWrapMode {
|
|
@@ -41,6 +47,8 @@ export class USDZText implements IBehaviorElement {
|
|
|
41
47
|
horizontalAlignment?: HorizontalAlignment;
|
|
42
48
|
verticalAlignment?: VerticalAlignment;
|
|
43
49
|
|
|
50
|
+
material?: Material;
|
|
51
|
+
|
|
44
52
|
setDepth(depth: number): USDZText {
|
|
45
53
|
this.depth = depth;
|
|
46
54
|
return this;
|
|
@@ -94,6 +102,10 @@ export class USDZText implements IBehaviorElement {
|
|
|
94
102
|
if (this.verticalAlignment)
|
|
95
103
|
writer.appendLine(`token verticalAlignment = "${this.verticalAlignment}"`);
|
|
96
104
|
|
|
105
|
+
if (this.material !== undefined) {
|
|
106
|
+
writer.appendLine(`rel material:binding = </Materials/Material_${this.material.id}>`)
|
|
107
|
+
}
|
|
108
|
+
|
|
97
109
|
writer.closeBlock();
|
|
98
110
|
|
|
99
111
|
}
|
|
@@ -120,22 +132,98 @@ export class TextBuilder {
|
|
|
120
132
|
text.height = height;
|
|
121
133
|
text.horizontalAlignment = horizontal;
|
|
122
134
|
text.verticalAlignment = vertical;
|
|
123
|
-
if (wrapMode)
|
|
135
|
+
if (wrapMode !== undefined)
|
|
124
136
|
text.wrapMode = wrapMode;
|
|
125
137
|
return text;
|
|
126
138
|
}
|
|
127
139
|
}
|
|
128
140
|
|
|
141
|
+
const rotateYAxisMatrix = new Matrix4().makeRotationY(Math.PI);
|
|
142
|
+
|
|
143
|
+
export class TextExtension implements IUSDExporterExtension {
|
|
144
|
+
get extensionName(): string {
|
|
145
|
+
return "text";
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
onExportObject(object: Object3D, model: USDObject, _context: USDZExporterContext) {
|
|
149
|
+
|
|
150
|
+
const text = GameObject.getComponent(object, Text);
|
|
151
|
+
if (text) {
|
|
152
|
+
const rt = GameObject.getComponent(object, RectTransform);
|
|
153
|
+
let width = 100;
|
|
154
|
+
let height = 100;
|
|
155
|
+
if (rt) {
|
|
156
|
+
width = rt.width;
|
|
157
|
+
height = rt.height;
|
|
158
|
+
}
|
|
159
|
+
const newModel = model.clone();
|
|
160
|
+
newModel.matrix = rotateYAxisMatrix.clone();
|
|
161
|
+
const color = new Color().copySRGBToLinear(text.color);
|
|
162
|
+
newModel.material = new MeshStandardMaterial({ color: color, emissive: color });
|
|
163
|
+
model.add(newModel);
|
|
164
|
+
|
|
165
|
+
// model.matrix.scale(new Vector3(100, 100, 100));
|
|
166
|
+
newModel.addEventListener("serialize", (writer: USDWriter, _context: USDZExporterContext) => {
|
|
167
|
+
const textObj = TextBuilder.multiLine(text.text, width, height, HorizontalAlignment.center, VerticalAlignment.bottom, TextWrapMode.flowing);
|
|
168
|
+
this.setTextAlignment(textObj, text.alignment);
|
|
169
|
+
this.setOverflow(textObj, text);
|
|
170
|
+
if (newModel.material)
|
|
171
|
+
textObj.material = newModel.material;
|
|
172
|
+
textObj.pointSize = this.convertToTextSize(text.fontSize);
|
|
173
|
+
textObj.depth = .001;
|
|
174
|
+
textObj.writeTo(undefined, writer);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private convertToTextSize(pixel: number) {
|
|
180
|
+
return 1 / 0.0502 * 144 * pixel;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private setOverflow(textObj: USDZText, text: Text) {
|
|
184
|
+
if (text.horizontalOverflow) {
|
|
185
|
+
textObj.wrapMode = TextWrapMode.singleLine;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
textObj.wrapMode = TextWrapMode.flowing;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
129
191
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
192
|
+
private setTextAlignment(text: USDZText, alignment: TextAnchor) {
|
|
193
|
+
switch (alignment) {
|
|
194
|
+
case TextAnchor.LowerLeft:
|
|
195
|
+
case TextAnchor.MiddleLeft:
|
|
196
|
+
case TextAnchor.UpperLeft:
|
|
197
|
+
text.horizontalAlignment = HorizontalAlignment.left;
|
|
198
|
+
break;
|
|
199
|
+
case TextAnchor.LowerCenter:
|
|
200
|
+
case TextAnchor.MiddleCenter:
|
|
201
|
+
case TextAnchor.UpperCenter:
|
|
202
|
+
text.horizontalAlignment = HorizontalAlignment.center;
|
|
203
|
+
break;
|
|
204
|
+
case TextAnchor.LowerRight:
|
|
205
|
+
case TextAnchor.MiddleRight:
|
|
206
|
+
case TextAnchor.UpperRight:
|
|
207
|
+
text.horizontalAlignment = HorizontalAlignment.right;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
switch (alignment) {
|
|
211
|
+
case TextAnchor.LowerLeft:
|
|
212
|
+
case TextAnchor.LowerCenter:
|
|
213
|
+
case TextAnchor.LowerRight:
|
|
214
|
+
text.verticalAlignment = VerticalAlignment.bottom;
|
|
215
|
+
break;
|
|
216
|
+
case TextAnchor.MiddleLeft:
|
|
217
|
+
case TextAnchor.MiddleCenter:
|
|
218
|
+
case TextAnchor.MiddleRight:
|
|
219
|
+
text.verticalAlignment = VerticalAlignment.middle;
|
|
220
|
+
break;
|
|
221
|
+
case TextAnchor.UpperLeft:
|
|
222
|
+
case TextAnchor.UpperCenter:
|
|
223
|
+
case TextAnchor.UpperRight:
|
|
224
|
+
text.verticalAlignment = VerticalAlignment.top;
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
139
227
|
}
|
|
140
228
|
}
|
|
141
229
|
|
|
@@ -2,7 +2,7 @@ import { applyPrototypeExtensions, registerPrototypeExtensions } from "./Extensi
|
|
|
2
2
|
import { Object3D } from "three";
|
|
3
3
|
import { Constructor, ConstructorConcrete, IComponent } from "../../engine/engine_types"
|
|
4
4
|
import { IComponent as Component } from "../../engine/engine_types";
|
|
5
|
-
import { addNewComponent, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, removeComponent } from "../../engine/engine_components";
|
|
5
|
+
import { moveComponentInstance, addNewComponent, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, removeComponent } from "../../engine/engine_components";
|
|
6
6
|
import { isActiveSelf, setActive, destroy } from "../../engine/engine_gameobject";
|
|
7
7
|
|
|
8
8
|
// used to decorate cloned object3D objects with the same added components defined above
|
|
@@ -24,6 +24,10 @@ Object3D.prototype["destroy"] = function () {
|
|
|
24
24
|
destroy(this);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
Object3D.prototype["addComponent"] = function <T extends IComponent>(instance: T) {
|
|
28
|
+
return moveComponentInstance(this, instance);
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
Object3D.prototype["addNewComponent"] = function <T extends Component>(type: ConstructorConcrete<T>) {
|
|
28
32
|
return addNewComponent(this, new type());
|
|
29
33
|
}
|
|
@@ -68,6 +68,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
68
68
|
if (debug)
|
|
69
69
|
console.log("Button Enter", this.animationTriggers?.highlightedTrigger, this.animator);
|
|
70
70
|
this._isHovered = true;
|
|
71
|
+
if (!this.interactable) return;
|
|
71
72
|
if (this.transition == Transition.Animation && this.animationTriggers && this.animator) {
|
|
72
73
|
this.animator.setTrigger(this.animationTriggers.highlightedTrigger);
|
|
73
74
|
}
|
|
@@ -81,6 +82,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
81
82
|
if (debug)
|
|
82
83
|
console.log("Button Exit", this.animationTriggers?.highlightedTrigger, this.animator);
|
|
83
84
|
this._isHovered = false;
|
|
85
|
+
if (!this.interactable) return;
|
|
84
86
|
if (this.transition == Transition.Animation && this.animationTriggers && this.animator) {
|
|
85
87
|
this.animator.setTrigger(this.animationTriggers.normalTrigger);
|
|
86
88
|
}
|
|
@@ -93,6 +95,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
93
95
|
onPointerDown(_) {
|
|
94
96
|
if (debug)
|
|
95
97
|
console.log("Button Down", this.animationTriggers?.highlightedTrigger, this.animator);
|
|
98
|
+
if (!this.interactable) return;
|
|
96
99
|
if (this.transition == Transition.Animation && this.animationTriggers && this.animator) {
|
|
97
100
|
this.animator.setTrigger(this.animationTriggers.pressedTrigger);
|
|
98
101
|
}
|
|
@@ -104,6 +107,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
104
107
|
onPointerUp(_) {
|
|
105
108
|
if (debug)
|
|
106
109
|
console.warn("Button Up", this.animationTriggers?.highlightedTrigger, this.animator, this._isHovered);
|
|
110
|
+
if (!this.interactable) return;
|
|
107
111
|
if (this.transition == Transition.Animation && this.animationTriggers && this.animator) {
|
|
108
112
|
this.animator.setTrigger(this._isHovered ? this.animationTriggers.highlightedTrigger : this.animationTriggers.normalTrigger);
|
|
109
113
|
}
|
|
@@ -113,6 +117,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
|
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
onPointerClick(_args: PointerEventData) {
|
|
120
|
+
if (!this.interactable) return;
|
|
116
121
|
if (debug) {
|
|
117
122
|
console.warn("Button Click", this.onClick);
|
|
118
123
|
showBalloonMessage("CLICKED button " + this.name + " at " + this.context.time.frameCount);
|
|
@@ -208,7 +208,7 @@ export class Canvas extends UIRootComponent implements ICanvas {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
onAfterRenderRoutine = () => {
|
|
211
|
-
if ((this.screenspace || this.
|
|
211
|
+
if ((this.screenspace || this.renderOnTop) && this.previousParent && this.context.mainCamera) {
|
|
212
212
|
if (this.screenspace) {
|
|
213
213
|
const camObj = this.context.mainCamera;
|
|
214
214
|
camObj?.add(this.gameObject);
|
|
@@ -293,7 +293,8 @@ export class Canvas extends UIRootComponent implements ICanvas {
|
|
|
293
293
|
let camera = this.context.mainCameraComponent;
|
|
294
294
|
let planeDistance: number = 10;
|
|
295
295
|
if (camera && camera.nearClipPlane > 0 && camera.farClipPlane > 0) {
|
|
296
|
-
|
|
296
|
+
// TODO: this is a hack/workaround for event system currently only passing events to the nearest object
|
|
297
|
+
planeDistance = Mathf.lerp(camera.nearClipPlane, camera.farClipPlane, .15);
|
|
297
298
|
}
|
|
298
299
|
if (this._renderMode === RenderMode.ScreenSpaceCamera) {
|
|
299
300
|
if (this.worldCamera)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Graphic } from "./Graphic";
|
|
2
2
|
import { FrameEvent } from "../../engine/engine_setup";
|
|
3
3
|
import { Behaviour, GameObject } from "../Component";
|
|
4
|
-
import { ICanvasGroup } from "./Interfaces";
|
|
4
|
+
import { ICanvasGroup, IHasAlphaFactor } from "./Interfaces";
|
|
5
5
|
import { serializable } from "../../engine/engine_serialization_decorator";
|
|
6
|
+
import { BaseUIComponent } from "./BaseUIComponent";
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
export class CanvasGroup extends Behaviour implements ICanvasGroup {
|
|
@@ -38,12 +39,12 @@ export class CanvasGroup extends Behaviour implements ICanvasGroup {
|
|
|
38
39
|
this.applyChangesNow();
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
private _buffer
|
|
42
|
+
private _buffer: Graphic[] = [];
|
|
42
43
|
private applyChangesNow() {
|
|
43
|
-
for (const ch of GameObject.getComponentsInChildren(this.gameObject,
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
for (const ch of GameObject.getComponentsInChildren(this.gameObject, BaseUIComponent, this._buffer)) {
|
|
45
|
+
const hasAlphaFactor = ch as any as IHasAlphaFactor;
|
|
46
|
+
if (hasAlphaFactor.setAlphaFactor)
|
|
47
|
+
hasAlphaFactor.setAlphaFactor(this._alpha);
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
}
|
|
@@ -9,12 +9,12 @@ import { onChange, scheduleAction } from "./Utils"
|
|
|
9
9
|
import { GameObject } from '../Component';
|
|
10
10
|
import SimpleStateBehavior from "three-mesh-ui/examples/behaviors/states/SimpleStateBehavior"
|
|
11
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';
|
|
14
12
|
|
|
15
|
-
const _colorStateObject: { backgroundColor: Color, backgroundOpacity: number } = {
|
|
13
|
+
const _colorStateObject: { backgroundColor: Color, backgroundOpacity: number, borderColor: Color, borderOpacity: number } = {
|
|
16
14
|
backgroundColor: new Color(1, 1, 1),
|
|
17
15
|
backgroundOpacity: 1,
|
|
16
|
+
borderColor: new Color(1, 1, 1),
|
|
17
|
+
borderOpacity: 1,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export class Graphic extends BaseUIComponent implements IGraphic, IRectTransformChangedReceiver {
|
|
@@ -35,10 +35,23 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
|
|
|
35
35
|
this._color.copy(col);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
private _alphaFactor: number = 1;
|
|
39
|
+
setAlphaFactor(factor: number) {
|
|
40
|
+
this._alphaFactor = factor;
|
|
41
|
+
this.onColorChanged();
|
|
42
|
+
}
|
|
43
|
+
get alphaFactor() {
|
|
44
|
+
return this._alphaFactor;
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
protected onColorChanged() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
if (this.uiObject) {
|
|
49
|
+
_colorStateObject.backgroundColor = this._color;
|
|
50
|
+
_colorStateObject.backgroundOpacity = this._color.alpha * this._alphaFactor;
|
|
51
|
+
this.applyEffects(_colorStateObject, this._alphaFactor);
|
|
52
|
+
this.uiObject.set(_colorStateObject);
|
|
53
|
+
this.markDirty();
|
|
54
|
+
}
|
|
42
55
|
}
|
|
43
56
|
|
|
44
57
|
// used via animations
|
|
@@ -52,10 +65,9 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
|
|
|
52
65
|
protected uiObject: ThreeMeshUI.Block | null = null;
|
|
53
66
|
private _color: RGBAColor = null!;
|
|
54
67
|
|
|
55
|
-
|
|
56
68
|
private _rect: RectTransform | null = null;
|
|
57
69
|
|
|
58
|
-
private _stateManager
|
|
70
|
+
private _stateManager: SimpleStateBehavior | null = null;
|
|
59
71
|
|
|
60
72
|
protected get rectTransform(): RectTransform {
|
|
61
73
|
if (!this._rect) {
|
|
@@ -65,7 +77,7 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
|
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
onParentRectTransformChanged() {
|
|
68
|
-
this.uiObject?.set({ width: this.rectTransform.width, height:this.rectTransform.height })
|
|
80
|
+
this.uiObject?.set({ width: this.rectTransform.width, height: this.rectTransform.height })
|
|
69
81
|
this.markDirty();
|
|
70
82
|
}
|
|
71
83
|
|
|
@@ -73,7 +85,7 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
|
|
|
73
85
|
super.__internalNewInstanceCreated();
|
|
74
86
|
this._rect = null;
|
|
75
87
|
this.uiObject = null;
|
|
76
|
-
if(this._color) this._color = this._color.clone();
|
|
88
|
+
if (this._color) this._color = this._color.clone();
|
|
77
89
|
}
|
|
78
90
|
|
|
79
91
|
setState(state: string) {
|
|
@@ -93,7 +105,7 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
|
|
|
93
105
|
// ie : (::firstChild::hover::disabled) where firstchild, hover and disabled are all on different channels
|
|
94
106
|
// In order to keep needle Raycaster and EventSystem intact, I added in v7 a SimpleStateBehavior, which acts as previously
|
|
95
107
|
|
|
96
|
-
if(
|
|
108
|
+
if (!this._stateManager) this._stateManager = new SimpleStateBehavior(this.uiObject);
|
|
97
109
|
//@ts-ignore
|
|
98
110
|
this.uiObject.setupState(state.state, state.attributes);
|
|
99
111
|
}
|
|
@@ -159,13 +171,13 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
|
|
|
159
171
|
}
|
|
160
172
|
protected onAfterCreated() { }
|
|
161
173
|
|
|
162
|
-
private applyEffects(opts){
|
|
174
|
+
private applyEffects(opts, alpha: number = 1) {
|
|
163
175
|
const outline = this.gameObject?.getComponent(Outline);
|
|
164
176
|
if (outline) {
|
|
165
177
|
if (outline.effectDistance) opts.borderWidth = Math.max(Math.abs(outline.effectDistance.x), Math.abs(outline.effectDistance.y));
|
|
166
178
|
if (outline.effectColor) {
|
|
167
179
|
opts.borderColor = outline.effectColor;
|
|
168
|
-
opts.borderOpacity = outline.effectColor.alpha;
|
|
180
|
+
opts.borderOpacity = outline.effectColor.alpha * alpha;
|
|
169
181
|
}
|
|
170
182
|
}
|
|
171
183
|
}
|
|
@@ -177,8 +189,8 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
|
|
|
177
189
|
this.setOptions({ backgroundOpacity: 0 });
|
|
178
190
|
if (tex) {
|
|
179
191
|
// workaround for https://github.com/needle-tools/needle-engine-support/issues/109
|
|
180
|
-
if(tex.encoding === sRGBEncoding) {
|
|
181
|
-
if(Graphic.textureCache.has(tex)) {
|
|
192
|
+
if (tex.encoding === sRGBEncoding) {
|
|
193
|
+
if (Graphic.textureCache.has(tex)) {
|
|
182
194
|
tex = Graphic.textureCache.get(tex)!;
|
|
183
195
|
} else {
|
|
184
196
|
const clone = tex.clone();
|
|
@@ -14,7 +14,11 @@ export interface ICanvasGroup {
|
|
|
14
14
|
interactable: boolean;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export interface
|
|
17
|
+
export interface IHasAlphaFactor {
|
|
18
|
+
setAlphaFactor(val: number);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface IGraphic extends IComponent, IHasAlphaFactor {
|
|
18
22
|
get isGraphic(): boolean;
|
|
19
23
|
raycastTarget: boolean;
|
|
20
24
|
}
|
|
@@ -2,12 +2,11 @@ import * as ThreeMeshUI from 'three-mesh-ui'
|
|
|
2
2
|
import { BaseUIComponent } from "./BaseUIComponent";
|
|
3
3
|
import { DocumentedOptions as ThreeMeshUIEveryOptions } from "three-mesh-ui/build/types/core/elements/MeshUIBaseElement";
|
|
4
4
|
import { serializable } from "../../engine/engine_serialization_decorator";
|
|
5
|
-
import {
|
|
6
|
-
import { EventSystem } from "./EventSystem";
|
|
5
|
+
import { Matrix4, Object3D, Quaternion, Vector2, Vector3 } from "three";
|
|
7
6
|
import { getParam } from "../../engine/engine_utils";
|
|
8
7
|
import { onChange } from "./Utils";
|
|
9
8
|
import { foreachComponentEnumerator } from "../../engine/engine_gameobject";
|
|
10
|
-
import { ICanvas, IRectTransform, IRectTransformChangedReceiver
|
|
9
|
+
import { ICanvas, IRectTransform, IRectTransformChangedReceiver } from "./Interfaces";
|
|
11
10
|
import { GameObject } from '../Component';
|
|
12
11
|
|
|
13
12
|
const debug = getParam("debugui");
|
|
@@ -43,14 +42,14 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
43
42
|
get rotation() { return this.gameObject.quaternion; }
|
|
44
43
|
get scale(): Vector3 { return this.gameObject.scale; }
|
|
45
44
|
|
|
46
|
-
private _anchoredPosition!:
|
|
45
|
+
private _anchoredPosition!: Vector2;
|
|
47
46
|
|
|
48
|
-
@serializable(
|
|
47
|
+
@serializable(Vector2)
|
|
49
48
|
get anchoredPosition() {
|
|
50
|
-
if (!this._anchoredPosition) this._anchoredPosition = new
|
|
49
|
+
if (!this._anchoredPosition) this._anchoredPosition = new Vector2();
|
|
51
50
|
return this._anchoredPosition;
|
|
52
51
|
}
|
|
53
|
-
private set anchoredPosition(value:
|
|
52
|
+
private set anchoredPosition(value: Vector2) {
|
|
54
53
|
this._anchoredPosition = value;
|
|
55
54
|
}
|
|
56
55
|
|
|
@@ -99,17 +98,24 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
99
98
|
private lastMatrix!: Matrix4;
|
|
100
99
|
private rectBlock!: Object3D;
|
|
101
100
|
private _transformNeedsUpdate: boolean = false;
|
|
101
|
+
private _initialPosition!: Vector3;
|
|
102
102
|
|
|
103
103
|
awake() {
|
|
104
104
|
super.awake();
|
|
105
|
+
// this is required if an animator animated the transform anchoring
|
|
106
|
+
if (!this._anchoredPosition)
|
|
107
|
+
this._anchoredPosition = new Vector2();
|
|
108
|
+
|
|
105
109
|
this.lastMatrix = new Matrix4();
|
|
106
110
|
this.rectBlock = new Object3D();
|
|
107
111
|
// Is this legacy? Not sure if this is still needed
|
|
108
112
|
this.rectBlock.position.z = .1;
|
|
109
113
|
this.rectBlock.name = this.name;
|
|
110
114
|
|
|
111
|
-
//
|
|
112
|
-
|
|
115
|
+
// TODO: get rid of the initial position
|
|
116
|
+
this._initialPosition = this.gameObject.position.clone();
|
|
117
|
+
this._initialPosition.z = 0;
|
|
118
|
+
this.onApplyTransform("RectTransform awake");
|
|
113
119
|
|
|
114
120
|
// TODO: we need to replace this with the watch that e.g. Rigibody is using (or the one in utils?)
|
|
115
121
|
// perhaps we can also just manually check the few properties in the update loops?
|
|
@@ -119,20 +125,6 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
119
125
|
onChange(this, "pivot", () => { this.markDirty(); });
|
|
120
126
|
onChange(this, "anchorMin", () => { this.markDirty(); });
|
|
121
127
|
onChange(this, "anchorMax", () => { this.markDirty(); });
|
|
122
|
-
|
|
123
|
-
// When exported with an anchored position offset we remove it here
|
|
124
|
-
// because it would otherwise be applied twice when the anchoring is animated
|
|
125
|
-
// Maybe we can get rid of this workaround if we just set the mesh ui position from the
|
|
126
|
-
// anchored position value but then we would have to make sure if a user/the engine updates
|
|
127
|
-
// "position" the change would also land in anchoredPosition
|
|
128
|
-
// Another solution would perhaps be to get rid of the extra "anchoredPosition" vector3
|
|
129
|
-
// and instead use the same vector3 instance on both "position" and "anchoredPosition"
|
|
130
|
-
// But I'm also not sure if this will not cause issues elsewhere later / be confusing?
|
|
131
|
-
// (that being said we can make anchoredPosition hidden)
|
|
132
|
-
if (!this.isRoot()) {
|
|
133
|
-
this.gameObject.position.x += this.anchoredPosition.x;
|
|
134
|
-
this.gameObject.position.y -= this.anchoredPosition.y;
|
|
135
|
-
}
|
|
136
128
|
}
|
|
137
129
|
|
|
138
130
|
onEnable() {
|
|
@@ -155,7 +147,7 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
155
147
|
}
|
|
156
148
|
|
|
157
149
|
get isDirty() {
|
|
158
|
-
if(!this._transformNeedsUpdate) this._transformNeedsUpdate = !this.lastMatrix.equals(this.gameObject.matrix);
|
|
150
|
+
if (!this._transformNeedsUpdate) this._transformNeedsUpdate = !this.lastMatrix.equals(this.gameObject.matrix);
|
|
159
151
|
return this._transformNeedsUpdate;
|
|
160
152
|
}
|
|
161
153
|
|
|
@@ -199,7 +191,6 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
199
191
|
else
|
|
200
192
|
this._parentRectTransform = undefined;
|
|
201
193
|
this._transformNeedsUpdate = false;
|
|
202
|
-
this.lastMatrix.copy(this.gameObject.matrix);
|
|
203
194
|
|
|
204
195
|
if (debugLayout) console.warn("RectTransform → ApplyTransform", this.name + " because " + reason);
|
|
205
196
|
|
|
@@ -223,7 +214,8 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
223
214
|
tempVec.set(0, 0, 0);
|
|
224
215
|
this.applyAnchoring(tempVec);
|
|
225
216
|
tempVec.z += this.offset;
|
|
226
|
-
tempVec.z -= this.gameObject.position.z;
|
|
217
|
+
// tempVec.z -= this.gameObject.position.z;
|
|
218
|
+
|
|
227
219
|
tempMatrix.identity();
|
|
228
220
|
tempMatrix.setPosition(tempVec.x, tempVec.y, tempVec.z);
|
|
229
221
|
uiobject.matrix.premultiply(tempMatrix);
|
|
@@ -236,6 +228,8 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
236
228
|
if (!canvas.screenspace) uiobject.rotation.y = Math.PI;
|
|
237
229
|
}
|
|
238
230
|
|
|
231
|
+
this.lastMatrix.copy(this.gameObject.matrix);
|
|
232
|
+
|
|
239
233
|
// iterate other components on this object that might need to know about the transform change
|
|
240
234
|
// e.g. Graphic components should update their width and height
|
|
241
235
|
const includeChildren = true;
|
|
@@ -259,10 +253,20 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
259
253
|
// }
|
|
260
254
|
// }
|
|
261
255
|
|
|
256
|
+
private _lastAnchoring!: Vector2;
|
|
257
|
+
|
|
262
258
|
/** applies the position offset to the passed in vector */
|
|
263
259
|
private applyAnchoring(pos: Vector3) {
|
|
264
|
-
|
|
265
|
-
|
|
260
|
+
|
|
261
|
+
if (!this._lastAnchoring) this._lastAnchoring = new Vector2();
|
|
262
|
+
const diff = this._lastAnchoring.sub(this._anchoredPosition)
|
|
263
|
+
this.gameObject.position.x += diff.x;
|
|
264
|
+
this.gameObject.position.y += diff.y;
|
|
265
|
+
this._lastAnchoring.copy(this._anchoredPosition);
|
|
266
|
+
|
|
267
|
+
pos.x += (this._initialPosition.x - this.gameObject.position.x);
|
|
268
|
+
pos.y += (this._initialPosition.y - this.gameObject.position.y);
|
|
269
|
+
pos.z += (this._initialPosition.z - this.gameObject.position.z);
|
|
266
270
|
|
|
267
271
|
const parent = this._parentRectTransform;
|
|
268
272
|
if (parent) {
|
|
@@ -6,7 +6,7 @@ import { updateRenderSettings } from './Utils';
|
|
|
6
6
|
import { Canvas } from './Canvas';
|
|
7
7
|
import { serializable } from '../../engine/engine_serialization_decorator';
|
|
8
8
|
import { getParam, resolveUrl } from '../../engine/engine_utils';
|
|
9
|
-
import { ICanvas } from './Interfaces';
|
|
9
|
+
import { ICanvas, IHasAlphaFactor } from './Interfaces';
|
|
10
10
|
|
|
11
11
|
const debug = getParam("debugtext");
|
|
12
12
|
|
|
@@ -38,7 +38,7 @@ export enum FontStyle {
|
|
|
38
38
|
BoldAndItalic = 3,
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export class Text extends Graphic {
|
|
41
|
+
export class Text extends Graphic implements IHasAlphaFactor {
|
|
42
42
|
|
|
43
43
|
@serializable()
|
|
44
44
|
alignment: TextAnchor = TextAnchor.UpperLeft;
|
|
@@ -55,6 +55,13 @@ export class Text extends Graphic {
|
|
|
55
55
|
@serializable()
|
|
56
56
|
fontStyle: FontStyle = FontStyle.Normal;
|
|
57
57
|
|
|
58
|
+
// private _alphaFactor : number = 1;
|
|
59
|
+
setAlphaFactor(factor: number): void {
|
|
60
|
+
super.setAlphaFactor(factor);
|
|
61
|
+
this.uiObject?.set({ fontOpacity: this.color.alpha * this.alphaFactor });
|
|
62
|
+
this.markDirty();
|
|
63
|
+
}
|
|
64
|
+
|
|
58
65
|
@serializable()
|
|
59
66
|
get text(): string {
|
|
60
67
|
return this._text;
|
|
@@ -78,11 +85,9 @@ export class Text extends Graphic {
|
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
set fontSize(val: number) {
|
|
81
|
-
|
|
82
88
|
// Setting that kind of property in a parent, would cascade to each 'non-overrided' children.
|
|
83
89
|
this._fontSize = val;
|
|
84
90
|
this.uiObject?.set({ fontSize: val });
|
|
85
|
-
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
|