@combos-fun/plugin-renderer-3d-text 0.1.7 → 0.1.8
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/README.md +5 -1
- package/agent-skill.md +12 -7
- package/dist/plugin-renderer-3d-text.cjs.js +30 -9
- package/dist/plugin-renderer-3d-text.cjs.js.map +1 -1
- package/dist/plugin-renderer-3d-text.cjs.prod.js +1 -1
- package/dist/plugin-renderer-3d-text.d.ts +12 -4
- package/dist/plugin-renderer-3d-text.esm.js +29 -10
- package/dist/plugin-renderer-3d-text.esm.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -52,9 +52,13 @@ The host injects `window.combos` into the game HTML head. The first
|
|
|
52
52
|
`requestI18n` runs in `beforeReady` and holds `combos-game:ready` / `start`
|
|
53
53
|
until the host replies. Put every later-screen template in `sourceTexts` so
|
|
54
54
|
those screens reuse the startup catalog instead of flashing source text.
|
|
55
|
+
The system keeps one growing session catalog of source templates and
|
|
56
|
+
translations; later `requestI18n` calls only run for templates still missing
|
|
57
|
+
from that catalog.
|
|
55
58
|
If the host returns `needed: true` but a template is missing from
|
|
56
59
|
`translations`, the system merges all current texts and waits for one more
|
|
57
|
-
`requestI18n` before showing that label.
|
|
60
|
+
`requestI18n` before showing that label. Returning to copy that is already in
|
|
61
|
+
`translations` does not call `requestI18n` again. Translation is applied only when
|
|
58
62
|
the result is `needed: true`. Without the injected SDK, the game stays on
|
|
59
63
|
the source text.
|
|
60
64
|
|
package/agent-skill.md
CHANGED
|
@@ -23,18 +23,22 @@ score.addComponent(new Text3D({
|
|
|
23
23
|
}));
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
**MUST** set `Text3DSystem` `sourceLocale` to the game's written language as a
|
|
27
|
+
BCP 47 tag (`en`, `en-US`, `zh-CN`, `ja-JP`, …). Match the `Text3D` literals,
|
|
28
|
+
not the player device locale. Omitting it disables host i18n.
|
|
27
29
|
|
|
28
30
|
```ts
|
|
29
31
|
new Text3DSystem({
|
|
30
|
-
sourceLocale: '
|
|
31
|
-
sourceTexts: ['
|
|
32
|
+
sourceLocale: 'zh-CN',
|
|
33
|
+
sourceTexts: ['开始游戏', '下一关已解锁'],
|
|
32
34
|
});
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
Pass **every** later-screen template in `sourceTexts` so the first
|
|
36
|
-
`requestI18n` translates the full catalog before `ready`.
|
|
37
|
-
|
|
38
|
+
`requestI18n` translates the full catalog before `ready`. The system keeps one
|
|
39
|
+
growing session catalog of source templates and translations: new labels are
|
|
40
|
+
added to it, and going back to earlier copy looks up that catalog instead of
|
|
41
|
+
rebuilding from the current screen. You can also call
|
|
38
42
|
`textSystem.declareSourceTexts([...])` during `onSystemsBootstrapComplete`.
|
|
39
43
|
|
|
40
44
|
The source template itself is the translation lookup key. After labels exist,
|
|
@@ -45,8 +49,9 @@ game `ready` / `start` until the host replies. Apply the result only when
|
|
|
45
49
|
missing from `translations`, merge every seeded and mounted template and
|
|
46
50
|
`requestI18n` once more before `ready`. After ready, a new label whose
|
|
47
51
|
translation is still missing stays empty, merges all current templates, waits
|
|
48
|
-
for one more `requestI18n`, then renders.
|
|
49
|
-
|
|
52
|
+
for one more `requestI18n`, then renders. Already-translated templates do not
|
|
53
|
+
trigger another `requestI18n` when the same labels go back to earlier copy.
|
|
54
|
+
`needed: false` keeps source text and does not hold later labels. Do not post `i18n-ready` / `set-i18n` from
|
|
50
55
|
this plugin. If no source locale or method is present, placeholder replacement
|
|
51
56
|
still works and source text stays as-is.
|
|
52
57
|
|
|
@@ -232,6 +232,17 @@ function hasSourceTranslation(sourceText, translations) {
|
|
|
232
232
|
function hasMissingSourceTranslations(sourceTexts, translations) {
|
|
233
233
|
return sourceTexts.some((text) => !hasSourceTranslation(text, translations));
|
|
234
234
|
}
|
|
235
|
+
function sourceTextsSignature(sourceTexts) {
|
|
236
|
+
return [...sourceTexts].sort().join('\0');
|
|
237
|
+
}
|
|
238
|
+
/** After the first host reply, only request again for templates still missing. */
|
|
239
|
+
function shouldRequestI18nForSourceTexts(sourceTexts, translations, state) {
|
|
240
|
+
if (!state.i18nNeeded)
|
|
241
|
+
return false;
|
|
242
|
+
if (!hasMissingSourceTranslations(sourceTexts, translations))
|
|
243
|
+
return false;
|
|
244
|
+
return sourceTextsSignature(sourceTexts) !== state.lastRequestedSourceTexts;
|
|
245
|
+
}
|
|
235
246
|
function shouldHoldForMissingTranslation(sourceText, translations, state) {
|
|
236
247
|
if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled)
|
|
237
248
|
return false;
|
|
@@ -280,7 +291,8 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
280
291
|
this.sourceLocale = '';
|
|
281
292
|
this.targetLocale = '';
|
|
282
293
|
this.translations = {};
|
|
283
|
-
this.
|
|
294
|
+
/** Growing catalog of every source template seen this session. */
|
|
295
|
+
this.knownSourceTexts = new Set();
|
|
284
296
|
this.lastRequestedSourceTexts = '';
|
|
285
297
|
this.i18nRequestScheduled = false;
|
|
286
298
|
this.i18nRequestId = 0;
|
|
@@ -298,7 +310,7 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
298
310
|
}
|
|
299
311
|
/** Register extra source templates before or after ready. First request includes these. */
|
|
300
312
|
declareSourceTexts(texts) {
|
|
301
|
-
|
|
313
|
+
this.rememberSourceTexts(texts);
|
|
302
314
|
this.scheduleI18nRequest();
|
|
303
315
|
}
|
|
304
316
|
async beforeReady() {
|
|
@@ -354,6 +366,7 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
354
366
|
this.threeContext.attachVisual(gameObject.id, textMesh, gameObject);
|
|
355
367
|
this.texts.set(gameObject.id, { mesh: textMesh, component });
|
|
356
368
|
this.poseBridges.set(gameObject.id, new pluginRenderer3d.VisualPoseBridge());
|
|
369
|
+
this.rememberSourceTexts([component.text]);
|
|
357
370
|
this.scheduleI18nRequest();
|
|
358
371
|
}
|
|
359
372
|
handleChange(changed) {
|
|
@@ -362,6 +375,8 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
362
375
|
return;
|
|
363
376
|
const component = changed.component;
|
|
364
377
|
entry.component = component;
|
|
378
|
+
if (changed.prop.prop[0] === 'text')
|
|
379
|
+
this.rememberSourceTexts([component.text]);
|
|
365
380
|
this.syncTextProps(entry.mesh, component);
|
|
366
381
|
entry.mesh.sync();
|
|
367
382
|
if (changed.prop.prop[0] === 'text')
|
|
@@ -426,12 +441,14 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
426
441
|
}
|
|
427
442
|
return localizeText(component.text, component.replacements, this.sourceLocale, this.targetLocale, this.translations);
|
|
428
443
|
}
|
|
444
|
+
rememberSourceTexts(texts) {
|
|
445
|
+
addSourceTexts(this.knownSourceTexts, texts);
|
|
446
|
+
}
|
|
429
447
|
collectSourceTexts() {
|
|
430
|
-
const sourceTexts = new Set(this.seededSourceTexts);
|
|
431
448
|
for (const entry of this.texts.values()) {
|
|
432
|
-
|
|
449
|
+
this.rememberSourceTexts([entry.component.text]);
|
|
433
450
|
}
|
|
434
|
-
return [...
|
|
451
|
+
return [...this.knownSourceTexts];
|
|
435
452
|
}
|
|
436
453
|
scheduleI18nRequest() {
|
|
437
454
|
if (!this.sourceLocale || !this.firstI18nSettled || this.i18nRequestScheduled)
|
|
@@ -446,15 +463,17 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
446
463
|
if (!this.sourceLocale || !this.firstI18nSettled)
|
|
447
464
|
return;
|
|
448
465
|
const sourceTexts = this.collectSourceTexts();
|
|
449
|
-
|
|
450
|
-
|
|
466
|
+
if (!shouldRequestI18nForSourceTexts(sourceTexts, this.translations, {
|
|
467
|
+
i18nNeeded: this.i18nNeeded,
|
|
468
|
+
lastRequestedSourceTexts: this.lastRequestedSourceTexts,
|
|
469
|
+
})) {
|
|
451
470
|
return;
|
|
471
|
+
}
|
|
452
472
|
void this.requestI18nAndApply();
|
|
453
473
|
}
|
|
454
474
|
async requestI18nAndApply() {
|
|
455
475
|
const sourceTexts = this.collectSourceTexts();
|
|
456
|
-
|
|
457
|
-
this.lastRequestedSourceTexts = signature;
|
|
476
|
+
this.lastRequestedSourceTexts = sourceTextsSignature(sourceTexts);
|
|
458
477
|
const requestId = ++this.i18nRequestId;
|
|
459
478
|
const result = await requestHostI18n({
|
|
460
479
|
sourceLocale: this.sourceLocale,
|
|
@@ -504,4 +523,6 @@ exports.mergeTranslations = mergeTranslations;
|
|
|
504
523
|
exports.parseI18nResult = parseI18nResult;
|
|
505
524
|
exports.requestHostI18n = requestHostI18n;
|
|
506
525
|
exports.shouldHoldForMissingTranslation = shouldHoldForMissingTranslation;
|
|
526
|
+
exports.shouldRequestI18nForSourceTexts = shouldRequestI18nForSourceTexts;
|
|
527
|
+
exports.sourceTextsSignature = sourceTextsSignature;
|
|
507
528
|
//# sourceMappingURL=plugin-renderer-3d-text.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-renderer-3d-text.cjs.js","sources":["../lib/component.ts","../lib/hostSdk.ts","../lib/localization.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\nimport type { TextReplacements } from './localization';\n\nexport type { TextReplacementValue, TextReplacements } from './localization';\n\nexport interface Text3DParams {\n text?: string;\n /** Values substituted into named placeholders such as `{score}`. */\n replacements?: TextReplacements;\n fontSize?: number;\n color?: number;\n anchorX?: string;\n anchorY?: string;\n maxWidth?: number;\n font?: string;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n}\n\nexport default class Text3D extends Component<Text3DParams> {\n static componentName: string = 'Text3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Text3D',\n\n label: 'text',\n\n description: 'Visible text content.',\n\n editor: 'text',\n\n })\n\n text: string = '';\n\n replacements: TextReplacements = {};\n\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'fontSize',\n description: 'Font size.',\n editor: 'number-stepper',\n })\n fontSize: number = 0.5;\n @Field({\n type: 'number',\n group: 'Text3D',\n label: 'color',\n description: 'Color value.',\n editor: 'number-stepper',\n })\n color: number = 0xffffff;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorX',\n description: 'Horizontal text anchor.',\n editor: 'text',\n })\n anchorX: string = 'center';\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorY',\n description: 'Vertical text anchor.',\n editor: 'text',\n })\n anchorY: string = 'middle';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'maxWidth',\n description: 'Maximum text wrap width.',\n editor: 'number-stepper',\n })\n maxWidth: number = 0;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'font',\n description: 'Font URL or path for troika-three-text (not an engine resource name).',\n editor: 'text',\n })\n font: string = '';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n\n init(obj?: Text3DParams) {\n if (!obj) return;\n const { replacements, ...rest } = obj;\n Object.assign(this, rest);\n if (replacements) this.replacements = { ...replacements };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` hostSdk. */\nimport type { TextTranslations } from './localization';\n\n/** Host-injected global. The SDK itself is not part of this repo. */\nexport const COMBOS_HOST_SDK = 'combos' as const;\n\nexport interface CombosI18nRequest {\n sourceLocale: string;\n sourceTexts: string[];\n}\n\nexport type CombosI18nResult =\n | { needed: false }\n | { needed: true; locale: string; translations: TextTranslations };\n\nexport interface CombosHostSdk {\n requestI18n?(request: CombosI18nRequest): Promise<CombosI18nResult>;\n}\n\ndeclare global {\n interface Window {\n combos?: CombosHostSdk;\n }\n}\n\nexport function hasCombosRequestI18n(\n sdk: CombosHostSdk | undefined | null = typeof window === 'undefined' ? undefined : window.combos,\n): sdk is CombosHostSdk & { requestI18n: NonNullable<CombosHostSdk['requestI18n']> } {\n return !!sdk && typeof sdk.requestI18n === 'function';\n}\n\nexport function parseI18nResult(data: unknown): CombosI18nResult {\n if (!data || typeof data !== 'object') return { needed: false };\n const input = data as {\n needed?: unknown;\n locale?: unknown;\n translations?: unknown;\n };\n if (input.needed !== true) return { needed: false };\n if (typeof input.locale !== 'string' || !input.locale.trim()) {\n return { needed: false };\n }\n if (\n !input.translations ||\n typeof input.translations !== 'object' ||\n Array.isArray(input.translations)\n ) {\n return { needed: false };\n }\n const entries = Object.entries(input.translations);\n if (entries.some(([, value]) => typeof value !== 'string')) {\n return { needed: false };\n }\n return {\n needed: true,\n locale: input.locale.trim(),\n translations: Object.fromEntries(entries) as TextTranslations,\n };\n}\n\n/** Ask the injected host SDK. Always resolves; missing method means no translation. */\nexport async function requestHostI18n(\n request: CombosI18nRequest,\n): Promise<CombosI18nResult> {\n if (typeof window === 'undefined' || !hasCombosRequestI18n(window.combos)) {\n return { needed: false };\n }\n try {\n return parseI18nResult(await window.combos.requestI18n(request));\n } catch {\n return { needed: false };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` localization. */\n\nexport type TextReplacementValue = string | number;\nexport type TextReplacements = Record<string, TextReplacementValue>;\nexport type TextTranslations = Record<string, string>;\n\nconst PLACEHOLDER_PATTERN = /\\{([A-Za-z_$][\\w$.-]*)\\}/g;\n\nexport function interpolateText(\n template: string,\n replacements?: TextReplacements,\n): string {\n if (!replacements) return template;\n return template.replace(PLACEHOLDER_PATTERN, (placeholder, name: string) => {\n if (!Object.prototype.hasOwnProperty.call(replacements, name)) {\n return placeholder;\n }\n return String(replacements[name]);\n });\n}\n\nexport function findTranslatedTemplate(\n sourceText: string,\n translations: TextTranslations,\n): string | undefined {\n if (Object.prototype.hasOwnProperty.call(translations, sourceText)) {\n return translations[sourceText];\n }\n const trimmed = sourceText.trim();\n if (\n trimmed &&\n trimmed !== sourceText &&\n Object.prototype.hasOwnProperty.call(translations, trimmed)\n ) {\n return translations[trimmed];\n }\n return undefined;\n}\n\nexport function hasSourceTranslation(\n sourceText: string,\n translations: TextTranslations,\n): boolean {\n return findTranslatedTemplate(sourceText, translations) !== undefined;\n}\n\nexport function hasMissingSourceTranslations(\n sourceTexts: readonly string[],\n translations: TextTranslations,\n): boolean {\n return sourceTexts.some((text) => !hasSourceTranslation(text, translations));\n}\n\nexport function shouldHoldForMissingTranslation(\n sourceText: string,\n translations: TextTranslations,\n state: {\n sourceLocale: string;\n targetLocale: string;\n i18nNeeded: boolean;\n firstI18nSettled: boolean;\n resolvedSourceTexts: ReadonlySet<string>;\n },\n): boolean {\n if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled) return false;\n if (state.sourceLocale.toLowerCase() === state.targetLocale.toLowerCase()) return false;\n const trimmed = sourceText.trim();\n if (!trimmed) return false;\n if (hasSourceTranslation(sourceText, translations)) return false;\n return !state.resolvedSourceTexts.has(trimmed);\n}\n\nexport function localizeText(\n sourceText: string,\n replacements: TextReplacements | undefined,\n sourceLocale: string,\n targetLocale: string,\n translations: TextTranslations,\n): string {\n const shouldTranslate =\n !!sourceLocale &&\n !!targetLocale &&\n sourceLocale.toLowerCase() !== targetLocale.toLowerCase();\n const template = shouldTranslate\n ? findTranslatedTemplate(sourceText, translations) ?? sourceText\n : sourceText;\n return interpolateText(template, replacements);\n}\n\nexport function addSourceTexts(\n target: Set<string>,\n texts?: Iterable<string | undefined | null>,\n) {\n if (!texts) return;\n for (const text of texts) {\n const source = typeof text === 'string' ? text.trim() : '';\n if (source) target.add(source);\n }\n}\n\nexport function mergeTranslations(\n current: TextTranslations,\n incoming: Record<string, unknown>,\n): TextTranslations {\n const next = { ...current };\n for (const [key, value] of Object.entries(incoming)) {\n if (typeof value === 'string') next[key] = value;\n }\n return next;\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport { Renderer3D, Renderer3DSystem, tagObject3D, Transform3D, VisualPoseBridge } from '@combos-fun/plugin-renderer-3d';\nimport { Text as TroikaText } from 'troika-three-text';\nimport Text3D from './component';\nimport { requestHostI18n } from './hostSdk';\nimport {\n addSourceTexts,\n hasMissingSourceTranslations,\n localizeText,\n mergeTranslations,\n shouldHoldForMissingTranslation,\n type TextTranslations,\n} from './localization';\n\nexport interface Text3DSystemParams {\n /** BCP 47 locale of the source text, for example `zh-CN`. Omit to disable host-driven i18n. */\n sourceLocale?: string;\n /**\n * All source templates to translate on first `requestI18n`, including copy\n * for screens that are not mounted yet. Later `Text3D` nodes reuse this catalog\n * and will not flash the source language.\n */\n sourceTexts?: string[];\n}\n\n@decorators.componentObserver({\n Text3D: [\n 'text',\n { prop: ['replacements'], deep: true },\n 'fontSize', 'color', 'anchorX', 'anchorY', 'maxWidth', 'font',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n ],\n})\nexport default class Text3DSystem extends Renderer3D<Text3DSystemParams> {\n static systemName = 'Text3DSystem';\n name: string = 'Text3DSystem';\n\n private texts = new Map<number, { mesh: TroikaText; component: Text3D }>();\n private poseBridges = new Map<number, VisualPoseBridge>();\n private sourceLocale = '';\n private targetLocale = '';\n private translations: TextTranslations = {};\n private seededSourceTexts = new Set<string>();\n private lastRequestedSourceTexts = '';\n private i18nRequestScheduled = false;\n private i18nRequestId = 0;\n private firstI18nSettled = false;\n private i18nNeeded = false;\n private resolvedSourceTexts = new Set<string>();\n\n init(params?: Text3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n this.sourceLocale = params?.sourceLocale?.trim() ?? '';\n this.targetLocale = this.sourceLocale;\n this.declareSourceTexts(params?.sourceTexts);\n }\n\n /** Register extra source templates before or after ready. First request includes these. */\n declareSourceTexts(texts?: string[]) {\n addSourceTexts(this.seededSourceTexts, texts);\n this.scheduleI18nRequest();\n }\n\n async beforeReady() {\n if (this.firstI18nSettled) return;\n this.update();\n if (!this.sourceLocale) {\n this.firstI18nSettled = true;\n return;\n }\n await this.requestI18nAndApply();\n if (\n this.i18nNeeded &&\n hasMissingSourceTranslations(this.collectSourceTexts(), this.translations)\n ) {\n await this.requestI18nAndApply();\n }\n this.firstI18nSettled = true;\n }\n\n setI18n(locale: string, translations: TextTranslations) {\n const targetLocale = locale?.trim();\n if (!targetLocale || !translations || typeof translations !== 'object') return;\n this.targetLocale = targetLocale;\n this.translations = mergeTranslations(this.translations, translations);\n this.refreshAllText();\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Text3D') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, changed.component as Text3D);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.handleRemove(changed.gameObject.id);\n } else {\n this.handleChange(changed);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Text3D) as Text3D;\n if (!component) return;\n\n const entry = this.texts.get(gameObject.id);\n if (!entry) return;\n this.applyPose(gameObject, component, entry.mesh);\n }\n\n private handleAdd(gameObject: GameObject, component: Text3D) {\n const textMesh = new TroikaText();\n this.syncTextProps(textMesh, component);\n textMesh.sync();\n tagObject3D(textMesh, gameObject.id);\n\n this.threeContext.attachVisual(gameObject.id, textMesh, gameObject);\n this.texts.set(gameObject.id, { mesh: textMesh, component });\n this.poseBridges.set(gameObject.id, new VisualPoseBridge());\n this.scheduleI18nRequest();\n }\n\n private handleChange(changed: ComponentChanged) {\n const entry = this.texts.get(changed.gameObject.id);\n if (!entry) return;\n const component = changed.component as Text3D;\n entry.component = component;\n this.syncTextProps(entry.mesh, component);\n entry.mesh.sync();\n if (changed.prop.prop[0] === 'text') this.scheduleI18nRequest();\n }\n\n private handleRemove(id: number) {\n const entry = this.texts.get(id);\n if (!entry) return;\n\n this.threeContext.detachVisual(id, entry.mesh);\n entry.mesh.dispose();\n this.texts.delete(id);\n this.poseBridges.delete(id);\n }\n\n private syncTextProps(textMesh: TroikaText, component: Text3D) {\n textMesh.text = this.resolveText(component);\n textMesh.fontSize = component.fontSize;\n textMesh.color = component.color;\n textMesh.anchorX = component.anchorX;\n textMesh.anchorY = component.anchorY;\n if (component.maxWidth > 0) {\n textMesh.maxWidth = component.maxWidth;\n }\n if (component.font) {\n textMesh.font = component.font;\n }\n }\n\n private applyPose(gameObject: GameObject, component: Text3D, textMesh: TroikaText) {\n let bridge = this.poseBridges.get(gameObject.id);\n if (!bridge) {\n bridge = new VisualPoseBridge();\n this.poseBridges.set(gameObject.id, bridge);\n }\n const transform = gameObject.getComponent(Transform3D) as Transform3D | undefined;\n if (!bridge.sync(component, transform)) {\n textMesh.position.set(0, 0, 0);\n textMesh.rotation.set(0, 0, 0);\n return;\n }\n textMesh.position.set(component.positionX, component.positionY, component.positionZ);\n textMesh.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n }\n\n onDestroy() {\n this.i18nRequestId += 1;\n this.firstI18nSettled = false;\n this.i18nNeeded = false;\n this.resolvedSourceTexts.clear();\n for (const [id] of this.texts) {\n this.handleRemove(id);\n }\n this.texts.clear();\n }\n\n private resolveText(component: Text3D): string {\n if (\n shouldHoldForMissingTranslation(component.text, this.translations, {\n sourceLocale: this.sourceLocale,\n targetLocale: this.targetLocale,\n i18nNeeded: this.i18nNeeded,\n firstI18nSettled: this.firstI18nSettled,\n resolvedSourceTexts: this.resolvedSourceTexts,\n })\n ) {\n return '';\n }\n return localizeText(\n component.text,\n component.replacements,\n this.sourceLocale,\n this.targetLocale,\n this.translations,\n );\n }\n\n private collectSourceTexts(): string[] {\n const sourceTexts = new Set(this.seededSourceTexts);\n for (const entry of this.texts.values()) {\n addSourceTexts(sourceTexts, [entry.component.text]);\n }\n return [...sourceTexts];\n }\n\n private scheduleI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled || this.i18nRequestScheduled) return;\n this.i18nRequestScheduled = true;\n queueMicrotask(() => {\n this.i18nRequestScheduled = false;\n this.startI18nRequest();\n });\n }\n\n private startI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled) return;\n const sourceTexts = this.collectSourceTexts();\n const signature = [...sourceTexts].sort().join('\\0');\n if (signature === this.lastRequestedSourceTexts) return;\n void this.requestI18nAndApply();\n }\n\n private async requestI18nAndApply() {\n const sourceTexts = this.collectSourceTexts();\n const signature = [...sourceTexts].sort().join('\\0');\n this.lastRequestedSourceTexts = signature;\n const requestId = ++this.i18nRequestId;\n const result = await requestHostI18n({\n sourceLocale: this.sourceLocale,\n sourceTexts,\n });\n if (requestId !== this.i18nRequestId) return;\n addSourceTexts(this.resolvedSourceTexts, sourceTexts);\n this.i18nNeeded = result.needed;\n if (!result.needed) {\n this.refreshAllText();\n return;\n }\n this.setI18n(result.locale, result.translations);\n }\n\n private refreshAllText() {\n for (const entry of this.texts.values()) {\n entry.mesh.text = this.resolveText(entry.component);\n entry.mesh.sync();\n }\n }\n}\n"],"names":["Component","__decorate","Field","Renderer3D","Renderer3DSystem","OBSERVER_TYPE","TroikaText","tagObject3D","VisualPoseBridge","Transform3D","decorators"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin-renderer-3d-text.cjs.js","sources":["../lib/component.ts","../lib/hostSdk.ts","../lib/localization.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\nimport type { TextReplacements } from './localization';\n\nexport type { TextReplacementValue, TextReplacements } from './localization';\n\nexport interface Text3DParams {\n text?: string;\n /** Values substituted into named placeholders such as `{score}`. */\n replacements?: TextReplacements;\n fontSize?: number;\n color?: number;\n anchorX?: string;\n anchorY?: string;\n maxWidth?: number;\n font?: string;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n}\n\nexport default class Text3D extends Component<Text3DParams> {\n static componentName: string = 'Text3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Text3D',\n\n label: 'text',\n\n description: 'Visible text content.',\n\n editor: 'text',\n\n })\n\n text: string = '';\n\n replacements: TextReplacements = {};\n\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'fontSize',\n description: 'Font size.',\n editor: 'number-stepper',\n })\n fontSize: number = 0.5;\n @Field({\n type: 'number',\n group: 'Text3D',\n label: 'color',\n description: 'Color value.',\n editor: 'number-stepper',\n })\n color: number = 0xffffff;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorX',\n description: 'Horizontal text anchor.',\n editor: 'text',\n })\n anchorX: string = 'center';\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorY',\n description: 'Vertical text anchor.',\n editor: 'text',\n })\n anchorY: string = 'middle';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'maxWidth',\n description: 'Maximum text wrap width.',\n editor: 'number-stepper',\n })\n maxWidth: number = 0;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'font',\n description: 'Font URL or path for troika-three-text (not an engine resource name).',\n editor: 'text',\n })\n font: string = '';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n\n init(obj?: Text3DParams) {\n if (!obj) return;\n const { replacements, ...rest } = obj;\n Object.assign(this, rest);\n if (replacements) this.replacements = { ...replacements };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` hostSdk. */\nimport type { TextTranslations } from './localization';\n\n/** Host-injected global. The SDK itself is not part of this repo. */\nexport const COMBOS_HOST_SDK = 'combos' as const;\n\nexport interface CombosI18nRequest {\n sourceLocale: string;\n sourceTexts: string[];\n}\n\nexport type CombosI18nResult =\n | { needed: false }\n | { needed: true; locale: string; translations: TextTranslations };\n\nexport interface CombosHostSdk {\n requestI18n?(request: CombosI18nRequest): Promise<CombosI18nResult>;\n}\n\ndeclare global {\n interface Window {\n combos?: CombosHostSdk;\n }\n}\n\nexport function hasCombosRequestI18n(\n sdk: CombosHostSdk | undefined | null = typeof window === 'undefined' ? undefined : window.combos,\n): sdk is CombosHostSdk & { requestI18n: NonNullable<CombosHostSdk['requestI18n']> } {\n return !!sdk && typeof sdk.requestI18n === 'function';\n}\n\nexport function parseI18nResult(data: unknown): CombosI18nResult {\n if (!data || typeof data !== 'object') return { needed: false };\n const input = data as {\n needed?: unknown;\n locale?: unknown;\n translations?: unknown;\n };\n if (input.needed !== true) return { needed: false };\n if (typeof input.locale !== 'string' || !input.locale.trim()) {\n return { needed: false };\n }\n if (\n !input.translations ||\n typeof input.translations !== 'object' ||\n Array.isArray(input.translations)\n ) {\n return { needed: false };\n }\n const entries = Object.entries(input.translations);\n if (entries.some(([, value]) => typeof value !== 'string')) {\n return { needed: false };\n }\n return {\n needed: true,\n locale: input.locale.trim(),\n translations: Object.fromEntries(entries) as TextTranslations,\n };\n}\n\n/** Ask the injected host SDK. Always resolves; missing method means no translation. */\nexport async function requestHostI18n(\n request: CombosI18nRequest,\n): Promise<CombosI18nResult> {\n if (typeof window === 'undefined' || !hasCombosRequestI18n(window.combos)) {\n return { needed: false };\n }\n try {\n return parseI18nResult(await window.combos.requestI18n(request));\n } catch {\n return { needed: false };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` localization. */\n\nexport type TextReplacementValue = string | number;\nexport type TextReplacements = Record<string, TextReplacementValue>;\nexport type TextTranslations = Record<string, string>;\n\nconst PLACEHOLDER_PATTERN = /\\{([A-Za-z_$][\\w$.-]*)\\}/g;\n\nexport function interpolateText(\n template: string,\n replacements?: TextReplacements,\n): string {\n if (!replacements) return template;\n return template.replace(PLACEHOLDER_PATTERN, (placeholder, name: string) => {\n if (!Object.prototype.hasOwnProperty.call(replacements, name)) {\n return placeholder;\n }\n return String(replacements[name]);\n });\n}\n\nexport function findTranslatedTemplate(\n sourceText: string,\n translations: TextTranslations,\n): string | undefined {\n if (Object.prototype.hasOwnProperty.call(translations, sourceText)) {\n return translations[sourceText];\n }\n const trimmed = sourceText.trim();\n if (\n trimmed &&\n trimmed !== sourceText &&\n Object.prototype.hasOwnProperty.call(translations, trimmed)\n ) {\n return translations[trimmed];\n }\n return undefined;\n}\n\nexport function hasSourceTranslation(\n sourceText: string,\n translations: TextTranslations,\n): boolean {\n return findTranslatedTemplate(sourceText, translations) !== undefined;\n}\n\nexport function hasMissingSourceTranslations(\n sourceTexts: readonly string[],\n translations: TextTranslations,\n): boolean {\n return sourceTexts.some((text) => !hasSourceTranslation(text, translations));\n}\n\nexport function sourceTextsSignature(sourceTexts: readonly string[]): string {\n return [...sourceTexts].sort().join('\\0');\n}\n\n/** After the first host reply, only request again for templates still missing. */\nexport function shouldRequestI18nForSourceTexts(\n sourceTexts: readonly string[],\n translations: TextTranslations,\n state: {\n i18nNeeded: boolean;\n lastRequestedSourceTexts: string;\n },\n): boolean {\n if (!state.i18nNeeded) return false;\n if (!hasMissingSourceTranslations(sourceTexts, translations)) return false;\n return sourceTextsSignature(sourceTexts) !== state.lastRequestedSourceTexts;\n}\n\nexport function shouldHoldForMissingTranslation(\n sourceText: string,\n translations: TextTranslations,\n state: {\n sourceLocale: string;\n targetLocale: string;\n i18nNeeded: boolean;\n firstI18nSettled: boolean;\n resolvedSourceTexts: ReadonlySet<string>;\n },\n): boolean {\n if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled) return false;\n if (state.sourceLocale.toLowerCase() === state.targetLocale.toLowerCase()) return false;\n const trimmed = sourceText.trim();\n if (!trimmed) return false;\n if (hasSourceTranslation(sourceText, translations)) return false;\n return !state.resolvedSourceTexts.has(trimmed);\n}\n\nexport function localizeText(\n sourceText: string,\n replacements: TextReplacements | undefined,\n sourceLocale: string,\n targetLocale: string,\n translations: TextTranslations,\n): string {\n const shouldTranslate =\n !!sourceLocale &&\n !!targetLocale &&\n sourceLocale.toLowerCase() !== targetLocale.toLowerCase();\n const template = shouldTranslate\n ? findTranslatedTemplate(sourceText, translations) ?? sourceText\n : sourceText;\n return interpolateText(template, replacements);\n}\n\nexport function addSourceTexts(\n target: Set<string>,\n texts?: Iterable<string | undefined | null>,\n) {\n if (!texts) return;\n for (const text of texts) {\n const source = typeof text === 'string' ? text.trim() : '';\n if (source) target.add(source);\n }\n}\n\nexport function mergeTranslations(\n current: TextTranslations,\n incoming: Record<string, unknown>,\n): TextTranslations {\n const next = { ...current };\n for (const [key, value] of Object.entries(incoming)) {\n if (typeof value === 'string') next[key] = value;\n }\n return next;\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport { Renderer3D, Renderer3DSystem, tagObject3D, Transform3D, VisualPoseBridge } from '@combos-fun/plugin-renderer-3d';\nimport { Text as TroikaText } from 'troika-three-text';\nimport Text3D from './component';\nimport { requestHostI18n } from './hostSdk';\nimport {\n addSourceTexts,\n hasMissingSourceTranslations,\n localizeText,\n mergeTranslations,\n shouldHoldForMissingTranslation,\n shouldRequestI18nForSourceTexts,\n sourceTextsSignature,\n type TextTranslations,\n} from './localization';\n\nexport interface Text3DSystemParams {\n /** BCP 47 locale of the source text, for example `zh-CN`. Omit to disable host-driven i18n. */\n sourceLocale?: string;\n /**\n * All source templates to translate on first `requestI18n`, including copy\n * for screens that are not mounted yet. The system also keeps a growing\n * session catalog of every later template it sees.\n */\n sourceTexts?: string[];\n}\n\n@decorators.componentObserver({\n Text3D: [\n 'text',\n { prop: ['replacements'], deep: true },\n 'fontSize', 'color', 'anchorX', 'anchorY', 'maxWidth', 'font',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n ],\n})\nexport default class Text3DSystem extends Renderer3D<Text3DSystemParams> {\n static systemName = 'Text3DSystem';\n name: string = 'Text3DSystem';\n\n private texts = new Map<number, { mesh: TroikaText; component: Text3D }>();\n private poseBridges = new Map<number, VisualPoseBridge>();\n private sourceLocale = '';\n private targetLocale = '';\n private translations: TextTranslations = {};\n /** Growing catalog of every source template seen this session. */\n private knownSourceTexts = new Set<string>();\n private lastRequestedSourceTexts = '';\n private i18nRequestScheduled = false;\n private i18nRequestId = 0;\n private firstI18nSettled = false;\n private i18nNeeded = false;\n private resolvedSourceTexts = new Set<string>();\n\n init(params?: Text3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n this.sourceLocale = params?.sourceLocale?.trim() ?? '';\n this.targetLocale = this.sourceLocale;\n this.declareSourceTexts(params?.sourceTexts);\n }\n\n /** Register extra source templates before or after ready. First request includes these. */\n declareSourceTexts(texts?: string[]) {\n this.rememberSourceTexts(texts);\n this.scheduleI18nRequest();\n }\n\n async beforeReady() {\n if (this.firstI18nSettled) return;\n this.update();\n if (!this.sourceLocale) {\n this.firstI18nSettled = true;\n return;\n }\n await this.requestI18nAndApply();\n if (\n this.i18nNeeded &&\n hasMissingSourceTranslations(this.collectSourceTexts(), this.translations)\n ) {\n await this.requestI18nAndApply();\n }\n this.firstI18nSettled = true;\n }\n\n setI18n(locale: string, translations: TextTranslations) {\n const targetLocale = locale?.trim();\n if (!targetLocale || !translations || typeof translations !== 'object') return;\n this.targetLocale = targetLocale;\n this.translations = mergeTranslations(this.translations, translations);\n this.refreshAllText();\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Text3D') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, changed.component as Text3D);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.handleRemove(changed.gameObject.id);\n } else {\n this.handleChange(changed);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Text3D) as Text3D;\n if (!component) return;\n\n const entry = this.texts.get(gameObject.id);\n if (!entry) return;\n this.applyPose(gameObject, component, entry.mesh);\n }\n\n private handleAdd(gameObject: GameObject, component: Text3D) {\n const textMesh = new TroikaText();\n this.syncTextProps(textMesh, component);\n textMesh.sync();\n tagObject3D(textMesh, gameObject.id);\n\n this.threeContext.attachVisual(gameObject.id, textMesh, gameObject);\n this.texts.set(gameObject.id, { mesh: textMesh, component });\n this.poseBridges.set(gameObject.id, new VisualPoseBridge());\n this.rememberSourceTexts([component.text]);\n this.scheduleI18nRequest();\n }\n\n private handleChange(changed: ComponentChanged) {\n const entry = this.texts.get(changed.gameObject.id);\n if (!entry) return;\n const component = changed.component as Text3D;\n entry.component = component;\n if (changed.prop.prop[0] === 'text') this.rememberSourceTexts([component.text]);\n this.syncTextProps(entry.mesh, component);\n entry.mesh.sync();\n if (changed.prop.prop[0] === 'text') this.scheduleI18nRequest();\n }\n\n private handleRemove(id: number) {\n const entry = this.texts.get(id);\n if (!entry) return;\n\n this.threeContext.detachVisual(id, entry.mesh);\n entry.mesh.dispose();\n this.texts.delete(id);\n this.poseBridges.delete(id);\n }\n\n private syncTextProps(textMesh: TroikaText, component: Text3D) {\n textMesh.text = this.resolveText(component);\n textMesh.fontSize = component.fontSize;\n textMesh.color = component.color;\n textMesh.anchorX = component.anchorX;\n textMesh.anchorY = component.anchorY;\n if (component.maxWidth > 0) {\n textMesh.maxWidth = component.maxWidth;\n }\n if (component.font) {\n textMesh.font = component.font;\n }\n }\n\n private applyPose(gameObject: GameObject, component: Text3D, textMesh: TroikaText) {\n let bridge = this.poseBridges.get(gameObject.id);\n if (!bridge) {\n bridge = new VisualPoseBridge();\n this.poseBridges.set(gameObject.id, bridge);\n }\n const transform = gameObject.getComponent(Transform3D) as Transform3D | undefined;\n if (!bridge.sync(component, transform)) {\n textMesh.position.set(0, 0, 0);\n textMesh.rotation.set(0, 0, 0);\n return;\n }\n textMesh.position.set(component.positionX, component.positionY, component.positionZ);\n textMesh.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n }\n\n onDestroy() {\n this.i18nRequestId += 1;\n this.firstI18nSettled = false;\n this.i18nNeeded = false;\n this.resolvedSourceTexts.clear();\n for (const [id] of this.texts) {\n this.handleRemove(id);\n }\n this.texts.clear();\n }\n\n private resolveText(component: Text3D): string {\n if (\n shouldHoldForMissingTranslation(component.text, this.translations, {\n sourceLocale: this.sourceLocale,\n targetLocale: this.targetLocale,\n i18nNeeded: this.i18nNeeded,\n firstI18nSettled: this.firstI18nSettled,\n resolvedSourceTexts: this.resolvedSourceTexts,\n })\n ) {\n return '';\n }\n return localizeText(\n component.text,\n component.replacements,\n this.sourceLocale,\n this.targetLocale,\n this.translations,\n );\n }\n\n private rememberSourceTexts(texts?: Iterable<string | undefined | null>) {\n addSourceTexts(this.knownSourceTexts, texts);\n }\n\n private collectSourceTexts(): string[] {\n for (const entry of this.texts.values()) {\n this.rememberSourceTexts([entry.component.text]);\n }\n return [...this.knownSourceTexts];\n }\n\n private scheduleI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled || this.i18nRequestScheduled) return;\n this.i18nRequestScheduled = true;\n queueMicrotask(() => {\n this.i18nRequestScheduled = false;\n this.startI18nRequest();\n });\n }\n\n private startI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled) return;\n const sourceTexts = this.collectSourceTexts();\n if (\n !shouldRequestI18nForSourceTexts(sourceTexts, this.translations, {\n i18nNeeded: this.i18nNeeded,\n lastRequestedSourceTexts: this.lastRequestedSourceTexts,\n })\n ) {\n return;\n }\n void this.requestI18nAndApply();\n }\n\n private async requestI18nAndApply() {\n const sourceTexts = this.collectSourceTexts();\n this.lastRequestedSourceTexts = sourceTextsSignature(sourceTexts);\n const requestId = ++this.i18nRequestId;\n const result = await requestHostI18n({\n sourceLocale: this.sourceLocale,\n sourceTexts,\n });\n if (requestId !== this.i18nRequestId) return;\n addSourceTexts(this.resolvedSourceTexts, sourceTexts);\n this.i18nNeeded = result.needed;\n if (!result.needed) {\n this.refreshAllText();\n return;\n }\n this.setI18n(result.locale, result.translations);\n }\n\n private refreshAllText() {\n for (const entry of this.texts.values()) {\n entry.mesh.text = this.resolveText(entry.component);\n entry.mesh.sync();\n }\n }\n}\n"],"names":["Component","__decorate","Field","Renderer3D","Renderer3DSystem","OBSERVER_TYPE","TroikaText","tagObject3D","VisualPoseBridge","Transform3D","decorators"],"mappings":";;;;;;;;AAwBc,MAAO,MAAO,SAAQA,gBAAuB,CAAA;AAA3D,IAAA,WAAA,GAAA;;QAiBE,IAAA,CAAA,IAAI,GAAW,EAAE;QAEjB,IAAA,CAAA,YAAY,GAAqB,EAAE;QAUnC,IAAA,CAAA,QAAQ,GAAW,GAAG;QAQtB,IAAA,CAAA,KAAK,GAAW,QAAQ;QAQxB,IAAA,CAAA,OAAO,GAAW,QAAQ;QAQ1B,IAAA,CAAA,OAAO,GAAW,QAAQ;QAS1B,IAAA,CAAA,QAAQ,GAAW,CAAC;QAQpB,IAAA,CAAA,IAAI,GAAW,EAAE;QASjB,IAAA,CAAA,SAAS,GAAW,CAAC;QASrB,IAAA,CAAA,SAAS,GAAW,CAAC;QASrB,IAAA,CAAA,SAAS,GAAW,CAAC;QASrB,IAAA,CAAA,SAAS,GAAW,CAAC;QASrB,IAAA,CAAA,SAAS,GAAW,CAAC;QASrB,IAAA,CAAA,SAAS,GAAW,CAAC;IAQvB;aAnIS,IAAA,CAAA,aAAa,GAAW,QAAX,CAAoB;AA6HxC,IAAA,IAAI,CAAC,GAAkB,EAAA;AACrB,QAAA,IAAI,CAAC,GAAG;YAAE;QACV,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG;AACrC,QAAA,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;AACzB,QAAA,IAAI,YAAY;AAAE,YAAA,IAAI,CAAC,YAAY,GAAG,EAAE,GAAG,YAAY,EAAE;IAC3D;;AAlHAC,gBAAA,CAAA;AAdC,IAAAC,wBAAK,CAAC;AAEL,QAAA,IAAI,EAAE,QAAQ;AAEd,QAAA,KAAK,EAAE,QAAQ;AAEf,QAAA,KAAK,EAAE,MAAM;AAEb,QAAA,WAAW,EAAE,uBAAuB;AAEpC,QAAA,MAAM,EAAE,MAAM;KAEf;AAEiB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,CAAA;AAYlBD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,UAAU;AACjB,QAAA,WAAW,EAAE,YAAY;AACzB,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACsB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,UAAA,EAAA,MAAA,CAAA;AAQvBD,gBAAA,CAAA;AAPC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,WAAW,EAAE,cAAc;AAC3B,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACwB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,OAAA,EAAA,MAAA,CAAA;AAQzBD,gBAAA,CAAA;AAPC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,WAAW,EAAE,yBAAyB;AACtC,QAAA,MAAM,EAAE,MAAM;KACf;AAC0B,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,SAAA,EAAA,MAAA,CAAA;AAQ3BD,gBAAA,CAAA;AAPC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,WAAW,EAAE,uBAAuB;AACpC,QAAA,MAAM,EAAE,MAAM;KACf;AAC0B,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,SAAA,EAAA,MAAA,CAAA;AAS3BD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,GAAG;AACT,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,UAAU;AACjB,QAAA,WAAW,EAAE,0BAA0B;AACvC,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACoB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,UAAA,EAAA,MAAA,CAAA;AAQrBD,gBAAA,CAAA;AAPC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,WAAW,EAAE,uEAAuE;AACpF,QAAA,MAAM,EAAE,MAAM;KACf;AACiB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,CAAA;AASlBD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,GAAG;AACT,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,WAAW;AAClB,QAAA,WAAW,EAAE,mBAAmB;AAChC,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACqB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,WAAA,EAAA,MAAA,CAAA;AAStBD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,GAAG;AACT,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,WAAW;AAClB,QAAA,WAAW,EAAE,mBAAmB;AAChC,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACqB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,WAAA,EAAA,MAAA,CAAA;AAStBD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,GAAG;AACT,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,WAAW;AAClB,QAAA,WAAW,EAAE,mBAAmB;AAChC,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACqB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,WAAA,EAAA,MAAA,CAAA;AAStBD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,WAAW;AAClB,QAAA,WAAW,EAAE,+BAA+B;AAC5C,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACqB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,WAAA,EAAA,MAAA,CAAA;AAStBD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,WAAW;AAClB,QAAA,WAAW,EAAE,+BAA+B;AAC5C,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACqB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,WAAA,EAAA,MAAA,CAAA;AAStBD,gBAAA,CAAA;AARC,IAAAC,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,KAAK,EAAE,WAAW;AAClB,QAAA,WAAW,EAAE,+BAA+B;AAC5C,QAAA,MAAM,EAAE,gBAAgB;KACzB;AACqB,CAAA,EAAA,MAAA,CAAA,SAAA,EAAA,WAAA,EAAA,MAAA,CAAA;;ACjJxB;AACO,MAAM,eAAe,GAAG;SAqBf,oBAAoB,CAClC,GAAA,GAAwC,OAAO,MAAM,KAAK,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAA;IAEjG,OAAO,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,UAAU;AACvD;AAEM,SAAU,eAAe,CAAC,IAAa,EAAA;AAC3C,IAAA,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;AAAE,QAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;IAC/D,MAAM,KAAK,GAAG,IAIb;AACD,IAAA,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;AAAE,QAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;AACnD,IAAA,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE;AAC5D,QAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;IAC1B;IACA,IACE,CAAC,KAAK,CAAC,YAAY;AACnB,QAAA,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ;QACtC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,EACjC;AACA,QAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;IAC1B;IACA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;AAClD,IAAA,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE;AAC1D,QAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;IAC1B;IACA,OAAO;AACL,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;AAC3B,QAAA,YAAY,EAAE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAqB;KAC9D;AACH;AAEA;AACO,eAAe,eAAe,CACnC,OAA0B,EAAA;AAE1B,IAAA,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;AACzE,QAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;IAC1B;AACA,IAAA,IAAI;AACF,QAAA,OAAO,eAAe,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAClE;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;IAC1B;AACF;;ACxEA;AAMA,MAAM,mBAAmB,GAAG,2BAA2B;AAEjD,SAAU,eAAe,CAC7B,QAAgB,EAChB,YAA+B,EAAA;AAE/B,IAAA,IAAI,CAAC,YAAY;AAAE,QAAA,OAAO,QAAQ;IAClC,OAAO,QAAQ,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,WAAW,EAAE,IAAY,KAAI;AACzE,QAAA,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE;AAC7D,YAAA,OAAO,WAAW;QACpB;AACA,QAAA,OAAO,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AACnC,IAAA,CAAC,CAAC;AACJ;AAEM,SAAU,sBAAsB,CACpC,UAAkB,EAClB,YAA8B,EAAA;AAE9B,IAAA,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE;AAClE,QAAA,OAAO,YAAY,CAAC,UAAU,CAAC;IACjC;AACA,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE;AACjC,IAAA,IACE,OAAO;AACP,QAAA,OAAO,KAAK,UAAU;AACtB,QAAA,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,EAC3D;AACA,QAAA,OAAO,YAAY,CAAC,OAAO,CAAC;IAC9B;AACA,IAAA,OAAO,SAAS;AAClB;AAEM,SAAU,oBAAoB,CAClC,UAAkB,EAClB,YAA8B,EAAA;IAE9B,OAAO,sBAAsB,CAAC,UAAU,EAAE,YAAY,CAAC,KAAK,SAAS;AACvE;AAEM,SAAU,4BAA4B,CAC1C,WAA8B,EAC9B,YAA8B,EAAA;AAE9B,IAAA,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AAC9E;AAEM,SAAU,oBAAoB,CAAC,WAA8B,EAAA;AACjE,IAAA,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3C;AAEA;SACgB,+BAA+B,CAC7C,WAA8B,EAC9B,YAA8B,EAC9B,KAGC,EAAA;IAED,IAAI,CAAC,KAAK,CAAC,UAAU;AAAE,QAAA,OAAO,KAAK;AACnC,IAAA,IAAI,CAAC,4BAA4B,CAAC,WAAW,EAAE,YAAY,CAAC;AAAE,QAAA,OAAO,KAAK;IAC1E,OAAO,oBAAoB,CAAC,WAAW,CAAC,KAAK,KAAK,CAAC,wBAAwB;AAC7E;SAEgB,+BAA+B,CAC7C,UAAkB,EAClB,YAA8B,EAC9B,KAMC,EAAA;AAED,IAAA,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,gBAAgB;AAAE,QAAA,OAAO,KAAK;AACrF,IAAA,IAAI,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE;AAAE,QAAA,OAAO,KAAK;AACvF,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE;AACjC,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;AAC1B,IAAA,IAAI,oBAAoB,CAAC,UAAU,EAAE,YAAY,CAAC;AAAE,QAAA,OAAO,KAAK;IAChE,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC;AAChD;AAEM,SAAU,YAAY,CAC1B,UAAkB,EAClB,YAA0C,EAC1C,YAAoB,EACpB,YAAoB,EACpB,YAA8B,EAAA;AAE9B,IAAA,MAAM,eAAe,GACnB,CAAC,CAAC,YAAY;AACd,QAAA,CAAC,CAAC,YAAY;QACd,YAAY,CAAC,WAAW,EAAE,KAAK,YAAY,CAAC,WAAW,EAAE;IAC3D,MAAM,QAAQ,GAAG;UACb,sBAAsB,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI;UACpD,UAAU;AACd,IAAA,OAAO,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC;AAChD;AAEM,SAAU,cAAc,CAC5B,MAAmB,EACnB,KAA2C,EAAA;AAE3C,IAAA,IAAI,CAAC,KAAK;QAAE;AACZ,IAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,QAAA,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;AAC1D,QAAA,IAAI,MAAM;AAAE,YAAA,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;IAChC;AACF;AAEM,SAAU,iBAAiB,CAC/B,OAAyB,EACzB,QAAiC,EAAA;AAEjC,IAAA,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE;AAC3B,IAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;QACnD,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,YAAA,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK;IAClD;AACA,IAAA,OAAO,IAAI;AACb;;AC3Fe,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQC,2BAA8B,CAAA;AAAzD,IAAA,WAAA,GAAA;;QAEb,IAAA,CAAA,IAAI,GAAW,cAAc;AAErB,QAAA,IAAA,CAAA,KAAK,GAAG,IAAI,GAAG,EAAmD;AAClE,QAAA,IAAA,CAAA,WAAW,GAAG,IAAI,GAAG,EAA4B;QACjD,IAAA,CAAA,YAAY,GAAG,EAAE;QACjB,IAAA,CAAA,YAAY,GAAG,EAAE;QACjB,IAAA,CAAA,YAAY,GAAqB,EAAE;;AAEnC,QAAA,IAAA,CAAA,gBAAgB,GAAG,IAAI,GAAG,EAAU;QACpC,IAAA,CAAA,wBAAwB,GAAG,EAAE;QAC7B,IAAA,CAAA,oBAAoB,GAAG,KAAK;QAC5B,IAAA,CAAA,aAAa,GAAG,CAAC;QACjB,IAAA,CAAA,gBAAgB,GAAG,KAAK;QACxB,IAAA,CAAA,UAAU,GAAG,KAAK;AAClB,QAAA,IAAA,CAAA,mBAAmB,GAAG,IAAI,GAAG,EAAU;IAwNjD;aAvOS,IAAA,CAAA,UAAU,GAAG,cAAH,CAAkB;AAiBnC,IAAA,IAAI,CAAC,MAA2B,EAAA;QAC9B,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAACC,iCAAgB,CAAqB;AAClF,QAAA,gBAAgB,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC/C,IAAI,CAAC,YAAY,GAAG,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE;AACtD,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY;AACrC,QAAA,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,WAAW,CAAC;IAC9C;;AAGA,IAAA,kBAAkB,CAAC,KAAgB,EAAA;AACjC,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC;QAC/B,IAAI,CAAC,mBAAmB,EAAE;IAC5B;AAEA,IAAA,MAAM,WAAW,GAAA;QACf,IAAI,IAAI,CAAC,gBAAgB;YAAE;QAC3B,IAAI,CAAC,MAAM,EAAE;AACb,QAAA,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;AACtB,YAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI;YAC5B;QACF;AACA,QAAA,MAAM,IAAI,CAAC,mBAAmB,EAAE;QAChC,IACE,IAAI,CAAC,UAAU;YACf,4BAA4B,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,EAC1E;AACA,YAAA,MAAM,IAAI,CAAC,mBAAmB,EAAE;QAClC;AACA,QAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI;IAC9B;IAEA,OAAO,CAAC,MAAc,EAAE,YAA8B,EAAA;AACpD,QAAA,MAAM,YAAY,GAAG,MAAM,EAAE,IAAI,EAAE;QACnC,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ;YAAE;AACxE,QAAA,IAAI,CAAC,YAAY,GAAG,YAAY;QAChC,IAAI,CAAC,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC;QACtE,IAAI,CAAC,cAAc,EAAE;IACvB;AAEA,IAAA,gBAAgB,CAAC,OAAyB,EAAA;AACxC,QAAA,IAAI,OAAO,CAAC,aAAa,KAAK,QAAQ;YAAE;QAExC,IAAI,OAAO,CAAC,IAAI,KAAKC,oBAAa,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,SAAmB,CAAC;QACjE;aAAO,IAAI,OAAO,CAAC,IAAI,KAAKA,oBAAa,CAAC,MAAM,EAAE;YAChD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C;aAAO;AACL,YAAA,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;QAC5B;IACF;AAEA,IAAA,cAAc,CAAC,UAAsB,EAAA;QACnC,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,MAAM,CAAW;AAC3D,QAAA,IAAI,CAAC,SAAS;YAAE;AAEhB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;AAC3C,QAAA,IAAI,CAAC,KAAK;YAAE;QACZ,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC;IACnD;IAEQ,SAAS,CAAC,UAAsB,EAAE,SAAiB,EAAA;AACzD,QAAA,MAAM,QAAQ,GAAG,IAAIC,oBAAU,EAAE;AACjC,QAAA,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,CAAC;QACvC,QAAQ,CAAC,IAAI,EAAE;AACf,QAAAC,4BAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;AAEpC,QAAA,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC;AACnE,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAC5D,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,IAAIC,iCAAgB,EAAE,CAAC;QAC3D,IAAI,CAAC,mBAAmB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,mBAAmB,EAAE;IAC5B;AAEQ,IAAA,YAAY,CAAC,OAAyB,EAAA;AAC5C,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;AACnD,QAAA,IAAI,CAAC,KAAK;YAAE;AACZ,QAAA,MAAM,SAAS,GAAG,OAAO,CAAC,SAAmB;AAC7C,QAAA,KAAK,CAAC,SAAS,GAAG,SAAS;QAC3B,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM;YAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/E,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;AACzC,QAAA,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;QACjB,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM;YAAE,IAAI,CAAC,mBAAmB,EAAE;IACjE;AAEQ,IAAA,YAAY,CAAC,EAAU,EAAA;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;AAChC,QAAA,IAAI,CAAC,KAAK;YAAE;QAEZ,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC;AAC9C,QAAA,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE;AACpB,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;AACrB,QAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7B;IAEQ,aAAa,CAAC,QAAoB,EAAE,SAAiB,EAAA;QAC3D,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;AAC3C,QAAA,QAAQ,CAAC,QAAQ,GAAG,SAAS,CAAC,QAAQ;AACtC,QAAA,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK;AAChC,QAAA,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO;AACpC,QAAA,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO;AACpC,QAAA,IAAI,SAAS,CAAC,QAAQ,GAAG,CAAC,EAAE;AAC1B,YAAA,QAAQ,CAAC,QAAQ,GAAG,SAAS,CAAC,QAAQ;QACxC;AACA,QAAA,IAAI,SAAS,CAAC,IAAI,EAAE;AAClB,YAAA,QAAQ,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI;QAChC;IACF;AAEQ,IAAA,SAAS,CAAC,UAAsB,EAAE,SAAiB,EAAE,QAAoB,EAAA;AAC/E,QAAA,IAAI,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,GAAG,IAAIA,iCAAgB,EAAE;YAC/B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC;QAC7C;QACA,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAACC,4BAAW,CAA4B;QACjF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE;YACtC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9B,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9B;QACF;AACA,QAAA,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC;AACpF,QAAA,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC;IACtF;IAEA,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,aAAa,IAAI,CAAC;AACvB,QAAA,IAAI,CAAC,gBAAgB,GAAG,KAAK;AAC7B,QAAA,IAAI,CAAC,UAAU,GAAG,KAAK;AACvB,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE;QAChC,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE;AAC7B,YAAA,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACvB;AACA,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;IACpB;AAEQ,IAAA,WAAW,CAAC,SAAiB,EAAA;QACnC,IACE,+BAA+B,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;AAC9C,SAAA,CAAC,EACF;AACA,YAAA,OAAO,EAAE;QACX;QACA,OAAO,YAAY,CACjB,SAAS,CAAC,IAAI,EACd,SAAS,CAAC,YAAY,EACtB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,CAClB;IACH;AAEQ,IAAA,mBAAmB,CAAC,KAA2C,EAAA;AACrE,QAAA,cAAc,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC;IAC9C;IAEQ,kBAAkB,GAAA;QACxB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE;YACvC,IAAI,CAAC,mBAAmB,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAClD;AACA,QAAA,OAAO,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC;IACnC;IAEQ,mBAAmB,GAAA;AACzB,QAAA,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,oBAAoB;YAAE;AAC/E,QAAA,IAAI,CAAC,oBAAoB,GAAG,IAAI;QAChC,cAAc,CAAC,MAAK;AAClB,YAAA,IAAI,CAAC,oBAAoB,GAAG,KAAK;YACjC,IAAI,CAAC,gBAAgB,EAAE;AACzB,QAAA,CAAC,CAAC;IACJ;IAEQ,gBAAgB,GAAA;QACtB,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE;AAClD,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,EAAE;QAC7C,IACE,CAAC,+BAA+B,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,EAAE;YAC/D,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,wBAAwB,EAAE,IAAI,CAAC,wBAAwB;AACxD,SAAA,CAAC,EACF;YACA;QACF;AACA,QAAA,KAAK,IAAI,CAAC,mBAAmB,EAAE;IACjC;AAEQ,IAAA,MAAM,mBAAmB,GAAA;AAC/B,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,EAAE;AAC7C,QAAA,IAAI,CAAC,wBAAwB,GAAG,oBAAoB,CAAC,WAAW,CAAC;AACjE,QAAA,MAAM,SAAS,GAAG,EAAE,IAAI,CAAC,aAAa;AACtC,QAAA,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;YACnC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,WAAW;AACZ,SAAA,CAAC;AACF,QAAA,IAAI,SAAS,KAAK,IAAI,CAAC,aAAa;YAAE;AACtC,QAAA,cAAc,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC;AACrD,QAAA,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM;AAC/B,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAClB,IAAI,CAAC,cAAc,EAAE;YACrB;QACF;QACA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC;IAClD;IAEQ,cAAc,GAAA;QACpB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE;AACvC,YAAA,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC;AACnD,YAAA,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;QACnB;IACF;;AAvOmB,YAAY,GAAAR,gBAAA,CAAA;IAThCS,iBAAU,CAAC,iBAAiB,CAAC;AAC5B,QAAA,MAAM,EAAE;YACN,MAAM;YACN,EAAE,IAAI,EAAE,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;YACtC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM;YAC7D,WAAW,EAAE,WAAW,EAAE,WAAW;YACrC,WAAW,EAAE,WAAW,EAAE,WAAW;AACtC,SAAA;KACF;AACoB,CAAA,EAAA,YAAY,CAwOhC;2BAxOoB,YAAY;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("tslib"),t=require("@combos-fun/engine"),o=require("@combos-fun/inspector-decorator"),s=require("@combos-fun/plugin-renderer-3d"),r=require("troika-three-text");class i extends t.Component{constructor(){super(...arguments),this.text="",this.replacements={},this.fontSize=.5,this.color=16777215,this.anchorX="center",this.anchorY="middle",this.maxWidth=0,this.font="",this.positionX=0,this.positionY=0,this.positionZ=0,this.rotationX=0,this.rotationY=0,this.rotationZ=0}static{this.componentName="Text3D"}init(e){if(!e)return;const{replacements:t,...o}=e;Object.assign(this,o),t&&(this.replacements={...t})}}e.__decorate([o.Field({type:"string",group:"Text3D",label:"text",description:"Visible text content.",editor:"text"})],i.prototype,"text",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"fontSize",description:"Font size.",editor:"number-stepper"})],i.prototype,"fontSize",void 0),e.__decorate([o.Field({type:"number",group:"Text3D",label:"color",description:"Color value.",editor:"number-stepper"})],i.prototype,"color",void 0),e.__decorate([o.Field({type:"string",group:"Text3D",label:"anchorX",description:"Horizontal text anchor.",editor:"text"})],i.prototype,"anchorX",void 0),e.__decorate([o.Field({type:"string",group:"Text3D",label:"anchorY",description:"Vertical text anchor.",editor:"text"})],i.prototype,"anchorY",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"maxWidth",description:"Maximum text wrap width.",editor:"number-stepper"})],i.prototype,"maxWidth",void 0),e.__decorate([o.Field({type:"string",group:"Text3D",label:"font",description:"Font URL or path for troika-three-text (not an engine resource name).",editor:"text"})],i.prototype,"font",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"positionX",description:"Local X position.",editor:"number-stepper"})],i.prototype,"positionX",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"positionY",description:"Local Y position.",editor:"number-stepper"})],i.prototype,"positionY",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"positionZ",description:"Local Z position.",editor:"number-stepper"})],i.prototype,"positionZ",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"rotationX",description:"Rotation around X in radians.",editor:"number-stepper"})],i.prototype,"rotationX",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"rotationY",description:"Rotation around Y in radians.",editor:"number-stepper"})],i.prototype,"rotationY",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"rotationZ",description:"Rotation around Z in radians.",editor:"number-stepper"})],i.prototype,"rotationZ",void 0);function n(e=("undefined"==typeof window?void 0:window.combos)){return!!e&&"function"==typeof e.requestI18n}function a(e){if(!e||"object"!=typeof e)return{needed:!1};const t=e;if(!0!==t.needed)return{needed:!1};if("string"!=typeof t.locale||!t.locale.trim())return{needed:!1};if(!t.translations||"object"!=typeof t.translations||Array.isArray(t.translations))return{needed:!1};const o=Object.entries(t.translations);return o.some(([,e])=>"string"!=typeof e)?{needed:!1}:{needed:!0,locale:t.locale.trim(),translations:Object.fromEntries(o)}}async function c(e){if("undefined"==typeof window||!n(window.combos))return{needed:!1};try{return a(await window.combos.requestI18n(e))}catch{return{needed:!1}}}const d=/\{([A-Za-z_$][\w$.-]*)\}/g;function p(e,t){return t?e.replace(d,(e,o)=>Object.prototype.hasOwnProperty.call(t,o)?String(t[o]):e):e}function l(e,t){if(Object.prototype.hasOwnProperty.call(t,e))return t[e];const o=e.trim();return o&&o!==e&&Object.prototype.hasOwnProperty.call(t,o)?t[o]:void 0}function
|
|
1
|
+
"use strict";var e=require("tslib"),t=require("@combos-fun/engine"),o=require("@combos-fun/inspector-decorator"),s=require("@combos-fun/plugin-renderer-3d"),r=require("troika-three-text");class i extends t.Component{constructor(){super(...arguments),this.text="",this.replacements={},this.fontSize=.5,this.color=16777215,this.anchorX="center",this.anchorY="middle",this.maxWidth=0,this.font="",this.positionX=0,this.positionY=0,this.positionZ=0,this.rotationX=0,this.rotationY=0,this.rotationZ=0}static{this.componentName="Text3D"}init(e){if(!e)return;const{replacements:t,...o}=e;Object.assign(this,o),t&&(this.replacements={...t})}}e.__decorate([o.Field({type:"string",group:"Text3D",label:"text",description:"Visible text content.",editor:"text"})],i.prototype,"text",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"fontSize",description:"Font size.",editor:"number-stepper"})],i.prototype,"fontSize",void 0),e.__decorate([o.Field({type:"number",group:"Text3D",label:"color",description:"Color value.",editor:"number-stepper"})],i.prototype,"color",void 0),e.__decorate([o.Field({type:"string",group:"Text3D",label:"anchorX",description:"Horizontal text anchor.",editor:"text"})],i.prototype,"anchorX",void 0),e.__decorate([o.Field({type:"string",group:"Text3D",label:"anchorY",description:"Vertical text anchor.",editor:"text"})],i.prototype,"anchorY",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"maxWidth",description:"Maximum text wrap width.",editor:"number-stepper"})],i.prototype,"maxWidth",void 0),e.__decorate([o.Field({type:"string",group:"Text3D",label:"font",description:"Font URL or path for troika-three-text (not an engine resource name).",editor:"text"})],i.prototype,"font",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"positionX",description:"Local X position.",editor:"number-stepper"})],i.prototype,"positionX",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"positionY",description:"Local Y position.",editor:"number-stepper"})],i.prototype,"positionY",void 0),e.__decorate([o.Field({type:"number",step:.1,group:"Text3D",label:"positionZ",description:"Local Z position.",editor:"number-stepper"})],i.prototype,"positionZ",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"rotationX",description:"Rotation around X in radians.",editor:"number-stepper"})],i.prototype,"rotationX",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"rotationY",description:"Rotation around Y in radians.",editor:"number-stepper"})],i.prototype,"rotationY",void 0),e.__decorate([o.Field({type:"number",step:.01,group:"Text3D",label:"rotationZ",description:"Rotation around Z in radians.",editor:"number-stepper"})],i.prototype,"rotationZ",void 0);function n(e=("undefined"==typeof window?void 0:window.combos)){return!!e&&"function"==typeof e.requestI18n}function a(e){if(!e||"object"!=typeof e)return{needed:!1};const t=e;if(!0!==t.needed)return{needed:!1};if("string"!=typeof t.locale||!t.locale.trim())return{needed:!1};if(!t.translations||"object"!=typeof t.translations||Array.isArray(t.translations))return{needed:!1};const o=Object.entries(t.translations);return o.some(([,e])=>"string"!=typeof e)?{needed:!1}:{needed:!0,locale:t.locale.trim(),translations:Object.fromEntries(o)}}async function c(e){if("undefined"==typeof window||!n(window.combos))return{needed:!1};try{return a(await window.combos.requestI18n(e))}catch{return{needed:!1}}}const d=/\{([A-Za-z_$][\w$.-]*)\}/g;function p(e,t){return t?e.replace(d,(e,o)=>Object.prototype.hasOwnProperty.call(t,o)?String(t[o]):e):e}function l(e,t){if(Object.prototype.hasOwnProperty.call(t,e))return t[e];const o=e.trim();return o&&o!==e&&Object.prototype.hasOwnProperty.call(t,o)?t[o]:void 0}function u(e,t){return void 0!==l(e,t)}function h(e,t){return e.some(e=>!u(e,t))}function x(e){return[...e].sort().join("\0")}function m(e,t,o){return!!o.i18nNeeded&&(!!h(e,t)&&x(e)!==o.lastRequestedSourceTexts)}function f(e,t,o){if(!o.sourceLocale||!o.i18nNeeded||!o.firstI18nSettled)return!1;if(o.sourceLocale.toLowerCase()===o.targetLocale.toLowerCase())return!1;const s=e.trim();return!!s&&(!u(e,t)&&!o.resolvedSourceTexts.has(s))}function T(e,t,o,s,r){return p(!!o&&!!s&&o.toLowerCase()!==s.toLowerCase()?l(e,r)??e:e,t)}function y(e,t){if(t)for(const o of t){const t="string"==typeof o?o.trim():"";t&&e.add(t)}}function S(e,t){const o={...e};for(const[e,s]of Object.entries(t))"string"==typeof s&&(o[e]=s);return o}let b=class extends s.Renderer3D{constructor(){super(...arguments),this.name="Text3DSystem",this.texts=new Map,this.poseBridges=new Map,this.sourceLocale="",this.targetLocale="",this.translations={},this.knownSourceTexts=new Set,this.lastRequestedSourceTexts="",this.i18nRequestScheduled=!1,this.i18nRequestId=0,this.firstI18nSettled=!1,this.i18nNeeded=!1,this.resolvedSourceTexts=new Set}static{this.systemName="Text3DSystem"}init(e){this.game.getSystem(s.Renderer3DSystem).rendererManager.register(this),this.sourceLocale=e?.sourceLocale?.trim()??"",this.targetLocale=this.sourceLocale,this.declareSourceTexts(e?.sourceTexts)}declareSourceTexts(e){this.rememberSourceTexts(e),this.scheduleI18nRequest()}async beforeReady(){this.firstI18nSettled||(this.update(),this.sourceLocale?(await this.requestI18nAndApply(),this.i18nNeeded&&h(this.collectSourceTexts(),this.translations)&&await this.requestI18nAndApply(),this.firstI18nSettled=!0):this.firstI18nSettled=!0)}setI18n(e,t){const o=e?.trim();o&&t&&"object"==typeof t&&(this.targetLocale=o,this.translations=S(this.translations,t),this.refreshAllText())}componentChanged(e){"Text3D"===e.componentName&&(e.type===t.OBSERVER_TYPE.ADD?this.handleAdd(e.gameObject,e.component):e.type===t.OBSERVER_TYPE.REMOVE?this.handleRemove(e.gameObject.id):this.handleChange(e))}rendererUpdate(e){const t=e.getComponent(i);if(!t)return;const o=this.texts.get(e.id);o&&this.applyPose(e,t,o.mesh)}handleAdd(e,t){const o=new r.Text;this.syncTextProps(o,t),o.sync(),s.tagObject3D(o,e.id),this.threeContext.attachVisual(e.id,o,e),this.texts.set(e.id,{mesh:o,component:t}),this.poseBridges.set(e.id,new s.VisualPoseBridge),this.rememberSourceTexts([t.text]),this.scheduleI18nRequest()}handleChange(e){const t=this.texts.get(e.gameObject.id);if(!t)return;const o=e.component;t.component=o,"text"===e.prop.prop[0]&&this.rememberSourceTexts([o.text]),this.syncTextProps(t.mesh,o),t.mesh.sync(),"text"===e.prop.prop[0]&&this.scheduleI18nRequest()}handleRemove(e){const t=this.texts.get(e);t&&(this.threeContext.detachVisual(e,t.mesh),t.mesh.dispose(),this.texts.delete(e),this.poseBridges.delete(e))}syncTextProps(e,t){e.text=this.resolveText(t),e.fontSize=t.fontSize,e.color=t.color,e.anchorX=t.anchorX,e.anchorY=t.anchorY,t.maxWidth>0&&(e.maxWidth=t.maxWidth),t.font&&(e.font=t.font)}applyPose(e,t,o){let r=this.poseBridges.get(e.id);r||(r=new s.VisualPoseBridge,this.poseBridges.set(e.id,r));const i=e.getComponent(s.Transform3D);if(!r.sync(t,i))return o.position.set(0,0,0),void o.rotation.set(0,0,0);o.position.set(t.positionX,t.positionY,t.positionZ),o.rotation.set(t.rotationX,t.rotationY,t.rotationZ)}onDestroy(){this.i18nRequestId+=1,this.firstI18nSettled=!1,this.i18nNeeded=!1,this.resolvedSourceTexts.clear();for(const[e]of this.texts)this.handleRemove(e);this.texts.clear()}resolveText(e){return f(e.text,this.translations,{sourceLocale:this.sourceLocale,targetLocale:this.targetLocale,i18nNeeded:this.i18nNeeded,firstI18nSettled:this.firstI18nSettled,resolvedSourceTexts:this.resolvedSourceTexts})?"":T(e.text,e.replacements,this.sourceLocale,this.targetLocale,this.translations)}rememberSourceTexts(e){y(this.knownSourceTexts,e)}collectSourceTexts(){for(const e of this.texts.values())this.rememberSourceTexts([e.component.text]);return[...this.knownSourceTexts]}scheduleI18nRequest(){this.sourceLocale&&this.firstI18nSettled&&!this.i18nRequestScheduled&&(this.i18nRequestScheduled=!0,queueMicrotask(()=>{this.i18nRequestScheduled=!1,this.startI18nRequest()}))}startI18nRequest(){if(!this.sourceLocale||!this.firstI18nSettled)return;m(this.collectSourceTexts(),this.translations,{i18nNeeded:this.i18nNeeded,lastRequestedSourceTexts:this.lastRequestedSourceTexts})&&this.requestI18nAndApply()}async requestI18nAndApply(){const e=this.collectSourceTexts();this.lastRequestedSourceTexts=x(e);const t=++this.i18nRequestId,o=await c({sourceLocale:this.sourceLocale,sourceTexts:e});t===this.i18nRequestId&&(y(this.resolvedSourceTexts,e),this.i18nNeeded=o.needed,o.needed?this.setI18n(o.locale,o.translations):this.refreshAllText())}refreshAllText(){for(const e of this.texts.values())e.mesh.text=this.resolveText(e.component),e.mesh.sync()}};b=e.__decorate([t.decorators.componentObserver({Text3D:["text",{prop:["replacements"],deep:!0},"fontSize","color","anchorX","anchorY","maxWidth","font","positionX","positionY","positionZ","rotationX","rotationY","rotationZ"]})],b);var g=b;exports.COMBOS_HOST_SDK="combos",exports.Text3D=i,exports.Text3DSystem=g,exports.addSourceTexts=y,exports.findTranslatedTemplate=l,exports.hasCombosRequestI18n=n,exports.hasMissingSourceTranslations=h,exports.hasSourceTranslation=u,exports.interpolateText=p,exports.localizeText=T,exports.mergeTranslations=S,exports.parseI18nResult=a,exports.requestHostI18n=c,exports.shouldHoldForMissingTranslation=f,exports.shouldRequestI18nForSourceTexts=m,exports.sourceTextsSignature=x;
|
|
@@ -9,6 +9,12 @@ declare function interpolateText(template: string, replacements?: TextReplacemen
|
|
|
9
9
|
declare function findTranslatedTemplate(sourceText: string, translations: TextTranslations): string | undefined;
|
|
10
10
|
declare function hasSourceTranslation(sourceText: string, translations: TextTranslations): boolean;
|
|
11
11
|
declare function hasMissingSourceTranslations(sourceTexts: readonly string[], translations: TextTranslations): boolean;
|
|
12
|
+
declare function sourceTextsSignature(sourceTexts: readonly string[]): string;
|
|
13
|
+
/** After the first host reply, only request again for templates still missing. */
|
|
14
|
+
declare function shouldRequestI18nForSourceTexts(sourceTexts: readonly string[], translations: TextTranslations, state: {
|
|
15
|
+
i18nNeeded: boolean;
|
|
16
|
+
lastRequestedSourceTexts: string;
|
|
17
|
+
}): boolean;
|
|
12
18
|
declare function shouldHoldForMissingTranslation(sourceText: string, translations: TextTranslations, state: {
|
|
13
19
|
sourceLocale: string;
|
|
14
20
|
targetLocale: string;
|
|
@@ -61,8 +67,8 @@ interface Text3DSystemParams {
|
|
|
61
67
|
sourceLocale?: string;
|
|
62
68
|
/**
|
|
63
69
|
* All source templates to translate on first `requestI18n`, including copy
|
|
64
|
-
* for screens that are not mounted yet.
|
|
65
|
-
*
|
|
70
|
+
* for screens that are not mounted yet. The system also keeps a growing
|
|
71
|
+
* session catalog of every later template it sees.
|
|
66
72
|
*/
|
|
67
73
|
sourceTexts?: string[];
|
|
68
74
|
}
|
|
@@ -74,7 +80,8 @@ declare class Text3DSystem extends Renderer3D<Text3DSystemParams> {
|
|
|
74
80
|
private sourceLocale;
|
|
75
81
|
private targetLocale;
|
|
76
82
|
private translations;
|
|
77
|
-
|
|
83
|
+
/** Growing catalog of every source template seen this session. */
|
|
84
|
+
private knownSourceTexts;
|
|
78
85
|
private lastRequestedSourceTexts;
|
|
79
86
|
private i18nRequestScheduled;
|
|
80
87
|
private i18nRequestId;
|
|
@@ -95,6 +102,7 @@ declare class Text3DSystem extends Renderer3D<Text3DSystemParams> {
|
|
|
95
102
|
private applyPose;
|
|
96
103
|
onDestroy(): void;
|
|
97
104
|
private resolveText;
|
|
105
|
+
private rememberSourceTexts;
|
|
98
106
|
private collectSourceTexts;
|
|
99
107
|
private scheduleI18nRequest;
|
|
100
108
|
private startI18nRequest;
|
|
@@ -132,5 +140,5 @@ declare function parseI18nResult(data: unknown): CombosI18nResult;
|
|
|
132
140
|
/** Ask the injected host SDK. Always resolves; missing method means no translation. */
|
|
133
141
|
declare function requestHostI18n(request: CombosI18nRequest): Promise<CombosI18nResult>;
|
|
134
142
|
|
|
135
|
-
export { COMBOS_HOST_SDK, Text3D, Text3DSystem, addSourceTexts, findTranslatedTemplate, hasCombosRequestI18n, hasMissingSourceTranslations, hasSourceTranslation, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n, shouldHoldForMissingTranslation };
|
|
143
|
+
export { COMBOS_HOST_SDK, Text3D, Text3DSystem, addSourceTexts, findTranslatedTemplate, hasCombosRequestI18n, hasMissingSourceTranslations, hasSourceTranslation, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n, shouldHoldForMissingTranslation, shouldRequestI18nForSourceTexts, sourceTextsSignature };
|
|
136
144
|
export type { CombosHostSdk, CombosI18nRequest, CombosI18nResult, Text3DParams, Text3DSystemParams, TextReplacementValue, TextReplacements, TextTranslations };
|
|
@@ -230,6 +230,17 @@ function hasSourceTranslation(sourceText, translations) {
|
|
|
230
230
|
function hasMissingSourceTranslations(sourceTexts, translations) {
|
|
231
231
|
return sourceTexts.some((text) => !hasSourceTranslation(text, translations));
|
|
232
232
|
}
|
|
233
|
+
function sourceTextsSignature(sourceTexts) {
|
|
234
|
+
return [...sourceTexts].sort().join('\0');
|
|
235
|
+
}
|
|
236
|
+
/** After the first host reply, only request again for templates still missing. */
|
|
237
|
+
function shouldRequestI18nForSourceTexts(sourceTexts, translations, state) {
|
|
238
|
+
if (!state.i18nNeeded)
|
|
239
|
+
return false;
|
|
240
|
+
if (!hasMissingSourceTranslations(sourceTexts, translations))
|
|
241
|
+
return false;
|
|
242
|
+
return sourceTextsSignature(sourceTexts) !== state.lastRequestedSourceTexts;
|
|
243
|
+
}
|
|
233
244
|
function shouldHoldForMissingTranslation(sourceText, translations, state) {
|
|
234
245
|
if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled)
|
|
235
246
|
return false;
|
|
@@ -278,7 +289,8 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
278
289
|
this.sourceLocale = '';
|
|
279
290
|
this.targetLocale = '';
|
|
280
291
|
this.translations = {};
|
|
281
|
-
this.
|
|
292
|
+
/** Growing catalog of every source template seen this session. */
|
|
293
|
+
this.knownSourceTexts = new Set();
|
|
282
294
|
this.lastRequestedSourceTexts = '';
|
|
283
295
|
this.i18nRequestScheduled = false;
|
|
284
296
|
this.i18nRequestId = 0;
|
|
@@ -296,7 +308,7 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
296
308
|
}
|
|
297
309
|
/** Register extra source templates before or after ready. First request includes these. */
|
|
298
310
|
declareSourceTexts(texts) {
|
|
299
|
-
|
|
311
|
+
this.rememberSourceTexts(texts);
|
|
300
312
|
this.scheduleI18nRequest();
|
|
301
313
|
}
|
|
302
314
|
async beforeReady() {
|
|
@@ -352,6 +364,7 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
352
364
|
this.threeContext.attachVisual(gameObject.id, textMesh, gameObject);
|
|
353
365
|
this.texts.set(gameObject.id, { mesh: textMesh, component });
|
|
354
366
|
this.poseBridges.set(gameObject.id, new VisualPoseBridge());
|
|
367
|
+
this.rememberSourceTexts([component.text]);
|
|
355
368
|
this.scheduleI18nRequest();
|
|
356
369
|
}
|
|
357
370
|
handleChange(changed) {
|
|
@@ -360,6 +373,8 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
360
373
|
return;
|
|
361
374
|
const component = changed.component;
|
|
362
375
|
entry.component = component;
|
|
376
|
+
if (changed.prop.prop[0] === 'text')
|
|
377
|
+
this.rememberSourceTexts([component.text]);
|
|
363
378
|
this.syncTextProps(entry.mesh, component);
|
|
364
379
|
entry.mesh.sync();
|
|
365
380
|
if (changed.prop.prop[0] === 'text')
|
|
@@ -424,12 +439,14 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
424
439
|
}
|
|
425
440
|
return localizeText(component.text, component.replacements, this.sourceLocale, this.targetLocale, this.translations);
|
|
426
441
|
}
|
|
442
|
+
rememberSourceTexts(texts) {
|
|
443
|
+
addSourceTexts(this.knownSourceTexts, texts);
|
|
444
|
+
}
|
|
427
445
|
collectSourceTexts() {
|
|
428
|
-
const sourceTexts = new Set(this.seededSourceTexts);
|
|
429
446
|
for (const entry of this.texts.values()) {
|
|
430
|
-
|
|
447
|
+
this.rememberSourceTexts([entry.component.text]);
|
|
431
448
|
}
|
|
432
|
-
return [...
|
|
449
|
+
return [...this.knownSourceTexts];
|
|
433
450
|
}
|
|
434
451
|
scheduleI18nRequest() {
|
|
435
452
|
if (!this.sourceLocale || !this.firstI18nSettled || this.i18nRequestScheduled)
|
|
@@ -444,15 +461,17 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
444
461
|
if (!this.sourceLocale || !this.firstI18nSettled)
|
|
445
462
|
return;
|
|
446
463
|
const sourceTexts = this.collectSourceTexts();
|
|
447
|
-
|
|
448
|
-
|
|
464
|
+
if (!shouldRequestI18nForSourceTexts(sourceTexts, this.translations, {
|
|
465
|
+
i18nNeeded: this.i18nNeeded,
|
|
466
|
+
lastRequestedSourceTexts: this.lastRequestedSourceTexts,
|
|
467
|
+
})) {
|
|
449
468
|
return;
|
|
469
|
+
}
|
|
450
470
|
void this.requestI18nAndApply();
|
|
451
471
|
}
|
|
452
472
|
async requestI18nAndApply() {
|
|
453
473
|
const sourceTexts = this.collectSourceTexts();
|
|
454
|
-
|
|
455
|
-
this.lastRequestedSourceTexts = signature;
|
|
474
|
+
this.lastRequestedSourceTexts = sourceTextsSignature(sourceTexts);
|
|
456
475
|
const requestId = ++this.i18nRequestId;
|
|
457
476
|
const result = await requestHostI18n({
|
|
458
477
|
sourceLocale: this.sourceLocale,
|
|
@@ -488,5 +507,5 @@ Text3DSystem = __decorate([
|
|
|
488
507
|
], Text3DSystem);
|
|
489
508
|
var Text3DSystem_default = Text3DSystem;
|
|
490
509
|
|
|
491
|
-
export { COMBOS_HOST_SDK, Text3D, Text3DSystem_default as Text3DSystem, addSourceTexts, findTranslatedTemplate, hasCombosRequestI18n, hasMissingSourceTranslations, hasSourceTranslation, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n, shouldHoldForMissingTranslation };
|
|
510
|
+
export { COMBOS_HOST_SDK, Text3D, Text3DSystem_default as Text3DSystem, addSourceTexts, findTranslatedTemplate, hasCombosRequestI18n, hasMissingSourceTranslations, hasSourceTranslation, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n, shouldHoldForMissingTranslation, shouldRequestI18nForSourceTexts, sourceTextsSignature };
|
|
492
511
|
//# sourceMappingURL=plugin-renderer-3d-text.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-renderer-3d-text.esm.js","sources":["../lib/component.ts","../lib/hostSdk.ts","../lib/localization.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\nimport type { TextReplacements } from './localization';\n\nexport type { TextReplacementValue, TextReplacements } from './localization';\n\nexport interface Text3DParams {\n text?: string;\n /** Values substituted into named placeholders such as `{score}`. */\n replacements?: TextReplacements;\n fontSize?: number;\n color?: number;\n anchorX?: string;\n anchorY?: string;\n maxWidth?: number;\n font?: string;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n}\n\nexport default class Text3D extends Component<Text3DParams> {\n static componentName: string = 'Text3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Text3D',\n\n label: 'text',\n\n description: 'Visible text content.',\n\n editor: 'text',\n\n })\n\n text: string = '';\n\n replacements: TextReplacements = {};\n\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'fontSize',\n description: 'Font size.',\n editor: 'number-stepper',\n })\n fontSize: number = 0.5;\n @Field({\n type: 'number',\n group: 'Text3D',\n label: 'color',\n description: 'Color value.',\n editor: 'number-stepper',\n })\n color: number = 0xffffff;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorX',\n description: 'Horizontal text anchor.',\n editor: 'text',\n })\n anchorX: string = 'center';\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorY',\n description: 'Vertical text anchor.',\n editor: 'text',\n })\n anchorY: string = 'middle';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'maxWidth',\n description: 'Maximum text wrap width.',\n editor: 'number-stepper',\n })\n maxWidth: number = 0;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'font',\n description: 'Font URL or path for troika-three-text (not an engine resource name).',\n editor: 'text',\n })\n font: string = '';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n\n init(obj?: Text3DParams) {\n if (!obj) return;\n const { replacements, ...rest } = obj;\n Object.assign(this, rest);\n if (replacements) this.replacements = { ...replacements };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` hostSdk. */\nimport type { TextTranslations } from './localization';\n\n/** Host-injected global. The SDK itself is not part of this repo. */\nexport const COMBOS_HOST_SDK = 'combos' as const;\n\nexport interface CombosI18nRequest {\n sourceLocale: string;\n sourceTexts: string[];\n}\n\nexport type CombosI18nResult =\n | { needed: false }\n | { needed: true; locale: string; translations: TextTranslations };\n\nexport interface CombosHostSdk {\n requestI18n?(request: CombosI18nRequest): Promise<CombosI18nResult>;\n}\n\ndeclare global {\n interface Window {\n combos?: CombosHostSdk;\n }\n}\n\nexport function hasCombosRequestI18n(\n sdk: CombosHostSdk | undefined | null = typeof window === 'undefined' ? undefined : window.combos,\n): sdk is CombosHostSdk & { requestI18n: NonNullable<CombosHostSdk['requestI18n']> } {\n return !!sdk && typeof sdk.requestI18n === 'function';\n}\n\nexport function parseI18nResult(data: unknown): CombosI18nResult {\n if (!data || typeof data !== 'object') return { needed: false };\n const input = data as {\n needed?: unknown;\n locale?: unknown;\n translations?: unknown;\n };\n if (input.needed !== true) return { needed: false };\n if (typeof input.locale !== 'string' || !input.locale.trim()) {\n return { needed: false };\n }\n if (\n !input.translations ||\n typeof input.translations !== 'object' ||\n Array.isArray(input.translations)\n ) {\n return { needed: false };\n }\n const entries = Object.entries(input.translations);\n if (entries.some(([, value]) => typeof value !== 'string')) {\n return { needed: false };\n }\n return {\n needed: true,\n locale: input.locale.trim(),\n translations: Object.fromEntries(entries) as TextTranslations,\n };\n}\n\n/** Ask the injected host SDK. Always resolves; missing method means no translation. */\nexport async function requestHostI18n(\n request: CombosI18nRequest,\n): Promise<CombosI18nResult> {\n if (typeof window === 'undefined' || !hasCombosRequestI18n(window.combos)) {\n return { needed: false };\n }\n try {\n return parseI18nResult(await window.combos.requestI18n(request));\n } catch {\n return { needed: false };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` localization. */\n\nexport type TextReplacementValue = string | number;\nexport type TextReplacements = Record<string, TextReplacementValue>;\nexport type TextTranslations = Record<string, string>;\n\nconst PLACEHOLDER_PATTERN = /\\{([A-Za-z_$][\\w$.-]*)\\}/g;\n\nexport function interpolateText(\n template: string,\n replacements?: TextReplacements,\n): string {\n if (!replacements) return template;\n return template.replace(PLACEHOLDER_PATTERN, (placeholder, name: string) => {\n if (!Object.prototype.hasOwnProperty.call(replacements, name)) {\n return placeholder;\n }\n return String(replacements[name]);\n });\n}\n\nexport function findTranslatedTemplate(\n sourceText: string,\n translations: TextTranslations,\n): string | undefined {\n if (Object.prototype.hasOwnProperty.call(translations, sourceText)) {\n return translations[sourceText];\n }\n const trimmed = sourceText.trim();\n if (\n trimmed &&\n trimmed !== sourceText &&\n Object.prototype.hasOwnProperty.call(translations, trimmed)\n ) {\n return translations[trimmed];\n }\n return undefined;\n}\n\nexport function hasSourceTranslation(\n sourceText: string,\n translations: TextTranslations,\n): boolean {\n return findTranslatedTemplate(sourceText, translations) !== undefined;\n}\n\nexport function hasMissingSourceTranslations(\n sourceTexts: readonly string[],\n translations: TextTranslations,\n): boolean {\n return sourceTexts.some((text) => !hasSourceTranslation(text, translations));\n}\n\nexport function shouldHoldForMissingTranslation(\n sourceText: string,\n translations: TextTranslations,\n state: {\n sourceLocale: string;\n targetLocale: string;\n i18nNeeded: boolean;\n firstI18nSettled: boolean;\n resolvedSourceTexts: ReadonlySet<string>;\n },\n): boolean {\n if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled) return false;\n if (state.sourceLocale.toLowerCase() === state.targetLocale.toLowerCase()) return false;\n const trimmed = sourceText.trim();\n if (!trimmed) return false;\n if (hasSourceTranslation(sourceText, translations)) return false;\n return !state.resolvedSourceTexts.has(trimmed);\n}\n\nexport function localizeText(\n sourceText: string,\n replacements: TextReplacements | undefined,\n sourceLocale: string,\n targetLocale: string,\n translations: TextTranslations,\n): string {\n const shouldTranslate =\n !!sourceLocale &&\n !!targetLocale &&\n sourceLocale.toLowerCase() !== targetLocale.toLowerCase();\n const template = shouldTranslate\n ? findTranslatedTemplate(sourceText, translations) ?? sourceText\n : sourceText;\n return interpolateText(template, replacements);\n}\n\nexport function addSourceTexts(\n target: Set<string>,\n texts?: Iterable<string | undefined | null>,\n) {\n if (!texts) return;\n for (const text of texts) {\n const source = typeof text === 'string' ? text.trim() : '';\n if (source) target.add(source);\n }\n}\n\nexport function mergeTranslations(\n current: TextTranslations,\n incoming: Record<string, unknown>,\n): TextTranslations {\n const next = { ...current };\n for (const [key, value] of Object.entries(incoming)) {\n if (typeof value === 'string') next[key] = value;\n }\n return next;\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport { Renderer3D, Renderer3DSystem, tagObject3D, Transform3D, VisualPoseBridge } from '@combos-fun/plugin-renderer-3d';\nimport { Text as TroikaText } from 'troika-three-text';\nimport Text3D from './component';\nimport { requestHostI18n } from './hostSdk';\nimport {\n addSourceTexts,\n hasMissingSourceTranslations,\n localizeText,\n mergeTranslations,\n shouldHoldForMissingTranslation,\n type TextTranslations,\n} from './localization';\n\nexport interface Text3DSystemParams {\n /** BCP 47 locale of the source text, for example `zh-CN`. Omit to disable host-driven i18n. */\n sourceLocale?: string;\n /**\n * All source templates to translate on first `requestI18n`, including copy\n * for screens that are not mounted yet. Later `Text3D` nodes reuse this catalog\n * and will not flash the source language.\n */\n sourceTexts?: string[];\n}\n\n@decorators.componentObserver({\n Text3D: [\n 'text',\n { prop: ['replacements'], deep: true },\n 'fontSize', 'color', 'anchorX', 'anchorY', 'maxWidth', 'font',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n ],\n})\nexport default class Text3DSystem extends Renderer3D<Text3DSystemParams> {\n static systemName = 'Text3DSystem';\n name: string = 'Text3DSystem';\n\n private texts = new Map<number, { mesh: TroikaText; component: Text3D }>();\n private poseBridges = new Map<number, VisualPoseBridge>();\n private sourceLocale = '';\n private targetLocale = '';\n private translations: TextTranslations = {};\n private seededSourceTexts = new Set<string>();\n private lastRequestedSourceTexts = '';\n private i18nRequestScheduled = false;\n private i18nRequestId = 0;\n private firstI18nSettled = false;\n private i18nNeeded = false;\n private resolvedSourceTexts = new Set<string>();\n\n init(params?: Text3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n this.sourceLocale = params?.sourceLocale?.trim() ?? '';\n this.targetLocale = this.sourceLocale;\n this.declareSourceTexts(params?.sourceTexts);\n }\n\n /** Register extra source templates before or after ready. First request includes these. */\n declareSourceTexts(texts?: string[]) {\n addSourceTexts(this.seededSourceTexts, texts);\n this.scheduleI18nRequest();\n }\n\n async beforeReady() {\n if (this.firstI18nSettled) return;\n this.update();\n if (!this.sourceLocale) {\n this.firstI18nSettled = true;\n return;\n }\n await this.requestI18nAndApply();\n if (\n this.i18nNeeded &&\n hasMissingSourceTranslations(this.collectSourceTexts(), this.translations)\n ) {\n await this.requestI18nAndApply();\n }\n this.firstI18nSettled = true;\n }\n\n setI18n(locale: string, translations: TextTranslations) {\n const targetLocale = locale?.trim();\n if (!targetLocale || !translations || typeof translations !== 'object') return;\n this.targetLocale = targetLocale;\n this.translations = mergeTranslations(this.translations, translations);\n this.refreshAllText();\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Text3D') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, changed.component as Text3D);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.handleRemove(changed.gameObject.id);\n } else {\n this.handleChange(changed);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Text3D) as Text3D;\n if (!component) return;\n\n const entry = this.texts.get(gameObject.id);\n if (!entry) return;\n this.applyPose(gameObject, component, entry.mesh);\n }\n\n private handleAdd(gameObject: GameObject, component: Text3D) {\n const textMesh = new TroikaText();\n this.syncTextProps(textMesh, component);\n textMesh.sync();\n tagObject3D(textMesh, gameObject.id);\n\n this.threeContext.attachVisual(gameObject.id, textMesh, gameObject);\n this.texts.set(gameObject.id, { mesh: textMesh, component });\n this.poseBridges.set(gameObject.id, new VisualPoseBridge());\n this.scheduleI18nRequest();\n }\n\n private handleChange(changed: ComponentChanged) {\n const entry = this.texts.get(changed.gameObject.id);\n if (!entry) return;\n const component = changed.component as Text3D;\n entry.component = component;\n this.syncTextProps(entry.mesh, component);\n entry.mesh.sync();\n if (changed.prop.prop[0] === 'text') this.scheduleI18nRequest();\n }\n\n private handleRemove(id: number) {\n const entry = this.texts.get(id);\n if (!entry) return;\n\n this.threeContext.detachVisual(id, entry.mesh);\n entry.mesh.dispose();\n this.texts.delete(id);\n this.poseBridges.delete(id);\n }\n\n private syncTextProps(textMesh: TroikaText, component: Text3D) {\n textMesh.text = this.resolveText(component);\n textMesh.fontSize = component.fontSize;\n textMesh.color = component.color;\n textMesh.anchorX = component.anchorX;\n textMesh.anchorY = component.anchorY;\n if (component.maxWidth > 0) {\n textMesh.maxWidth = component.maxWidth;\n }\n if (component.font) {\n textMesh.font = component.font;\n }\n }\n\n private applyPose(gameObject: GameObject, component: Text3D, textMesh: TroikaText) {\n let bridge = this.poseBridges.get(gameObject.id);\n if (!bridge) {\n bridge = new VisualPoseBridge();\n this.poseBridges.set(gameObject.id, bridge);\n }\n const transform = gameObject.getComponent(Transform3D) as Transform3D | undefined;\n if (!bridge.sync(component, transform)) {\n textMesh.position.set(0, 0, 0);\n textMesh.rotation.set(0, 0, 0);\n return;\n }\n textMesh.position.set(component.positionX, component.positionY, component.positionZ);\n textMesh.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n }\n\n onDestroy() {\n this.i18nRequestId += 1;\n this.firstI18nSettled = false;\n this.i18nNeeded = false;\n this.resolvedSourceTexts.clear();\n for (const [id] of this.texts) {\n this.handleRemove(id);\n }\n this.texts.clear();\n }\n\n private resolveText(component: Text3D): string {\n if (\n shouldHoldForMissingTranslation(component.text, this.translations, {\n sourceLocale: this.sourceLocale,\n targetLocale: this.targetLocale,\n i18nNeeded: this.i18nNeeded,\n firstI18nSettled: this.firstI18nSettled,\n resolvedSourceTexts: this.resolvedSourceTexts,\n })\n ) {\n return '';\n }\n return localizeText(\n component.text,\n component.replacements,\n this.sourceLocale,\n this.targetLocale,\n this.translations,\n );\n }\n\n private collectSourceTexts(): string[] {\n const sourceTexts = new Set(this.seededSourceTexts);\n for (const entry of this.texts.values()) {\n addSourceTexts(sourceTexts, [entry.component.text]);\n }\n return [...sourceTexts];\n }\n\n private scheduleI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled || this.i18nRequestScheduled) return;\n this.i18nRequestScheduled = true;\n queueMicrotask(() => {\n this.i18nRequestScheduled = false;\n this.startI18nRequest();\n });\n }\n\n private startI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled) return;\n const sourceTexts = this.collectSourceTexts();\n const signature = [...sourceTexts].sort().join('\\0');\n if (signature === this.lastRequestedSourceTexts) return;\n void this.requestI18nAndApply();\n }\n\n private async requestI18nAndApply() {\n const sourceTexts = this.collectSourceTexts();\n const signature = [...sourceTexts].sort().join('\\0');\n this.lastRequestedSourceTexts = signature;\n const requestId = ++this.i18nRequestId;\n const result = await requestHostI18n({\n sourceLocale: this.sourceLocale,\n sourceTexts,\n });\n if (requestId !== this.i18nRequestId) return;\n addSourceTexts(this.resolvedSourceTexts, sourceTexts);\n this.i18nNeeded = result.needed;\n if (!result.needed) {\n this.refreshAllText();\n return;\n }\n this.setI18n(result.locale, result.translations);\n }\n\n private refreshAllText() {\n for (const entry of this.texts.values()) {\n entry.mesh.text = this.resolveText(entry.component);\n entry.mesh.sync();\n }\n }\n}\n"],"names":["TroikaText"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin-renderer-3d-text.esm.js","sources":["../lib/component.ts","../lib/hostSdk.ts","../lib/localization.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\nimport type { TextReplacements } from './localization';\n\nexport type { TextReplacementValue, TextReplacements } from './localization';\n\nexport interface Text3DParams {\n text?: string;\n /** Values substituted into named placeholders such as `{score}`. */\n replacements?: TextReplacements;\n fontSize?: number;\n color?: number;\n anchorX?: string;\n anchorY?: string;\n maxWidth?: number;\n font?: string;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n}\n\nexport default class Text3D extends Component<Text3DParams> {\n static componentName: string = 'Text3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Text3D',\n\n label: 'text',\n\n description: 'Visible text content.',\n\n editor: 'text',\n\n })\n\n text: string = '';\n\n replacements: TextReplacements = {};\n\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'fontSize',\n description: 'Font size.',\n editor: 'number-stepper',\n })\n fontSize: number = 0.5;\n @Field({\n type: 'number',\n group: 'Text3D',\n label: 'color',\n description: 'Color value.',\n editor: 'number-stepper',\n })\n color: number = 0xffffff;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorX',\n description: 'Horizontal text anchor.',\n editor: 'text',\n })\n anchorX: string = 'center';\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'anchorY',\n description: 'Vertical text anchor.',\n editor: 'text',\n })\n anchorY: string = 'middle';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'maxWidth',\n description: 'Maximum text wrap width.',\n editor: 'number-stepper',\n })\n maxWidth: number = 0;\n @Field({\n type: 'string',\n group: 'Text3D',\n label: 'font',\n description: 'Font URL or path for troika-three-text (not an engine resource name).',\n editor: 'text',\n })\n font: string = '';\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Text3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Text3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n\n init(obj?: Text3DParams) {\n if (!obj) return;\n const { replacements, ...rest } = obj;\n Object.assign(this, rest);\n if (replacements) this.replacements = { ...replacements };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` hostSdk. */\nimport type { TextTranslations } from './localization';\n\n/** Host-injected global. The SDK itself is not part of this repo. */\nexport const COMBOS_HOST_SDK = 'combos' as const;\n\nexport interface CombosI18nRequest {\n sourceLocale: string;\n sourceTexts: string[];\n}\n\nexport type CombosI18nResult =\n | { needed: false }\n | { needed: true; locale: string; translations: TextTranslations };\n\nexport interface CombosHostSdk {\n requestI18n?(request: CombosI18nRequest): Promise<CombosI18nResult>;\n}\n\ndeclare global {\n interface Window {\n combos?: CombosHostSdk;\n }\n}\n\nexport function hasCombosRequestI18n(\n sdk: CombosHostSdk | undefined | null = typeof window === 'undefined' ? undefined : window.combos,\n): sdk is CombosHostSdk & { requestI18n: NonNullable<CombosHostSdk['requestI18n']> } {\n return !!sdk && typeof sdk.requestI18n === 'function';\n}\n\nexport function parseI18nResult(data: unknown): CombosI18nResult {\n if (!data || typeof data !== 'object') return { needed: false };\n const input = data as {\n needed?: unknown;\n locale?: unknown;\n translations?: unknown;\n };\n if (input.needed !== true) return { needed: false };\n if (typeof input.locale !== 'string' || !input.locale.trim()) {\n return { needed: false };\n }\n if (\n !input.translations ||\n typeof input.translations !== 'object' ||\n Array.isArray(input.translations)\n ) {\n return { needed: false };\n }\n const entries = Object.entries(input.translations);\n if (entries.some(([, value]) => typeof value !== 'string')) {\n return { needed: false };\n }\n return {\n needed: true,\n locale: input.locale.trim(),\n translations: Object.fromEntries(entries) as TextTranslations,\n };\n}\n\n/** Ask the injected host SDK. Always resolves; missing method means no translation. */\nexport async function requestHostI18n(\n request: CombosI18nRequest,\n): Promise<CombosI18nResult> {\n if (typeof window === 'undefined' || !hasCombosRequestI18n(window.combos)) {\n return { needed: false };\n }\n try {\n return parseI18nResult(await window.combos.requestI18n(request));\n } catch {\n return { needed: false };\n }\n}\n","/** Keep identical to `@combos-fun/plugin-renderer-text` localization. */\n\nexport type TextReplacementValue = string | number;\nexport type TextReplacements = Record<string, TextReplacementValue>;\nexport type TextTranslations = Record<string, string>;\n\nconst PLACEHOLDER_PATTERN = /\\{([A-Za-z_$][\\w$.-]*)\\}/g;\n\nexport function interpolateText(\n template: string,\n replacements?: TextReplacements,\n): string {\n if (!replacements) return template;\n return template.replace(PLACEHOLDER_PATTERN, (placeholder, name: string) => {\n if (!Object.prototype.hasOwnProperty.call(replacements, name)) {\n return placeholder;\n }\n return String(replacements[name]);\n });\n}\n\nexport function findTranslatedTemplate(\n sourceText: string,\n translations: TextTranslations,\n): string | undefined {\n if (Object.prototype.hasOwnProperty.call(translations, sourceText)) {\n return translations[sourceText];\n }\n const trimmed = sourceText.trim();\n if (\n trimmed &&\n trimmed !== sourceText &&\n Object.prototype.hasOwnProperty.call(translations, trimmed)\n ) {\n return translations[trimmed];\n }\n return undefined;\n}\n\nexport function hasSourceTranslation(\n sourceText: string,\n translations: TextTranslations,\n): boolean {\n return findTranslatedTemplate(sourceText, translations) !== undefined;\n}\n\nexport function hasMissingSourceTranslations(\n sourceTexts: readonly string[],\n translations: TextTranslations,\n): boolean {\n return sourceTexts.some((text) => !hasSourceTranslation(text, translations));\n}\n\nexport function sourceTextsSignature(sourceTexts: readonly string[]): string {\n return [...sourceTexts].sort().join('\\0');\n}\n\n/** After the first host reply, only request again for templates still missing. */\nexport function shouldRequestI18nForSourceTexts(\n sourceTexts: readonly string[],\n translations: TextTranslations,\n state: {\n i18nNeeded: boolean;\n lastRequestedSourceTexts: string;\n },\n): boolean {\n if (!state.i18nNeeded) return false;\n if (!hasMissingSourceTranslations(sourceTexts, translations)) return false;\n return sourceTextsSignature(sourceTexts) !== state.lastRequestedSourceTexts;\n}\n\nexport function shouldHoldForMissingTranslation(\n sourceText: string,\n translations: TextTranslations,\n state: {\n sourceLocale: string;\n targetLocale: string;\n i18nNeeded: boolean;\n firstI18nSettled: boolean;\n resolvedSourceTexts: ReadonlySet<string>;\n },\n): boolean {\n if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled) return false;\n if (state.sourceLocale.toLowerCase() === state.targetLocale.toLowerCase()) return false;\n const trimmed = sourceText.trim();\n if (!trimmed) return false;\n if (hasSourceTranslation(sourceText, translations)) return false;\n return !state.resolvedSourceTexts.has(trimmed);\n}\n\nexport function localizeText(\n sourceText: string,\n replacements: TextReplacements | undefined,\n sourceLocale: string,\n targetLocale: string,\n translations: TextTranslations,\n): string {\n const shouldTranslate =\n !!sourceLocale &&\n !!targetLocale &&\n sourceLocale.toLowerCase() !== targetLocale.toLowerCase();\n const template = shouldTranslate\n ? findTranslatedTemplate(sourceText, translations) ?? sourceText\n : sourceText;\n return interpolateText(template, replacements);\n}\n\nexport function addSourceTexts(\n target: Set<string>,\n texts?: Iterable<string | undefined | null>,\n) {\n if (!texts) return;\n for (const text of texts) {\n const source = typeof text === 'string' ? text.trim() : '';\n if (source) target.add(source);\n }\n}\n\nexport function mergeTranslations(\n current: TextTranslations,\n incoming: Record<string, unknown>,\n): TextTranslations {\n const next = { ...current };\n for (const [key, value] of Object.entries(incoming)) {\n if (typeof value === 'string') next[key] = value;\n }\n return next;\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport { Renderer3D, Renderer3DSystem, tagObject3D, Transform3D, VisualPoseBridge } from '@combos-fun/plugin-renderer-3d';\nimport { Text as TroikaText } from 'troika-three-text';\nimport Text3D from './component';\nimport { requestHostI18n } from './hostSdk';\nimport {\n addSourceTexts,\n hasMissingSourceTranslations,\n localizeText,\n mergeTranslations,\n shouldHoldForMissingTranslation,\n shouldRequestI18nForSourceTexts,\n sourceTextsSignature,\n type TextTranslations,\n} from './localization';\n\nexport interface Text3DSystemParams {\n /** BCP 47 locale of the source text, for example `zh-CN`. Omit to disable host-driven i18n. */\n sourceLocale?: string;\n /**\n * All source templates to translate on first `requestI18n`, including copy\n * for screens that are not mounted yet. The system also keeps a growing\n * session catalog of every later template it sees.\n */\n sourceTexts?: string[];\n}\n\n@decorators.componentObserver({\n Text3D: [\n 'text',\n { prop: ['replacements'], deep: true },\n 'fontSize', 'color', 'anchorX', 'anchorY', 'maxWidth', 'font',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n ],\n})\nexport default class Text3DSystem extends Renderer3D<Text3DSystemParams> {\n static systemName = 'Text3DSystem';\n name: string = 'Text3DSystem';\n\n private texts = new Map<number, { mesh: TroikaText; component: Text3D }>();\n private poseBridges = new Map<number, VisualPoseBridge>();\n private sourceLocale = '';\n private targetLocale = '';\n private translations: TextTranslations = {};\n /** Growing catalog of every source template seen this session. */\n private knownSourceTexts = new Set<string>();\n private lastRequestedSourceTexts = '';\n private i18nRequestScheduled = false;\n private i18nRequestId = 0;\n private firstI18nSettled = false;\n private i18nNeeded = false;\n private resolvedSourceTexts = new Set<string>();\n\n init(params?: Text3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n this.sourceLocale = params?.sourceLocale?.trim() ?? '';\n this.targetLocale = this.sourceLocale;\n this.declareSourceTexts(params?.sourceTexts);\n }\n\n /** Register extra source templates before or after ready. First request includes these. */\n declareSourceTexts(texts?: string[]) {\n this.rememberSourceTexts(texts);\n this.scheduleI18nRequest();\n }\n\n async beforeReady() {\n if (this.firstI18nSettled) return;\n this.update();\n if (!this.sourceLocale) {\n this.firstI18nSettled = true;\n return;\n }\n await this.requestI18nAndApply();\n if (\n this.i18nNeeded &&\n hasMissingSourceTranslations(this.collectSourceTexts(), this.translations)\n ) {\n await this.requestI18nAndApply();\n }\n this.firstI18nSettled = true;\n }\n\n setI18n(locale: string, translations: TextTranslations) {\n const targetLocale = locale?.trim();\n if (!targetLocale || !translations || typeof translations !== 'object') return;\n this.targetLocale = targetLocale;\n this.translations = mergeTranslations(this.translations, translations);\n this.refreshAllText();\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Text3D') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, changed.component as Text3D);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.handleRemove(changed.gameObject.id);\n } else {\n this.handleChange(changed);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Text3D) as Text3D;\n if (!component) return;\n\n const entry = this.texts.get(gameObject.id);\n if (!entry) return;\n this.applyPose(gameObject, component, entry.mesh);\n }\n\n private handleAdd(gameObject: GameObject, component: Text3D) {\n const textMesh = new TroikaText();\n this.syncTextProps(textMesh, component);\n textMesh.sync();\n tagObject3D(textMesh, gameObject.id);\n\n this.threeContext.attachVisual(gameObject.id, textMesh, gameObject);\n this.texts.set(gameObject.id, { mesh: textMesh, component });\n this.poseBridges.set(gameObject.id, new VisualPoseBridge());\n this.rememberSourceTexts([component.text]);\n this.scheduleI18nRequest();\n }\n\n private handleChange(changed: ComponentChanged) {\n const entry = this.texts.get(changed.gameObject.id);\n if (!entry) return;\n const component = changed.component as Text3D;\n entry.component = component;\n if (changed.prop.prop[0] === 'text') this.rememberSourceTexts([component.text]);\n this.syncTextProps(entry.mesh, component);\n entry.mesh.sync();\n if (changed.prop.prop[0] === 'text') this.scheduleI18nRequest();\n }\n\n private handleRemove(id: number) {\n const entry = this.texts.get(id);\n if (!entry) return;\n\n this.threeContext.detachVisual(id, entry.mesh);\n entry.mesh.dispose();\n this.texts.delete(id);\n this.poseBridges.delete(id);\n }\n\n private syncTextProps(textMesh: TroikaText, component: Text3D) {\n textMesh.text = this.resolveText(component);\n textMesh.fontSize = component.fontSize;\n textMesh.color = component.color;\n textMesh.anchorX = component.anchorX;\n textMesh.anchorY = component.anchorY;\n if (component.maxWidth > 0) {\n textMesh.maxWidth = component.maxWidth;\n }\n if (component.font) {\n textMesh.font = component.font;\n }\n }\n\n private applyPose(gameObject: GameObject, component: Text3D, textMesh: TroikaText) {\n let bridge = this.poseBridges.get(gameObject.id);\n if (!bridge) {\n bridge = new VisualPoseBridge();\n this.poseBridges.set(gameObject.id, bridge);\n }\n const transform = gameObject.getComponent(Transform3D) as Transform3D | undefined;\n if (!bridge.sync(component, transform)) {\n textMesh.position.set(0, 0, 0);\n textMesh.rotation.set(0, 0, 0);\n return;\n }\n textMesh.position.set(component.positionX, component.positionY, component.positionZ);\n textMesh.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n }\n\n onDestroy() {\n this.i18nRequestId += 1;\n this.firstI18nSettled = false;\n this.i18nNeeded = false;\n this.resolvedSourceTexts.clear();\n for (const [id] of this.texts) {\n this.handleRemove(id);\n }\n this.texts.clear();\n }\n\n private resolveText(component: Text3D): string {\n if (\n shouldHoldForMissingTranslation(component.text, this.translations, {\n sourceLocale: this.sourceLocale,\n targetLocale: this.targetLocale,\n i18nNeeded: this.i18nNeeded,\n firstI18nSettled: this.firstI18nSettled,\n resolvedSourceTexts: this.resolvedSourceTexts,\n })\n ) {\n return '';\n }\n return localizeText(\n component.text,\n component.replacements,\n this.sourceLocale,\n this.targetLocale,\n this.translations,\n );\n }\n\n private rememberSourceTexts(texts?: Iterable<string | undefined | null>) {\n addSourceTexts(this.knownSourceTexts, texts);\n }\n\n private collectSourceTexts(): string[] {\n for (const entry of this.texts.values()) {\n this.rememberSourceTexts([entry.component.text]);\n }\n return [...this.knownSourceTexts];\n }\n\n private scheduleI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled || this.i18nRequestScheduled) return;\n this.i18nRequestScheduled = true;\n queueMicrotask(() => {\n this.i18nRequestScheduled = false;\n this.startI18nRequest();\n });\n }\n\n private startI18nRequest() {\n if (!this.sourceLocale || !this.firstI18nSettled) return;\n const sourceTexts = this.collectSourceTexts();\n if (\n !shouldRequestI18nForSourceTexts(sourceTexts, this.translations, {\n i18nNeeded: this.i18nNeeded,\n lastRequestedSourceTexts: this.lastRequestedSourceTexts,\n })\n ) {\n return;\n }\n void this.requestI18nAndApply();\n }\n\n private async requestI18nAndApply() {\n const sourceTexts = this.collectSourceTexts();\n this.lastRequestedSourceTexts = sourceTextsSignature(sourceTexts);\n const requestId = ++this.i18nRequestId;\n const result = await requestHostI18n({\n sourceLocale: this.sourceLocale,\n sourceTexts,\n });\n if (requestId !== this.i18nRequestId) return;\n addSourceTexts(this.resolvedSourceTexts, sourceTexts);\n this.i18nNeeded = result.needed;\n if (!result.needed) {\n this.refreshAllText();\n return;\n }\n this.setI18n(result.locale, result.translations);\n }\n\n private refreshAllText() {\n for (const entry of this.texts.values()) {\n entry.mesh.text = this.resolveText(entry.component);\n entry.mesh.sync();\n }\n }\n}\n"],"names":["TroikaText"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@combos-fun/plugin-renderer-3d-text",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "3D text rendering, backed by troika-three-text",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/plugin-renderer-3d-text.esm.js",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"three": "^0.172.0",
|
|
30
30
|
"troika-three-text": "^0.52.3",
|
|
31
|
-
"@combos-fun/
|
|
32
|
-
"@combos-fun/
|
|
33
|
-
"@combos-fun/
|
|
31
|
+
"@combos-fun/engine": "0.1.8",
|
|
32
|
+
"@combos-fun/inspector-decorator": "0.1.8",
|
|
33
|
+
"@combos-fun/plugin-renderer-3d": "0.1.8"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"tsx": "^4.20.3"
|