Created
May 3, 2024 18:19
-
-
Save hartmannr76/c8e677c79754f48b67e37e3262a7f31d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import unreal | |
def register(): | |
menu_owner = "AnimSequenceBoneFixer_AddControlsForSelected" | |
tool_menus = unreal.ToolMenus.get() | |
menu = tool_menus.extend_menu('ContentBrowser.AssetContextMenu.AnimSequence') | |
if (menu): | |
entry = add_controls_for_selected() | |
entry.init_entry(menu_owner, | |
"ContentBrowser.AssetContextMenu.AnimSequence", "GetAssetActions", "FixAnimBones", "Fix Anim Bones") | |
menu.add_menu_entry_object(entry) | |
@unreal.uclass() | |
class add_controls_for_selected_options(unreal.Object): | |
'''Custom class for AnimSequence creation settings''' | |
child_parent_mappings = unreal.uproperty(unreal.Map(str, str), meta={"DisplayName": "Child->Parent Mappings"}) | |
def _post_init(self): | |
'''Set default class values after initialization''' | |
self.child_parent_mappings = unreal.Map(str, str) | |
@unreal.uclass() | |
class add_controls_for_selected(unreal.ToolMenuEntryScript): | |
''' | |
Custom Tool Menu Entry for AnimSequence Bone Fix | |
This is mostly just an automated version of https://www.youtube.com/watch?v=2ZFoEi9XRms | |
Takes in a list of child->parent bone mappings, creates a LevelSequence, | |
bakes the selected AnimSequence into the LevelSequence, snaps the selected | |
mappings, saves the AnimSequence back out, and deletes the LevelSequence | |
so you are left with a clean repo. | |
''' | |
user_data = add_controls_for_selected_options() | |
@unreal.ufunction(override=True) | |
def get_label(self, context): | |
''' | |
Override function for label of menu entry item | |
''' | |
return "Fix animations" | |
@unreal.ufunction(override=True) | |
def get_tool_tip(self, context): | |
'''Override function for tool tip hover text''' | |
return "Fix Controls from selected Bones" | |
@unreal.ufunction(override=True) | |
def can_execute(self, context): | |
'''Override function for if the menu entry can be executed''' | |
anim_seq_context = context.find_by_class( | |
unreal.ContentBrowserAssetContextMenuContext) | |
return len(anim_seq_context.selected_assets) > 0 | |
@unreal.ufunction(override=True) | |
def execute(self, context): | |
'''Override function for the menu entry execution''' | |
anim_seq_context = unreal.ContentBrowserAssetContextMenuContext.cast(context.find_by_class( | |
unreal.ContentBrowserAssetContextMenuContext)) | |
object_details_view_options = unreal.EditorDialogLibraryObjectDetailsViewOptions() | |
object_details_view_options.show_object_name = False | |
object_details_view_options.allow_search = False | |
if not unreal.EditorDialog.show_object_details_view( | |
"Anim Fixer", | |
self.user_data, | |
object_details_view_options | |
): | |
return | |
for anim_seq in anim_seq_context.selected_assets: | |
seq_path = f'{anim_seq.package_path}/FixDrivers' | |
driver_asset_name = f'FixDriver_{anim_seq.asset_name}' | |
asset = unreal.AnimSequence.cast(anim_seq.get_asset()) | |
sequencer = unreal.LevelSequence.cast(unreal.AssetToolsHelpers.get_asset_tools().create_asset(driver_asset_name, seq_path, unreal.LevelSequence, unreal.LevelSequenceFactoryNew())) | |
sequencer.set_display_rate(asset.data_model_interface.get_frame_rate()) | |
sequencer.set_playback_end(asset.data_model_interface.get_number_of_frames()) | |
sequencer.set_work_range_end(asset.get_play_length()) | |
anim_seq_export_options = unreal.AnimSeqExportOption() | |
anim_seq_export_options.export_transforms = True | |
anim_seq_export_options.export_attribute_curves = True | |
actor_binding = sequencer.add_spawnable_from_instance(asset) | |
unreal.SequencerTools.link_anim_sequence(sequencer, asset, anim_seq_export_options, actor_binding) | |
baked = unreal.ControlRigSequencerLibrary.bake_to_control_rig( | |
unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem).get_editor_world(), | |
sequencer, | |
unreal.FKControlRig, | |
anim_seq_export_options, | |
False, | |
0.001, | |
actor_binding | |
) | |
unreal.LevelSequenceEditorBlueprintLibrary.open_level_sequence(sequencer) | |
if baked: | |
rig_proxy = unreal.ControlRigSequencerBindingProxy.cast(unreal.ControlRigSequencerLibrary.get_control_rigs(sequencer)[0]) | |
snap_settings = unreal.ControlRigSnapSettings() | |
snap_settings.keep_offset = False | |
snap_settings.snap_position = True | |
snap_settings.snap_rotation = True | |
snap_settings.snap_scale = False | |
# ('ik_foot_r_control', 'foot_r_control'), ('ik_foot_l_control', 'foot_l_control') | |
for child, parent in self.user_data.child_parent_mappings.items(): | |
unreal.ControlRigSequencerLibrary.snap_control_rig( | |
sequencer, | |
unreal.FrameNumber(0), | |
unreal.FrameNumber(sequencer.get_playback_end()), | |
unreal.ControlRigSnapperSelection( | |
control_rigs=[ | |
unreal.ControlRigForWorldTransforms( | |
control_rig=rig_proxy.control_rig, | |
control_names=[child] | |
), | |
] | |
), | |
unreal.ControlRigSnapperSelection( | |
control_rigs=[ | |
unreal.ControlRigForWorldTransforms( | |
control_rig=rig_proxy.control_rig, | |
control_names=[parent] | |
), | |
] | |
), | |
snap_settings | |
) | |
unreal.SequencerTools.export_anim_sequence( | |
unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem).get_editor_world(), | |
sequencer, | |
asset, | |
anim_seq_export_options, | |
actor_binding, | |
False | |
) | |
del rig_proxy | |
del actor_binding | |
else: | |
print('no good') | |
unreal.LevelSequenceEditorBlueprintLibrary.close_level_sequence() | |
unreal.SequencerTools.clear_linked_anim_sequences(sequencer) | |
unreal.EditorAssetLibrary.save_directory('/Game/', True, True) | |
unreal.EditorAssetLibrary.delete_loaded_asset(sequencer) | |
del sequencer | |
register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment