forked from potatosalad775/MWC_Localization_Core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMLCUtils.cs
More file actions
160 lines (133 loc) · 5.25 KB
/
MLCUtils.cs
File metadata and controls
160 lines (133 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using UnityEngine;
using System.Collections.Generic;
namespace MWC_Localization_Core
{
/// <summary>
/// String normalization utilities for localization
/// </summary>
public static class MLCUtils
{
/// <summary>
/// Format string for use as translation key (uppercase, no spaces/newlines)
/// </summary>
public static string FormatUpperKey(string original)
{
if (string.IsNullOrEmpty(original))
return original;
// Single-pass: skip whitespace chars and uppercase in one allocation
char[] buffer = new char[original.Length];
int len = 0;
for (int i = 0; i < original.Length; i++)
{
char c = original[i];
if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
continue;
buffer[len++] = char.ToUpperInvariant(c);
}
if (len == 0)
return string.Empty;
return new string(buffer, 0, len);
}
// Cache for GameObject paths to improve performance
private static Dictionary<GameObject, string> pathCache = new Dictionary<GameObject, string>();
// Cache for expensive GameObject.Find(path) lookups
private static Dictionary<string, GameObject> gameObjectFindCache = new Dictionary<string, GameObject>();
// Cache for inactive lookup helpers (resolved via Resources.FindObjectsOfTypeAll)
private static Dictionary<string, PlayMakerFSM> inactiveFsmPathNameCache = new Dictionary<string, PlayMakerFSM>();
public static string GetGameObjectPath(GameObject obj)
{
if (obj == null)
return string.Empty;
// Check cache first
if (pathCache.TryGetValue(obj, out string cachedPath))
return cachedPath;
// Build path using List + Reverse
List<string> pathParts = new List<string>();
Transform current = obj.transform;
while (current != null)
{
pathParts.Add(current.name);
current = current.parent;
}
// Reverse and join
pathParts.Reverse();
string path = string.Join("/", pathParts.ToArray());
// Cache the path (limit cache size to prevent memory bloat)
if (pathCache.Count < 10000)
{
pathCache[obj] = path;
}
return path;
}
/// <summary>
/// Cached wrapper around GameObject.Find(path).
/// Returns null when not found, and invalidates stale cached references.
/// </summary>
public static GameObject FindGameObjectCached(string path)
{
if (string.IsNullOrEmpty(path))
return null;
if (gameObjectFindCache.TryGetValue(path, out GameObject cachedObj))
{
if (cachedObj != null)
return cachedObj;
gameObjectFindCache.Remove(path);
}
GameObject found = GameObject.Find(path);
if (found != null)
{
gameObjectFindCache[path] = found;
}
return found;
}
/// <summary>
/// Find PlayMakerFSM by object path + FSM name, including inactive objects.
/// Uses a cache and falls back to Resources.FindObjectsOfTypeAll when needed.
/// </summary>
public static PlayMakerFSM FindFsmIncludingInactiveByPathAndName(string objectPath, string fsmName)
{
if (string.IsNullOrEmpty(objectPath) || string.IsNullOrEmpty(fsmName))
return null;
string cacheKey = objectPath + "|" + fsmName;
if (inactiveFsmPathNameCache.TryGetValue(cacheKey, out PlayMakerFSM cachedFsm))
{
if (cachedFsm != null && cachedFsm.gameObject != null)
return cachedFsm;
inactiveFsmPathNameCache.Remove(cacheKey);
}
PlayMakerFSM[] allFsms = Resources.FindObjectsOfTypeAll<PlayMakerFSM>();
if (allFsms == null)
return null;
for (int i = 0; i < allFsms.Length; i++)
{
PlayMakerFSM fsm = allFsms[i];
if (fsm == null || fsm.gameObject == null)
continue;
string path = GetGameObjectPath(fsm.gameObject);
if (path == objectPath && fsm.FsmName == fsmName)
{
inactiveFsmPathNameCache[cacheKey] = fsm;
return fsm;
}
}
return null;
}
/// <summary>
/// Shared accessor for all TextMeshes including inactive ones.
/// </summary>
public static TextMesh[] GetAllTextMeshesIncludingInactive()
{
return Resources.FindObjectsOfTypeAll<TextMesh>();
}
/// <summary>
/// Clear all runtime caches.
/// Call this on scene changes and reloads.
/// </summary>
public static void ClearCaches()
{
pathCache.Clear();
gameObjectFindCache.Clear();
inactiveFsmPathNameCache.Clear();
}
}
}