Skip to content

Commit 7e35431

Browse files
committed
Ignore cyclic dependencies and patch List<T> types
1 parent a538a9d commit 7e35431

File tree

1 file changed

+57
-6
lines changed

1 file changed

+57
-6
lines changed

UnityPyTypetreeCodegen/__main__.py

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
"from UnityPy.classes import *",
6666
"from UnityPy.classes.math import (ColorRGBA, Matrix3x4f, Matrix4x4f, Quaternionf, Vector2f, Vector3f, Vector4f, float3, float4,)",
6767
'''T = TypeVar("T")
68-
def typetree_defined(clazz : T) -> T:
68+
def UTTCGen(clazz : T) -> T:
6969
"""dataclass-like decorator for typetree classess with nested type support
7070
7171
limitations:
@@ -115,6 +115,17 @@ def __repr__(self) -> str:
115115
clazz.__init__ = __init__
116116
clazz.__repr__ = __repr__
117117
return clazz
118+
119+
# Helper functions
120+
def UTTCGen_Reread(Mono: MonoBehaviour):
121+
script = Mono.m_Script.read()
122+
fullname = script.m_ClassName
123+
if script.m_Namespace:
124+
fullname = f"{script.m_Namespace}.{fullname}"
125+
definition = TYPETREE_DEFS.get(fullname, None)
126+
assert definition is not None, f"Typetree definition for {fullname} not found"
127+
raw_def = Mono.object_reader.read_typetree(definition)
128+
return raw_def, fullname
118129
''',
119130
]
120131
)
@@ -123,9 +134,41 @@ def __repr__(self) -> str:
123134

124135

125136
def translate_name(m_Name: str, **kwargs):
137+
NG = "<>|`="
126138
m_Name = m_Name.replace("<>", "__generic_") # Generic templates
127139
m_Name = m_Name.replace("<", "_").replace(">", "_") # Templated
128-
m_Name = m_Name.replace("=", "_") # Special chars
140+
for c in NG:
141+
m_Name = m_Name.replace(c, "_")
142+
RESERVED_NAMES = {
143+
"class",
144+
"def",
145+
"return",
146+
"if",
147+
"else",
148+
"elif",
149+
"for",
150+
"while",
151+
"in",
152+
"is",
153+
"not",
154+
"and",
155+
"or",
156+
"from",
157+
"import",
158+
"as",
159+
"with",
160+
"try",
161+
"except",
162+
"finally",
163+
"raise",
164+
"assert",
165+
"break",
166+
"continue",
167+
"pass",
168+
"yield",
169+
}
170+
if m_Name in RESERVED_NAMES:
171+
m_Name = "_" + m_Name
129172
return m_Name
130173

131174

@@ -169,6 +212,7 @@ def translate_type(
169212

170213

171214
def declare_field(name: str, type: str, org_type: str = None):
215+
name = translate_name(name)
172216
if type not in {"object", "List[object]", "PPtr[object]"}:
173217
return f"{name} : {type}"
174218
else:
@@ -200,7 +244,8 @@ def dfs(u):
200244
for clazz in graph:
201245
if not vis[clazz]:
202246
flag &= dfs(clazz)
203-
assert flag, "graph contains cycle"
247+
# XXX: Shouldn't happen. Need to figure out how this is possible
248+
# assert flag, "graph contains cycle"
204249
return topo
205250

206251

@@ -252,7 +297,7 @@ def emit_line(*lines: str):
252297
clazz = translate_name(clazz)
253298
clazzes.append(clazz)
254299
clazz_fields = list()
255-
emit_line(f"@typetree_defined")
300+
emit_line(f"@UTTCGen")
256301
if lvl1:
257302
parent = translate_type(fields[0].m_Type, strip=True, fallback=False)
258303
emit_line(f"class {clazz}({parent}):")
@@ -264,10 +309,16 @@ def emit_line(*lines: str):
264309
raise ValueError # XXX: Should NEVER happen
265310
pa_dep1 = dp[parent]
266311
cur_dep1 = pa_dep1
267-
for i, field in enumerate(filter(lambda field: field.m_Level == 1, fields)):
268-
if i < pa_dep1:
312+
for dep, (i, field) in enumerate(
313+
filter(lambda field: field[1].m_Level == 1, enumerate(fields))
314+
):
315+
if dep < pa_dep1:
269316
# Skip parent fields at lvl1
270317
continue
318+
if i + 1 < len(fields) and fields[i + 1].m_Type == "Array":
319+
if field.m_Type.startswith("List"):
320+
# Rename this to Type[]
321+
field.m_Type = fields[i + 3].m_Type + "[]"
271322
name, type = field.m_Name, translate_type(
272323
field.m_Type, typenames=classname_nodes | import_defs
273324
)

0 commit comments

Comments
 (0)