summaryrefslogtreecommitdiffstats
path: root/libunity.py
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2022-10-20 20:11:31 -0700
committeryum <yum.food.vr@gmail.com>2022-10-20 20:11:31 -0700
commitb9c6b3e8ff698b87e8f5c2a429d264a740c5c716 (patch)
tree512a392e9851ee9c77328e85bce08a26c1b05b49 /libunity.py
parent3a0fe46d258559e641d0b379443280a549ff154f (diff)
Add "off" animation generator
Add utility to programmatically generate "off" animations. Scans every animation in the project, checks if it sets anything nonzero, and if so, generates a copy of it which sets everything to zero. This is useful for transitioning away from write defaults.
Diffstat (limited to 'libunity.py')
-rw-r--r--libunity.py109
1 files changed, 69 insertions, 40 deletions
diff --git a/libunity.py b/libunity.py
index 0ecc5e2..db69202 100644
--- a/libunity.py
+++ b/libunity.py
@@ -715,49 +715,58 @@ class UnityAnimator():
#print("len float curves: {}".format(len(new_clip.mapping['m_FloatCurves'].sequence)), file=sys.stderr)
- #print("generated animation: {}".format(str(new_anim)), file=sys.stderr)
- with open(generated_anim_path, "w") as f:
- f.write(str(new_anim))
+ def generateOffAnimations(self, guid_map, generated_anim_dir):
+ animator_state_id = '1102'
+ for node in self.nodes:
+ if node.class_id != animator_state_id:
+ continue
- meta = Metadata()
- with open(generated_anim_path + ".meta", "w") as f:
- f.write(str(meta))
+ # Looking at an animation state.
+ motion = node.mapping['AnimatorState'].mapping['m_Motion']
+ if not 'guid' in motion.mapping:
+ continue
+ guid = motion.mapping['guid']
- # OK, we have an animation and a GUID. Let's generate a layer now.
- layer = self.addLayer('TaSTT_Reset_Animations', add_to_head = True)
+ # Looking at an animation.
+ if not guid in guid_map.keys():
+ continue
- reset_left_state = self.addAnimatorState(layer, 'TaSTT_Reset_Animations_Left')
- self.setAnimatorStateAnimation(reset_left_state, meta.guid)
- reset_right_state = self.addAnimatorState(layer, 'TaSTT_Reset_Animations_Right')
- self.setAnimatorStateAnimation(reset_right_state, meta.guid)
+ animation_path = guid_map[guid]
+ print("Checking animation at {}".format(animation_path), file=sys.stderr)
+ parser = UnityParser()
+ parser.parseFile(animation_path)
+ anim = UnityAnimator()
+ anim.addNodes(parser.nodes)
- # Add noop state
- noop_state = self.addAnimatorState(layer, 'TaSTT_Reset_Animations_Noop', is_default_state = True)
- noop_anim_meta = Metadata()
- noop_anim_meta.load('Animations/TaSTT_Do_Nothing.anim')
- self.setAnimatorStateAnimation(noop_state, noop_anim_meta.guid)
- noop_trans = self.addTransition(noop_state.anchor)
- self.addTransitionIntegerGreaterCondition(None, noop_trans,
- 'GestureLeft', 0)
- self.addTransitionIntegerGreaterCondition(None, noop_trans,
- 'GestureRight', 0)
- tmp_trans = layer.mapping['AnimatorStateMachine'].mapping['m_AnyStateTransitions'].addChildMapping()
- tmp_trans.mapping['fileID'] = noop_trans.anchor
-
- # Create any state transitions to the animated
- # states. When Gesture{Left,Right} is 0 in either hand, AKA no gesture
- # is being used, we fire the animation.
- left_trans = self.addTransition(reset_left_state.anchor)
- self.addTransitionIntegerEqualityCondition(None, left_trans,
- 'GestureLeft', 0)
- tmp_trans = layer.mapping['AnimatorStateMachine'].mapping['m_AnyStateTransitions'].addChildMapping()
- tmp_trans.mapping['fileID'] = left_trans.anchor
-
- right_trans = self.addTransition(reset_right_state.anchor)
- self.addTransitionIntegerEqualityCondition(None, right_trans,
- 'GestureRight', 0)
- tmp_trans = layer.mapping['AnimatorStateMachine'].mapping['m_AnyStateTransitions'].addChildMapping()
- tmp_trans.mapping['fileID'] = right_trans.anchor
+ clip = anim.peekNodeOfClass('74')
+
+ has_nonzero = False
+ curve_members = ["m_FloatCurves", "m_EditorCurves"]
+ for memb in curve_members:
+ for curve in clip.mapping['AnimationClip'].mapping[memb].sequence:
+ attr = curve.mapping['attribute']
+ path = curve.mapping['path']
+
+ for m_curve in curve.mapping['curve'].mapping['m_Curve'].sequence:
+ if m_curve.mapping['value'] != '0':
+ has_nonzero = True
+ m_curve.mapping['value'] = '0'
+
+ if not has_nonzero:
+ print("Animation does not set anything nonzero")
+ continue
+
+ print("Animation sets things nonzero, fixing")
+
+ new_anim_path = "OFF_{}".format(os.path.basename(animation_path))
+ new_anim_path = "{}/{}".format(generated_anim_dir, new_anim_path)
+
+ with open(new_anim_path, "w") as f:
+ f.write(str(anim))
+
+ meta = Metadata()
+ with open(new_anim_path + ".meta", "w") as f:
+ f.write(str(meta))
def addTransitionBooleanCondition(self, from_state, trans, param, branch):
# Populate the transition's condition logic.
@@ -1156,8 +1165,28 @@ if __name__ == "__main__":
anim = parser0.parseFile(args.fx0)
print("Fixing write defaults", file=sys.stderr)
- anim.fixWriteDefaults(guid_map, "generated/animations/TaSTT_Reset_Animation.anim")
+ anim_dir = "generated/animations/"
+ os.makedirs(anim_dir, exist_ok=True)
+ anim.fixWriteDefaults(guid_map, anim_dir + "TaSTT_Reset_Animation.anim")
print(str(anim))
+ elif args.cmd == "gen_off_anims":
+ if not args.fx0 or not args.guid_map:
+ print("--fx0 and --guid_map required")
+ parser.print_help()
+ parser.exit(1)
+
+ guid_map = {}
+ with open(args.guid_map, 'rb') as f:
+ guid_map = pickle.load(f)
+
+ print("Parsing {}".format(args.fx0), file=sys.stderr)
+ parser0 = MulticoreUnityParser()
+ anim = parser0.parseFile(args.fx0)
+
+ print("Generating off animations", file=sys.stderr)
+ anim_dir = "generated/animations/"
+ os.makedirs(anim_dir, exist_ok=True)
+ anim.generateOffAnimations(guid_map, "generated/animations")
elif args.cmd == "add_toggle":
if not args.fx0: