@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
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Graphic } from './Graphic';
|
|
2
2
|
import * as ThreeMeshUI from 'three-mesh-ui'
|
|
3
|
-
import {
|
|
4
|
-
import { RectTransform } from './RectTransform';
|
|
3
|
+
import { DocumentedOptions as ThreeMeshUIEveryOptions } from "three-mesh-ui/build/types/core/elements/MeshUIBaseElement";
|
|
5
4
|
import { Color } from 'three';
|
|
6
|
-
import { FrameEvent } from '../../engine/engine_setup';
|
|
7
5
|
import { updateRenderSettings } from './Utils';
|
|
8
6
|
import { Canvas } from './Canvas';
|
|
9
7
|
import { serializable } from '../../engine/engine_serialization_decorator';
|
|
10
8
|
import { getParam, resolveUrl } from '../../engine/engine_utils';
|
|
9
|
+
import { ICanvas } from './Interfaces';
|
|
11
10
|
|
|
12
11
|
const debug = getParam("debugtext");
|
|
13
12
|
|
|
@@ -32,7 +31,7 @@ enum HorizontalWrapMode {
|
|
|
32
31
|
Overflow = 1,
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
enum FontStyle {
|
|
34
|
+
export enum FontStyle {
|
|
36
35
|
Normal = 0,
|
|
37
36
|
Bold = 1,
|
|
38
37
|
Italic = 2,
|
|
@@ -53,7 +52,7 @@ export class Text extends Graphic {
|
|
|
53
52
|
lineSpacing: number = 1;
|
|
54
53
|
@serializable()
|
|
55
54
|
supportRichText: boolean = false;
|
|
56
|
-
@serializable()
|
|
55
|
+
@serializable(URL)
|
|
57
56
|
font?: string;
|
|
58
57
|
@serializable()
|
|
59
58
|
fontStyle: FontStyle = FontStyle.Normal;
|
|
@@ -62,94 +61,108 @@ export class Text extends Graphic {
|
|
|
62
61
|
get text(): string {
|
|
63
62
|
return this._text;
|
|
64
63
|
}
|
|
64
|
+
|
|
65
65
|
set text(val: string) {
|
|
66
|
+
|
|
67
|
+
|
|
66
68
|
this._text = val;
|
|
67
|
-
|
|
68
|
-
this.createText(val, this.getTextOpts(), this.supportRichText);
|
|
69
|
-
}
|
|
70
|
-
if (this._textMeshUi) {
|
|
71
|
-
if (this._textMeshUi.length > 1) {
|
|
72
|
-
this.requestRebuild();
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
//@ts-ignore
|
|
76
|
-
this._textMeshUi[0].set({ content: val });
|
|
77
|
-
this.markDirty();
|
|
78
|
-
}
|
|
69
|
+
this.feedText(this.text, this.supportRichText);
|
|
79
70
|
}
|
|
71
|
+
|
|
80
72
|
private set_text(val: string) {
|
|
81
73
|
this.text = val;
|
|
82
74
|
}
|
|
83
75
|
|
|
84
76
|
@serializable()
|
|
85
|
-
get fontSize(): number {
|
|
77
|
+
get fontSize(): number {
|
|
78
|
+
return this._fontSize;
|
|
79
|
+
}
|
|
80
|
+
|
|
86
81
|
set fontSize(val: number) {
|
|
82
|
+
|
|
83
|
+
// Setting that kind of property in a parent, would cascade to each 'non-overrided' children.
|
|
87
84
|
this._fontSize = val;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.requestRebuild();
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
//@ts-ignore
|
|
94
|
-
this._textMeshUi[0].set({ fontSize: val });
|
|
95
|
-
this.markDirty();
|
|
96
|
-
}
|
|
85
|
+
this.uiObject?.set({ fontSize: val });
|
|
86
|
+
|
|
97
87
|
}
|
|
98
88
|
|
|
89
|
+
|
|
99
90
|
protected onColorChanged(): void {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this._textMeshUi[0].set({ fontColor: col, fontOpacity: col.alpha });
|
|
108
|
-
this.markDirty();
|
|
91
|
+
this.uiObject?.set({ color: this.color, fontOpacity: this.color.alpha });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
onParentRectTransformChanged(): void {
|
|
95
|
+
super.onParentRectTransformChanged();
|
|
96
|
+
if (this.uiObject) {
|
|
97
|
+
this.updateOverflow();
|
|
109
98
|
}
|
|
110
99
|
}
|
|
111
100
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.startCoroutine(this.rebuildDelayedRoutine(), FrameEvent.EarlyUpdate);
|
|
101
|
+
onBeforeRender(): void {
|
|
102
|
+
if (this.uiObject && (this.Root as any as ICanvas).screenspace) {
|
|
103
|
+
this.updateOverflow();
|
|
104
|
+
}
|
|
117
105
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this.
|
|
106
|
+
|
|
107
|
+
private updateOverflow() {
|
|
108
|
+
// HACK: force the text overflow to update
|
|
109
|
+
const overflow = (this.uiObject as any)?._overflow;
|
|
110
|
+
if (overflow) {
|
|
111
|
+
overflow._needsUpdate = true;
|
|
112
|
+
this.markDirty();
|
|
125
113
|
}
|
|
126
|
-
this.createText(this.text, this.getTextOpts(), this.supportRichText);
|
|
127
|
-
this.markDirty();
|
|
128
114
|
}
|
|
129
115
|
|
|
130
116
|
protected onCreate(_opts: any): void {
|
|
131
117
|
if (debug) console.log(this);
|
|
132
|
-
|
|
133
|
-
if (
|
|
118
|
+
|
|
119
|
+
if (this.horizontalOverflow == HorizontalWrapMode.Overflow) {
|
|
120
|
+
// Only line characters in the textContent (\n,\r\t) would be able to multiline the text
|
|
121
|
+
_opts.whiteSpace = 'pre';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (this.verticalOverflow == VerticalWrapMode.Truncate) {
|
|
134
125
|
this.context.renderer.localClippingEnabled = true;
|
|
126
|
+
_opts.overflow = 'hidden';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
// @marwie : this combination is currently KO. See sample "Overflow Overview"
|
|
131
|
+
if (this.horizontalOverflow == HorizontalWrapMode.Overflow && this.verticalOverflow == VerticalWrapMode.Truncate) {
|
|
132
|
+
// This could fix this combination, but would require anchors updates to replace element
|
|
133
|
+
// _opts.width = 'auto';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
_opts.lineHeight = this.lineSpacing;
|
|
138
|
+
|
|
139
|
+
// @marwie : Should be fixed. Currently _opts are always fed with :
|
|
140
|
+
// backgroundOpacity : color.opacity
|
|
141
|
+
// backgroundColor : color
|
|
142
|
+
delete _opts.backgroundOpacity;
|
|
143
|
+
delete _opts.backgroundColor;
|
|
144
|
+
|
|
145
|
+
// helper to show bounds of text element
|
|
146
|
+
if (debug) {
|
|
147
|
+
_opts.backgroundColor = 0xff9900;
|
|
148
|
+
_opts.backgroundOpacity = 0.5;
|
|
149
|
+
}
|
|
135
150
|
|
|
136
151
|
const rt = this.rectTransform;
|
|
137
|
-
// this._container = this._textMeshUi;
|
|
138
|
-
// every mesh ui component must be inside a block
|
|
139
|
-
// images emit nothing but blocks
|
|
140
|
-
// this code should probably be moved somewhere else and also handle raw image / anything that emits block (sprite?)
|
|
141
|
-
// so we only add extra blocks if the parent doesnt have one yet
|
|
142
|
-
// maybe we can just ask the component the text will be added to to not rely on our unity components?
|
|
143
|
-
// this can hopefully be removed once this is fixed/improved: https://github.com/felixmariotto/three-mesh-ui/issues/168
|
|
144
|
-
this._textContainer = this.uiObject = this.createBlock(rt, hideOverflow, null, true);
|
|
145
152
|
|
|
153
|
+
// Texts now support both options, block and inline, and inline has all default to inherit
|
|
154
|
+
_opts = { ..._opts, ...this.getTextOpts() };
|
|
146
155
|
|
|
147
|
-
this.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
156
|
+
this.getAlignment(_opts);
|
|
157
|
+
|
|
158
|
+
if (debug) {
|
|
159
|
+
_opts.backgroundColor = Math.random() * 0xffffff;
|
|
160
|
+
_opts.backgroundOpacity = 0.1;
|
|
151
161
|
}
|
|
152
|
-
|
|
162
|
+
|
|
163
|
+
this.uiObject = rt.createNewText(_opts);
|
|
164
|
+
this.feedText(this.text, this.supportRichText);
|
|
165
|
+
|
|
153
166
|
}
|
|
154
167
|
|
|
155
168
|
onAfterAddedToScene() {
|
|
@@ -159,8 +172,9 @@ export class Text extends Graphic {
|
|
|
159
172
|
|
|
160
173
|
private _text: string = "";
|
|
161
174
|
private _fontSize: number = 12;
|
|
162
|
-
|
|
163
|
-
private
|
|
175
|
+
|
|
176
|
+
private _textMeshUi: Array<ThreeMeshUI.Inline> | null = null;
|
|
177
|
+
|
|
164
178
|
|
|
165
179
|
private getTextOpts(): object {
|
|
166
180
|
let fontSize = this.fontSize;
|
|
@@ -168,15 +182,15 @@ export class Text extends Graphic {
|
|
|
168
182
|
// fontSize /= this.canvas?.scaleFactor;
|
|
169
183
|
// }
|
|
170
184
|
|
|
171
|
-
|
|
185
|
+
|
|
172
186
|
const textOpts = {
|
|
173
|
-
|
|
174
|
-
fontColor: this.color,
|
|
187
|
+
color: this.color,
|
|
175
188
|
fontOpacity: this.color.alpha,
|
|
176
189
|
fontSize: fontSize,
|
|
177
190
|
fontKerning: "normal",
|
|
191
|
+
|
|
178
192
|
};
|
|
179
|
-
this.setFont(textOpts, this.fontStyle);
|
|
193
|
+
this.setFont(textOpts as ThreeMeshUIEveryOptions, this.fontStyle);
|
|
180
194
|
return textOpts;
|
|
181
195
|
}
|
|
182
196
|
|
|
@@ -186,190 +200,128 @@ export class Text extends Graphic {
|
|
|
186
200
|
this._didHandleTextRenderOnTop = false;
|
|
187
201
|
if (this.uiObject) {
|
|
188
202
|
// @ts-ignore
|
|
189
|
-
|
|
190
|
-
|
|
203
|
+
|
|
204
|
+
// @TODO : Evaluate the need of keeping it anonymous.
|
|
205
|
+
// From v7.x afterUpdate can be removed but requires a reference
|
|
206
|
+
this.uiObject.addAfterUpdate(() => {
|
|
191
207
|
// We need to update the shadow owner when the text updates
|
|
192
208
|
// because once the font has loaded we get new children (a new mesh)
|
|
193
|
-
// which is the text, it needs to be linked back to this component
|
|
209
|
+
// which is the text, it needs to be linked back to this component
|
|
194
210
|
// to be properly handled by the EventSystem
|
|
195
211
|
// since the EventSystem looks for shadow component owners to handle events
|
|
196
212
|
this.setShadowComponentOwner(this.uiObject);
|
|
197
213
|
this.markDirty();
|
|
198
|
-
};
|
|
214
|
+
});
|
|
199
215
|
}
|
|
200
216
|
|
|
201
|
-
setTimeout(()=> this.markDirty(), 10);
|
|
217
|
+
setTimeout(() => this.markDirty(), 10);
|
|
202
218
|
}
|
|
203
219
|
|
|
204
|
-
private
|
|
205
|
-
//@ts-ignore
|
|
206
|
-
const opts: ThreeMeshUI.BlockOptions = {};
|
|
207
|
-
|
|
208
|
-
// @TODO : THH would require update for 7.x
|
|
209
|
-
opts.hiddenOverflow = hideOverflow;
|
|
210
|
-
|
|
211
|
-
// @TODO : THH would require update for 7.x
|
|
212
|
-
opts.interLine = (this.lineSpacing - 1) * this.fontSize * 1.333;
|
|
213
|
-
|
|
214
|
-
this.getAlignment(opts, isTextIntermediate);
|
|
215
|
-
const block = rt.createNewBlock(opts);
|
|
216
|
-
// The text block should never write depth to avoid z-fighting
|
|
217
|
-
const mat = block["backgroundMaterial"];
|
|
218
|
-
if(mat) mat.depthWrite = false;
|
|
219
|
-
if (content) {
|
|
220
|
-
if (Array.isArray(content)) {
|
|
221
|
-
block.add(...content);
|
|
222
|
-
} else {
|
|
223
|
-
block.add(content);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return block;
|
|
227
|
-
}
|
|
220
|
+
private getAlignment(opts: ThreeMeshUIEveryOptions): ThreeMeshUIEveryOptions {
|
|
228
221
|
|
|
229
|
-
|
|
230
|
-
private getAlignment(opts: ThreeMeshUI.BlockOptions | any, isTextIntermediate: boolean = false): ThreeMeshUI.BlockOptions {
|
|
231
|
-
if (!isTextIntermediate) {
|
|
232
|
-
opts.contentDirection = "row";
|
|
233
|
-
|
|
234
|
-
switch (this.alignment) {
|
|
235
|
-
case TextAnchor.UpperLeft:
|
|
236
|
-
case TextAnchor.MiddleLeft:
|
|
237
|
-
case TextAnchor.LowerLeft:
|
|
238
|
-
opts.textAlign = "left";
|
|
239
|
-
break;
|
|
240
|
-
case TextAnchor.UpperCenter:
|
|
241
|
-
case TextAnchor.MiddleCenter:
|
|
242
|
-
case TextAnchor.LowerCenter:
|
|
243
|
-
opts.textAlign = "center";
|
|
244
|
-
|
|
245
|
-
break;
|
|
246
|
-
case TextAnchor.UpperRight:
|
|
247
|
-
case TextAnchor.MiddleRight:
|
|
248
|
-
case TextAnchor.LowerRight:
|
|
249
|
-
opts.textAlign = "right";
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
222
|
+
opts.flexDirection = "column";
|
|
253
223
|
|
|
254
224
|
switch (this.alignment) {
|
|
255
|
-
// @info ThreeMeshUI remaining alignment : space-between|space-around|"stretch(experimental)"
|
|
256
|
-
default:
|
|
257
225
|
case TextAnchor.UpperLeft:
|
|
258
|
-
case TextAnchor.UpperCenter:
|
|
259
|
-
case TextAnchor.UpperRight:
|
|
260
|
-
opts.justifyContent = "start";
|
|
261
|
-
break;
|
|
262
226
|
case TextAnchor.MiddleLeft:
|
|
263
|
-
case TextAnchor.MiddleCenter:
|
|
264
|
-
case TextAnchor.MiddleRight:
|
|
265
|
-
opts.justifyContent = "center";
|
|
266
|
-
break;
|
|
267
227
|
case TextAnchor.LowerLeft:
|
|
228
|
+
opts.textAlign = "left";
|
|
229
|
+
break;
|
|
230
|
+
case TextAnchor.UpperCenter:
|
|
231
|
+
case TextAnchor.MiddleCenter:
|
|
268
232
|
case TextAnchor.LowerCenter:
|
|
233
|
+
opts.textAlign = "center";
|
|
234
|
+
|
|
235
|
+
break;
|
|
236
|
+
case TextAnchor.UpperRight:
|
|
237
|
+
case TextAnchor.MiddleRight:
|
|
269
238
|
case TextAnchor.LowerRight:
|
|
270
|
-
opts.
|
|
239
|
+
opts.textAlign = "right";
|
|
271
240
|
break;
|
|
272
241
|
}
|
|
273
242
|
|
|
274
|
-
|
|
243
|
+
|
|
275
244
|
switch (this.alignment) {
|
|
245
|
+
default:
|
|
276
246
|
case TextAnchor.UpperLeft:
|
|
277
|
-
case TextAnchor.
|
|
278
|
-
case TextAnchor.
|
|
247
|
+
case TextAnchor.UpperCenter:
|
|
248
|
+
case TextAnchor.UpperRight:
|
|
279
249
|
opts.alignItems = "start";
|
|
280
250
|
break;
|
|
281
|
-
case TextAnchor.
|
|
251
|
+
case TextAnchor.MiddleLeft:
|
|
282
252
|
case TextAnchor.MiddleCenter:
|
|
283
|
-
case TextAnchor.
|
|
253
|
+
case TextAnchor.MiddleRight:
|
|
284
254
|
opts.alignItems = "center";
|
|
285
|
-
|
|
286
255
|
break;
|
|
287
|
-
case TextAnchor.
|
|
288
|
-
case TextAnchor.
|
|
256
|
+
case TextAnchor.LowerLeft:
|
|
257
|
+
case TextAnchor.LowerCenter:
|
|
289
258
|
case TextAnchor.LowerRight:
|
|
290
259
|
opts.alignItems = "end";
|
|
291
260
|
break;
|
|
292
261
|
}
|
|
293
|
-
return opts;
|
|
294
|
-
}
|
|
295
262
|
|
|
296
|
-
|
|
297
|
-
if (this.horizontalOverflow === HorizontalWrapMode.Overflow) {
|
|
298
|
-
setTimeout(() => {
|
|
299
|
-
if (!this._textMeshUi) return;
|
|
300
|
-
const container = this._textMeshUi[0].parent;
|
|
301
|
-
if (!container) return;
|
|
302
|
-
//@ts-ignore
|
|
303
|
-
if (container.lines) {
|
|
304
|
-
//@ts-ignore
|
|
305
|
-
let newWidth = container.lines.reduce((accu, line) => { return accu + line.width }, 0);
|
|
306
|
-
//@ts-ignore
|
|
307
|
-
newWidth += container.getFontSize() * 5;
|
|
308
|
-
//@ts-ignore
|
|
309
|
-
newWidth += (container.padding * 2 || 0);
|
|
310
|
-
newWidth += this.fontSize * 1.5;
|
|
311
|
-
// TODO: handle alignment!
|
|
312
|
-
// const pos = container.position;
|
|
313
|
-
// pos.x = this.gameObject.position.x * -.01 + newWidth * .5 - this.rect.sizeDelta.x * .005;
|
|
314
|
-
// this._textMeshUi.set({ position: pos });
|
|
315
|
-
//@ts-ignore
|
|
316
|
-
container.set({ width: newWidth });
|
|
317
|
-
this.ensureShadowComponentOwner();
|
|
318
|
-
}
|
|
319
|
-
}, 1);
|
|
320
|
-
}
|
|
263
|
+
return opts;
|
|
321
264
|
}
|
|
322
265
|
|
|
323
|
-
private
|
|
324
|
-
if (
|
|
325
|
-
|
|
326
|
-
if (c[$shadowDomOwner] === undefined)
|
|
327
|
-
c[$shadowDomOwner] = this;
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
}
|
|
266
|
+
private feedText(text: string, richText: boolean) {
|
|
267
|
+
// if (!text || text.length <= 0) return;
|
|
268
|
+
// if (!text ) return;
|
|
331
269
|
|
|
332
|
-
|
|
333
|
-
if (!text || text.length <= 0) return;
|
|
270
|
+
if (!this.uiObject) return null;
|
|
334
271
|
if (!this._textMeshUi)
|
|
335
272
|
this._textMeshUi = [];
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
273
|
+
|
|
274
|
+
// this.uiObject.textContent = text;
|
|
275
|
+
// return ;
|
|
276
|
+
|
|
277
|
+
if (!richText || text.length === 0) {
|
|
278
|
+
//@TODO: @swingingtom how would the text content be set?
|
|
279
|
+
//@ts-ignore
|
|
280
|
+
this.uiObject.textContent = text;
|
|
281
|
+
} else {
|
|
282
|
+
|
|
283
|
+
|
|
347
284
|
let currentTag: TagInfo | null = this.getNextTag(text);
|
|
348
285
|
if (!currentTag) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
286
|
+
//@TODO: @swingingtom how would the text content be set?
|
|
287
|
+
//@ts-ignore
|
|
288
|
+
return this.uiObject.textContent = text;
|
|
289
|
+
} else if (currentTag.startIndex > 0) {
|
|
290
|
+
this.uiObject.add(new ThreeMeshUI.Inline({ textContent: text.substring(0, currentTag.startIndex), color: 'inherit' }))
|
|
353
291
|
}
|
|
354
292
|
const stackArray: Array<TagStackEntry> = [];
|
|
355
293
|
while (currentTag) {
|
|
356
294
|
const next = this.getNextTag(text, currentTag.endIndex);
|
|
295
|
+
|
|
296
|
+
const opts = {
|
|
297
|
+
fontFamily: this.uiObject?.get('fontFamily'),
|
|
298
|
+
color: 'inherit',
|
|
299
|
+
textContent: ""
|
|
300
|
+
}
|
|
301
|
+
|
|
357
302
|
if (next) {
|
|
358
|
-
|
|
303
|
+
|
|
304
|
+
opts.textContent = this.getText(text, currentTag, next);
|
|
305
|
+
|
|
359
306
|
this.handleTag(currentTag, opts, stackArray);
|
|
360
|
-
this.
|
|
361
|
-
|
|
362
|
-
else {
|
|
363
|
-
|
|
307
|
+
this.uiObject?.add(new ThreeMeshUI.Inline(opts))
|
|
308
|
+
|
|
309
|
+
} else {
|
|
310
|
+
|
|
311
|
+
opts.textContent = text.substring(currentTag.endIndex);
|
|
312
|
+
|
|
364
313
|
this.handleTag(currentTag, opts, stackArray);
|
|
365
|
-
this.
|
|
314
|
+
this.uiObject?.add(new ThreeMeshUI.Inline(opts))
|
|
366
315
|
}
|
|
367
316
|
currentTag = next;
|
|
368
317
|
}
|
|
369
318
|
}
|
|
319
|
+
|
|
320
|
+
return null;
|
|
370
321
|
}
|
|
371
322
|
|
|
372
323
|
private _didHandleTextRenderOnTop: boolean = false;
|
|
324
|
+
|
|
373
325
|
private handleTextRenderOnTop() {
|
|
374
326
|
if (this._didHandleTextRenderOnTop) return;
|
|
375
327
|
this._didHandleTextRenderOnTop = true;
|
|
@@ -377,11 +329,17 @@ export class Text extends Graphic {
|
|
|
377
329
|
}
|
|
378
330
|
|
|
379
331
|
// waits for all the text objects to be ready to set the render on top setting
|
|
380
|
-
|
|
332
|
+
// @THH : this isn't true anymore. We can set mesh and material properties before their counterparts are created.
|
|
333
|
+
// Values would automatically be passed when created. Not sure for depthWrite but it can be added;
|
|
334
|
+
private * renderOnTopCoroutine() {
|
|
381
335
|
if (!this.canvas) return;
|
|
382
336
|
const updatedRendering: boolean[] = [];
|
|
383
337
|
const canvas = this.canvas;
|
|
384
|
-
const settings = {
|
|
338
|
+
const settings = {
|
|
339
|
+
renderOnTop: canvas.renderOnTop,
|
|
340
|
+
depthWrite: canvas.depthWrite,
|
|
341
|
+
doubleSided: canvas.doubleSided
|
|
342
|
+
};
|
|
385
343
|
while (true) {
|
|
386
344
|
let isWaitingForElementToUpdate = false;
|
|
387
345
|
if (this._textMeshUi) {
|
|
@@ -407,36 +365,31 @@ export class Text extends Graphic {
|
|
|
407
365
|
// console.log(tag);
|
|
408
366
|
if (!tag.isEndTag) {
|
|
409
367
|
if (tag.type.includes("color")) {
|
|
410
|
-
const stackEntry = new TagStackEntry(tag, {
|
|
368
|
+
const stackEntry = new TagStackEntry(tag, { color: opts.color });
|
|
411
369
|
stackArray.push(stackEntry);
|
|
412
370
|
if (tag.type.length > 6) // color=
|
|
413
371
|
{
|
|
414
|
-
const col = tag.type.substring(
|
|
415
|
-
opts.
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
372
|
+
const col = parseInt("0x" + tag.type.substring(7));
|
|
373
|
+
opts.color = col;
|
|
374
|
+
} else {
|
|
418
375
|
// if it does not contain a color it is white
|
|
419
|
-
opts.
|
|
376
|
+
opts.color = new Color(1, 1, 1);
|
|
420
377
|
}
|
|
421
|
-
}
|
|
422
|
-
|
|
378
|
+
} else if (tag.type == "b") {
|
|
379
|
+
this.setFont(opts, FontStyle.Bold);
|
|
423
380
|
const stackEntry = new TagStackEntry(tag, {
|
|
424
|
-
|
|
425
|
-
fontTexture: opts.fontTexture,
|
|
381
|
+
fontWeight: 700,
|
|
426
382
|
});
|
|
427
383
|
stackArray.push(stackEntry);
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
else if (tag.type == "i") {
|
|
384
|
+
} else if (tag.type == "i") {
|
|
385
|
+
this.setFont(opts, FontStyle.Italic);
|
|
431
386
|
const stackEntry = new TagStackEntry(tag, {
|
|
432
|
-
|
|
433
|
-
fontTexture: opts.fontTexture,
|
|
387
|
+
fontStyle: 'italic'
|
|
434
388
|
});
|
|
435
389
|
stackArray.push(stackEntry);
|
|
436
|
-
|
|
390
|
+
|
|
437
391
|
}
|
|
438
|
-
}
|
|
439
|
-
else {
|
|
392
|
+
} else {
|
|
440
393
|
if (stackArray.length > 0) {
|
|
441
394
|
const last = stackArray.pop();
|
|
442
395
|
if (last) {
|
|
@@ -464,60 +417,126 @@ export class Text extends Graphic {
|
|
|
464
417
|
return null;
|
|
465
418
|
}
|
|
466
419
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
if (style === FontStyle.Italic)return resolveUrl(this.sourceId, fontName);
|
|
494
|
-
fontName = fontName.substring(0, fontName.length - "-italic".length);
|
|
495
|
-
}
|
|
496
|
-
else if (fontNameLower.endsWith("-bolditalic")) {
|
|
497
|
-
if (style === FontStyle.BoldAndItalic)return resolveUrl(this.sourceId, fontName);
|
|
498
|
-
fontName = fontName.substring(0, fontName.length - "-bolditalic".length);
|
|
499
|
-
}
|
|
500
|
-
else
|
|
501
|
-
// If a font does not have a specific style suffic we dont support getting the correct font style
|
|
502
|
-
return resolveUrl(this.sourceId, fontName);
|
|
420
|
+
/**
|
|
421
|
+
* Update provided opts to have a proper fontDefinition : family+weight+style
|
|
422
|
+
* Ensure Family and Variant are registered in FontLibrary
|
|
423
|
+
*
|
|
424
|
+
* @param opts
|
|
425
|
+
* @param fontStyle
|
|
426
|
+
* @private
|
|
427
|
+
*/
|
|
428
|
+
private setFont(opts: ThreeMeshUIEveryOptions, fontStyle: FontStyle) {
|
|
429
|
+
|
|
430
|
+
// @TODO : THH could be useful to uniformize font family name :
|
|
431
|
+
// This would ease possible html/vr matching
|
|
432
|
+
// - Arial instead of assets/arial
|
|
433
|
+
// - Arial should stay Arial instead of arial
|
|
434
|
+
if (!this.font) return;
|
|
435
|
+
let familyName = this.font;
|
|
436
|
+
|
|
437
|
+
// ensure a font family is register under this name
|
|
438
|
+
let fontFamily = ThreeMeshUI.FontLibrary.getFontFamily(familyName as string);
|
|
439
|
+
if (!fontFamily)
|
|
440
|
+
fontFamily = ThreeMeshUI.FontLibrary.addFontFamily(familyName as string);
|
|
441
|
+
|
|
442
|
+
// @TODO: @swingingtom how should the font be set?
|
|
443
|
+
//@ts-ignore
|
|
444
|
+
opts.fontFamily = fontFamily;
|
|
445
|
+
const lowerFamilyName = familyName.toLowerCase();
|
|
503
446
|
|
|
504
|
-
switch (
|
|
447
|
+
switch (fontStyle) {
|
|
448
|
+
default:
|
|
505
449
|
case FontStyle.Normal:
|
|
506
|
-
|
|
507
|
-
|
|
450
|
+
opts.fontWeight = 400;
|
|
451
|
+
opts.fontStyle = "normal";
|
|
452
|
+
break
|
|
453
|
+
|
|
508
454
|
case FontStyle.Bold:
|
|
509
|
-
|
|
455
|
+
opts.fontWeight = 700;
|
|
456
|
+
opts.fontStyle = "normal";
|
|
457
|
+
if (!lowerFamilyName.includes("-bold"))
|
|
458
|
+
familyName += "-bold";
|
|
510
459
|
break;
|
|
460
|
+
|
|
511
461
|
case FontStyle.Italic:
|
|
512
|
-
|
|
462
|
+
opts.fontWeight = 400;
|
|
463
|
+
opts.fontStyle = "italic"
|
|
464
|
+
if (!lowerFamilyName.includes("-italic"))
|
|
465
|
+
familyName += "-italic";
|
|
513
466
|
break;
|
|
467
|
+
|
|
514
468
|
case FontStyle.BoldAndItalic:
|
|
515
|
-
|
|
516
|
-
|
|
469
|
+
opts.fontStyle = 'italic';
|
|
470
|
+
opts.fontWeight = 400;
|
|
471
|
+
if (!lowerFamilyName.includes("-bold"))
|
|
472
|
+
familyName += "-bold";
|
|
473
|
+
if (!lowerFamilyName.includes("-italic"))
|
|
474
|
+
familyName += "-italic";
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
// Ensure a fontVariant is registered
|
|
479
|
+
//@TODO: @swingingtom add type for fontWeight
|
|
480
|
+
let fontVariant = fontFamily.getVariant(opts.fontWeight as any as string, opts.fontStyle);
|
|
481
|
+
if (!fontVariant) {
|
|
482
|
+
let jsonPath = familyName;
|
|
483
|
+
if (!jsonPath?.endsWith("-msdf.json")) jsonPath += "-msdf.json";
|
|
484
|
+
let texturePath = familyName;
|
|
485
|
+
if (!texturePath?.endsWith(".png")) texturePath += ".png";
|
|
486
|
+
|
|
487
|
+
//@TODO: @swingingtom add type for fontWeight
|
|
488
|
+
//@TODO: @swingingtom addVariant return type is wrong (should be FontVariant)
|
|
489
|
+
fontVariant = fontFamily.addVariant(opts.fontWeight as any as string, opts.fontStyle, jsonPath, texturePath as string) as any as ThreeMeshUI.FontVariant;
|
|
490
|
+
fontVariant?.addEventListener('ready', () => {
|
|
491
|
+
this.markDirty();
|
|
492
|
+
});
|
|
517
493
|
}
|
|
518
494
|
|
|
519
|
-
return resolveUrl(this.sourceId, fontName);
|
|
520
495
|
}
|
|
496
|
+
|
|
497
|
+
// private getFontStyleName(style: FontStyle): string | null {
|
|
498
|
+
// if (!this.font) return null;
|
|
499
|
+
// let fontName = this.font;
|
|
500
|
+
|
|
501
|
+
// // if a font path has a known suffix we remove it
|
|
502
|
+
// const fontNameLower = fontName.toLowerCase();
|
|
503
|
+
// if (fontNameLower.endsWith("-regular")) {
|
|
504
|
+
// if (style === FontStyle.Normal) return resolveUrl(this.sourceId, fontName);
|
|
505
|
+
// fontName = fontName.substring(0, fontName.length - "-regular".length);
|
|
506
|
+
// }
|
|
507
|
+
// else if (fontNameLower.endsWith("-bold")) {
|
|
508
|
+
// if (style === FontStyle.Bold) return resolveUrl(this.sourceId, fontName);
|
|
509
|
+
// fontName = fontName.substring(0, fontName.length - "-bold".length);
|
|
510
|
+
// }
|
|
511
|
+
// else if (fontNameLower.endsWith("-italic")) {
|
|
512
|
+
// if (style === FontStyle.Italic) return resolveUrl(this.sourceId, fontName);
|
|
513
|
+
// fontName = fontName.substring(0, fontName.length - "-italic".length);
|
|
514
|
+
// }
|
|
515
|
+
// else if (fontNameLower.endsWith("-bolditalic")) {
|
|
516
|
+
// if (style === FontStyle.BoldAndItalic) return resolveUrl(this.sourceId, fontName);
|
|
517
|
+
// fontName = fontName.substring(0, fontName.length - "-bolditalic".length);
|
|
518
|
+
// }
|
|
519
|
+
// else
|
|
520
|
+
// // If a font does not have a specific style suffic we dont support getting the correct font style
|
|
521
|
+
// return resolveUrl(this.sourceId, fontName);
|
|
522
|
+
|
|
523
|
+
// switch (style) {
|
|
524
|
+
// case FontStyle.Normal:
|
|
525
|
+
// fontName += "-regular";
|
|
526
|
+
// break;
|
|
527
|
+
// case FontStyle.Bold:
|
|
528
|
+
// fontName += "-bold";
|
|
529
|
+
// break;
|
|
530
|
+
// case FontStyle.Italic:
|
|
531
|
+
// fontName += "-italic";
|
|
532
|
+
// break;
|
|
533
|
+
// case FontStyle.BoldAndItalic:
|
|
534
|
+
// fontName += "-bolditalic";
|
|
535
|
+
// break;
|
|
536
|
+
// }
|
|
537
|
+
|
|
538
|
+
// return resolveUrl(this.sourceId, fontName);
|
|
539
|
+
// }
|
|
521
540
|
}
|
|
522
541
|
|
|
523
542
|
class TagStackEntry {
|