diff options
| author | yum <yum.food.vr@gmail.com> | 2022-10-20 18:42:42 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2022-10-20 18:44:08 -0700 |
| commit | 3a0fe46d258559e641d0b379443280a549ff154f (patch) | |
| tree | adf2f71b48035720f4295d437387d40f24fd7afd /libunity.py | |
| parent | d7c225ab3fcad600e93e9464886702fd269fedd5 (diff) | |
Add preliminary support for negative anchors
Some animators generate negative anchors. Casting to u64 doesn't produce
an anchor with a valid prefix, so idk what it is. Use the class ID from
the little !u! bit instead of deriving it from the anchor.
Some things probably don't work yet.
Diffstat (limited to 'libunity.py')
| -rw-r--r-- | libunity.py | 92 |
1 files changed, 40 insertions, 52 deletions
diff --git a/libunity.py b/libunity.py index 2e375af..0ecc5e2 100644 --- a/libunity.py +++ b/libunity.py @@ -362,44 +362,14 @@ class Mapping(Node): for k, v in self.mapping.items(): cb(v) -def classId(anchor): - # AnimatorController - if anchor.startswith("91"): - return "91" - # MonoBehaviour - if anchor.startswith("114"): - return "114" - # BlendTree - if anchor.startswith("206"): - return "206" - # AnimatorStateTransition - if anchor.startswith("1101"): - return "1101" - # AnimatorState - if anchor.startswith("1102"): - return "1102" - # AnimatorStateMachine - if anchor.startswith("1107"): - return "1107" - # AnimatorTransition - if anchor.startswith("1109"): - return "1109" - - # IDK what this is lmao - if anchor.startswith("74"): - return "74" - if anchor.startswith("115"): - return "115" - - raise Exception("Unrecognized object: {}".format(anchor)) - class UnityDocument(Mapping): + def __init__(self): + super().__init__() + self.class_id = None + def __str__(self): return super().__str__() - def classId(self): - return classId(self.anchor) - # Class representing a Unity AnimatorController. Implements manipulations, like # merging and reanchoring. class UnityAnimator(): @@ -421,11 +391,11 @@ class UnityAnimator(): raise Exception("Duplicate anchor: {}, node 1: {}, node 2: {}".format(anchor, str(node), str(self.id_to_node[anchor]))) self.id_to_node[anchor] = node - if classId(anchor) in self.class_to_next_id: - cur_next = self.class_to_next_id[classId(anchor)] - self.class_to_next_id[classId(anchor)] = max(int(anchor), cur_next) + if node.class_id in self.class_to_next_id: + cur_next = self.class_to_next_id[node.class_id] + self.class_to_next_id[node.class_id] = max(int(anchor), cur_next) else: - self.class_to_next_id[classId(anchor)] = int(anchor) + self.class_to_next_id[node.class_id] = int(anchor) for k in self.class_to_next_id.keys(): self.class_to_next_id[k] += 1 @@ -442,18 +412,18 @@ class UnityAnimator(): return new_id - def getUniqueId(self, anchor): + def getUniqueId(self, node): # For whatever reason, generating a new ID for the MonoBehaviour # embedded in VRChat's default animation ctrler makes Unity spit out # warnings. Reuse the old one. - if classId(anchor) == "114": - return int(anchor) + if node.class_id == "114": + return int(node.anchor) - if anchor in self.id_mapping.keys(): - return self.id_mapping[anchor] + if node.anchor in self.id_mapping.keys(): + return self.id_mapping[node.anchor] - new_id = self.allocateId(classId(anchor)) - self.id_mapping[anchor] = new_id + new_id = self.allocateId(node.class_id) + self.id_mapping[node.anchor] = new_id return new_id def mergeIterator(self, v): @@ -470,14 +440,14 @@ class UnityAnimator(): def peekNodeOfClass(self, classId): for node in self.nodes: - if node.classId() == classId: + if node.class_id == classId: return node return None def popNodeOfClass(self, classId): result = None for node in self.nodes: - if node.classId() == classId: + if node.class_id == classId: result = node self.nodes.remove(result) break @@ -529,13 +499,13 @@ class UnityAnimator(): # Mapping from class ID (string) to new class ID (int) self.id_mapping = self.id_mapping0 for node in self.nodes: - new_id = self.getUniqueId(node.anchor) + new_id = self.getUniqueId(node) node.anchor = str(new_id) node.forEach(self.mergeIterator) self.id_mapping = self.id_mapping1 for node in other.nodes: - new_id = self.getUniqueId(node.anchor) + new_id = self.getUniqueId(node) node.anchor = str(new_id) node.forEach(self.mergeIterator) @@ -587,6 +557,7 @@ class UnityAnimator(): # Create layer object layer = UnityDocument() + layer.class_id = "1107" layer.anchor = str(new_id) mach = layer.addChildMapping('AnimatorStateMachine') @@ -633,6 +604,7 @@ class UnityAnimator(): node = new_anim.nodes[0] new_id = self.allocateId('1102') + node.class_id = "1102" node.anchor = str(new_id) state = node.mapping['AnimatorState'] state.mapping['m_Name'] = state_name @@ -665,6 +637,7 @@ class UnityAnimator(): node = new_transition.nodes[0] new_id = self.allocateId('1101') + node.class_id = "1101" node.anchor = str(new_id) state = node.mapping['AnimatorStateTransition'] state.mapping['m_DstState'].mapping['fileID'] = dst_state_id @@ -691,7 +664,7 @@ class UnityAnimator(): animator_state_id = '1102' for node in self.nodes: - if node.classId() != animator_state_id: + if node.class_id != animator_state_id: continue # Looking at an animator state. @@ -851,7 +824,7 @@ class UnityAnimator(): noop_anim_meta.load(noop_anim_path) for node in self.nodes: - if classId(node.anchor) != "1102": + if node.class_id != "1102": continue motion = node.mapping['AnimatorState'].mapping['m_Motion'] replace = False @@ -873,7 +846,7 @@ def unityAnimatorToString(nodes): """[1:][:-1] lines.append(preamble) for doc in nodes: - lines.append("--- !u!" + doc.classId() + " &" + doc.anchor) + lines.append("--- !u!" + doc.class_id + " &" + doc.anchor) lines.append(str(doc)) result = '\n'.join(lines) @@ -940,6 +913,19 @@ class UnityParser: lines.append("...\n") return '\n'.join(lines) + def getClassIds(self, yaml_str): + anchor_to_class_id = {} + for line in yaml_str.split("\n"): + if not line.startswith("---"): + continue + + parts = line.split() + class_id = parts[1][3:] + anchor = parts[2][1:] + anchor_to_class_id[anchor] = class_id + + return anchor_to_class_id + def parseFile(self, yaml_file): yaml_str = "" with open(yaml_file, "r") as f: @@ -947,6 +933,7 @@ class UnityParser: return self.parse(yaml_str) def parse(self, yaml_str): + anchor_to_class_id = self.getClassIds(yaml_str) yaml_str = self.cleanYaml(yaml_str) for event in yaml.parse(yaml_str): @@ -978,6 +965,7 @@ class UnityParser: if self.cur_node == None: self.cur_node = UnityDocument() self.cur_node.anchor = event.anchor + self.cur_node.class_id = anchor_to_class_id[event.anchor] else: self.cur_node = self.cur_node.addChildMapping(self.cur_scalar) self.pushState(self.MAPPING_START) |
