Improved loading of blend layouts in Blender to behave like to JSON one

This commit is contained in:
Simone Barbieri 2021-11-12 15:42:10 +00:00
parent d2ae004b49
commit 41220adfca
6 changed files with 62 additions and 22 deletions

View file

@ -42,10 +42,13 @@ def get_unique_number(
return f"{count:0>2}" return f"{count:0>2}"
def prepare_data(data, container_name): def prepare_data(data, container_name=None):
name = data.name name = data.name
local_data = data.make_local() local_data = data.make_local()
local_data.name = f"{container_name}:{name}" if container_name:
local_data.name = f"{container_name}:{name}"
else:
local_data.name = f"{name}"
return local_data return local_data

View file

@ -10,6 +10,7 @@ from avalon import api
from avalon.blender.pipeline import AVALON_CONTAINERS from avalon.blender.pipeline import AVALON_CONTAINERS
from avalon.blender.pipeline import AVALON_CONTAINER_ID from avalon.blender.pipeline import AVALON_CONTAINER_ID
from avalon.blender.pipeline import AVALON_PROPERTY from avalon.blender.pipeline import AVALON_PROPERTY
from openpype import lib
from openpype.hosts.blender.api import plugin from openpype.hosts.blender.api import plugin
@ -59,7 +60,9 @@ class BlendLayoutLoader(plugin.AssetLoader):
library = bpy.data.libraries.get(bpy.path.basename(libpath)) library = bpy.data.libraries.get(bpy.path.basename(libpath))
bpy.data.libraries.remove(library) bpy.data.libraries.remove(library)
def _process(self, libpath, asset_group, group_name, actions): def _process(
self, libpath, asset_group, group_name, asset, representation, actions
):
with bpy.data.libraries.load( with bpy.data.libraries.load(
libpath, link=True, relative=False libpath, link=True, relative=False
) as (data_from, data_to): ) as (data_from, data_to):
@ -106,7 +109,7 @@ class BlendLayoutLoader(plugin.AssetLoader):
parent.objects.link(obj) parent.objects.link(obj)
for obj in objects: for obj in objects:
local_obj = plugin.prepare_data(obj, group_name) local_obj = plugin.prepare_data(obj)
action = None action = None
@ -125,11 +128,12 @@ class BlendLayoutLoader(plugin.AssetLoader):
if material_slot.material: if material_slot.material:
plugin.prepare_data(material_slot.material, group_name) plugin.prepare_data(material_slot.material, group_name)
elif local_obj.type == 'ARMATURE': elif local_obj.type == 'ARMATURE':
plugin.prepare_data(local_obj.data, group_name) plugin.prepare_data(local_obj.data)
if action is not None: if action is not None:
local_obj.animation_data.action = action local_obj.animation_data.action = action
elif local_obj.animation_data.action is not None: elif (local_obj.animation_data and
local_obj.animation_data.action is not None):
plugin.prepare_data( plugin.prepare_data(
local_obj.animation_data.action, group_name) local_obj.animation_data.action, group_name)
@ -140,6 +144,21 @@ class BlendLayoutLoader(plugin.AssetLoader):
for t in v.targets: for t in v.targets:
t.id = local_obj t.id = local_obj
elif local_obj.type == 'EMPTY':
creator_plugin = lib.get_creator_by_name("CreateAnimation")
if not creator_plugin:
raise ValueError("Creator plugin \"CreateAnimation\" was "
"not found.")
api.create(
creator_plugin,
name=local_obj.name.split(':')[-1] + "_animation",
asset=asset,
options={"useSelection": False,
"asset_group": local_obj},
data={"dependencies": representation}
)
if not local_obj.get(AVALON_PROPERTY): if not local_obj.get(AVALON_PROPERTY):
local_obj[AVALON_PROPERTY] = dict() local_obj[AVALON_PROPERTY] = dict()
@ -168,6 +187,7 @@ class BlendLayoutLoader(plugin.AssetLoader):
libpath = self.fname libpath = self.fname
asset = context["asset"]["name"] asset = context["asset"]["name"]
subset = context["subset"]["name"] subset = context["subset"]["name"]
representation = str(context["representation"]["_id"])
asset_name = plugin.asset_name(asset, subset) asset_name = plugin.asset_name(asset, subset)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(asset, subset)
@ -183,7 +203,8 @@ class BlendLayoutLoader(plugin.AssetLoader):
asset_group.empty_display_type = 'SINGLE_ARROW' asset_group.empty_display_type = 'SINGLE_ARROW'
avalon_container.objects.link(asset_group) avalon_container.objects.link(asset_group)
objects = self._process(libpath, asset_group, group_name, None) objects = self._process(
libpath, asset_group, group_name, asset, representation, None)
for child in asset_group.children: for child in asset_group.children:
if child.get(AVALON_PROPERTY): if child.get(AVALON_PROPERTY):

View file

@ -29,12 +29,13 @@ class ExtractBlendAnimation(openpype.api.Extractor):
if isinstance(obj, bpy.types.Object) and obj.type == 'EMPTY': if isinstance(obj, bpy.types.Object) and obj.type == 'EMPTY':
child = obj.children[0] child = obj.children[0]
if child and child.type == 'ARMATURE': if child and child.type == 'ARMATURE':
if not obj.animation_data: if child.animation_data and child.animation_data.action:
obj.animation_data_create() if not obj.animation_data:
obj.animation_data.action = child.animation_data.action obj.animation_data_create()
obj.animation_data_clear() obj.animation_data.action = child.animation_data.action
data_blocks.add(child.animation_data.action) obj.animation_data_clear()
data_blocks.add(obj) data_blocks.add(child.animation_data.action)
data_blocks.add(obj)
bpy.data.libraries.write(filepath, data_blocks) bpy.data.libraries.write(filepath, data_blocks)

View file

@ -123,7 +123,7 @@ class ExtractAnimationFBX(api.Extractor):
json_path = os.path.join(stagingdir, json_filename) json_path = os.path.join(stagingdir, json_filename)
json_dict = { json_dict = {
"instance_name": asset_group.get(AVALON_PROPERTY).get("namespace") "instance_name": asset_group.get(AVALON_PROPERTY).get("objectName")
} }
# collection = instance.data.get("name") # collection = instance.data.get("name")

View file

@ -183,20 +183,35 @@ class AnimationFBXLoader(api.Loader):
task.set_editor_property('destination_name', name) task.set_editor_property('destination_name', name)
task.set_editor_property('replace_existing', True) task.set_editor_property('replace_existing', True)
task.set_editor_property('automated', True) task.set_editor_property('automated', True)
task.set_editor_property('save', False) task.set_editor_property('save', True)
# set import options here # set import options here
task.options.set_editor_property( task.options.set_editor_property(
'automated_import_should_detect_type', True) 'automated_import_should_detect_type', False)
task.options.set_editor_property( task.options.set_editor_property(
'original_import_type', unreal.FBXImportType.FBXIT_ANIMATION) 'original_import_type', unreal.FBXImportType.FBXIT_SKELETAL_MESH)
task.options.set_editor_property(
'mesh_type_to_import', unreal.FBXImportType.FBXIT_ANIMATION)
task.options.set_editor_property('import_mesh', False) task.options.set_editor_property('import_mesh', False)
task.options.set_editor_property('import_animations', True) task.options.set_editor_property('import_animations', True)
task.options.set_editor_property('override_full_name', True)
task.options.skeletal_mesh_import_data.set_editor_property( task.options.anim_sequence_import_data.set_editor_property(
'import_content_type', 'animation_length',
unreal.FBXImportContentType.FBXICT_SKINNING_WEIGHTS unreal.FBXAnimationLengthImportType.FBXALIT_EXPORTED_TIME
) )
task.options.anim_sequence_import_data.set_editor_property(
'import_meshes_in_bone_hierarchy', False)
task.options.anim_sequence_import_data.set_editor_property(
'use_default_sample_rate', True)
task.options.anim_sequence_import_data.set_editor_property(
'import_custom_attribute', True)
task.options.anim_sequence_import_data.set_editor_property(
'import_bone_tracks', True)
task.options.anim_sequence_import_data.set_editor_property(
'remove_redundant_keys', True)
task.options.anim_sequence_import_data.set_editor_property(
'convert_scene', True)
skeletal_mesh = unreal.EditorAssetLibrary.load_asset( skeletal_mesh = unreal.EditorAssetLibrary.load_asset(
container.get('namespace') + "/" + container.get('asset_name')) container.get('namespace') + "/" + container.get('asset_name'))
@ -229,7 +244,7 @@ class AnimationFBXLoader(api.Loader):
unreal.EditorAssetLibrary.delete_directory(path) unreal.EditorAssetLibrary.delete_directory(path)
asset_content = unreal.EditorAssetLibrary.list_assets( asset_content = unreal.EditorAssetLibrary.list_assets(
parent_path, recursive=False parent_path, recursive=False, include_folder=True
) )
if len(asset_content) == 0: if len(asset_content) == 0:

View file

@ -504,7 +504,7 @@ class LayoutLoader(api.Loader):
EditorAssetLibrary.delete_directory(path) EditorAssetLibrary.delete_directory(path)
asset_content = EditorAssetLibrary.list_assets( asset_content = EditorAssetLibrary.list_assets(
parent_path, recursive=False parent_path, recursive=False, include_folder=True
) )
if len(asset_content) == 0: if len(asset_content) == 0: