@combos-fun/plugin-renderer-3d-text 0.1.5 → 0.1.7
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 -3
- package/agent-skill.md +9 -5
- package/dist/plugin-renderer-3d-text.cjs.js +58 -3
- 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 +13 -1
- package/dist/plugin-renderer-3d-text.esm.js +55 -4
- package/dist/plugin-renderer-3d-text.esm.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -52,9 +52,11 @@ 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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
If the host returns `needed: true` but a template is missing from
|
|
56
|
+
`translations`, the system merges all current texts and waits for one more
|
|
57
|
+
`requestI18n` before showing that label. Translation is applied only when
|
|
58
|
+
the result is `needed: true`. Without the injected SDK, the game stays on
|
|
59
|
+
the source text.
|
|
58
60
|
|
|
59
61
|
## License
|
|
60
62
|
|
package/agent-skill.md
CHANGED
|
@@ -40,11 +40,15 @@ reuse that cache and do not flash the source language. You can also call
|
|
|
40
40
|
The source template itself is the translation lookup key. After labels exist,
|
|
41
41
|
the system checks that `window.combos.requestI18n` exists. The first
|
|
42
42
|
`requestI18n({ sourceLocale, sourceTexts })` runs in `beforeReady` and holds
|
|
43
|
-
game `ready` / `start` until the host replies.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
game `ready` / `start` until the host replies. Apply the result only when
|
|
44
|
+
`needed: true`. If that reply is `needed: true` but a current template is
|
|
45
|
+
missing from `translations`, merge every seeded and mounted template and
|
|
46
|
+
`requestI18n` once more before `ready`. After ready, a new label whose
|
|
47
|
+
translation is still missing stays empty, merges all current templates, waits
|
|
48
|
+
for one more `requestI18n`, then renders. `needed: false` keeps source text
|
|
49
|
+
and does not hold later labels. Do not post `i18n-ready` / `set-i18n` from
|
|
50
|
+
this plugin. If no source locale or method is present, placeholder replacement
|
|
51
|
+
still works and source text stays as-is.
|
|
48
52
|
|
|
49
53
|
## Parameters
|
|
50
54
|
|
|
@@ -214,12 +214,42 @@ function interpolateText(template, replacements) {
|
|
|
214
214
|
return String(replacements[name]);
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
|
+
function findTranslatedTemplate(sourceText, translations) {
|
|
218
|
+
if (Object.prototype.hasOwnProperty.call(translations, sourceText)) {
|
|
219
|
+
return translations[sourceText];
|
|
220
|
+
}
|
|
221
|
+
const trimmed = sourceText.trim();
|
|
222
|
+
if (trimmed &&
|
|
223
|
+
trimmed !== sourceText &&
|
|
224
|
+
Object.prototype.hasOwnProperty.call(translations, trimmed)) {
|
|
225
|
+
return translations[trimmed];
|
|
226
|
+
}
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
function hasSourceTranslation(sourceText, translations) {
|
|
230
|
+
return findTranslatedTemplate(sourceText, translations) !== undefined;
|
|
231
|
+
}
|
|
232
|
+
function hasMissingSourceTranslations(sourceTexts, translations) {
|
|
233
|
+
return sourceTexts.some((text) => !hasSourceTranslation(text, translations));
|
|
234
|
+
}
|
|
235
|
+
function shouldHoldForMissingTranslation(sourceText, translations, state) {
|
|
236
|
+
if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled)
|
|
237
|
+
return false;
|
|
238
|
+
if (state.sourceLocale.toLowerCase() === state.targetLocale.toLowerCase())
|
|
239
|
+
return false;
|
|
240
|
+
const trimmed = sourceText.trim();
|
|
241
|
+
if (!trimmed)
|
|
242
|
+
return false;
|
|
243
|
+
if (hasSourceTranslation(sourceText, translations))
|
|
244
|
+
return false;
|
|
245
|
+
return !state.resolvedSourceTexts.has(trimmed);
|
|
246
|
+
}
|
|
217
247
|
function localizeText(sourceText, replacements, sourceLocale, targetLocale, translations) {
|
|
218
248
|
const shouldTranslate = !!sourceLocale &&
|
|
219
249
|
!!targetLocale &&
|
|
220
250
|
sourceLocale.toLowerCase() !== targetLocale.toLowerCase();
|
|
221
|
-
const template = shouldTranslate
|
|
222
|
-
? translations
|
|
251
|
+
const template = shouldTranslate
|
|
252
|
+
? findTranslatedTemplate(sourceText, translations) ?? sourceText
|
|
223
253
|
: sourceText;
|
|
224
254
|
return interpolateText(template, replacements);
|
|
225
255
|
}
|
|
@@ -255,6 +285,8 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
255
285
|
this.i18nRequestScheduled = false;
|
|
256
286
|
this.i18nRequestId = 0;
|
|
257
287
|
this.firstI18nSettled = false;
|
|
288
|
+
this.i18nNeeded = false;
|
|
289
|
+
this.resolvedSourceTexts = new Set();
|
|
258
290
|
}
|
|
259
291
|
static { this.systemName = 'Text3DSystem'; }
|
|
260
292
|
init(params) {
|
|
@@ -278,6 +310,10 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
278
310
|
return;
|
|
279
311
|
}
|
|
280
312
|
await this.requestI18nAndApply();
|
|
313
|
+
if (this.i18nNeeded &&
|
|
314
|
+
hasMissingSourceTranslations(this.collectSourceTexts(), this.translations)) {
|
|
315
|
+
await this.requestI18nAndApply();
|
|
316
|
+
}
|
|
281
317
|
this.firstI18nSettled = true;
|
|
282
318
|
}
|
|
283
319
|
setI18n(locale, translations) {
|
|
@@ -371,12 +407,23 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
371
407
|
onDestroy() {
|
|
372
408
|
this.i18nRequestId += 1;
|
|
373
409
|
this.firstI18nSettled = false;
|
|
410
|
+
this.i18nNeeded = false;
|
|
411
|
+
this.resolvedSourceTexts.clear();
|
|
374
412
|
for (const [id] of this.texts) {
|
|
375
413
|
this.handleRemove(id);
|
|
376
414
|
}
|
|
377
415
|
this.texts.clear();
|
|
378
416
|
}
|
|
379
417
|
resolveText(component) {
|
|
418
|
+
if (shouldHoldForMissingTranslation(component.text, this.translations, {
|
|
419
|
+
sourceLocale: this.sourceLocale,
|
|
420
|
+
targetLocale: this.targetLocale,
|
|
421
|
+
i18nNeeded: this.i18nNeeded,
|
|
422
|
+
firstI18nSettled: this.firstI18nSettled,
|
|
423
|
+
resolvedSourceTexts: this.resolvedSourceTexts,
|
|
424
|
+
})) {
|
|
425
|
+
return '';
|
|
426
|
+
}
|
|
380
427
|
return localizeText(component.text, component.replacements, this.sourceLocale, this.targetLocale, this.translations);
|
|
381
428
|
}
|
|
382
429
|
collectSourceTexts() {
|
|
@@ -415,8 +462,12 @@ let Text3DSystem = class Text3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
415
462
|
});
|
|
416
463
|
if (requestId !== this.i18nRequestId)
|
|
417
464
|
return;
|
|
418
|
-
|
|
465
|
+
addSourceTexts(this.resolvedSourceTexts, sourceTexts);
|
|
466
|
+
this.i18nNeeded = result.needed;
|
|
467
|
+
if (!result.needed) {
|
|
468
|
+
this.refreshAllText();
|
|
419
469
|
return;
|
|
470
|
+
}
|
|
420
471
|
this.setI18n(result.locale, result.translations);
|
|
421
472
|
}
|
|
422
473
|
refreshAllText() {
|
|
@@ -443,10 +494,14 @@ exports.COMBOS_HOST_SDK = COMBOS_HOST_SDK;
|
|
|
443
494
|
exports.Text3D = Text3D;
|
|
444
495
|
exports.Text3DSystem = Text3DSystem_default;
|
|
445
496
|
exports.addSourceTexts = addSourceTexts;
|
|
497
|
+
exports.findTranslatedTemplate = findTranslatedTemplate;
|
|
446
498
|
exports.hasCombosRequestI18n = hasCombosRequestI18n;
|
|
499
|
+
exports.hasMissingSourceTranslations = hasMissingSourceTranslations;
|
|
500
|
+
exports.hasSourceTranslation = hasSourceTranslation;
|
|
447
501
|
exports.interpolateText = interpolateText;
|
|
448
502
|
exports.localizeText = localizeText;
|
|
449
503
|
exports.mergeTranslations = mergeTranslations;
|
|
450
504
|
exports.parseI18nResult = parseI18nResult;
|
|
451
505
|
exports.requestHostI18n = requestHostI18n;
|
|
506
|
+
exports.shouldHoldForMissingTranslation = shouldHoldForMissingTranslation;
|
|
452
507
|
//# 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 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 =\n shouldTranslate && Object.prototype.hasOwnProperty.call(translations, sourceText)\n ? 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 localizeText,\n mergeTranslations,\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\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 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 for (const [id] of this.texts) {\n this.handleRemove(id);\n }\n this.texts.clear();\n }\n\n private resolveText(component: Text3D): string {\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 if (!result.needed) return;\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 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 +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"),
|
|
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 h(e,t){return void 0!==l(e,t)}function u(e,t){return e.some(e=>!h(e,t))}function x(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&&(!h(e,t)&&!o.resolvedSourceTexts.has(s))}function m(e,t,o,s,r){return p(!!o&&!!s&&o.toLowerCase()!==s.toLowerCase()?l(e,r)??e:e,t)}function f(e,t){if(t)for(const o of t){const t="string"==typeof o?o.trim():"";t&&e.add(t)}}function y(e,t){const o={...e};for(const[e,s]of Object.entries(t))"string"==typeof s&&(o[e]=s);return o}let T=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.seededSourceTexts=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){f(this.seededSourceTexts,e),this.scheduleI18nRequest()}async beforeReady(){this.firstI18nSettled||(this.update(),this.sourceLocale?(await this.requestI18nAndApply(),this.i18nNeeded&&u(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=y(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.scheduleI18nRequest()}handleChange(e){const t=this.texts.get(e.gameObject.id);if(!t)return;const o=e.component;t.component=o,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 x(e.text,this.translations,{sourceLocale:this.sourceLocale,targetLocale:this.targetLocale,i18nNeeded:this.i18nNeeded,firstI18nSettled:this.firstI18nSettled,resolvedSourceTexts:this.resolvedSourceTexts})?"":m(e.text,e.replacements,this.sourceLocale,this.targetLocale,this.translations)}collectSourceTexts(){const e=new Set(this.seededSourceTexts);for(const t of this.texts.values())f(e,[t.component.text]);return[...e]}scheduleI18nRequest(){this.sourceLocale&&this.firstI18nSettled&&!this.i18nRequestScheduled&&(this.i18nRequestScheduled=!0,queueMicrotask(()=>{this.i18nRequestScheduled=!1,this.startI18nRequest()}))}startI18nRequest(){if(!this.sourceLocale||!this.firstI18nSettled)return;[...this.collectSourceTexts()].sort().join("\0")!==this.lastRequestedSourceTexts&&this.requestI18nAndApply()}async requestI18nAndApply(){const e=this.collectSourceTexts(),t=[...e].sort().join("\0");this.lastRequestedSourceTexts=t;const o=++this.i18nRequestId,s=await c({sourceLocale:this.sourceLocale,sourceTexts:e});o===this.i18nRequestId&&(f(this.resolvedSourceTexts,e),this.i18nNeeded=s.needed,s.needed?this.setI18n(s.locale,s.translations):this.refreshAllText())}refreshAllText(){for(const e of this.texts.values())e.mesh.text=this.resolveText(e.component),e.mesh.sync()}};T=e.__decorate([t.decorators.componentObserver({Text3D:["text",{prop:["replacements"],deep:!0},"fontSize","color","anchorX","anchorY","maxWidth","font","positionX","positionY","positionZ","rotationX","rotationY","rotationZ"]})],T);var g=T;exports.COMBOS_HOST_SDK="combos",exports.Text3D=i,exports.Text3DSystem=g,exports.addSourceTexts=f,exports.findTranslatedTemplate=l,exports.hasCombosRequestI18n=n,exports.hasMissingSourceTranslations=u,exports.hasSourceTranslation=h,exports.interpolateText=p,exports.localizeText=m,exports.mergeTranslations=y,exports.parseI18nResult=a,exports.requestHostI18n=c,exports.shouldHoldForMissingTranslation=x;
|
|
@@ -6,6 +6,16 @@ type TextReplacementValue = string | number;
|
|
|
6
6
|
type TextReplacements = Record<string, TextReplacementValue>;
|
|
7
7
|
type TextTranslations = Record<string, string>;
|
|
8
8
|
declare function interpolateText(template: string, replacements?: TextReplacements): string;
|
|
9
|
+
declare function findTranslatedTemplate(sourceText: string, translations: TextTranslations): string | undefined;
|
|
10
|
+
declare function hasSourceTranslation(sourceText: string, translations: TextTranslations): boolean;
|
|
11
|
+
declare function hasMissingSourceTranslations(sourceTexts: readonly string[], translations: TextTranslations): boolean;
|
|
12
|
+
declare function shouldHoldForMissingTranslation(sourceText: string, translations: TextTranslations, state: {
|
|
13
|
+
sourceLocale: string;
|
|
14
|
+
targetLocale: string;
|
|
15
|
+
i18nNeeded: boolean;
|
|
16
|
+
firstI18nSettled: boolean;
|
|
17
|
+
resolvedSourceTexts: ReadonlySet<string>;
|
|
18
|
+
}): boolean;
|
|
9
19
|
declare function localizeText(sourceText: string, replacements: TextReplacements | undefined, sourceLocale: string, targetLocale: string, translations: TextTranslations): string;
|
|
10
20
|
declare function addSourceTexts(target: Set<string>, texts?: Iterable<string | undefined | null>): void;
|
|
11
21
|
declare function mergeTranslations(current: TextTranslations, incoming: Record<string, unknown>): TextTranslations;
|
|
@@ -69,6 +79,8 @@ declare class Text3DSystem extends Renderer3D<Text3DSystemParams> {
|
|
|
69
79
|
private i18nRequestScheduled;
|
|
70
80
|
private i18nRequestId;
|
|
71
81
|
private firstI18nSettled;
|
|
82
|
+
private i18nNeeded;
|
|
83
|
+
private resolvedSourceTexts;
|
|
72
84
|
init(params?: Text3DSystemParams): void;
|
|
73
85
|
/** Register extra source templates before or after ready. First request includes these. */
|
|
74
86
|
declareSourceTexts(texts?: string[]): void;
|
|
@@ -120,5 +132,5 @@ declare function parseI18nResult(data: unknown): CombosI18nResult;
|
|
|
120
132
|
/** Ask the injected host SDK. Always resolves; missing method means no translation. */
|
|
121
133
|
declare function requestHostI18n(request: CombosI18nRequest): Promise<CombosI18nResult>;
|
|
122
134
|
|
|
123
|
-
export { COMBOS_HOST_SDK, Text3D, Text3DSystem, addSourceTexts, hasCombosRequestI18n, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n };
|
|
135
|
+
export { COMBOS_HOST_SDK, Text3D, Text3DSystem, addSourceTexts, findTranslatedTemplate, hasCombosRequestI18n, hasMissingSourceTranslations, hasSourceTranslation, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n, shouldHoldForMissingTranslation };
|
|
124
136
|
export type { CombosHostSdk, CombosI18nRequest, CombosI18nResult, Text3DParams, Text3DSystemParams, TextReplacementValue, TextReplacements, TextTranslations };
|
|
@@ -212,12 +212,42 @@ function interpolateText(template, replacements) {
|
|
|
212
212
|
return String(replacements[name]);
|
|
213
213
|
});
|
|
214
214
|
}
|
|
215
|
+
function findTranslatedTemplate(sourceText, translations) {
|
|
216
|
+
if (Object.prototype.hasOwnProperty.call(translations, sourceText)) {
|
|
217
|
+
return translations[sourceText];
|
|
218
|
+
}
|
|
219
|
+
const trimmed = sourceText.trim();
|
|
220
|
+
if (trimmed &&
|
|
221
|
+
trimmed !== sourceText &&
|
|
222
|
+
Object.prototype.hasOwnProperty.call(translations, trimmed)) {
|
|
223
|
+
return translations[trimmed];
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
function hasSourceTranslation(sourceText, translations) {
|
|
228
|
+
return findTranslatedTemplate(sourceText, translations) !== undefined;
|
|
229
|
+
}
|
|
230
|
+
function hasMissingSourceTranslations(sourceTexts, translations) {
|
|
231
|
+
return sourceTexts.some((text) => !hasSourceTranslation(text, translations));
|
|
232
|
+
}
|
|
233
|
+
function shouldHoldForMissingTranslation(sourceText, translations, state) {
|
|
234
|
+
if (!state.sourceLocale || !state.i18nNeeded || !state.firstI18nSettled)
|
|
235
|
+
return false;
|
|
236
|
+
if (state.sourceLocale.toLowerCase() === state.targetLocale.toLowerCase())
|
|
237
|
+
return false;
|
|
238
|
+
const trimmed = sourceText.trim();
|
|
239
|
+
if (!trimmed)
|
|
240
|
+
return false;
|
|
241
|
+
if (hasSourceTranslation(sourceText, translations))
|
|
242
|
+
return false;
|
|
243
|
+
return !state.resolvedSourceTexts.has(trimmed);
|
|
244
|
+
}
|
|
215
245
|
function localizeText(sourceText, replacements, sourceLocale, targetLocale, translations) {
|
|
216
246
|
const shouldTranslate = !!sourceLocale &&
|
|
217
247
|
!!targetLocale &&
|
|
218
248
|
sourceLocale.toLowerCase() !== targetLocale.toLowerCase();
|
|
219
|
-
const template = shouldTranslate
|
|
220
|
-
? translations
|
|
249
|
+
const template = shouldTranslate
|
|
250
|
+
? findTranslatedTemplate(sourceText, translations) ?? sourceText
|
|
221
251
|
: sourceText;
|
|
222
252
|
return interpolateText(template, replacements);
|
|
223
253
|
}
|
|
@@ -253,6 +283,8 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
253
283
|
this.i18nRequestScheduled = false;
|
|
254
284
|
this.i18nRequestId = 0;
|
|
255
285
|
this.firstI18nSettled = false;
|
|
286
|
+
this.i18nNeeded = false;
|
|
287
|
+
this.resolvedSourceTexts = new Set();
|
|
256
288
|
}
|
|
257
289
|
static { this.systemName = 'Text3DSystem'; }
|
|
258
290
|
init(params) {
|
|
@@ -276,6 +308,10 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
276
308
|
return;
|
|
277
309
|
}
|
|
278
310
|
await this.requestI18nAndApply();
|
|
311
|
+
if (this.i18nNeeded &&
|
|
312
|
+
hasMissingSourceTranslations(this.collectSourceTexts(), this.translations)) {
|
|
313
|
+
await this.requestI18nAndApply();
|
|
314
|
+
}
|
|
279
315
|
this.firstI18nSettled = true;
|
|
280
316
|
}
|
|
281
317
|
setI18n(locale, translations) {
|
|
@@ -369,12 +405,23 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
369
405
|
onDestroy() {
|
|
370
406
|
this.i18nRequestId += 1;
|
|
371
407
|
this.firstI18nSettled = false;
|
|
408
|
+
this.i18nNeeded = false;
|
|
409
|
+
this.resolvedSourceTexts.clear();
|
|
372
410
|
for (const [id] of this.texts) {
|
|
373
411
|
this.handleRemove(id);
|
|
374
412
|
}
|
|
375
413
|
this.texts.clear();
|
|
376
414
|
}
|
|
377
415
|
resolveText(component) {
|
|
416
|
+
if (shouldHoldForMissingTranslation(component.text, this.translations, {
|
|
417
|
+
sourceLocale: this.sourceLocale,
|
|
418
|
+
targetLocale: this.targetLocale,
|
|
419
|
+
i18nNeeded: this.i18nNeeded,
|
|
420
|
+
firstI18nSettled: this.firstI18nSettled,
|
|
421
|
+
resolvedSourceTexts: this.resolvedSourceTexts,
|
|
422
|
+
})) {
|
|
423
|
+
return '';
|
|
424
|
+
}
|
|
378
425
|
return localizeText(component.text, component.replacements, this.sourceLocale, this.targetLocale, this.translations);
|
|
379
426
|
}
|
|
380
427
|
collectSourceTexts() {
|
|
@@ -413,8 +460,12 @@ let Text3DSystem = class Text3DSystem extends Renderer3D {
|
|
|
413
460
|
});
|
|
414
461
|
if (requestId !== this.i18nRequestId)
|
|
415
462
|
return;
|
|
416
|
-
|
|
463
|
+
addSourceTexts(this.resolvedSourceTexts, sourceTexts);
|
|
464
|
+
this.i18nNeeded = result.needed;
|
|
465
|
+
if (!result.needed) {
|
|
466
|
+
this.refreshAllText();
|
|
417
467
|
return;
|
|
468
|
+
}
|
|
418
469
|
this.setI18n(result.locale, result.translations);
|
|
419
470
|
}
|
|
420
471
|
refreshAllText() {
|
|
@@ -437,5 +488,5 @@ Text3DSystem = __decorate([
|
|
|
437
488
|
], Text3DSystem);
|
|
438
489
|
var Text3DSystem_default = Text3DSystem;
|
|
439
490
|
|
|
440
|
-
export { COMBOS_HOST_SDK, Text3D, Text3DSystem_default as Text3DSystem, addSourceTexts, hasCombosRequestI18n, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n };
|
|
491
|
+
export { COMBOS_HOST_SDK, Text3D, Text3DSystem_default as Text3DSystem, addSourceTexts, findTranslatedTemplate, hasCombosRequestI18n, hasMissingSourceTranslations, hasSourceTranslation, interpolateText, localizeText, mergeTranslations, parseI18nResult, requestHostI18n, shouldHoldForMissingTranslation };
|
|
441
492
|
//# 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 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 =\n shouldTranslate && Object.prototype.hasOwnProperty.call(translations, sourceText)\n ? 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 localizeText,\n mergeTranslations,\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\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 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 for (const [id] of this.texts) {\n this.handleRemove(id);\n }\n this.texts.clear();\n }\n\n private resolveText(component: Text3D): string {\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 if (!result.needed) return;\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 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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"}
|
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.7",
|
|
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/plugin-renderer-3d": "0.1.
|
|
32
|
-
"@combos-fun/
|
|
33
|
-
"@combos-fun/
|
|
31
|
+
"@combos-fun/plugin-renderer-3d": "0.1.7",
|
|
32
|
+
"@combos-fun/engine": "0.1.7",
|
|
33
|
+
"@combos-fun/inspector-decorator": "0.1.7"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"tsx": "^4.20.3"
|