mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
Improved update for Geometry Caches
This commit is contained in:
parent
671844fa07
commit
8392695623
2 changed files with 153 additions and 91 deletions
|
|
@ -649,30 +649,43 @@ def generate_sequence(h, h_dir):
|
|||
return sequence, (min_frame, max_frame)
|
||||
|
||||
|
||||
def replace_static_mesh_actors(old_assets, new_assets):
|
||||
def _get_comps_and_assets(
|
||||
component_class, asset_class, old_assets, new_assets
|
||||
):
|
||||
eas = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
|
||||
smes = unreal.get_editor_subsystem(unreal.StaticMeshEditorSubsystem)
|
||||
|
||||
comps = eas.get_all_level_actors_components()
|
||||
static_mesh_comps = [
|
||||
c for c in comps if isinstance(c, unreal.StaticMeshComponent)
|
||||
components = [
|
||||
c for c in comps if isinstance(c, component_class)
|
||||
]
|
||||
|
||||
# Get all the static meshes among the old assets in a dictionary with
|
||||
# the name as key
|
||||
old_meshes = {}
|
||||
selected_old_assets = {}
|
||||
for a in old_assets:
|
||||
asset = unreal.EditorAssetLibrary.load_asset(a)
|
||||
if isinstance(asset, unreal.StaticMesh):
|
||||
old_meshes[asset.get_name()] = asset
|
||||
if isinstance(asset, asset_class):
|
||||
selected_old_assets[asset.get_name()] = asset
|
||||
|
||||
# Get all the static meshes among the new assets in a dictionary with
|
||||
# the name as key
|
||||
new_meshes = {}
|
||||
selected_new_assets = {}
|
||||
for a in new_assets:
|
||||
asset = unreal.EditorAssetLibrary.load_asset(a)
|
||||
if isinstance(asset, unreal.StaticMesh):
|
||||
new_meshes[asset.get_name()] = asset
|
||||
if isinstance(asset, asset_class):
|
||||
selected_new_assets[asset.get_name()] = asset
|
||||
|
||||
return components, selected_old_assets, selected_new_assets
|
||||
|
||||
|
||||
def replace_static_mesh_actors(old_assets, new_assets):
|
||||
smes = unreal.get_editor_subsystem(unreal.StaticMeshEditorSubsystem)
|
||||
|
||||
static_mesh_comps, old_meshes, new_meshes = _get_comps_and_assets(
|
||||
unreal.StaticMeshComponent,
|
||||
unreal.StaticMesh,
|
||||
old_assets,
|
||||
new_assets
|
||||
)
|
||||
|
||||
for old_name, old_mesh in old_meshes.items():
|
||||
new_mesh = new_meshes.get(old_name)
|
||||
|
|
@ -685,28 +698,12 @@ def replace_static_mesh_actors(old_assets, new_assets):
|
|||
|
||||
|
||||
def replace_skeletal_mesh_actors(old_assets, new_assets):
|
||||
eas = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
|
||||
|
||||
comps = eas.get_all_level_actors_components()
|
||||
skeletal_mesh_comps = [
|
||||
c for c in comps if isinstance(c, unreal.SkeletalMeshComponent)
|
||||
]
|
||||
|
||||
# Get all the static meshes among the old assets in a dictionary with
|
||||
# the name as key
|
||||
old_meshes = {}
|
||||
for a in old_assets:
|
||||
asset = unreal.EditorAssetLibrary.load_asset(a)
|
||||
if isinstance(asset, unreal.SkeletalMesh):
|
||||
old_meshes[asset.get_name()] = asset
|
||||
|
||||
# Get all the static meshes among the new assets in a dictionary with
|
||||
# the name as key
|
||||
new_meshes = {}
|
||||
for a in new_assets:
|
||||
asset = unreal.EditorAssetLibrary.load_asset(a)
|
||||
if isinstance(asset, unreal.SkeletalMesh):
|
||||
new_meshes[asset.get_name()] = asset
|
||||
skeletal_mesh_comps, old_meshes, new_meshes = _get_comps_and_assets(
|
||||
unreal.SkeletalMeshComponent,
|
||||
unreal.SkeletalMesh,
|
||||
old_assets,
|
||||
new_assets
|
||||
)
|
||||
|
||||
for old_name, old_mesh in old_meshes.items():
|
||||
new_mesh = new_meshes.get(old_name)
|
||||
|
|
@ -719,6 +716,25 @@ def replace_skeletal_mesh_actors(old_assets, new_assets):
|
|||
comp.set_skeletal_mesh_asset(new_mesh)
|
||||
|
||||
|
||||
def replace_geometry_cache_actors(old_assets, new_assets):
|
||||
geometry_cache_comps, old_caches, new_caches = _get_comps_and_assets(
|
||||
unreal.SkeletalMeshComponent,
|
||||
unreal.SkeletalMesh,
|
||||
old_assets,
|
||||
new_assets
|
||||
)
|
||||
|
||||
for old_name, old_mesh in old_caches.items():
|
||||
new_mesh = new_caches.get(old_name)
|
||||
|
||||
if not new_mesh:
|
||||
continue
|
||||
|
||||
for comp in geometry_cache_comps:
|
||||
if comp.get_editor_property("geometry_cache") == old_mesh:
|
||||
comp.set_geometry_cache(new_mesh)
|
||||
|
||||
|
||||
def delete_previous_asset_if_unused(container, asset_content):
|
||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,12 @@ from openpype.pipeline import (
|
|||
AYON_CONTAINER_ID
|
||||
)
|
||||
from openpype.hosts.unreal.api import plugin
|
||||
from openpype.hosts.unreal.api import pipeline as unreal_pipeline
|
||||
from openpype.hosts.unreal.api.pipeline import (
|
||||
create_container,
|
||||
imprint,
|
||||
replace_geometry_cache_actors,
|
||||
delete_previous_asset_if_unused,
|
||||
)
|
||||
|
||||
import unreal # noqa
|
||||
|
||||
|
|
@ -21,8 +26,11 @@ class PointCacheAlembicLoader(plugin.Loader):
|
|||
icon = "cube"
|
||||
color = "orange"
|
||||
|
||||
root = "/Game/Ayon/Assets"
|
||||
|
||||
@staticmethod
|
||||
def get_task(
|
||||
self, filename, asset_dir, asset_name, replace,
|
||||
filename, asset_dir, asset_name, replace,
|
||||
frame_start=None, frame_end=None
|
||||
):
|
||||
task = unreal.AssetImportTask()
|
||||
|
|
@ -38,8 +46,6 @@ class PointCacheAlembicLoader(plugin.Loader):
|
|||
task.set_editor_property('automated', True)
|
||||
task.set_editor_property('save', True)
|
||||
|
||||
# set import options here
|
||||
# Unreal 4.24 ignores the settings. It works with Unreal 4.26
|
||||
options.set_editor_property(
|
||||
'import_type', unreal.AlembicImportType.GEOMETRY_CACHE)
|
||||
|
||||
|
|
@ -64,13 +70,42 @@ class PointCacheAlembicLoader(plugin.Loader):
|
|||
|
||||
return task
|
||||
|
||||
def load(self, context, name, namespace, data):
|
||||
"""Load and containerise representation into Content Browser.
|
||||
def import_and_containerize(
|
||||
self, filepath, asset_dir, asset_name, container_name,
|
||||
frame_start, frame_end
|
||||
):
|
||||
unreal.EditorAssetLibrary.make_directory(asset_dir)
|
||||
|
||||
This is two step process. First, import FBX to temporary path and
|
||||
then call `containerise()` on it - this moves all content to new
|
||||
directory and then it will create AssetContainer there and imprint it
|
||||
with metadata. This will mark this path as container.
|
||||
task = self.get_task(
|
||||
filepath, asset_dir, asset_name, False, frame_start, frame_end)
|
||||
|
||||
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task])
|
||||
|
||||
# Create Asset Container
|
||||
create_container(container=container_name, path=asset_dir)
|
||||
|
||||
def imprint(
|
||||
self, asset, asset_dir, container_name, asset_name, representation,
|
||||
frame_start, frame_end
|
||||
):
|
||||
data = {
|
||||
"schema": "ayon:container-2.0",
|
||||
"id": AYON_CONTAINER_ID,
|
||||
"asset": asset,
|
||||
"namespace": asset_dir,
|
||||
"container_name": container_name,
|
||||
"asset_name": asset_name,
|
||||
"loader": str(self.__class__.__name__),
|
||||
"representation": representation["_id"],
|
||||
"parent": representation["parent"],
|
||||
"family": representation["context"]["family"],
|
||||
"frame_start": frame_start,
|
||||
"frame_end": frame_end
|
||||
}
|
||||
imprint(f"{asset_dir}/{container_name}", data)
|
||||
|
||||
def load(self, context, name, namespace, options):
|
||||
"""Load and containerise representation into Content Browser.
|
||||
|
||||
Args:
|
||||
context (dict): application context
|
||||
|
|
@ -79,30 +114,28 @@ class PointCacheAlembicLoader(plugin.Loader):
|
|||
This is not passed here, so namespace is set
|
||||
by `containerise()` because only then we know
|
||||
real path.
|
||||
data (dict): Those would be data to be imprinted. This is not used
|
||||
now, data are imprinted by `containerise()`.
|
||||
data (dict): Those would be data to be imprinted.
|
||||
|
||||
Returns:
|
||||
list(str): list of container content
|
||||
|
||||
"""
|
||||
# Create directory for asset and Ayon container
|
||||
root = "/Game/Ayon/Assets"
|
||||
asset = context.get('asset').get('name')
|
||||
suffix = "_CON"
|
||||
if asset:
|
||||
asset_name = "{}_{}".format(asset, name)
|
||||
asset_name = f"{asset}_{name}" if asset else f"{name}"
|
||||
version = context.get('version')
|
||||
# Check if version is hero version and use different name
|
||||
if not version.get("name") and version.get('type') == "hero_version":
|
||||
name_version = f"{name}_hero"
|
||||
else:
|
||||
asset_name = "{}".format(name)
|
||||
name_version = f"{name}_v{version.get('name'):03d}"
|
||||
|
||||
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
||||
asset_dir, container_name = tools.create_unique_asset_name(
|
||||
"{}/{}/{}".format(root, asset, name), suffix="")
|
||||
f"{self.root}/{asset}/{name_version}", suffix="")
|
||||
|
||||
container_name += suffix
|
||||
|
||||
unreal.EditorAssetLibrary.make_directory(asset_dir)
|
||||
|
||||
frame_start = context.get('asset').get('data').get('frameStart')
|
||||
frame_end = context.get('asset').get('data').get('frameEnd')
|
||||
|
||||
|
|
@ -111,30 +144,17 @@ class PointCacheAlembicLoader(plugin.Loader):
|
|||
if frame_start == frame_end:
|
||||
frame_end += 1
|
||||
|
||||
path = self.filepath_from_context(context)
|
||||
task = self.get_task(
|
||||
path, asset_dir, asset_name, False, frame_start, frame_end)
|
||||
if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir):
|
||||
path = self.filepath_from_context(context)
|
||||
|
||||
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) # noqa: E501
|
||||
|
||||
# Create Asset Container
|
||||
unreal_pipeline.create_container(
|
||||
container=container_name, path=asset_dir)
|
||||
self.import_and_containerize(
|
||||
path, asset_dir, asset_name, container_name,
|
||||
frame_start, frame_end)
|
||||
|
||||
data = {
|
||||
"schema": "ayon:container-2.0",
|
||||
"id": AYON_CONTAINER_ID,
|
||||
"asset": asset,
|
||||
"namespace": asset_dir,
|
||||
"container_name": container_name,
|
||||
"asset_name": asset_name,
|
||||
"loader": str(self.__class__.__name__),
|
||||
"representation": context["representation"]["_id"],
|
||||
"parent": context["representation"]["parent"],
|
||||
"family": context["representation"]["context"]["family"]
|
||||
}
|
||||
unreal_pipeline.imprint(
|
||||
"{}/{}".format(asset_dir, container_name), data)
|
||||
self.imprint(
|
||||
asset, asset_dir, container_name, asset_name,
|
||||
context["representation"], frame_start, frame_end)
|
||||
|
||||
asset_content = unreal.EditorAssetLibrary.list_assets(
|
||||
asset_dir, recursive=True, include_folder=True
|
||||
|
|
@ -146,32 +166,58 @@ class PointCacheAlembicLoader(plugin.Loader):
|
|||
return asset_content
|
||||
|
||||
def update(self, container, representation):
|
||||
name = container["asset_name"]
|
||||
source_path = get_representation_path(representation)
|
||||
destination_path = container["namespace"]
|
||||
representation["context"]
|
||||
context = representation.get("context", {})
|
||||
|
||||
task = self.get_task(source_path, destination_path, name, False)
|
||||
# do import fbx and replace existing data
|
||||
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task])
|
||||
unreal.log_warning(context)
|
||||
|
||||
container_path = "{}/{}".format(container["namespace"],
|
||||
container["objectName"])
|
||||
# update metadata
|
||||
unreal_pipeline.imprint(
|
||||
container_path,
|
||||
{
|
||||
"representation": str(representation["_id"]),
|
||||
"parent": str(representation["parent"])
|
||||
})
|
||||
if not context:
|
||||
raise RuntimeError("No context found in representation")
|
||||
|
||||
# Create directory for asset and Ayon container
|
||||
asset = context.get('asset')
|
||||
name = context.get('subset')
|
||||
suffix = "_CON"
|
||||
asset_name = f"{asset}_{name}" if asset else f"{name}"
|
||||
version = context.get('version')
|
||||
# Check if version is hero version and use different name
|
||||
name_version = f"{name}_v{version:03d}" if version else f"{name}_hero"
|
||||
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
||||
asset_dir, container_name = tools.create_unique_asset_name(
|
||||
f"{self.root}/{asset}/{name_version}", suffix="")
|
||||
|
||||
container_name += suffix
|
||||
|
||||
frame_start = int(container.get("frame_start"))
|
||||
frame_end = int(container.get("frame_end"))
|
||||
|
||||
if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir):
|
||||
path = get_representation_path(representation)
|
||||
|
||||
self.import_and_containerize(
|
||||
path, asset_dir, asset_name, container_name,
|
||||
frame_start, frame_end)
|
||||
|
||||
self.imprint(
|
||||
asset, asset_dir, container_name, asset_name, representation,
|
||||
frame_start, frame_end)
|
||||
|
||||
asset_content = unreal.EditorAssetLibrary.list_assets(
|
||||
destination_path, recursive=True, include_folder=True
|
||||
asset_dir, recursive=True, include_folder=False
|
||||
)
|
||||
|
||||
for a in asset_content:
|
||||
unreal.EditorAssetLibrary.save_asset(a)
|
||||
|
||||
old_assets = unreal.EditorAssetLibrary.list_assets(
|
||||
container["namespace"], recursive=True, include_folder=False
|
||||
)
|
||||
|
||||
replace_geometry_cache_actors(old_assets, asset_content)
|
||||
|
||||
unreal.EditorLevelLibrary.save_current_level()
|
||||
|
||||
delete_previous_asset_if_unused(container, old_assets)
|
||||
|
||||
def remove(self, container):
|
||||
path = container["namespace"]
|
||||
parent_path = os.path.dirname(path)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue