@@ -73,29 +73,30 @@ def get_current_context():
73
73
74
74
:return dict: A dictionary of values that are the current context.
75
75
"""
76
- active_object = bpy .context .active_object
77
-
78
76
selected_objects = []
79
77
for selected_object in bpy .context .selected_objects :
80
- active_action = None
78
+ active_action_name = ''
81
79
# get the selected objects active animation
82
80
if selected_object .animation_data :
83
- active_action = selected_object .animation_data .action
81
+ if selected_object .animation_data .action :
82
+ active_action_name = selected_object .animation_data .action .name
84
83
85
84
# save the selected object reference and its active animation
86
- selected_objects .append ([selected_object , active_action ])
85
+ selected_objects .append ([selected_object . name , active_action_name ])
87
86
88
87
current_context = {
89
- 'visible_objects' : bpy .context .visible_objects ,
88
+ 'visible_objects' : [ visible_object . name for visible_object in bpy .context .visible_objects ] ,
90
89
'selected_objects' : selected_objects ,
91
- 'active_object' : active_object ,
92
90
'mode' : bpy .context .mode
93
91
}
94
92
95
93
# save the current action if there is one
94
+ active_object = bpy .context .active_object
96
95
if active_object :
96
+ current_context ['active_object' ] = active_object .name
97
97
if active_object .animation_data :
98
- current_context ['active_animation' ] = active_object .animation_data .action
98
+ if active_object .animation_data .action :
99
+ current_context ['active_animation' ] = active_object .animation_data .action .name
99
100
100
101
return current_context
101
102
@@ -106,21 +107,27 @@ def set_context(context):
106
107
107
108
:param dict context: A dictionary of values the the context should be set to.
108
109
"""
109
- active_object = context ['active_object' ]
110
-
111
110
# set the visible objects
112
- for scene_object in context ['visible_objects' ]:
113
- scene_object .hide_set (False )
111
+ for visible_object_name in context ['visible_objects' ]:
112
+ visible_object = bpy .data .objects .get (visible_object_name )
113
+ if visible_object :
114
+ visible_object .hide_set (False )
114
115
115
116
# set the selected objects
116
- for scene_object in context ['selected_objects' ]:
117
- scene_object [0 ].select_set (True )
117
+ for scene_object_name , active_action_name in context ['selected_objects' ]:
118
+ scene_object = bpy .data .objects .get (scene_object_name )
119
+ if scene_object :
120
+ scene_object .select_set (True )
121
+
118
122
# set the objects active animation
119
- if scene_object [1 ]:
120
- scene_object [0 ].animation_data .action = scene_object [1 ]
123
+ active_action = bpy .data .objects .get (active_action_name )
124
+ if active_action :
125
+ scene_object .animation_data .action = active_action
121
126
122
127
# set the active object
123
- bpy .context .view_layer .objects .active = active_object
128
+ active_object_name = context .get ('active_object' )
129
+ if active_object_name :
130
+ bpy .context .view_layer .objects .active = bpy .data .objects .get (active_object_name )
124
131
125
132
# set the mode
126
133
if bpy .context .mode != context ['mode' ]:
@@ -164,7 +171,7 @@ def remove_extra_data(data_blocks, original_data_blocks):
164
171
data_blocks .remove (data_block_to_remove )
165
172
166
173
167
- def remove_object_scale_keyframes (scale , actions ):
174
+ def remove_object_scale_keyframes (actions ):
168
175
"""
169
176
This function removes all scale keyframes the exist a object in the provided actions.
170
177
@@ -619,8 +626,8 @@ def scale_object_actions(unordered_objects, actions, scale_factor):
619
626
keyframe_point .handle_left [1 ] = keyframe_point .handle_left [1 ] * scale [fcurve .array_index ]
620
627
keyframe_point .handle_right [1 ] = keyframe_point .handle_right [1 ] * scale [fcurve .array_index ]
621
628
622
- # apply the scale on the object
623
- bpy .ops .object .transform_apply (location = False , rotation = False , scale = True )
629
+ # apply the scale on the object
630
+ bpy .ops .object .transform_apply (location = False , rotation = False , scale = True )
624
631
625
632
626
633
def import_unreal_4_asset (file_path ):
@@ -643,7 +650,7 @@ def import_unreal_4_asset(file_path):
643
650
scale_object_actions (bpy .context .selected_objects , imported_actions , 1 )
644
651
645
652
# remove the object scale keyframes
646
- remove_object_scale_keyframes (scale = 1 , actions = imported_actions )
653
+ remove_object_scale_keyframes (actions = imported_actions )
647
654
648
655
# round keyframes
649
656
round_keyframes (imported_actions )
@@ -657,4 +664,90 @@ def import_asset(file_path, properties):
657
664
:param object properties: The property group that contains variables that maintain the addon's correct state.
658
665
"""
659
666
if properties .source_application == 'ue4' :
660
- import_unreal_4_asset (file_path )
667
+ import_unreal_4_asset (file_path )
668
+
669
+ clear_undo_history ('Asset Import' )
670
+
671
+
672
+ def recreate_lod_meshes (mesh_objects ):
673
+ """
674
+ This function recreates the provided lod meshes by duplicating them and deleting there originals.
675
+
676
+ :param list mesh_objects: A list of lod mesh objects.
677
+ :return object: The new object.
678
+ """
679
+ new_mesh_objects = []
680
+ # get the current selection and context
681
+ context = get_current_context ()
682
+
683
+ for mesh_object in mesh_objects :
684
+ if 'LOD' in mesh_object .name :
685
+
686
+ previous_object_name = mesh_object .name
687
+ previous_mesh_name = mesh_object .data .name
688
+
689
+ # deselect all objects
690
+ deselect_all_objects ()
691
+
692
+ # select and duplicate the mesh object
693
+ mesh_object .select_set (True )
694
+ bpy .ops .object .duplicate ()
695
+
696
+ # remove the old object
697
+ bpy .data .objects .remove (mesh_object )
698
+
699
+ # remove the old mesh
700
+ previous_mesh = bpy .data .meshes .get (previous_mesh_name )
701
+ if previous_mesh :
702
+ bpy .data .meshes .remove (previous_mesh )
703
+
704
+ new_mesh_object = bpy .context .selected_objects [0 ]
705
+
706
+ # rename the duplicated object to the old name
707
+ new_mesh_object .name = previous_object_name
708
+ # rename the duplicated mesh to the old name
709
+ new_mesh_object .data .name = previous_mesh_name
710
+
711
+ new_mesh_objects .append (new_mesh_object )
712
+
713
+ # restore selection and context
714
+ set_context (context )
715
+
716
+ return new_mesh_objects
717
+
718
+
719
+ def clear_undo_history (message ):
720
+ """
721
+ This function clears blenders undo history by doing a deselect all operation and repeatedly
722
+ pushing that operation into the undo stack until all previous history is cleared from the undo
723
+ history.
724
+
725
+ :param str message: The message to display in the undo history.
726
+ """
727
+ # run this null operator
728
+ bpy .ops .send2ue .null_operator ()
729
+
730
+ # repeatedly push the last operator into the undo stack till there are no more undo steps
731
+ for item in range (0 , bpy .context .preferences .edit .undo_steps + 1 ):
732
+ bpy .ops .ed .undo_push (message = message )
733
+
734
+
735
+ def resolve_path (path ):
736
+ """
737
+ This function checks if a given path is relative and returns the full
738
+ path else returns the original path
739
+
740
+ :param str path: The input path
741
+ :return str: The expanded path
742
+ """
743
+
744
+ # Check for a relative path input. Relative paths are represented
745
+ # by '//' eg. '//another/path/relative/to/blend_file'
746
+ if path .startswith ('//' ) or path .startswith ('./' ):
747
+ # Build an absolute path resolving the relative path from the blend file
748
+ path = bpy .path .abspath (path .replace ("./" , "//" , 1 ))
749
+
750
+ # Make sure the path has the correct OS separators
751
+ path = bpy .path .native_pathsep (path )
752
+
753
+ return path
0 commit comments