mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
Merge pull request #3116 from simonebarbieri/enhancement/unreal-layouts_and_camera_update_and_improvements
This commit is contained in:
commit
7fbb1dfa91
6 changed files with 607 additions and 309 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
|
import os
|
||||||
|
|
||||||
import unreal
|
import unreal
|
||||||
|
|
||||||
|
from openpype.api import Anatomy
|
||||||
from openpype.hosts.unreal.api import pipeline
|
from openpype.hosts.unreal.api import pipeline
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,6 +49,15 @@ def start_rendering():
|
||||||
if data["family"] == "render":
|
if data["family"] == "render":
|
||||||
inst_data.append(data)
|
inst_data.append(data)
|
||||||
|
|
||||||
|
try:
|
||||||
|
project = os.environ.get("AVALON_PROJECT")
|
||||||
|
anatomy = Anatomy(project)
|
||||||
|
root = anatomy.roots['renders']
|
||||||
|
except Exception:
|
||||||
|
raise Exception("Could not find render root in anatomy settings.")
|
||||||
|
|
||||||
|
render_dir = f"{root}/{project}"
|
||||||
|
|
||||||
# subsystem = unreal.get_editor_subsystem(
|
# subsystem = unreal.get_editor_subsystem(
|
||||||
# unreal.MoviePipelineQueueSubsystem)
|
# unreal.MoviePipelineQueueSubsystem)
|
||||||
# queue = subsystem.get_queue()
|
# queue = subsystem.get_queue()
|
||||||
|
|
@ -105,7 +117,7 @@ def start_rendering():
|
||||||
settings.custom_end_frame = r.get("frame_range")[1]
|
settings.custom_end_frame = r.get("frame_range")[1]
|
||||||
settings.use_custom_playback_range = True
|
settings.use_custom_playback_range = True
|
||||||
settings.file_name_format = "{sequence_name}.{frame_number}"
|
settings.file_name_format = "{sequence_name}.{frame_number}"
|
||||||
settings.output_directory.path += r.get('output')
|
settings.output_directory.path = f"{render_dir}/{r.get('output')}"
|
||||||
|
|
||||||
renderPass = job.get_configuration().find_or_add_setting_by_class(
|
renderPass = job.get_configuration().find_or_add_setting_by_class(
|
||||||
unreal.MoviePipelineDeferredPassBase)
|
unreal.MoviePipelineDeferredPassBase)
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,6 @@ class AnimationFBXLoader(plugin.Loader):
|
||||||
Returns:
|
Returns:
|
||||||
list(str): list of container content
|
list(str): list of container content
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Create directory for asset and avalon container
|
# Create directory for asset and avalon container
|
||||||
hierarchy = context.get('asset').get('data').get('parents')
|
hierarchy = context.get('asset').get('data').get('parents')
|
||||||
root = "/Game/OpenPype"
|
root = "/Game/OpenPype"
|
||||||
|
|
@ -149,11 +148,30 @@ class AnimationFBXLoader(plugin.Loader):
|
||||||
asset_dir, container_name = tools.create_unique_asset_name(
|
asset_dir, container_name = tools.create_unique_asset_name(
|
||||||
f"{root}/Animations/{asset}/{name}", suffix="")
|
f"{root}/Animations/{asset}/{name}", suffix="")
|
||||||
|
|
||||||
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
|
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["World"],
|
||||||
|
package_paths=[f"{root}/{hierarchy[0]}"],
|
||||||
|
recursive_paths=False)
|
||||||
|
levels = ar.get_assets(filter)
|
||||||
|
master_level = levels[0].get_editor_property('object_path')
|
||||||
|
|
||||||
hierarchy_dir = root
|
hierarchy_dir = root
|
||||||
for h in hierarchy:
|
for h in hierarchy:
|
||||||
hierarchy_dir = f"{hierarchy_dir}/{h}"
|
hierarchy_dir = f"{hierarchy_dir}/{h}"
|
||||||
hierarchy_dir = f"{hierarchy_dir}/{asset}"
|
hierarchy_dir = f"{hierarchy_dir}/{asset}"
|
||||||
|
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["World"],
|
||||||
|
package_paths=[f"{hierarchy_dir}/"],
|
||||||
|
recursive_paths=True)
|
||||||
|
levels = ar.get_assets(filter)
|
||||||
|
level = levels[0].get_editor_property('object_path')
|
||||||
|
|
||||||
|
unreal.EditorLevelLibrary.save_all_dirty_levels()
|
||||||
|
unreal.EditorLevelLibrary.load_level(level)
|
||||||
|
|
||||||
container_name += suffix
|
container_name += suffix
|
||||||
|
|
||||||
EditorAssetLibrary.make_directory(asset_dir)
|
EditorAssetLibrary.make_directory(asset_dir)
|
||||||
|
|
@ -165,7 +183,7 @@ class AnimationFBXLoader(plugin.Loader):
|
||||||
|
|
||||||
instance_name = data.get("instance_name")
|
instance_name = data.get("instance_name")
|
||||||
|
|
||||||
animation = self._process(asset_dir, container_name, instance_name)
|
animation = self._process(asset_dir, asset_name, instance_name)
|
||||||
|
|
||||||
asset_content = EditorAssetLibrary.list_assets(
|
asset_content = EditorAssetLibrary.list_assets(
|
||||||
hierarchy_dir, recursive=True, include_folder=False)
|
hierarchy_dir, recursive=True, include_folder=False)
|
||||||
|
|
@ -224,6 +242,9 @@ class AnimationFBXLoader(plugin.Loader):
|
||||||
for a in imported_content:
|
for a in imported_content:
|
||||||
EditorAssetLibrary.save_asset(a)
|
EditorAssetLibrary.save_asset(a)
|
||||||
|
|
||||||
|
unreal.EditorLevelLibrary.save_current_level()
|
||||||
|
unreal.EditorLevelLibrary.load_level(master_level)
|
||||||
|
|
||||||
def update(self, container, representation):
|
def update(self, container, representation):
|
||||||
name = container["asset_name"]
|
name = container["asset_name"]
|
||||||
source_path = get_representation_path(representation)
|
source_path = get_representation_path(representation)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Load camera from FBX."""
|
"""Load camera from FBX."""
|
||||||
import os
|
from pathlib import Path
|
||||||
|
|
||||||
import unreal
|
import unreal
|
||||||
from unreal import EditorAssetLibrary
|
from unreal import EditorAssetLibrary
|
||||||
|
|
@ -268,68 +268,242 @@ class CameraLoader(plugin.Loader):
|
||||||
return asset_content
|
return asset_content
|
||||||
|
|
||||||
def update(self, container, representation):
|
def update(self, container, representation):
|
||||||
path = container["namespace"]
|
|
||||||
|
|
||||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
|
||||||
|
|
||||||
asset_content = EditorAssetLibrary.list_assets(
|
root = "/Game/OpenPype"
|
||||||
path, recursive=False, include_folder=False
|
|
||||||
)
|
|
||||||
asset_name = ""
|
|
||||||
for a in asset_content:
|
|
||||||
asset = ar.get_asset_by_object_path(a)
|
|
||||||
if a.endswith("_CON"):
|
|
||||||
loaded_asset = EditorAssetLibrary.load_asset(a)
|
|
||||||
EditorAssetLibrary.set_metadata_tag(
|
|
||||||
loaded_asset, "representation", str(representation["_id"])
|
|
||||||
)
|
|
||||||
EditorAssetLibrary.set_metadata_tag(
|
|
||||||
loaded_asset, "parent", str(representation["parent"])
|
|
||||||
)
|
|
||||||
asset_name = EditorAssetLibrary.get_metadata_tag(
|
|
||||||
loaded_asset, "asset_name"
|
|
||||||
)
|
|
||||||
elif asset.asset_class == "LevelSequence":
|
|
||||||
EditorAssetLibrary.delete_asset(a)
|
|
||||||
|
|
||||||
sequence = tools.create_asset(
|
asset_dir = container.get('namespace')
|
||||||
asset_name=asset_name,
|
|
||||||
package_path=path,
|
context = representation.get("context")
|
||||||
asset_class=unreal.LevelSequence,
|
|
||||||
factory=unreal.LevelSequenceFactoryNew()
|
hierarchy = context.get('hierarchy').split("/")
|
||||||
|
h_dir = f"{root}/{hierarchy[0]}"
|
||||||
|
h_asset = hierarchy[0]
|
||||||
|
master_level = f"{h_dir}/{h_asset}_map.{h_asset}_map"
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_current_level()
|
||||||
|
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["LevelSequence"],
|
||||||
|
package_paths=[asset_dir],
|
||||||
|
recursive_paths=False)
|
||||||
|
sequences = ar.get_assets(filter)
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["World"],
|
||||||
|
package_paths=[str(Path(asset_dir).parent.as_posix())],
|
||||||
|
recursive_paths=True)
|
||||||
|
maps = ar.get_assets(filter)
|
||||||
|
|
||||||
|
# There should be only one map in the list
|
||||||
|
EditorLevelLibrary.load_level(maps[0].get_full_name())
|
||||||
|
|
||||||
|
level_sequence = sequences[0].get_asset()
|
||||||
|
|
||||||
|
display_rate = level_sequence.get_display_rate()
|
||||||
|
playback_start = level_sequence.get_playback_start()
|
||||||
|
playback_end = level_sequence.get_playback_end()
|
||||||
|
|
||||||
|
sequence_name = f"{container.get('asset')}_camera"
|
||||||
|
|
||||||
|
# Get the actors in the level sequence.
|
||||||
|
objs = unreal.SequencerTools.get_bound_objects(
|
||||||
|
unreal.EditorLevelLibrary.get_editor_world(),
|
||||||
|
level_sequence,
|
||||||
|
level_sequence.get_bindings(),
|
||||||
|
unreal.SequencerScriptingRange(
|
||||||
|
has_start_value=True,
|
||||||
|
has_end_value=True,
|
||||||
|
inclusive_start=level_sequence.get_playback_start(),
|
||||||
|
exclusive_end=level_sequence.get_playback_end()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
io_asset = legacy_io.Session["AVALON_ASSET"]
|
# Delete actors from the map
|
||||||
asset_doc = legacy_io.find_one({
|
for o in objs:
|
||||||
"type": "asset",
|
if o.bound_objects[0].get_class().get_name() == "CineCameraActor":
|
||||||
"name": io_asset
|
actor_path = o.bound_objects[0].get_path_name().split(":")[-1]
|
||||||
})
|
actor = EditorLevelLibrary.get_actor_reference(actor_path)
|
||||||
|
EditorLevelLibrary.destroy_actor(actor)
|
||||||
|
|
||||||
data = asset_doc.get("data")
|
# Remove the Level Sequence from the parent.
|
||||||
|
# We need to traverse the hierarchy from the master sequence to find
|
||||||
|
# the level sequence.
|
||||||
|
root = "/Game/OpenPype"
|
||||||
|
namespace = container.get('namespace').replace(f"{root}/", "")
|
||||||
|
ms_asset = namespace.split('/')[0]
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["LevelSequence"],
|
||||||
|
package_paths=[f"{root}/{ms_asset}"],
|
||||||
|
recursive_paths=False)
|
||||||
|
sequences = ar.get_assets(filter)
|
||||||
|
master_sequence = sequences[0].get_asset()
|
||||||
|
|
||||||
if data:
|
sequences = [master_sequence]
|
||||||
sequence.set_display_rate(unreal.FrameRate(data.get("fps"), 1.0))
|
|
||||||
sequence.set_playback_start(data.get("frameStart"))
|
parent = None
|
||||||
sequence.set_playback_end(data.get("frameEnd"))
|
sub_scene = None
|
||||||
|
for s in sequences:
|
||||||
|
tracks = s.get_master_tracks()
|
||||||
|
subscene_track = None
|
||||||
|
for t in tracks:
|
||||||
|
if t.get_class() == unreal.MovieSceneSubTrack.static_class():
|
||||||
|
subscene_track = t
|
||||||
|
break
|
||||||
|
if subscene_track:
|
||||||
|
sections = subscene_track.get_sections()
|
||||||
|
for ss in sections:
|
||||||
|
if ss.get_sequence().get_name() == sequence_name:
|
||||||
|
parent = s
|
||||||
|
sub_scene = ss
|
||||||
|
# subscene_track.remove_section(ss)
|
||||||
|
break
|
||||||
|
sequences.append(ss.get_sequence())
|
||||||
|
# Update subscenes indexes.
|
||||||
|
i = 0
|
||||||
|
for ss in sections:
|
||||||
|
ss.set_row_index(i)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if parent:
|
||||||
|
break
|
||||||
|
|
||||||
|
assert parent, "Could not find the parent sequence"
|
||||||
|
|
||||||
|
EditorAssetLibrary.delete_asset(level_sequence.get_path_name())
|
||||||
|
|
||||||
settings = unreal.MovieSceneUserImportFBXSettings()
|
settings = unreal.MovieSceneUserImportFBXSettings()
|
||||||
settings.set_editor_property('reduce_keys', False)
|
settings.set_editor_property('reduce_keys', False)
|
||||||
|
|
||||||
|
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
||||||
|
new_sequence = tools.create_asset(
|
||||||
|
asset_name=sequence_name,
|
||||||
|
package_path=asset_dir,
|
||||||
|
asset_class=unreal.LevelSequence,
|
||||||
|
factory=unreal.LevelSequenceFactoryNew()
|
||||||
|
)
|
||||||
|
|
||||||
|
new_sequence.set_display_rate(display_rate)
|
||||||
|
new_sequence.set_playback_start(playback_start)
|
||||||
|
new_sequence.set_playback_end(playback_end)
|
||||||
|
|
||||||
|
sub_scene.set_sequence(new_sequence)
|
||||||
|
|
||||||
unreal.SequencerTools.import_fbx(
|
unreal.SequencerTools.import_fbx(
|
||||||
EditorLevelLibrary.get_editor_world(),
|
EditorLevelLibrary.get_editor_world(),
|
||||||
sequence,
|
new_sequence,
|
||||||
sequence.get_bindings(),
|
new_sequence.get_bindings(),
|
||||||
settings,
|
settings,
|
||||||
str(representation["data"]["path"])
|
str(representation["data"]["path"])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"representation": str(representation["_id"]),
|
||||||
|
"parent": str(representation["parent"])
|
||||||
|
}
|
||||||
|
unreal_pipeline.imprint(
|
||||||
|
"{}/{}".format(asset_dir, container.get('container_name')), data)
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_current_level()
|
||||||
|
|
||||||
|
asset_content = EditorAssetLibrary.list_assets(
|
||||||
|
asset_dir, recursive=True, include_folder=False)
|
||||||
|
|
||||||
|
for a in asset_content:
|
||||||
|
EditorAssetLibrary.save_asset(a)
|
||||||
|
|
||||||
|
EditorLevelLibrary.load_level(master_level)
|
||||||
|
|
||||||
def remove(self, container):
|
def remove(self, container):
|
||||||
path = container["namespace"]
|
path = Path(container.get("namespace"))
|
||||||
parent_path = os.path.dirname(path)
|
parent_path = str(path.parent.as_posix())
|
||||||
|
|
||||||
EditorAssetLibrary.delete_directory(path)
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["LevelSequence"],
|
||||||
|
package_paths=[f"{str(path.as_posix())}"],
|
||||||
|
recursive_paths=False)
|
||||||
|
sequences = ar.get_assets(filter)
|
||||||
|
|
||||||
|
if not sequences:
|
||||||
|
raise Exception("Could not find sequence.")
|
||||||
|
|
||||||
|
world = ar.get_asset_by_object_path(
|
||||||
|
EditorLevelLibrary.get_editor_world().get_path_name())
|
||||||
|
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["World"],
|
||||||
|
package_paths=[f"{parent_path}"],
|
||||||
|
recursive_paths=True)
|
||||||
|
maps = ar.get_assets(filter)
|
||||||
|
|
||||||
|
# There should be only one map in the list
|
||||||
|
if not maps:
|
||||||
|
raise Exception("Could not find map.")
|
||||||
|
|
||||||
|
map = maps[0]
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_all_dirty_levels()
|
||||||
|
EditorLevelLibrary.load_level(map.get_full_name())
|
||||||
|
|
||||||
|
# Remove the camera from the level.
|
||||||
|
actors = EditorLevelLibrary.get_all_level_actors()
|
||||||
|
|
||||||
|
for a in actors:
|
||||||
|
if a.__class__ == unreal.CineCameraActor:
|
||||||
|
EditorLevelLibrary.destroy_actor(a)
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_all_dirty_levels()
|
||||||
|
EditorLevelLibrary.load_level(world.get_full_name())
|
||||||
|
|
||||||
|
# There should be only one sequence in the path.
|
||||||
|
sequence_name = sequences[0].asset_name
|
||||||
|
|
||||||
|
# Remove the Level Sequence from the parent.
|
||||||
|
# We need to traverse the hierarchy from the master sequence to find
|
||||||
|
# the level sequence.
|
||||||
|
root = "/Game/OpenPype"
|
||||||
|
namespace = container.get('namespace').replace(f"{root}/", "")
|
||||||
|
ms_asset = namespace.split('/')[0]
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["LevelSequence"],
|
||||||
|
package_paths=[f"{root}/{ms_asset}"],
|
||||||
|
recursive_paths=False)
|
||||||
|
sequences = ar.get_assets(filter)
|
||||||
|
master_sequence = sequences[0].get_asset()
|
||||||
|
|
||||||
|
sequences = [master_sequence]
|
||||||
|
|
||||||
|
parent = None
|
||||||
|
for s in sequences:
|
||||||
|
tracks = s.get_master_tracks()
|
||||||
|
subscene_track = None
|
||||||
|
for t in tracks:
|
||||||
|
if t.get_class() == unreal.MovieSceneSubTrack.static_class():
|
||||||
|
subscene_track = t
|
||||||
|
break
|
||||||
|
if subscene_track:
|
||||||
|
sections = subscene_track.get_sections()
|
||||||
|
for ss in sections:
|
||||||
|
if ss.get_sequence().get_name() == sequence_name:
|
||||||
|
parent = s
|
||||||
|
subscene_track.remove_section(ss)
|
||||||
|
break
|
||||||
|
sequences.append(ss.get_sequence())
|
||||||
|
# Update subscenes indexes.
|
||||||
|
i = 0
|
||||||
|
for ss in sections:
|
||||||
|
ss.set_row_index(i)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if parent:
|
||||||
|
break
|
||||||
|
|
||||||
|
assert parent, "Could not find the parent sequence"
|
||||||
|
|
||||||
|
EditorAssetLibrary.delete_directory(str(path.as_posix()))
|
||||||
|
|
||||||
|
# Check if there isn't any more assets in the parent folder, and
|
||||||
|
# delete it if not.
|
||||||
asset_content = EditorAssetLibrary.list_assets(
|
asset_content = EditorAssetLibrary.list_assets(
|
||||||
parent_path, recursive=False, include_folder=True
|
parent_path, recursive=False, include_folder=True
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,13 @@ class LayoutLoader(plugin.Loader):
|
||||||
|
|
||||||
actors.append(actor)
|
actors.append(actor)
|
||||||
|
|
||||||
|
binding = None
|
||||||
|
for p in sequence.get_possessables():
|
||||||
|
if p.get_name() == actor.get_name():
|
||||||
|
binding = p
|
||||||
|
break
|
||||||
|
|
||||||
|
if not binding:
|
||||||
binding = sequence.add_possessable(actor)
|
binding = sequence.add_possessable(actor)
|
||||||
|
|
||||||
bindings.append(binding)
|
bindings.append(binding)
|
||||||
|
|
@ -299,16 +306,102 @@ class LayoutLoader(plugin.Loader):
|
||||||
# Add animation to the sequencer
|
# Add animation to the sequencer
|
||||||
bindings = bindings_dict.get(instance_name)
|
bindings = bindings_dict.get(instance_name)
|
||||||
|
|
||||||
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
|
|
||||||
for binding in bindings:
|
for binding in bindings:
|
||||||
binding.add_track(unreal.MovieSceneSkeletalAnimationTrack)
|
tracks = binding.get_tracks()
|
||||||
for track in binding.get_tracks():
|
track = None
|
||||||
|
if not tracks:
|
||||||
|
track = binding.add_track(
|
||||||
|
unreal.MovieSceneSkeletalAnimationTrack)
|
||||||
|
else:
|
||||||
|
track = tracks[0]
|
||||||
|
|
||||||
|
sections = track.get_sections()
|
||||||
|
section = None
|
||||||
|
if not sections:
|
||||||
section = track.add_section()
|
section = track.add_section()
|
||||||
|
else:
|
||||||
|
section = sections[0]
|
||||||
|
|
||||||
|
sec_params = section.get_editor_property('params')
|
||||||
|
curr_anim = sec_params.get_editor_property('animation')
|
||||||
|
|
||||||
|
if curr_anim:
|
||||||
|
# Checks if the animation path has a container.
|
||||||
|
# If it does, it means that the animation is already
|
||||||
|
# in the sequencer.
|
||||||
|
anim_path = str(Path(
|
||||||
|
curr_anim.get_path_name()).parent
|
||||||
|
).replace('\\', '/')
|
||||||
|
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["AssetContainer"],
|
||||||
|
package_paths=[anim_path],
|
||||||
|
recursive_paths=False)
|
||||||
|
containers = ar.get_assets(filter)
|
||||||
|
|
||||||
|
if len(containers) > 0:
|
||||||
|
return
|
||||||
|
|
||||||
section.set_range(
|
section.set_range(
|
||||||
sequence.get_playback_start(),
|
sequence.get_playback_start(),
|
||||||
sequence.get_playback_end())
|
sequence.get_playback_end())
|
||||||
sec_params = section.get_editor_property('params')
|
sec_params = section.get_editor_property('params')
|
||||||
sec_params.set_editor_property('animation', animation)
|
sec_params.set_editor_property('animation', animation)
|
||||||
|
|
||||||
|
def _generate_sequence(self, h, h_dir):
|
||||||
|
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
||||||
|
|
||||||
|
sequence = tools.create_asset(
|
||||||
|
asset_name=h,
|
||||||
|
package_path=h_dir,
|
||||||
|
asset_class=unreal.LevelSequence,
|
||||||
|
factory=unreal.LevelSequenceFactoryNew()
|
||||||
|
)
|
||||||
|
|
||||||
|
asset_data = legacy_io.find_one({
|
||||||
|
"type": "asset",
|
||||||
|
"name": h_dir.split('/')[-1]
|
||||||
|
})
|
||||||
|
|
||||||
|
id = asset_data.get('_id')
|
||||||
|
|
||||||
|
start_frames = []
|
||||||
|
end_frames = []
|
||||||
|
|
||||||
|
elements = list(
|
||||||
|
legacy_io.find({"type": "asset", "data.visualParent": id}))
|
||||||
|
for e in elements:
|
||||||
|
start_frames.append(e.get('data').get('clipIn'))
|
||||||
|
end_frames.append(e.get('data').get('clipOut'))
|
||||||
|
|
||||||
|
elements.extend(legacy_io.find({
|
||||||
|
"type": "asset",
|
||||||
|
"data.visualParent": e.get('_id')
|
||||||
|
}))
|
||||||
|
|
||||||
|
min_frame = min(start_frames)
|
||||||
|
max_frame = max(end_frames)
|
||||||
|
|
||||||
|
sequence.set_display_rate(
|
||||||
|
unreal.FrameRate(asset_data.get('data').get("fps"), 1.0))
|
||||||
|
sequence.set_playback_start(min_frame)
|
||||||
|
sequence.set_playback_end(max_frame)
|
||||||
|
|
||||||
|
tracks = sequence.get_master_tracks()
|
||||||
|
track = None
|
||||||
|
for t in tracks:
|
||||||
|
if (t.get_class() ==
|
||||||
|
unreal.MovieSceneCameraCutTrack.static_class()):
|
||||||
|
track = t
|
||||||
|
break
|
||||||
|
if not track:
|
||||||
|
track = sequence.add_master_track(
|
||||||
|
unreal.MovieSceneCameraCutTrack)
|
||||||
|
|
||||||
|
return sequence, (min_frame, max_frame)
|
||||||
|
|
||||||
def _process(self, lib_path, asset_dir, sequence, loaded=None):
|
def _process(self, lib_path, asset_dir, sequence, loaded=None):
|
||||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
|
|
||||||
|
|
@ -326,6 +419,8 @@ class LayoutLoader(plugin.Loader):
|
||||||
actors_dict = {}
|
actors_dict = {}
|
||||||
bindings_dict = {}
|
bindings_dict = {}
|
||||||
|
|
||||||
|
loaded_assets = []
|
||||||
|
|
||||||
for element in data:
|
for element in data:
|
||||||
reference = None
|
reference = None
|
||||||
if element.get('reference_fbx'):
|
if element.get('reference_fbx'):
|
||||||
|
|
@ -360,7 +455,7 @@ class LayoutLoader(plugin.Loader):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
"asset_dir": asset_dir
|
# "asset_dir": asset_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
assets = load_container(
|
assets = load_container(
|
||||||
|
|
@ -370,6 +465,17 @@ class LayoutLoader(plugin.Loader):
|
||||||
options=options
|
options=options
|
||||||
)
|
)
|
||||||
|
|
||||||
|
container = None
|
||||||
|
|
||||||
|
for asset in assets:
|
||||||
|
obj = ar.get_asset_by_object_path(asset).get_asset()
|
||||||
|
if obj.get_class().get_name() == 'AssetContainer':
|
||||||
|
container = obj
|
||||||
|
if obj.get_class().get_name() == 'Skeleton':
|
||||||
|
skeleton = obj
|
||||||
|
|
||||||
|
loaded_assets.append(container.get_path_name())
|
||||||
|
|
||||||
instances = [
|
instances = [
|
||||||
item for item in data
|
item for item in data
|
||||||
if (item.get('reference_fbx') == reference or
|
if (item.get('reference_fbx') == reference or
|
||||||
|
|
@ -390,15 +496,6 @@ class LayoutLoader(plugin.Loader):
|
||||||
actors_dict[inst] = actors
|
actors_dict[inst] = actors
|
||||||
bindings_dict[inst] = bindings
|
bindings_dict[inst] = bindings
|
||||||
|
|
||||||
if family == 'rig':
|
|
||||||
# Finds skeleton among the imported assets
|
|
||||||
for asset in assets:
|
|
||||||
obj = ar.get_asset_by_object_path(asset).get_asset()
|
|
||||||
if obj.get_class().get_name() == 'Skeleton':
|
|
||||||
skeleton = obj
|
|
||||||
if skeleton:
|
|
||||||
break
|
|
||||||
|
|
||||||
if skeleton:
|
if skeleton:
|
||||||
skeleton_dict[reference] = skeleton
|
skeleton_dict[reference] = skeleton
|
||||||
else:
|
else:
|
||||||
|
|
@ -411,6 +508,8 @@ class LayoutLoader(plugin.Loader):
|
||||||
asset_dir, path, instance_name, skeleton, actors_dict,
|
asset_dir, path, instance_name, skeleton, actors_dict,
|
||||||
animation_file, bindings_dict, sequence)
|
animation_file, bindings_dict, sequence)
|
||||||
|
|
||||||
|
return loaded_assets
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _remove_family(assets, components, class_name, prop_name):
|
def _remove_family(assets, components, class_name, prop_name):
|
||||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
|
|
@ -478,10 +577,10 @@ class LayoutLoader(plugin.Loader):
|
||||||
hierarchy = context.get('asset').get('data').get('parents')
|
hierarchy = context.get('asset').get('data').get('parents')
|
||||||
root = self.ASSET_ROOT
|
root = self.ASSET_ROOT
|
||||||
hierarchy_dir = root
|
hierarchy_dir = root
|
||||||
hierarchy_list = []
|
hierarchy_dir_list = []
|
||||||
for h in hierarchy:
|
for h in hierarchy:
|
||||||
hierarchy_dir = f"{hierarchy_dir}/{h}"
|
hierarchy_dir = f"{hierarchy_dir}/{h}"
|
||||||
hierarchy_list.append(hierarchy_dir)
|
hierarchy_dir_list.append(hierarchy_dir)
|
||||||
asset = context.get('asset').get('name')
|
asset = context.get('asset').get('name')
|
||||||
suffix = "_CON"
|
suffix = "_CON"
|
||||||
if asset:
|
if asset:
|
||||||
|
|
@ -499,43 +598,31 @@ class LayoutLoader(plugin.Loader):
|
||||||
|
|
||||||
# Create map for the shot, and create hierarchy of map. If the maps
|
# Create map for the shot, and create hierarchy of map. If the maps
|
||||||
# already exist, we will use them.
|
# already exist, we will use them.
|
||||||
maps = []
|
h_dir = hierarchy_dir_list[0]
|
||||||
for h in hierarchy_list:
|
h_asset = hierarchy[0]
|
||||||
a = h.split('/')[-1]
|
master_level = f"{h_dir}/{h_asset}_map.{h_asset}_map"
|
||||||
map = f"{h}/{a}_map.{a}_map"
|
if not EditorAssetLibrary.does_asset_exist(master_level):
|
||||||
new = False
|
EditorLevelLibrary.new_level(f"{h_dir}/{h_asset}_map")
|
||||||
|
|
||||||
if not EditorAssetLibrary.does_asset_exist(map):
|
|
||||||
EditorLevelLibrary.new_level(f"{h}/{a}_map")
|
|
||||||
new = True
|
|
||||||
|
|
||||||
maps.append({"map": map, "new": new})
|
|
||||||
|
|
||||||
|
level = f"{asset_dir}/{asset}_map.{asset}_map"
|
||||||
EditorLevelLibrary.new_level(f"{asset_dir}/{asset}_map")
|
EditorLevelLibrary.new_level(f"{asset_dir}/{asset}_map")
|
||||||
maps.append(
|
|
||||||
{"map": f"{asset_dir}/{asset}_map.{asset}_map", "new": True})
|
|
||||||
|
|
||||||
for i in range(0, len(maps) - 1):
|
EditorLevelLibrary.load_level(master_level)
|
||||||
for j in range(i + 1, len(maps)):
|
|
||||||
if maps[j].get('new'):
|
|
||||||
EditorLevelLibrary.load_level(maps[i].get('map'))
|
|
||||||
EditorLevelUtils.add_level_to_world(
|
EditorLevelUtils.add_level_to_world(
|
||||||
EditorLevelLibrary.get_editor_world(),
|
EditorLevelLibrary.get_editor_world(),
|
||||||
maps[j].get('map'),
|
level,
|
||||||
unreal.LevelStreamingDynamic
|
unreal.LevelStreamingDynamic
|
||||||
)
|
)
|
||||||
EditorLevelLibrary.save_all_dirty_levels()
|
EditorLevelLibrary.save_all_dirty_levels()
|
||||||
|
EditorLevelLibrary.load_level(level)
|
||||||
EditorLevelLibrary.load_level(maps[-1].get('map'))
|
|
||||||
|
|
||||||
# Get all the sequences in the hierarchy. It will create them, if
|
# Get all the sequences in the hierarchy. It will create them, if
|
||||||
# they don't exist.
|
# they don't exist.
|
||||||
sequences = []
|
sequences = []
|
||||||
frame_ranges = []
|
frame_ranges = []
|
||||||
i = 0
|
for (h_dir, h) in zip(hierarchy_dir_list, hierarchy):
|
||||||
for h in hierarchy_list:
|
|
||||||
root_content = EditorAssetLibrary.list_assets(
|
root_content = EditorAssetLibrary.list_assets(
|
||||||
h, recursive=False, include_folder=False)
|
h_dir, recursive=False, include_folder=False)
|
||||||
|
|
||||||
existing_sequences = [
|
existing_sequences = [
|
||||||
EditorAssetLibrary.find_asset_data(asset)
|
EditorAssetLibrary.find_asset_data(asset)
|
||||||
|
|
@ -545,55 +632,10 @@ class LayoutLoader(plugin.Loader):
|
||||||
]
|
]
|
||||||
|
|
||||||
if not existing_sequences:
|
if not existing_sequences:
|
||||||
sequence = tools.create_asset(
|
sequence, frame_range = self._generate_sequence(h, h_dir)
|
||||||
asset_name=hierarchy[i],
|
|
||||||
package_path=h,
|
|
||||||
asset_class=unreal.LevelSequence,
|
|
||||||
factory=unreal.LevelSequenceFactoryNew()
|
|
||||||
)
|
|
||||||
|
|
||||||
asset_data = legacy_io.find_one({
|
|
||||||
"type": "asset",
|
|
||||||
"name": h.split('/')[-1]
|
|
||||||
})
|
|
||||||
|
|
||||||
id = asset_data.get('_id')
|
|
||||||
|
|
||||||
start_frames = []
|
|
||||||
end_frames = []
|
|
||||||
|
|
||||||
elements = list(
|
|
||||||
legacy_io.find({"type": "asset", "data.visualParent": id}))
|
|
||||||
for e in elements:
|
|
||||||
start_frames.append(e.get('data').get('clipIn'))
|
|
||||||
end_frames.append(e.get('data').get('clipOut'))
|
|
||||||
|
|
||||||
elements.extend(legacy_io.find({
|
|
||||||
"type": "asset",
|
|
||||||
"data.visualParent": e.get('_id')
|
|
||||||
}))
|
|
||||||
|
|
||||||
min_frame = min(start_frames)
|
|
||||||
max_frame = max(end_frames)
|
|
||||||
|
|
||||||
sequence.set_display_rate(
|
|
||||||
unreal.FrameRate(asset_data.get('data').get("fps"), 1.0))
|
|
||||||
sequence.set_playback_start(min_frame)
|
|
||||||
sequence.set_playback_end(max_frame)
|
|
||||||
|
|
||||||
sequences.append(sequence)
|
sequences.append(sequence)
|
||||||
frame_ranges.append((min_frame, max_frame))
|
frame_ranges.append(frame_range)
|
||||||
|
|
||||||
tracks = sequence.get_master_tracks()
|
|
||||||
track = None
|
|
||||||
for t in tracks:
|
|
||||||
if (t.get_class() ==
|
|
||||||
unreal.MovieSceneCameraCutTrack.static_class()):
|
|
||||||
track = t
|
|
||||||
break
|
|
||||||
if not track:
|
|
||||||
track = sequence.add_master_track(
|
|
||||||
unreal.MovieSceneCameraCutTrack)
|
|
||||||
else:
|
else:
|
||||||
for e in existing_sequences:
|
for e in existing_sequences:
|
||||||
sequences.append(e.get_asset())
|
sequences.append(e.get_asset())
|
||||||
|
|
@ -601,8 +643,6 @@ class LayoutLoader(plugin.Loader):
|
||||||
e.get_asset().get_playback_start(),
|
e.get_asset().get_playback_start(),
|
||||||
e.get_asset().get_playback_end()))
|
e.get_asset().get_playback_end()))
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
shot = tools.create_asset(
|
shot = tools.create_asset(
|
||||||
asset_name=asset,
|
asset_name=asset,
|
||||||
package_path=asset_dir,
|
package_path=asset_dir,
|
||||||
|
|
@ -612,15 +652,11 @@ class LayoutLoader(plugin.Loader):
|
||||||
|
|
||||||
# sequences and frame_ranges have the same length
|
# sequences and frame_ranges have the same length
|
||||||
for i in range(0, len(sequences) - 1):
|
for i in range(0, len(sequences) - 1):
|
||||||
maps_to_add = []
|
|
||||||
for j in range(i + 1, len(maps)):
|
|
||||||
maps_to_add.append(maps[j].get('map'))
|
|
||||||
|
|
||||||
self._set_sequence_hierarchy(
|
self._set_sequence_hierarchy(
|
||||||
sequences[i], sequences[i + 1],
|
sequences[i], sequences[i + 1],
|
||||||
frame_ranges[i][1],
|
frame_ranges[i][1],
|
||||||
frame_ranges[i + 1][0], frame_ranges[i + 1][1],
|
frame_ranges[i + 1][0], frame_ranges[i + 1][1],
|
||||||
maps_to_add)
|
[level])
|
||||||
|
|
||||||
data = self._get_data(asset)
|
data = self._get_data(asset)
|
||||||
shot.set_display_rate(
|
shot.set_display_rate(
|
||||||
|
|
@ -631,11 +667,11 @@ class LayoutLoader(plugin.Loader):
|
||||||
sequences[-1], shot,
|
sequences[-1], shot,
|
||||||
frame_ranges[-1][1],
|
frame_ranges[-1][1],
|
||||||
data.get('clipIn'), data.get('clipOut'),
|
data.get('clipIn'), data.get('clipOut'),
|
||||||
[maps[-1].get('map')])
|
[level])
|
||||||
|
|
||||||
EditorLevelLibrary.load_level(maps[-1].get('map'))
|
EditorLevelLibrary.load_level(level)
|
||||||
|
|
||||||
self._process(self.fname, asset_dir, shot)
|
loaded_assets = self._process(self.fname, asset_dir, shot)
|
||||||
|
|
||||||
for s in sequences:
|
for s in sequences:
|
||||||
EditorAssetLibrary.save_asset(s.get_full_name())
|
EditorAssetLibrary.save_asset(s.get_full_name())
|
||||||
|
|
@ -656,7 +692,8 @@ class LayoutLoader(plugin.Loader):
|
||||||
"loader": str(self.__class__.__name__),
|
"loader": str(self.__class__.__name__),
|
||||||
"representation": context["representation"]["_id"],
|
"representation": context["representation"]["_id"],
|
||||||
"parent": context["representation"]["parent"],
|
"parent": context["representation"]["parent"],
|
||||||
"family": context["representation"]["context"]["family"]
|
"family": context["representation"]["context"]["family"],
|
||||||
|
"loaded_assets": loaded_assets
|
||||||
}
|
}
|
||||||
unreal_pipeline.imprint(
|
unreal_pipeline.imprint(
|
||||||
"{}/{}".format(asset_dir, container_name), data)
|
"{}/{}".format(asset_dir, container_name), data)
|
||||||
|
|
@ -667,148 +704,192 @@ class LayoutLoader(plugin.Loader):
|
||||||
for a in asset_content:
|
for a in asset_content:
|
||||||
EditorAssetLibrary.save_asset(a)
|
EditorAssetLibrary.save_asset(a)
|
||||||
|
|
||||||
EditorLevelLibrary.load_level(maps[0].get('map'))
|
EditorLevelLibrary.load_level(master_level)
|
||||||
|
|
||||||
return asset_content
|
return asset_content
|
||||||
|
|
||||||
def update(self, container, representation):
|
def update(self, container, representation):
|
||||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
|
|
||||||
|
root = "/Game/OpenPype"
|
||||||
|
|
||||||
|
asset_dir = container.get('namespace')
|
||||||
|
|
||||||
|
context = representation.get("context")
|
||||||
|
|
||||||
|
hierarchy = context.get('hierarchy').split("/")
|
||||||
|
h_dir = f"{root}/{hierarchy[0]}"
|
||||||
|
h_asset = hierarchy[0]
|
||||||
|
master_level = f"{h_dir}/{h_asset}_map.{h_asset}_map"
|
||||||
|
|
||||||
|
# # Create a temporary level to delete the layout level.
|
||||||
|
# EditorLevelLibrary.save_all_dirty_levels()
|
||||||
|
# EditorAssetLibrary.make_directory(f"{root}/tmp")
|
||||||
|
# tmp_level = f"{root}/tmp/temp_map"
|
||||||
|
# if not EditorAssetLibrary.does_asset_exist(f"{tmp_level}.temp_map"):
|
||||||
|
# EditorLevelLibrary.new_level(tmp_level)
|
||||||
|
# else:
|
||||||
|
# EditorLevelLibrary.load_level(tmp_level)
|
||||||
|
|
||||||
|
# Get layout level
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["World"],
|
||||||
|
package_paths=[asset_dir],
|
||||||
|
recursive_paths=False)
|
||||||
|
levels = ar.get_assets(filter)
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["LevelSequence"],
|
||||||
|
package_paths=[asset_dir],
|
||||||
|
recursive_paths=False)
|
||||||
|
sequences = ar.get_assets(filter)
|
||||||
|
|
||||||
|
layout_level = levels[0].get_editor_property('object_path')
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_all_dirty_levels()
|
||||||
|
EditorLevelLibrary.load_level(layout_level)
|
||||||
|
|
||||||
|
# Delete all the actors in the level
|
||||||
|
actors = unreal.EditorLevelLibrary.get_all_level_actors()
|
||||||
|
for actor in actors:
|
||||||
|
unreal.EditorLevelLibrary.destroy_actor(actor)
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_current_level()
|
||||||
|
|
||||||
|
EditorAssetLibrary.delete_directory(f"{asset_dir}/animations/")
|
||||||
|
|
||||||
source_path = get_representation_path(representation)
|
source_path = get_representation_path(representation)
|
||||||
destination_path = container["namespace"]
|
|
||||||
lib_path = Path(get_representation_path(representation))
|
|
||||||
|
|
||||||
self._remove_actors(destination_path)
|
loaded_assets = self._process(
|
||||||
|
source_path, asset_dir, sequences[0].get_asset())
|
||||||
|
|
||||||
# Delete old animations
|
data = {
|
||||||
anim_path = f"{destination_path}/animations/"
|
|
||||||
EditorAssetLibrary.delete_directory(anim_path)
|
|
||||||
|
|
||||||
with open(source_path, "r") as fp:
|
|
||||||
data = json.load(fp)
|
|
||||||
|
|
||||||
references = [e.get('reference_fbx') for e in data]
|
|
||||||
asset_containers = self._get_asset_containers(destination_path)
|
|
||||||
loaded = []
|
|
||||||
|
|
||||||
# Delete all the assets imported with the previous version of the
|
|
||||||
# layout, if they're not in the new layout.
|
|
||||||
for asset_container in asset_containers:
|
|
||||||
if asset_container.get_editor_property(
|
|
||||||
'asset_name') == container["objectName"]:
|
|
||||||
continue
|
|
||||||
ref = EditorAssetLibrary.get_metadata_tag(
|
|
||||||
asset_container.get_asset(), 'representation')
|
|
||||||
ppath = asset_container.get_editor_property('package_path')
|
|
||||||
|
|
||||||
if ref not in references:
|
|
||||||
# If the asset is not in the new layout, delete it.
|
|
||||||
# Also check if the parent directory is empty, and delete that
|
|
||||||
# as well, if it is.
|
|
||||||
EditorAssetLibrary.delete_directory(ppath)
|
|
||||||
|
|
||||||
parent = os.path.dirname(str(ppath))
|
|
||||||
parent_content = EditorAssetLibrary.list_assets(
|
|
||||||
parent, recursive=False, include_folder=True
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(parent_content) == 0:
|
|
||||||
EditorAssetLibrary.delete_directory(parent)
|
|
||||||
else:
|
|
||||||
# If the asset is in the new layout, search the instances in
|
|
||||||
# the JSON file, and create actors for them.
|
|
||||||
|
|
||||||
actors_dict = {}
|
|
||||||
skeleton_dict = {}
|
|
||||||
|
|
||||||
for element in data:
|
|
||||||
reference = element.get('reference_fbx')
|
|
||||||
instance_name = element.get('instance_name')
|
|
||||||
|
|
||||||
skeleton = None
|
|
||||||
|
|
||||||
if reference == ref and ref not in loaded:
|
|
||||||
loaded.append(ref)
|
|
||||||
|
|
||||||
family = element.get('family')
|
|
||||||
|
|
||||||
assets = EditorAssetLibrary.list_assets(
|
|
||||||
ppath, recursive=True, include_folder=False)
|
|
||||||
|
|
||||||
instances = [
|
|
||||||
item for item in data
|
|
||||||
if item.get('reference_fbx') == reference]
|
|
||||||
|
|
||||||
for instance in instances:
|
|
||||||
transform = instance.get('transform')
|
|
||||||
inst = instance.get('instance_name')
|
|
||||||
|
|
||||||
actors = []
|
|
||||||
|
|
||||||
if family == 'model':
|
|
||||||
actors = self._process_family(
|
|
||||||
assets, 'StaticMesh', transform, inst)
|
|
||||||
elif family == 'rig':
|
|
||||||
actors = self._process_family(
|
|
||||||
assets, 'SkeletalMesh', transform, inst)
|
|
||||||
actors_dict[inst] = actors
|
|
||||||
|
|
||||||
if family == 'rig':
|
|
||||||
# Finds skeleton among the imported assets
|
|
||||||
for asset in assets:
|
|
||||||
obj = ar.get_asset_by_object_path(
|
|
||||||
asset).get_asset()
|
|
||||||
if obj.get_class().get_name() == 'Skeleton':
|
|
||||||
skeleton = obj
|
|
||||||
if skeleton:
|
|
||||||
break
|
|
||||||
|
|
||||||
if skeleton:
|
|
||||||
skeleton_dict[reference] = skeleton
|
|
||||||
else:
|
|
||||||
skeleton = skeleton_dict.get(reference)
|
|
||||||
|
|
||||||
animation_file = element.get('animation')
|
|
||||||
|
|
||||||
if animation_file and skeleton:
|
|
||||||
self._import_animation(
|
|
||||||
destination_path, lib_path,
|
|
||||||
instance_name, skeleton,
|
|
||||||
actors_dict, animation_file)
|
|
||||||
|
|
||||||
self._process(source_path, destination_path, loaded)
|
|
||||||
|
|
||||||
container_path = "{}/{}".format(container["namespace"],
|
|
||||||
container["objectName"])
|
|
||||||
# update metadata
|
|
||||||
unreal_pipeline.imprint(
|
|
||||||
container_path,
|
|
||||||
{
|
|
||||||
"representation": str(representation["_id"]),
|
"representation": str(representation["_id"]),
|
||||||
"parent": str(representation["parent"])
|
"parent": str(representation["parent"]),
|
||||||
})
|
"loaded_assets": loaded_assets
|
||||||
|
}
|
||||||
|
unreal_pipeline.imprint(
|
||||||
|
"{}/{}".format(asset_dir, container.get('container_name')), data)
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_current_level()
|
||||||
|
|
||||||
asset_content = EditorAssetLibrary.list_assets(
|
asset_content = EditorAssetLibrary.list_assets(
|
||||||
destination_path, recursive=True, include_folder=False)
|
asset_dir, recursive=True, include_folder=False)
|
||||||
|
|
||||||
for a in asset_content:
|
for a in asset_content:
|
||||||
EditorAssetLibrary.save_asset(a)
|
EditorAssetLibrary.save_asset(a)
|
||||||
|
|
||||||
|
EditorLevelLibrary.load_level(master_level)
|
||||||
|
|
||||||
def remove(self, container):
|
def remove(self, container):
|
||||||
"""
|
"""
|
||||||
First, destroy all actors of the assets to be removed. Then, deletes
|
Delete the layout. First, check if the assets loaded with the layout
|
||||||
the asset's directory.
|
are used by other layouts. If not, delete the assets.
|
||||||
"""
|
"""
|
||||||
path = container["namespace"]
|
path = Path(container.get("namespace"))
|
||||||
parent_path = os.path.dirname(path)
|
|
||||||
|
|
||||||
self._remove_actors(path)
|
containers = unreal_pipeline.ls()
|
||||||
|
layout_containers = [
|
||||||
|
c for c in containers
|
||||||
|
if (c.get('asset_name') != container.get('asset_name') and
|
||||||
|
c.get('family') == "layout")]
|
||||||
|
|
||||||
EditorAssetLibrary.delete_directory(path)
|
# Check if the assets have been loaded by other layouts, and deletes
|
||||||
|
# them if they haven't.
|
||||||
|
for asset in container.get('loaded_assets'):
|
||||||
|
layouts = [
|
||||||
|
lc for lc in layout_containers
|
||||||
|
if asset in lc.get('loaded_assets')]
|
||||||
|
|
||||||
|
if len(layouts) == 0:
|
||||||
|
EditorAssetLibrary.delete_directory(str(Path(asset).parent))
|
||||||
|
|
||||||
|
# Remove the Level Sequence from the parent.
|
||||||
|
# We need to traverse the hierarchy from the master sequence to find
|
||||||
|
# the level sequence.
|
||||||
|
root = "/Game/OpenPype"
|
||||||
|
namespace = container.get('namespace').replace(f"{root}/", "")
|
||||||
|
ms_asset = namespace.split('/')[0]
|
||||||
|
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["LevelSequence"],
|
||||||
|
package_paths=[f"{root}/{ms_asset}"],
|
||||||
|
recursive_paths=False)
|
||||||
|
sequences = ar.get_assets(filter)
|
||||||
|
master_sequence = sequences[0].get_asset()
|
||||||
|
filter = unreal.ARFilter(
|
||||||
|
class_names=["World"],
|
||||||
|
package_paths=[f"{root}/{ms_asset}"],
|
||||||
|
recursive_paths=False)
|
||||||
|
levels = ar.get_assets(filter)
|
||||||
|
master_level = levels[0].get_editor_property('object_path')
|
||||||
|
|
||||||
|
sequences = [master_sequence]
|
||||||
|
|
||||||
|
parent = None
|
||||||
|
for s in sequences:
|
||||||
|
tracks = s.get_master_tracks()
|
||||||
|
subscene_track = None
|
||||||
|
visibility_track = None
|
||||||
|
for t in tracks:
|
||||||
|
if t.get_class() == unreal.MovieSceneSubTrack.static_class():
|
||||||
|
subscene_track = t
|
||||||
|
if (t.get_class() ==
|
||||||
|
unreal.MovieSceneLevelVisibilityTrack.static_class()):
|
||||||
|
visibility_track = t
|
||||||
|
if subscene_track:
|
||||||
|
sections = subscene_track.get_sections()
|
||||||
|
for ss in sections:
|
||||||
|
if ss.get_sequence().get_name() == container.get('asset'):
|
||||||
|
parent = s
|
||||||
|
subscene_track.remove_section(ss)
|
||||||
|
break
|
||||||
|
sequences.append(ss.get_sequence())
|
||||||
|
# Update subscenes indexes.
|
||||||
|
i = 0
|
||||||
|
for ss in sections:
|
||||||
|
ss.set_row_index(i)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if visibility_track:
|
||||||
|
sections = visibility_track.get_sections()
|
||||||
|
for ss in sections:
|
||||||
|
if (unreal.Name(f"{container.get('asset')}_map")
|
||||||
|
in ss.get_level_names()):
|
||||||
|
visibility_track.remove_section(ss)
|
||||||
|
# Update visibility sections indexes.
|
||||||
|
i = -1
|
||||||
|
prev_name = []
|
||||||
|
for ss in sections:
|
||||||
|
if prev_name != ss.get_level_names():
|
||||||
|
i += 1
|
||||||
|
ss.set_row_index(i)
|
||||||
|
prev_name = ss.get_level_names()
|
||||||
|
if parent:
|
||||||
|
break
|
||||||
|
|
||||||
|
assert parent, "Could not find the parent sequence"
|
||||||
|
|
||||||
|
# Create a temporary level to delete the layout level.
|
||||||
|
EditorLevelLibrary.save_all_dirty_levels()
|
||||||
|
EditorAssetLibrary.make_directory(f"{root}/tmp")
|
||||||
|
tmp_level = f"{root}/tmp/temp_map"
|
||||||
|
if not EditorAssetLibrary.does_asset_exist(f"{tmp_level}.temp_map"):
|
||||||
|
EditorLevelLibrary.new_level(tmp_level)
|
||||||
|
else:
|
||||||
|
EditorLevelLibrary.load_level(tmp_level)
|
||||||
|
|
||||||
|
# Delete the layout directory.
|
||||||
|
EditorAssetLibrary.delete_directory(str(path))
|
||||||
|
|
||||||
|
EditorLevelLibrary.load_level(master_level)
|
||||||
|
EditorAssetLibrary.delete_directory(f"{root}/tmp")
|
||||||
|
|
||||||
|
EditorLevelLibrary.save_current_level()
|
||||||
|
|
||||||
|
# Delete the parent folder if there aren't any more layouts in it.
|
||||||
asset_content = EditorAssetLibrary.list_assets(
|
asset_content = EditorAssetLibrary.list_assets(
|
||||||
parent_path, recursive=False, include_folder=True
|
str(path.parent), recursive=False, include_folder=True
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(asset_content) == 0:
|
if len(asset_content) == 0:
|
||||||
EditorAssetLibrary.delete_directory(parent_path)
|
EditorAssetLibrary.delete_directory(str(path.parent))
|
||||||
|
|
|
||||||
|
|
@ -52,13 +52,15 @@ class SkeletalMeshFBXLoader(plugin.Loader):
|
||||||
asset_name = "{}_{}".format(asset, name)
|
asset_name = "{}_{}".format(asset, name)
|
||||||
else:
|
else:
|
||||||
asset_name = "{}".format(name)
|
asset_name = "{}".format(name)
|
||||||
|
version = context.get('version').get('name')
|
||||||
|
|
||||||
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
||||||
asset_dir, container_name = tools.create_unique_asset_name(
|
asset_dir, container_name = tools.create_unique_asset_name(
|
||||||
"{}/{}/{}".format(root, asset, name), suffix="")
|
f"{root}/{asset}/{name}_v{version:03d}", suffix="")
|
||||||
|
|
||||||
container_name += suffix
|
container_name += suffix
|
||||||
|
|
||||||
|
if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir):
|
||||||
unreal.EditorAssetLibrary.make_directory(asset_dir)
|
unreal.EditorAssetLibrary.make_directory(asset_dir)
|
||||||
|
|
||||||
task = unreal.AssetImportTask()
|
task = unreal.AssetImportTask()
|
||||||
|
|
@ -75,24 +77,23 @@ class SkeletalMeshFBXLoader(plugin.Loader):
|
||||||
options.set_editor_property('import_as_skeletal', True)
|
options.set_editor_property('import_as_skeletal', True)
|
||||||
options.set_editor_property('import_animations', False)
|
options.set_editor_property('import_animations', False)
|
||||||
options.set_editor_property('import_mesh', True)
|
options.set_editor_property('import_mesh', True)
|
||||||
options.set_editor_property('import_materials', True)
|
options.set_editor_property('import_materials', False)
|
||||||
options.set_editor_property('import_textures', True)
|
options.set_editor_property('import_textures', False)
|
||||||
options.set_editor_property('skeleton', None)
|
options.set_editor_property('skeleton', None)
|
||||||
options.set_editor_property('create_physics_asset', False)
|
options.set_editor_property('create_physics_asset', False)
|
||||||
|
|
||||||
options.set_editor_property('mesh_type_to_import',
|
options.set_editor_property(
|
||||||
|
'mesh_type_to_import',
|
||||||
unreal.FBXImportType.FBXIT_SKELETAL_MESH)
|
unreal.FBXImportType.FBXIT_SKELETAL_MESH)
|
||||||
|
|
||||||
options.skeletal_mesh_import_data.set_editor_property(
|
options.skeletal_mesh_import_data.set_editor_property(
|
||||||
'import_content_type',
|
'import_content_type',
|
||||||
unreal.FBXImportContentType.FBXICT_ALL
|
unreal.FBXImportContentType.FBXICT_ALL)
|
||||||
)
|
|
||||||
# set to import normals, otherwise Unreal will compute them
|
# set to import normals, otherwise Unreal will compute them
|
||||||
# and it will take a long time, depending on the size of the mesh
|
# and it will take a long time, depending on the size of the mesh
|
||||||
options.skeletal_mesh_import_data.set_editor_property(
|
options.skeletal_mesh_import_data.set_editor_property(
|
||||||
'normal_import_method',
|
'normal_import_method',
|
||||||
unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS
|
unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS)
|
||||||
)
|
|
||||||
|
|
||||||
task.options = options
|
task.options = options
|
||||||
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) # noqa: E501
|
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) # noqa: E501
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import unreal
|
import unreal
|
||||||
|
|
||||||
import pyblish.api
|
from openpype.api import Anatomy
|
||||||
from openpype.hosts.unreal.api import pipeline
|
from openpype.hosts.unreal.api import pipeline
|
||||||
|
import pyblish.api
|
||||||
|
|
||||||
|
|
||||||
class CollectRenderInstances(pyblish.api.InstancePlugin):
|
class CollectRenderInstances(pyblish.api.InstancePlugin):
|
||||||
|
|
@ -77,9 +80,15 @@ class CollectRenderInstances(pyblish.api.InstancePlugin):
|
||||||
|
|
||||||
self.log.debug(f"new instance data: {new_data}")
|
self.log.debug(f"new instance data: {new_data}")
|
||||||
|
|
||||||
project_dir = unreal.Paths.project_dir()
|
try:
|
||||||
render_dir = (f"{project_dir}/Saved/MovieRenders/"
|
project = os.environ.get("AVALON_PROJECT")
|
||||||
f"{s.get('output')}")
|
anatomy = Anatomy(project)
|
||||||
|
root = anatomy.roots['renders']
|
||||||
|
except Exception:
|
||||||
|
raise Exception(
|
||||||
|
"Could not find render root in anatomy settings.")
|
||||||
|
|
||||||
|
render_dir = f"{root}/{project}/{s.get('output')}"
|
||||||
render_path = Path(render_dir)
|
render_path = Path(render_dir)
|
||||||
|
|
||||||
frames = []
|
frames = []
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue