@@ -116,6 +116,144 @@ def copyHips(root_bone_name="Root", hip_bone_name="mixamorig:Hips", name_prefix=
116116 bpy .context .area .ui_type = 'VIEW_3D'
117117 bpy .ops .object .mode_set (mode = 'OBJECT' )
118118
119+ def fix_bones_nla (remove_prefix = False , name_prefix = "mixamorig:" ):
120+ bpy .ops .object .mode_set (mode = 'OBJECT' )
121+
122+ if not bpy .ops .object :
123+ log .warning ('[Mixamo Root] Could not find amature object, please select the armature' )
124+
125+ bpy .ops .object .transform_apply (location = True , rotation = True , scale = True )
126+ bpy .context .object .show_in_front = True
127+
128+ def scale_all_nla (armature ):
129+ bpy .ops .object .mode_set (mode = 'OBJECT' )
130+
131+ # prev_context=bpy.context.area.type
132+
133+ for track in [x for x in armature .animation_data .nla_tracks ]:
134+ bpy .context .active_nla_track = track
135+ for strip in track .strips :
136+ bpy .context .active_nla_strip = strip
137+ print (bpy .context .active_nla_strip )
138+
139+
140+ bpy .ops .object .mode_set (mode = 'POSE' )
141+ bpy .ops .pose .select_all (action = 'SELECT' )
142+ bpy .context .area .type = 'GRAPH_EDITOR'
143+ bpy .context .space_data .dopesheet .filter_text = "Location"
144+ bpy .context .space_data .pivot_point = 'CURSOR'
145+ bpy .context .space_data .dopesheet .use_filter_invert = False
146+
147+ bpy .ops .anim .channels_select_all (action = 'SELECT' )
148+
149+ bpy .ops .transform .resize (value = (1 , 0.01 , 1 ), orient_type = 'GLOBAL' ,
150+ orient_matrix = ((1 , 0 , 0 ), (0 , 1 , 0 ), (0 , 0 , 1 )),
151+ orient_matrix_type = 'GLOBAL' ,
152+ constraint_axis = (False , True , False ),
153+ mirror = True , use_proportional_edit = False ,
154+ proportional_edit_falloff = 'SMOOTH' ,
155+ proportional_size = 1 ,
156+ use_proportional_connected = False ,
157+ use_proportional_projected = False )
158+
159+ def copy_hips_nla (root_bone_name = "Root" , hip_bone_name = "mixamorig:Hips" , name_prefix = "mixamorig:" ):
160+ hip_bone_name = "Ctrl_Hips"
161+ bpy .ops .object .mode_set (mode = 'POSE' )
162+ previous_context = bpy .context .area .ui_type
163+ bpy .ops .pose .select_all (action = 'DESELECT' )
164+ while False :
165+ #SELECT OUR ROOT MOTION BONE
166+ # bpy.context.object.pose.bones[name_prefix + root_bone_name].bone.select = True
167+
168+ # bpy.ops.nla.tweakmode_enter()
169+ # bpy.context.area.ui_type = 'FCURVES'
170+
171+ # # SET FRAME TO ZERO
172+ # bpy.ops.graph.cursor_set(frame=0.0, value=0.0)
173+ # #ADD NEW KEYFRAME
174+ # bpy.ops.anim.keyframe_insert_menu(type='Location')
175+ # #SELECT ONLY HIPS AND LOCTAIUON GRAPH DATA
176+ # bpy.ops.pose.select_all(action='DESELECT')
177+ # bpy.context.object.pose.bones[hip_bone_name].bone.select = True
178+ # bpy.context.area.ui_type = 'DOPESHEET'
179+ # bpy.context.space_data.dopesheet.filter_text = "Location"
180+ # bpy.context.area.ui_type = 'FCURVES'
181+ # #COPY THE LOCATION VALUES OF THE HIPS AND DELETE THEM
182+ # bpy.ops.graph.copy()
183+ # bpy.ops.graph.select_all(action='DESELECT')
184+
185+ # myFcurves = bpy.context.object.animation_data.action.fcurves
186+
187+ # for i in myFcurves:
188+ # hip_bone_fcvurve = 'pose.bones["'+hip_bone_name+'"].location'
189+ # if str(i.data_path)==hip_bone_fcvurve:
190+ # myFcurves.remove(i)
191+
192+ # bpy.ops.pose.select_all(action='DESELECT')
193+ # bpy.context.object.pose.bones[name_prefix + root_bone_name].bone.select = True
194+ # bpy.ops.graph.paste()
195+
196+ # for animation data in object
197+ # for
198+ pass
199+
200+ for track in bpy .context .object .animation_data .nla_tracks :
201+ bpy .context .object .animation_data .nla_tracks .active = track
202+ for strip in track .strips :
203+ bpy .context .object .pose .bones [name_prefix + root_bone_name ].bone .select = True
204+ bpy .context .area .ui_type = 'NLA_EDITOR'
205+ bpy .ops .nla .tweakmode_enter ()
206+ bpy .context .area .ui_type = 'FCURVES'
207+ hip_curves = [fc for fc in strip .fcurves if hip_bone_name in fc .data_path and fc .data_path .startswith ('location' )]
208+
209+ # Copy Hips to root
210+ ## Insert keyframe for root bone
211+ start_frame = strip .action .frame_range [0 ]
212+ # frame sets the x axis cursor (determines the frame, and value the y axis cursor, which is the amplitude of the curve)
213+ bpy .ops .graph .cursor_set (frame = start_frame , value = 0.0 )
214+ bpy .ops .anim .keyframe_insert_menu (type = 'Location' )
215+ bpy .ops .pose .select_all (action = 'DESELECT' )
216+
217+ ## Copy Location fcruves
218+ bpy .context .object .pose .bones [hip_bone_name ].bone .select = True
219+ bpy .context .area .ui_type = 'DOPESHEET'
220+ bpy .context .space_data .dopesheet .filter_text = "Location"
221+ bpy .context .area .ui_type = 'FCURVES'
222+ bpy .ops .graph .copy ()
223+ bpy .ops .graph .select_all (action = 'DESELECT' )
224+
225+ ## We want to delete the hips locations
226+ allFcurves = strip .fcurves
227+ for fc in hip_curves :
228+ allFcurves .remove (fc )
229+
230+ ## Paste location fcurves to the root bone
231+ bpy .ops .pose .select_all (action = 'DESELECT' )
232+ bpy .context .object .pose .bones [name_prefix + root_bone_name ].bone .select = True
233+ bpy .ops .graph .paste ()
234+
235+
236+ loc_fcurves = [fc for fc in strip .fcurves if root_bone_name in fc .data_path and fc .data_path .startswith ('location' )]
237+
238+ # Update Root Bone
239+ # set z of root to min 0 (not negative).
240+ for fc in loc_fcurves :
241+ # Z axis location curve
242+ if fc .array_index == 2 :
243+ for kp in fc .keyframe_points :
244+ kp .co .z = min (0 , abs (kp .co .z ))
245+
246+ # Delete rotation curves for x(0) and y(1) axis. Should we delet Z rotation too?
247+ # rot_fcurves = [fc for fc in strip.fcurves if root_bone_name in fc.data_path and fc.data_path.startswith('rotation') and (fc.array_index == 0 or fc.array_index == 1)]
248+ # for fc in rot_fcurves:
249+ # strip.fcurves.remove(fc)
250+ # while(rot_fcurves):
251+ # fc = rot_fcurves.pop()
252+ # strip.fcurves.remove(fc)
253+ bpy .context .area .ui_type = 'NLA_EDITOR'
254+ bpy .ops .nla .tweakmode_exit ()
255+ bpy .context .area .ui_type = previous_context
256+ bpy .ops .object .mode_set (mode = 'OBJECT' )
119257
120258def deleteArmature (imported_objects = set ()):
121259 armature = None
@@ -164,6 +302,21 @@ def add_root_bone(root_bone_name="Root", hip_bone_name="mixamorig:Hips", remove_
164302 scaleAll ()
165303 copyHips (root_bone_name = root_bone_name , hip_bone_name = hip_bone_name , name_prefix = name_prefix )
166304
305+ def add_root_bone_nla (root_bone_name = "Root" , hip_bone_name = "mixamorig:Hips" , name_prefix = "mixamorig:" ):#remove_prefix=False, name_prefix="mixamorig:"):
306+ armature = bpy .context .selected_objects [0 ]
307+ bpy .ops .object .mode_set (mode = 'EDIT' )
308+
309+ # Add root bone to edit bones
310+ root_bone = armature .data .edit_bones .new (name_prefix + root_bone_name )
311+ root_bone .tail .z = .25
312+
313+ armature .data .edit_bones [hip_bone_name ].parent = armature .data .edit_bones [name_prefix + root_bone_name ]
314+ bpy .ops .object .mode_set (mode = 'OBJECT' )
315+
316+ # fix_bones_nla(remove_prefix=remove_prefix, name_prefix=name_prefix)
317+ # scale_all_nla()
318+ copy_hips_nla (root_bone_name = root_bone_name , hip_bone_name = hip_bone_name , name_prefix = name_prefix )
319+
167320def push (obj , action , track_name = None , start_frame = 0 ):
168321 # Simulate push :
169322 # * add a track
0 commit comments