mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 21:32:15 +01:00
Fix storing instance and context data correctly, fix removing instances + refactor instance nodes
This commit is contained in:
parent
3d10bfdf09
commit
8575c4843c
18 changed files with 140 additions and 241 deletions
|
|
@ -31,6 +31,14 @@ PREVIEW_COLLECTIONS: Dict = dict()
|
|||
TIMER_INTERVAL: float = 0.01 if platform.system() == "Windows" else 0.1
|
||||
|
||||
|
||||
def execute_function_in_main_thread(f):
|
||||
"""Decorator to move a function call into main thread items"""
|
||||
def wrapper(*args, **kwargs):
|
||||
mti = MainThreadItem(f, *args, **kwargs)
|
||||
execute_in_main_thread(mti)
|
||||
return wrapper
|
||||
|
||||
|
||||
class BlenderApplication(QtWidgets.QApplication):
|
||||
_instance = None
|
||||
blender_windows = {}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,10 @@ class BlenderHost(HostBase, IWorkfileHost, IPublishHost):
|
|||
Returns:
|
||||
dict: Context data stored using 'update_context_data'.
|
||||
"""
|
||||
return bpy.context.scene.openpype_context
|
||||
property = bpy.context.scene.get(AVALON_PROPERTY)
|
||||
if property:
|
||||
return property.to_dict()
|
||||
return {}
|
||||
|
||||
def update_context_data(self, data: dict, changes: dict):
|
||||
"""Override abstract method from IPublishHost.
|
||||
|
|
@ -149,7 +152,7 @@ class BlenderHost(HostBase, IWorkfileHost, IPublishHost):
|
|||
changes (dict): Only data that has been changed. Each value has
|
||||
tuple with '(<old>, <new>)' value.
|
||||
"""
|
||||
bpy.context.scene.openpype_context.update(data)
|
||||
bpy.context.scene[AVALON_PROPERTY] = data
|
||||
|
||||
|
||||
def pype_excepthook_handler(*args):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ from openpype.pipeline import (
|
|||
LoaderPlugin,
|
||||
get_current_task_name,
|
||||
)
|
||||
from openpype.lib import BoolDef
|
||||
|
||||
from .pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_INSTANCES,
|
||||
|
|
@ -149,6 +151,8 @@ class BaseCreator(Creator):
|
|||
"""Base class for Blender Creator plug-ins."""
|
||||
defaults = ['Main']
|
||||
|
||||
create_as_asset_group = False
|
||||
|
||||
@staticmethod
|
||||
def cache_subsets(shared_data):
|
||||
"""Cache instances for Creators shared data.
|
||||
|
|
@ -190,12 +194,12 @@ class BaseCreator(Creator):
|
|||
creator_id = avalon_prop.get('creator_identifier')
|
||||
if creator_id:
|
||||
# Creator instance
|
||||
cache.setdefault(creator_id, []).append(avalon_prop)
|
||||
cache.setdefault(creator_id, []).append(obj_or_col)
|
||||
else:
|
||||
family = avalon_prop.get('family')
|
||||
if family:
|
||||
# Legacy creator instance
|
||||
cache_legacy.setdefault(family, []).append(avalon_prop)
|
||||
cache_legacy.setdefault(family, []).append(obj_or_col)
|
||||
|
||||
shared_data["blender_cached_subsets"] = cache
|
||||
shared_data["blender_cached_legacy_subsets"] = cache_legacy
|
||||
|
|
@ -220,27 +224,29 @@ class BaseCreator(Creator):
|
|||
instances = bpy.data.collections.new(name=AVALON_INSTANCES)
|
||||
bpy.context.scene.collection.children.link(instances)
|
||||
|
||||
# Create instance collection
|
||||
collection = bpy.data.collections.new(
|
||||
name=asset_name(instance_data["asset"], subset_name)
|
||||
# Create asset group
|
||||
name = asset_name(instance_data["asset"], subset_name)
|
||||
if self.create_as_asset_group:
|
||||
# Create instance as empty
|
||||
instance_node = bpy.data.objects.new(name=name, object_data=None)
|
||||
instance_node.empty_display_type = 'SINGLE_ARROW'
|
||||
instances.objects.link(instance_node)
|
||||
else:
|
||||
# Create instance collection
|
||||
instance_node = bpy.data.collections.new(name=name)
|
||||
instances.children.link(instance_node)
|
||||
|
||||
self.set_instance_data(subset_name, instance_data)
|
||||
|
||||
instance = CreatedInstance(
|
||||
self.family, subset_name, instance_data, self
|
||||
)
|
||||
instances.children.link(collection)
|
||||
instance.transient_data["instance_node"] = instance_node
|
||||
self._add_instance_to_context(instance)
|
||||
|
||||
collection[AVALON_PROPERTY] = instance_node = {
|
||||
"name": collection.name,
|
||||
}
|
||||
imprint(instance_node, instance_data)
|
||||
|
||||
self.set_instance_data(subset_name, instance_data, instance_node)
|
||||
|
||||
self._add_instance_to_context(
|
||||
CreatedInstance(
|
||||
self.family, subset_name, instance_data, self
|
||||
)
|
||||
)
|
||||
|
||||
imprint(collection, instance_data)
|
||||
|
||||
return collection
|
||||
return instance_node
|
||||
|
||||
def collect_instances(self):
|
||||
"""Override abstract method from BaseCreator.
|
||||
|
|
@ -257,12 +263,14 @@ class BaseCreator(Creator):
|
|||
return
|
||||
|
||||
# Process only instances that were created by this creator
|
||||
for instance_data in cached_subsets.get(self.identifier, []):
|
||||
for instance_node in cached_subsets.get(self.identifier, []):
|
||||
property = instance_node.get(AVALON_PROPERTY)
|
||||
# Create instance object from existing data
|
||||
instance = CreatedInstance.from_existing(
|
||||
instance_data=instance_data.to_dict(),
|
||||
instance_data=property.to_dict(),
|
||||
creator=self
|
||||
)
|
||||
instance.transient_data["instance_node"] = instance_node
|
||||
|
||||
# Add instance to create context
|
||||
self._add_instance_to_context(instance)
|
||||
|
|
@ -276,41 +284,32 @@ class BaseCreator(Creator):
|
|||
and their changes, as a list of tuples."""
|
||||
for created_instance, _changes in update_list:
|
||||
data = created_instance.data_to_store()
|
||||
|
||||
imprint(data.get("instance_node", {}), data)
|
||||
node = created_instance.transient_data["instance_node"]
|
||||
if node:
|
||||
imprint(node, data)
|
||||
|
||||
def remove_instances(self, instances: List[CreatedInstance]):
|
||||
"""Override abstract method from BaseCreator.
|
||||
Method called when instances are removed.
|
||||
|
||||
Args:
|
||||
instance(List[CreatedInstance]): Instance objects to remove.
|
||||
"""
|
||||
for instance in instances:
|
||||
outliner_entity = instance.data.get("instance_node", {}).get(
|
||||
"datablock"
|
||||
)
|
||||
if not outliner_entity:
|
||||
continue
|
||||
node = instance.transient_data["instance_node"]
|
||||
|
||||
if isinstance(outliner_entity, bpy.types.Collection):
|
||||
for children in outliner_entity.children_recursive:
|
||||
if isinstance(node, bpy.types.Collection):
|
||||
for children in node.children_recursive:
|
||||
if isinstance(children, bpy.types.Collection):
|
||||
bpy.data.collections.remove(children)
|
||||
else:
|
||||
bpy.data.objects.remove(children)
|
||||
|
||||
bpy.data.collections.remove(outliner_entity)
|
||||
elif isinstance(outliner_entity, bpy.types.Object):
|
||||
bpy.data.objects.remove(outliner_entity)
|
||||
bpy.data.collections.remove(node)
|
||||
elif isinstance(node, bpy.types.Object):
|
||||
bpy.data.objects.remove(node)
|
||||
|
||||
self._remove_instance_from_context(instance)
|
||||
|
||||
def set_instance_data(
|
||||
self,
|
||||
subset_name: str,
|
||||
instance_data: dict,
|
||||
instance_node: bpy.types.ID,
|
||||
instance_data: dict
|
||||
):
|
||||
"""Fill instance data with required items.
|
||||
|
||||
|
|
@ -329,10 +328,16 @@ class BaseCreator(Creator):
|
|||
"label": subset_name,
|
||||
"task": get_current_task_name(),
|
||||
"subset": subset_name,
|
||||
"instance_node": instance_node,
|
||||
}
|
||||
)
|
||||
|
||||
def get_pre_create_attr_defs(self):
|
||||
return [
|
||||
BoolDef("use_selection",
|
||||
label="Use selection",
|
||||
default=True)
|
||||
]
|
||||
|
||||
|
||||
class Loader(LoaderPlugin):
|
||||
"""Base class for Loader plug-ins."""
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
import bpy
|
||||
|
||||
from openpype.hosts.blender.api.plugin import BaseCreator, asset_name
|
||||
from openpype.hosts.blender.api import lib
|
||||
from openpype.hosts.blender.api import lib, plugin
|
||||
|
||||
|
||||
class CreateAction(BaseCreator):
|
||||
class CreateAction(plugin.BaseCreator):
|
||||
"""Action output for character rigs."""
|
||||
|
||||
identifier = "io.openpype.creators.blender.action"
|
||||
|
|
@ -24,9 +23,9 @@ class CreateAction(BaseCreator):
|
|||
)
|
||||
|
||||
# Get instance name
|
||||
name = asset_name(instance_data["asset"], subset_name)
|
||||
name = plugin.asset_name(instance_data["asset"], subset_name)
|
||||
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
for obj in lib.get_selection():
|
||||
if (obj.animation_data is not None
|
||||
and obj.animation_data.action is not None):
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class CreateAnimation(plugin.BaseCreator):
|
|||
subset_name, instance_data, pre_create_data
|
||||
)
|
||||
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
selected = lib.get_selection()
|
||||
for obj in selected:
|
||||
collection.objects.link(obj)
|
||||
|
|
|
|||
|
|
@ -23,42 +23,17 @@ class CreateBlendScene(plugin.Creator):
|
|||
def create(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
"""Run the creator on Blender main thread."""
|
||||
mti = ops.MainThreadItem(
|
||||
self._process, subset_name, instance_data, pre_create_data
|
||||
)
|
||||
ops.execute_in_main_thread(mti)
|
||||
|
||||
def _process(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
# Get Instance Container or create it if it does not exist
|
||||
instances = bpy.data.collections.get(AVALON_INSTANCES)
|
||||
if not instances:
|
||||
instances = bpy.data.collections.new(name=AVALON_INSTANCES)
|
||||
bpy.context.scene.collection.children.link(instances)
|
||||
instance_node = super().create(subset_name,
|
||||
instance_data,
|
||||
pre_create_data)
|
||||
|
||||
# Create instance object
|
||||
asset = instance_data.get("asset")
|
||||
name = plugin.asset_name(asset, subset_name)
|
||||
|
||||
# Create the new asset group as collection
|
||||
asset_group = bpy.data.collections.new(name=name)
|
||||
instances.children.link(asset_group)
|
||||
asset_group[AVALON_PROPERTY] = instance_node = {
|
||||
"name": asset_group.name
|
||||
}
|
||||
|
||||
self.set_instance_data(subset_name, instance_data, instance_node)
|
||||
lib.imprint(asset_group, instance_data)
|
||||
|
||||
if (self.options or {}).get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
selection = lib.get_selection(include_collections=True)
|
||||
|
||||
for data in selection:
|
||||
if isinstance(data, bpy.types.Collection):
|
||||
asset_group.children.link(data)
|
||||
instance_node.children.link(data)
|
||||
elif isinstance(data, bpy.types.Object):
|
||||
asset_group.objects.link(data)
|
||||
instance_node.objects.link(data)
|
||||
|
||||
return asset_group
|
||||
return instance_node
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import bpy
|
||||
|
||||
from openpype.pipeline import get_current_task_name, CreatedInstance
|
||||
from openpype.pipeline import CreatedInstance
|
||||
from openpype.hosts.blender.api import plugin, lib, ops
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_INSTANCES,
|
||||
|
|
@ -19,43 +19,19 @@ class CreateCamera(plugin.BaseCreator):
|
|||
family = "camera"
|
||||
icon = "video-camera"
|
||||
|
||||
create_as_asset_group = True
|
||||
|
||||
@ops.execute_function_in_main_thread
|
||||
def create(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
"""Run the creator on Blender main thread."""
|
||||
self._add_instance_to_context(
|
||||
CreatedInstance(self.family, subset_name, instance_data, self)
|
||||
)
|
||||
|
||||
mti = ops.MainThreadItem(
|
||||
self._process, subset_name, instance_data, pre_create_data
|
||||
)
|
||||
ops.execute_in_main_thread(mti)
|
||||
asset_group = super().create(subset_name,
|
||||
instance_data,
|
||||
pre_create_data)
|
||||
|
||||
def _process(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
# Get Instance Container or create it if it does not exist
|
||||
instances = bpy.data.collections.get(AVALON_INSTANCES)
|
||||
if not instances:
|
||||
instances = bpy.data.collections.new(name=AVALON_INSTANCES)
|
||||
bpy.context.scene.collection.children.link(instances)
|
||||
|
||||
# Create instance object
|
||||
name = plugin.asset_name(instance_data["asset"], subset_name)
|
||||
|
||||
asset_group = bpy.data.objects.new(name=name, object_data=None)
|
||||
asset_group.empty_display_type = 'SINGLE_ARROW'
|
||||
instances.objects.link(asset_group)
|
||||
|
||||
asset_group[AVALON_PROPERTY] = instance_node = {
|
||||
"name": asset_group.name,
|
||||
}
|
||||
|
||||
self.set_instance_data(subset_name, instance_data, instance_node)
|
||||
lib.imprint(asset_group, instance_data)
|
||||
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
bpy.context.view_layer.objects.active = asset_group
|
||||
selected = lib.get_selection()
|
||||
for obj in selected:
|
||||
|
|
@ -67,6 +43,7 @@ class CreateCamera(plugin.BaseCreator):
|
|||
camera = bpy.data.cameras.new(subset_name)
|
||||
camera_obj = bpy.data.objects.new(subset_name, camera)
|
||||
|
||||
instances = bpy.data.collections.get(AVALON_INSTANCES)
|
||||
instances.objects.link(camera_obj)
|
||||
|
||||
camera_obj.select_set(True)
|
||||
|
|
|
|||
|
|
@ -19,43 +19,18 @@ class CreateLayout(plugin.BaseCreator):
|
|||
family = "layout"
|
||||
icon = "cubes"
|
||||
|
||||
create_as_asset_group = True
|
||||
|
||||
def create(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
"""Run the creator on Blender main thread."""
|
||||
self._add_instance_to_context(
|
||||
CreatedInstance(self.family, subset_name, instance_data, self)
|
||||
)
|
||||
|
||||
mti = ops.MainThreadItem(
|
||||
self._process, subset_name, instance_data, pre_create_data
|
||||
)
|
||||
ops.execute_in_main_thread(mti)
|
||||
|
||||
def _process(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
# Get Instance Container or create it if it does not exist
|
||||
instances = bpy.data.collections.get(AVALON_INSTANCES)
|
||||
if not instances:
|
||||
instances = bpy.data.collections.new(name=AVALON_INSTANCES)
|
||||
bpy.context.scene.collection.children.link(instances)
|
||||
|
||||
# Create instance object
|
||||
name = plugin.asset_name(instance_data["asset"], subset_name)
|
||||
asset_group = bpy.data.objects.new(name=name, object_data=None)
|
||||
asset_group.empty_display_type = 'SINGLE_ARROW'
|
||||
instances.objects.link(asset_group)
|
||||
|
||||
asset_group[AVALON_PROPERTY] = instance_node = {
|
||||
"name": asset_group.name,
|
||||
}
|
||||
|
||||
self.set_instance_data(subset_name, instance_data, instance_node)
|
||||
lib.imprint(asset_group, instance_data)
|
||||
asset_group = super().create(subset_name,
|
||||
instance_data,
|
||||
pre_create_data)
|
||||
|
||||
# Add selected objects to instance
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
bpy.context.view_layer.objects.active = asset_group
|
||||
selected = lib.get_selection()
|
||||
for obj in selected:
|
||||
|
|
|
|||
|
|
@ -19,48 +19,24 @@ class CreateModel(plugin.BaseCreator):
|
|||
family = "model"
|
||||
icon = "cube"
|
||||
|
||||
create_as_asset_group = True
|
||||
|
||||
@ops.execute_function_in_main_thread
|
||||
def create(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
"""Run the creator on Blender main thread."""
|
||||
self._add_instance_to_context(
|
||||
CreatedInstance(self.family, subset_name, instance_data, self)
|
||||
)
|
||||
|
||||
mti = ops.MainThreadItem(
|
||||
self._process, subset_name, instance_data, pre_create_data
|
||||
)
|
||||
ops.execute_in_main_thread(mti)
|
||||
|
||||
def _process(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
# Get Instance Container or create it if it does not exist
|
||||
instances = bpy.data.collections.get(AVALON_INSTANCES)
|
||||
if not instances:
|
||||
instances = bpy.data.collections.new(name=AVALON_INSTANCES)
|
||||
bpy.context.scene.collection.children.link(instances)
|
||||
|
||||
# Create instance object
|
||||
name = plugin.asset_name(instance_data["asset"], subset_name)
|
||||
asset_group = bpy.data.objects.new(name=name, object_data=None)
|
||||
asset_group.empty_display_type = 'SINGLE_ARROW'
|
||||
instances.objects.link(asset_group)
|
||||
|
||||
asset_group[AVALON_PROPERTY] = instance_node = {
|
||||
"name": asset_group.name,
|
||||
}
|
||||
|
||||
self.set_instance_data(subset_name, instance_data, instance_node)
|
||||
lib.imprint(asset_group, instance_data)
|
||||
asset_group = super().create(subset_name,
|
||||
instance_data,
|
||||
pre_create_data)
|
||||
|
||||
# Add selected objects to instance
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
bpy.context.view_layer.objects.active = asset_group
|
||||
selected = lib.get_selection()
|
||||
for obj in selected:
|
||||
obj.select_set(True)
|
||||
selected.append(asset_group)
|
||||
|
||||
bpy.ops.object.parent_set(keep_transform=True)
|
||||
|
||||
return asset_group
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class CreatePointcache(plugin.BaseCreator):
|
|||
subset_name, instance_data, pre_create_data
|
||||
)
|
||||
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
objects = lib.get_selection()
|
||||
for obj in objects:
|
||||
collection.objects.link(obj)
|
||||
|
|
|
|||
|
|
@ -21,11 +21,12 @@ class CreateReview(plugin.BaseCreator):
|
|||
subset_name, instance_data, pre_create_data
|
||||
)
|
||||
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
selected = lib.get_selection()
|
||||
for obj in selected:
|
||||
collection.objects.link(obj)
|
||||
elif pre_create_data.get("asset_group"):
|
||||
# TODO: What is the intended behavior for this?
|
||||
obj = (self.options or {}).get("asset_group")
|
||||
collection.objects.link(obj)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,43 +19,18 @@ class CreateRig(plugin.BaseCreator):
|
|||
family = "rig"
|
||||
icon = "wheelchair"
|
||||
|
||||
create_as_asset_group = True
|
||||
|
||||
@ops.execute_function_in_main_thread
|
||||
def create(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
"""Run the creator on Blender main thread."""
|
||||
self._add_instance_to_context(
|
||||
CreatedInstance(self.family, subset_name, instance_data, self)
|
||||
)
|
||||
|
||||
mti = ops.MainThreadItem(
|
||||
self._process, subset_name, instance_data, pre_create_data
|
||||
)
|
||||
ops.execute_in_main_thread(mti)
|
||||
|
||||
def _process(
|
||||
self, subset_name: str, instance_data: dict, pre_create_data: dict
|
||||
):
|
||||
# Get Instance Container or create it if it does not exist
|
||||
instances = bpy.data.collections.get(AVALON_INSTANCES)
|
||||
if not instances:
|
||||
instances = bpy.data.collections.new(name=AVALON_INSTANCES)
|
||||
bpy.context.scene.collection.children.link(instances)
|
||||
|
||||
# Create instance object
|
||||
name = plugin.asset_name(instance_data["asset"], subset_name)
|
||||
asset_group = bpy.data.objects.new(name=name, object_data=None)
|
||||
asset_group.empty_display_type = 'SINGLE_ARROW'
|
||||
instances.objects.link(asset_group)
|
||||
|
||||
asset_group[AVALON_PROPERTY] = instance_node = {
|
||||
"name": asset_group.name,
|
||||
}
|
||||
|
||||
self.set_instance_data(subset_name, instance_data, instance_node)
|
||||
lib.imprint(asset_group, instance_data)
|
||||
asset_group = super().create(subset_name,
|
||||
instance_data,
|
||||
pre_create_data)
|
||||
|
||||
# Add selected objects to instance
|
||||
if pre_create_data.get("useSelection"):
|
||||
if pre_create_data.get("use_selection"):
|
||||
bpy.context.view_layer.objects.active = asset_group
|
||||
selected = lib.get_selection()
|
||||
for obj in selected:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ import bpy
|
|||
from openpype.pipeline import CreatedInstance, AutoCreator
|
||||
from openpype.client import get_asset_by_name
|
||||
from openpype.hosts.blender.api.plugin import BaseCreator
|
||||
from openpype.hosts.blender.api.lib import imprint
|
||||
from openpype.hosts.blender.api.pipeline import AVALON_PROPERTY
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINERS
|
||||
)
|
||||
|
||||
|
||||
class CreateWorkfile(BaseCreator, AutoCreator):
|
||||
|
|
@ -53,6 +55,8 @@ class CreateWorkfile(BaseCreator, AutoCreator):
|
|||
current_instance = CreatedInstance(
|
||||
self.family, subset_name, data, self
|
||||
)
|
||||
instance_node = bpy.data.collections.get(AVALON_CONTAINERS, {})
|
||||
current_instance.transient_data["instance_node"] = instance_node
|
||||
self._add_instance_to_context(current_instance)
|
||||
elif (
|
||||
current_instance["asset"] != asset_name
|
||||
|
|
@ -73,28 +77,30 @@ class CreateWorkfile(BaseCreator, AutoCreator):
|
|||
)
|
||||
|
||||
def collect_instances(self):
|
||||
"""Collect workfile instances."""
|
||||
self.cache_subsets(self.collection_shared_data)
|
||||
cached_subsets = self.collection_shared_data["blender_cached_subsets"]
|
||||
for node in cached_subsets.get(self.identifier, []):
|
||||
created_instance = CreatedInstance.from_existing(
|
||||
self.read_instance_node(node), self
|
||||
)
|
||||
self._add_instance_to_context(created_instance)
|
||||
|
||||
def update_instances(self, update_list):
|
||||
"""Update workfile instances."""
|
||||
for created_inst, _changes in update_list:
|
||||
data = created_inst.data_to_store()
|
||||
node = data.get("instance_node")
|
||||
if not node:
|
||||
task_name = self.create_context.get_current_task_name()
|
||||
print("Collecting!")
|
||||
instance_node = bpy.data.collections.get(AVALON_CONTAINERS)
|
||||
if not instance_node:
|
||||
return
|
||||
print(instance_node)
|
||||
property = instance_node.get(AVALON_PROPERTY)
|
||||
if not property:
|
||||
return
|
||||
print(property)
|
||||
|
||||
bpy.context.scene[AVALON_PROPERTY] = node = {
|
||||
"name": f"workfile{task_name}"
|
||||
}
|
||||
# Create instance object from existing data
|
||||
instance = CreatedInstance.from_existing(
|
||||
instance_data=property.to_dict(),
|
||||
creator=self
|
||||
)
|
||||
instance.transient_data["instance_node"] = instance_node
|
||||
|
||||
created_inst["instance_node"] = node
|
||||
data = created_inst.data_to_store()
|
||||
# Add instance to create context
|
||||
self._add_instance_to_context(instance)
|
||||
|
||||
imprint(node, data)
|
||||
def remove_instances(self, instances):
|
||||
for instance in instances:
|
||||
node = instance.transient_data["instance_node"]
|
||||
del node[AVALON_PROPERTY]
|
||||
|
||||
self._remove_instance_from_context(instance)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ class BlendLoader(plugin.AssetLoader):
|
|||
|
||||
for rig in rigs:
|
||||
creator_plugin = get_legacy_creator_by_name("CreateAnimation")
|
||||
# TODO: Refactor legacy create usage to new style creators
|
||||
legacy_create(
|
||||
creator_plugin,
|
||||
name=rig.name.split(':')[-1] + "_animation",
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
|
|||
# raise ValueError("Creator plugin \"CreateCamera\" was "
|
||||
# "not found.")
|
||||
|
||||
# TODO: Refactor legacy create usage to new style creators
|
||||
# legacy_create(
|
||||
# creator_plugin,
|
||||
# name="camera",
|
||||
|
|
|
|||
|
|
@ -73,9 +73,8 @@ class CollectBlenderRender(pyblish.api.InstancePlugin):
|
|||
def process(self, instance):
|
||||
context = instance.context
|
||||
|
||||
render_data = bpy.data.collections[
|
||||
instance.data["instance_node"]["name"]
|
||||
].get("render_data")
|
||||
instance_node = instance.data["transientData"]["instance_node"]
|
||||
render_data = instance_node.get("render_data")
|
||||
|
||||
assert render_data, "No render data found."
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ class CollectReview(pyblish.api.InstancePlugin):
|
|||
|
||||
self.log.debug(f"instance: {instance}")
|
||||
|
||||
datablock = bpy.data.collections.get(
|
||||
instance.data.get("instance_node", {}).get("name", "")
|
||||
)
|
||||
datablock = instance.data["transientData"]["instance_node"]
|
||||
|
||||
# get cameras
|
||||
cameras = [
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class ValidateInstanceEmpty(pyblish.api.InstancePlugin):
|
|||
optional = False
|
||||
|
||||
def process(self, instance):
|
||||
asset_group = instance.data["instance_node"]
|
||||
asset_group = instance.data["transientData"]["instance_node"]
|
||||
|
||||
if isinstance(asset_group, bpy.types.Collection):
|
||||
if not (asset_group.objects or asset_group.children):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue