Initial commit: Unity WordConnect project

This commit is contained in:
2025-08-01 19:12:05 +08:00
commit f14db75802
3503 changed files with 448337 additions and 0 deletions

View File

@ -0,0 +1,29 @@
{
"name": "CandySmith.Localization.Editor",
"rootNamespace": "",
"references": [
" UnityEngine",
" UnityEditor",
"UnityEditor.UI",
"Unity.TextMeshPro.Editor",
"Unity.TextMeshPro",
"Reordable",
"CandySmith.BlockPuzzle.Main",
"CandySmith.Ads",
"CandySmith.IAP",
"DOTween.Modules",
"CandySmith.WordsToolkit.Main",
"VContainer"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 54ed5b0a667e4a0f987a5bacb1b15ba6
timeCreated: 1722189029

View File

@ -0,0 +1,40 @@
// // ©2015 - 2025 Candy Smith
// // All rights reserved
// // Redistribution of this software is strictly not allowed.
// // Copy of this software can be obtained from unity asset store only.
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// // THE SOFTWARE.
using UnityEditor;
using UnityEngine;
namespace WordsToolkit.Scripts.Localization.Editor
{
[CustomPropertyDrawer(typeof(LocalizationIndex))]
public class LocalizationDrawerUIE : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
position.height = EditorGUIUtility.singleLineHeight;
var r1 = position;
r1.width = 1;
var r2 = position;
r2.xMin = r1.xMax + 1;
r2.width = 50;
EditorGUI.BeginProperty(position, label, property);
// EditorGUI.PropertyField(r1, property.FindPropertyRelative("text"),new GUIContent("","Default text"));
EditorGUI.PropertyField(r2, property.FindPropertyRelative("index"), new GUIContent("", "Localization line index"));
r2.x += 50;
r2.width = 300;
EditorGUI.LabelField(r2, "Change text here: Resources/Localization/");
EditorGUI.EndProperty();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 944cf446217df453f8452f1e796751f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,67 @@
// // ©2015 - 2025 Candy Smith
// // All rights reserved
// // Redistribution of this software is strictly not allowed.
// // Copy of this software can be obtained from unity asset store only.
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// // THE SOFTWARE.
using System;
using UnityEditor;
using UnityEngine;
namespace WordsToolkit.Scripts.Localization.Editor
{
[CustomPropertyDrawer(typeof(LocalizationIndexFolder))]
public class LocalizationFoldDrawer : PropertyDrawer
{
private int offset;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
position.height = EditorGUIUtility.singleLineHeight;
property.isExpanded = EditorGUI.Foldout(position, property.isExpanded, "Text");
if (property.isExpanded)
{
offset = 5;
position.y += EditorGUIUtility.singleLineHeight;
ShowField(position, property, "description", "Description");
position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
ShowField(position, property, "failed", "Fail Description");
}
EditorGUI.EndProperty();
}
private void ShowField(Rect position, SerializedProperty property, string field, string label)
{
position.x += offset;
var r1 = position;
r1.width = 100;
EditorGUI.LabelField(r1, label);
position.x += offset;
var r2 = position;
r2.xMin = r1.xMax + 10;
EditorGUI.PropertyField(r2, property.FindPropertyRelative(field));
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return property.isExpanded ? EditorGUIUtility.singleLineHeight * 3 + EditorGUIUtility.standardVerticalSpacing * 2 : EditorGUIUtility.singleLineHeight;
}
}
[Serializable]
public class LocalizationIndexFolder
{
[Tooltip("Default text")]
public LocalizationIndex description;
public LocalizationIndex failed;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ceb71aa3d5e3348c6970c0b29d923e26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
// // ©2015 - 2025 Candy Smith
// // All rights reserved
// // Redistribution of this software is strictly not allowed.
// // Copy of this software can be obtained from unity asset store only.
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// // THE SOFTWARE.
using UnityEditor;
namespace WordsToolkit.Scripts.Localization.Editor
{
[InitializeOnLoad]
public class LocalizationInitializer
{
// static LocalizationInitializer()
// {
// EditorApplication.delayCall += Initialize;
// }
//
// static void Initialize()
// {
// if (!Application.isPlaying)
// {
// LocalizationManager.InitializeLocalization();
// }
// }
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d9a87bf82ff9497d866a51df91a94948
timeCreated: 1722323590

View File

@ -0,0 +1,49 @@
// // ©2015 - 2025 Candy Smith
// // All rights reserved
// // Redistribution of this software is strictly not allowed.
// // Copy of this software can be obtained from unity asset store only.
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// // THE SOFTWARE.
using TMPro;
using UnityEditor;
using UnityEngine;
namespace WordsToolkit.Scripts.Localization.Editor
{
public class LocalizedTextMeshProUGUICreator
{
[MenuItem("GameObject/UI/Localized TextMeshPro - Text (UI)")]
private static void CreateLocalizedTextMeshProUGUI()
{
// Create a new GameObject
var go = new GameObject("Localized TextMeshPro");
// Add the LocalizedTextMeshProUGUI component
var localizedText = go.AddComponent<LocalizedTextMeshProUGUI>();
localizedText.fontSize = 32;
localizedText.enableAutoSizing = true;
localizedText.fontSizeMin = 16;
localizedText.fontSizeMax = 200;
localizedText.alignment = TextAlignmentOptions.Center;
// Set the parent of the new object
if (Selection.activeGameObject != null)
{
go.transform.SetParent(Selection.activeGameObject.transform, false);
}
// Register the creation for undo
Undo.RegisterCreatedObjectUndo(go, "Create Localized TextMeshPro");
// Select the newly created object
Selection.activeGameObject = go;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5f8e705c10b94f8dbed011f2760f1cac
timeCreated: 1722330317

View File

@ -0,0 +1,99 @@
// // ©2015 - 2025 Candy Smith
// // All rights reserved
// // Redistribution of this software is strictly not allowed.
// // Copy of this software can be obtained from unity asset store only.
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// // THE SOFTWARE.
using TMPro.EditorUtilities;
using UnityEditor;
using UnityEngine;
using System.IO;
namespace WordsToolkit.Scripts.Localization.Editor
{
[CustomEditor(typeof(LocalizedTextMeshProUGUI), true)]
[CanEditMultipleObjects]
public class LocalizedTextMeshProUGUIEditor : TMP_EditorPanelUI
{
private SerializedProperty instanceIDProp;
private LocalizedTextMeshProUGUI localizedText;
private string lastKnownName;
protected override void OnEnable()
{
base.OnEnable();
instanceIDProp = serializedObject.FindProperty("instanceID");
localizedText = (LocalizedTextMeshProUGUI)target;
lastKnownName = localizedText.gameObject.name;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
if (localizedText != null && localizedText.gameObject.name != lastKnownName)
{
localizedText.text = localizedText.gameObject.name;
lastKnownName = localizedText.gameObject.name;
EditorUtility.SetDirty(localizedText);
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(instanceIDProp);
if (GUILayout.Button("Edit Localization"))
{
string relativePath = "Assets/WordConnectGameToolkit/Resources/Localization/English.txt";
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(relativePath);
if (asset != null)
{
AssetDatabase.OpenAsset(asset);
}
else
{
Debug.LogWarning("English.txt file not found at: " + relativePath);
}
}
if (EditorGUI.EndChangeCheck() || Event.current.type == EventType.Layout)
{
serializedObject.ApplyModifiedProperties();
UpdateLocalizedText();
}
EditorGUILayout.Space();
base.OnInspectorGUI();
if (serializedObject.ApplyModifiedProperties())
{
UpdateLocalizedText();
}
}
private void UpdateLocalizedText()
{
if (localizedText != null && !string.IsNullOrEmpty(localizedText.instanceID))
{
var originalText = localizedText.text;
var localizedString = LocalizationManager.instance.GetText(localizedText.instanceID, originalText);
if (localizedText.text != localizedString)
{
localizedText.text = localizedString;
if (PrefabUtility.IsPartOfPrefabInstance(localizedText))
{
PrefabUtility.RecordPrefabInstancePropertyModifications(localizedText);
}
EditorUtility.SetDirty(localizedText);
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9ee5acd244824d7bbd981db5e537507f
timeCreated: 1722188512

View File

@ -0,0 +1,111 @@
// // ©2015 - 2025 Candy Smith
// // All rights reserved
// // Redistribution of this software is strictly not allowed.
// // Copy of this software can be obtained from unity asset store only.
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// // THE SOFTWARE.
using System.Reflection;
using TMPro;
using UnityEditor;
namespace WordsToolkit.Scripts.Localization.Editor
{
public class TextMeshProReplacer : EditorWindow
{
[MenuItem("Tools/Replace TMP with LocalizedTMP")]
private static void ReplaceTextMeshProUGUI()
{
var selectedObjects = Selection.gameObjects;
if (selectedObjects.Length == 0)
{
EditorUtility.DisplayDialog("No Selection", "Please select at least one GameObject.", "OK");
return;
}
var replacedCount = 0;
foreach (var obj in selectedObjects)
{
var tmproComponents = obj.GetComponentsInChildren<TextMeshProUGUI>(true);
foreach (var tmproComponent in tmproComponents)
{
if (tmproComponent.GetType() == typeof(TextMeshProUGUI)) // Ensure we're not replacing already customized scripts
{
var localizeText = tmproComponent.GetComponent<LocalizeText>();
var instanceID = localizeText != null ? localizeText.instanceID : "";
// Store all relevant properties
var text = tmproComponent.text;
var font = tmproComponent.font;
var fontMaterial = tmproComponent.fontMaterial;
var color = tmproComponent.color;
var fontStyle = tmproComponent.fontStyle;
var fontSize = tmproComponent.fontSize;
var autoSizeTextContainer = tmproComponent.autoSizeTextContainer;
var enableAutoSizing = tmproComponent.enableAutoSizing;
var characterSpacing = tmproComponent.characterSpacing;
var wordSpacing = tmproComponent.wordSpacing;
var lineSpacing = tmproComponent.lineSpacing;
var paragraphSpacing = tmproComponent.paragraphSpacing;
var alignment = tmproComponent.alignment;
var enableWordWrapping = tmproComponent.enableWordWrapping;
var overflowMode = tmproComponent.overflowMode;
var isRightToLeftText = tmproComponent.isRightToLeftText;
var enableKerning = tmproComponent.enableKerning;
var extraPadding = tmproComponent.extraPadding;
var richText = tmproComponent.richText;
// Remove old component
DestroyImmediate(tmproComponent);
if (localizeText != null)
{
DestroyImmediate(localizeText);
}
// Add new component
var newComponent = obj.AddComponent<LocalizedTextMeshProUGUI>();
// Restore properties
newComponent.text = text;
newComponent.font = font;
newComponent.fontMaterial = fontMaterial;
newComponent.color = color;
newComponent.fontStyle = fontStyle;
newComponent.fontSize = fontSize;
newComponent.autoSizeTextContainer = autoSizeTextContainer;
newComponent.enableAutoSizing = enableAutoSizing;
newComponent.characterSpacing = characterSpacing;
newComponent.wordSpacing = wordSpacing;
newComponent.lineSpacing = lineSpacing;
newComponent.paragraphSpacing = paragraphSpacing;
newComponent.alignment = alignment;
newComponent.enableWordWrapping = enableWordWrapping;
newComponent.overflowMode = overflowMode;
newComponent.isRightToLeftText = isRightToLeftText;
newComponent.enableKerning = enableKerning;
newComponent.extraPadding = extraPadding;
newComponent.richText = richText;
// Set the instanceID using reflection (since it's private)
var fieldInfo = typeof(LocalizedTextMeshProUGUI).GetField("instanceID", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo != null)
{
fieldInfo.SetValue(newComponent, instanceID);
}
replacedCount++;
}
}
}
EditorUtility.DisplayDialog("Replacement Complete", $"Replaced {replacedCount} TextMeshProUGUI component(s) with LocalizedTextMeshProUGUI.", "OK");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2f2acec46fea4a4283963e2e0a1dc627
timeCreated: 1722188160