fix: LocalizedSubtitle

This commit is contained in:
Alexandre Coirier
2026-06-01 17:13:42 +02:00
parent 3718b3b298
commit d163629ba9
3 changed files with 38 additions and 162 deletions
@@ -1,127 +0,0 @@
using UnityEngine;
using UnityEditor;
using OctoCore.Localization;
using System.IO;
namespace Unheimlich.Editor
{
[CustomPropertyDrawer(typeof(OctoLocalizedTextData))]
public class LocalizedTextFieldDrawer : PropertyDrawer
{
private const float LINE_HEIGHT = 20f;
private const float SPACING = 2f;
private const float LABEL_WIDTH = 80f;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
// Height for label + EN field + FR field
return LINE_HEIGHT * 3 + SPACING * 2;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
OctoLocalizedTextData textData = property.objectReferenceValue as OctoLocalizedTextData;
// If null, create new OctoLocalizedTextData
if (textData == null)
{
textData = CreateLocalizedTextData(property);
property.objectReferenceValue = textData;
property.serializedObject.ApplyModifiedProperties();
}
// Draw label
Rect labelRect = new Rect(position.x, position.y, position.width, LINE_HEIGHT);
EditorGUI.LabelField(labelRect, label, EditorStyles.boldLabel);
// Draw EN field
Rect enRect = new Rect(position.x, position.y + LINE_HEIGHT + SPACING, position.width, LINE_HEIGHT);
DrawLanguageField(enRect, textData, OctoLanguages.English, "EN");
// Draw FR field
Rect frRect = new Rect(position.x, position.y + (LINE_HEIGHT + SPACING) * 2, position.width, LINE_HEIGHT);
DrawLanguageField(frRect, textData, OctoLanguages.French, "FR");
EditorGUI.EndProperty();
}
private void DrawLanguageField(Rect position, OctoLocalizedTextData textData, OctoLanguages language, string labelText)
{
if (textData == null) return;
// Ensure dictionary is initialized
if (textData.Languages.Dictionary == null || textData.Languages.Dictionary.Count == 0)
{
#if UNITY_EDITOR
textData.Init();
#endif
}
// Get language key
string langKey = language.ToString();
// Get current value
string currentValue = "";
if (textData.Languages.Dictionary.TryGetValue(langKey, out string value))
{
currentValue = value;
}
// Draw label
Rect labelRect = new Rect(position.x, position.y, LABEL_WIDTH, position.height);
EditorGUI.LabelField(labelRect, labelText + ":");
// Draw text field
Rect fieldRect = new Rect(position.x + LABEL_WIDTH, position.y, position.width - LABEL_WIDTH, position.height);
EditorGUI.BeginChangeCheck();
string newValue = EditorGUI.TextField(fieldRect, currentValue);
if (EditorGUI.EndChangeCheck())
{
// Update via indexer (Dictionary is read-only property but supports indexer)
textData.Languages.Dictionary[langKey] = newValue;
EditorUtility.SetDirty(textData);
AssetDatabase.SaveAssets();
}
}
private OctoLocalizedTextData CreateLocalizedTextData(SerializedProperty property)
{
// Get the object being edited
Object targetObject = property.serializedObject.targetObject;
string assetPath = AssetDatabase.GetAssetPath(targetObject);
if (string.IsNullOrEmpty(assetPath))
return null;
string directory = Path.GetDirectoryName(assetPath);
string fileName = Path.GetFileNameWithoutExtension(assetPath);
string propertyPath = property.propertyPath.Replace(".", "_");
// Create unique name
string textDataName = $"text_{fileName}_{propertyPath}";
string textDataPath = $"{directory}/{textDataName}.asset";
// Check if already exists
OctoLocalizedTextData existingData = AssetDatabase.LoadAssetAtPath<OctoLocalizedTextData>(textDataPath);
if (existingData != null)
return existingData;
// Create new OctoLocalizedTextData
OctoLocalizedTextData newTextData = ScriptableObject.CreateInstance<OctoLocalizedTextData>();
// Initialize via Init() method
newTextData.Init();
// Save asset
AssetDatabase.CreateAsset(newTextData, textDataPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return newTextData;
}
}
}
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 6566d44f45287f943b77aa92aaefeeb0
@@ -1,57 +1,62 @@
using UnityEngine;
using OctoCore.Localization;
using OctoFramework = OctoCore.OctoCore;
using System;
using Unheimlich.UI;
using UnityEngine;
using OctoFramework = OctoCore.OctoCore;
using OctoCore.Localization;
namespace Unheimlich.Features.Dialogue
{
/// <summary>
/// Bridges OctoLocalizedText and PerLetterFontShifter.
/// OctoLocalizedText writes to the source TMP, which is disabled by the shifter —
/// this component intercepts Localize() and forwards the result to SetText() instead.
/// </summary>
[RequireComponent(typeof(OctoLocalizedText))]
[RequireComponent(typeof(PerLetterFontShifter))]
public class LocalizedSubtitle : MonoBehaviour
{
private OctoLocalizedText _localizedText;
[SerializeField] private OctoLocalizedTextData _data;
private OctoLocalizedText _localizedText; // A retirer
private PerLetterFontShifter _shifter;
private Action localize;
private void Awake()
void Awake()
{
_localizedText = GetComponent<OctoLocalizedText>();
_localizedText = GetComponent<OctoLocalizedText>(); // A retirer
_shifter = GetComponent<PerLetterFontShifter>();
if (!OctoFramework.Instance)
{
Debug.LogWarning($"OctoCore.Instance not found");
return;
}
private void Start()
{
// OctoLocalizedText.Awake() has already run and called Localize() into the dead TMP.
// Pull the resolved text back out and push it into the shifter.
Refresh();
// Re-hook on language change so the shifter stays in sync.
if (OctoFramework.Instance)
OctoFramework.Instance.Localization.SubscribeOnLanguageWrittenChange(Refresh);
Localize();
OctoFramework.Instance.Localization.SubscribeOnLanguageWrittenChange(localize = Localize);
}
private void OnDestroy()
void OnDestroy()
{
if (OctoFramework.Instance)
OctoFramework.Instance.Localization.UnsubscribeOnLanguageWrittenChange(Refresh);
if (!OctoFramework.Instance) return;
if (localize != null)
{
OctoFramework.Instance.Localization.UnsubscribeOnLanguageWrittenChange(localize);
localize = null;
}
}
/// <summary>
/// Pulls the current localized string and pushes it to the shifter.
/// </summary>
private void Refresh()
private void Localize()
{
// Force OctoLocalizedText to re-resolve the string into the source TMP.
_localizedText.Localize();
string localized = "Not localized";
if (_data)
{
localized = OctoLocalization.GetLocalizedText(_data);
}
else // A retirer
{ // A retirer
_localizedText.Localize(); // A retirer
localized = GetComponent<TMPro.TextMeshProUGUI>().text; // A retirer
} // A retirer
// Read it back from the source TMP (it's disabled but the .text field is still set).
string resolved = GetComponent<TMPro.TextMeshProUGUI>().text;
_shifter.SetText(resolved);
_shifter.SetText(localized);
}
}
}