Merge branch 'develop' into enhancement/OP-7940_render_workfile_attributes

This commit is contained in:
Jakub Ježek 2024-01-24 16:07:18 +01:00 committed by GitHub
commit fa963bfc1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 238 additions and 144 deletions

View file

@ -35,6 +35,8 @@ body:
label: Version
description: What version are you running? Look to OpenPype Tray
options:
- 3.18.5-nightly.3
- 3.18.5-nightly.2
- 3.18.5-nightly.1
- 3.18.4
- 3.18.4-nightly.1
@ -133,8 +135,6 @@ body:
- 3.15.8-nightly.2
- 3.15.8-nightly.1
- 3.15.7
- 3.15.7-nightly.3
- 3.15.7-nightly.2
validations:
required: true
- type: dropdown

View file

@ -127,8 +127,9 @@ def isolate_objects(window, objects):
context = create_blender_context(selected=objects, window=window)
bpy.ops.view3d.view_axis(context, type="FRONT")
bpy.ops.view3d.localview(context)
with bpy.context.temp_override(**context):
bpy.ops.view3d.view_axis(type="FRONT")
bpy.ops.view3d.localview()
deselect_all()
@ -270,10 +271,12 @@ def _independent_window():
"""Create capture-window context."""
context = create_blender_context()
current_windows = set(bpy.context.window_manager.windows)
bpy.ops.wm.window_new(context)
window = list(set(bpy.context.window_manager.windows) - current_windows)[0]
context["window"] = window
try:
yield window
finally:
bpy.ops.wm.window_close(context)
with bpy.context.temp_override(**context):
bpy.ops.wm.window_new()
window = list(
set(bpy.context.window_manager.windows) - current_windows)[0]
context["window"] = window
try:
yield window
finally:
bpy.ops.wm.window_close()

View file

@ -67,7 +67,8 @@ class AudioLoader(plugin.AssetLoader):
oc = bpy.context.copy()
oc["area"] = window_manager.windows[-1].screen.areas[0]
bpy.ops.sequencer.sound_strip_add(oc, filepath=libpath, frame_start=1)
with bpy.context.temp_override(**oc):
bpy.ops.sequencer.sound_strip_add(filepath=libpath, frame_start=1)
window_manager.windows[-1].screen.areas[0].type = old_type
@ -156,17 +157,18 @@ class AudioLoader(plugin.AssetLoader):
oc = bpy.context.copy()
oc["area"] = window_manager.windows[-1].screen.areas[0]
# We deselect all sequencer strips, and then select the one we
# need to remove.
bpy.ops.sequencer.select_all(oc, action='DESELECT')
scene = bpy.context.scene
scene.sequence_editor.sequences_all[old_audio].select = True
with bpy.context.temp_override(**oc):
# We deselect all sequencer strips, and then select the one we
# need to remove.
bpy.ops.sequencer.select_all(action='DESELECT')
scene = bpy.context.scene
scene.sequence_editor.sequences_all[old_audio].select = True
bpy.ops.sequencer.delete(oc)
bpy.data.sounds.remove(bpy.data.sounds[old_audio])
bpy.ops.sequencer.delete()
bpy.data.sounds.remove(bpy.data.sounds[old_audio])
bpy.ops.sequencer.sound_strip_add(
oc, filepath=str(libpath), frame_start=1)
bpy.ops.sequencer.sound_strip_add(
filepath=str(libpath), frame_start=1)
window_manager.windows[-1].screen.areas[0].type = old_type
@ -205,12 +207,13 @@ class AudioLoader(plugin.AssetLoader):
oc = bpy.context.copy()
oc["area"] = window_manager.windows[-1].screen.areas[0]
# We deselect all sequencer strips, and then select the one we
# need to remove.
bpy.ops.sequencer.select_all(oc, action='DESELECT')
bpy.context.scene.sequence_editor.sequences_all[audio].select = True
bpy.ops.sequencer.delete(oc)
with bpy.context.temp_override(**oc):
# We deselect all sequencer strips, and then select the one we
# need to remove.
bpy.ops.sequencer.select_all(action='DESELECT')
scene = bpy.context.scene
scene.sequence_editor.sequences_all[audio].select = True
bpy.ops.sequencer.delete()
window_manager.windows[-1].screen.areas[0].type = old_type

View file

@ -102,7 +102,6 @@ class BlendLoader(plugin.AssetLoader):
# Link all the container children to the collection
for obj in container.children_recursive:
print(obj)
bpy.context.scene.collection.objects.link(obj)
# Remove the library from the blend file
@ -194,8 +193,20 @@ class BlendLoader(plugin.AssetLoader):
transform = asset_group.matrix_basis.copy()
old_data = dict(asset_group.get(AVALON_PROPERTY))
old_members = old_data.get("members", [])
parent = asset_group.parent
actions = {}
objects_with_anim = [
obj for obj in asset_group.children_recursive
if obj.animation_data]
for obj in objects_with_anim:
# Check if the object has an action and, if so, add it to a dict
# so we can restore it later. Save and restore the action only
# if it wasn't originally loaded from the current asset.
if obj.animation_data.action not in old_members:
actions[obj.name] = obj.animation_data.action
self.exec_remove(container)
asset_group, members = self._process_data(libpath, group_name)
@ -206,6 +217,11 @@ class BlendLoader(plugin.AssetLoader):
asset_group.matrix_basis = transform
asset_group.parent = parent
# Restore the actions
for obj in asset_group.children_recursive:
if obj.name in actions:
obj.animation_data.action = actions[obj.name]
# Restore the old data, but reset memebers, as they don't exist anymore
# This avoids a crash, because the memory addresses of those members
# are not valid anymore

View file

@ -55,13 +55,13 @@ class ExtractAnimationABC(
context = plugin.create_blender_context(
active=asset_group, selected=selected)
# We export the abc
bpy.ops.wm.alembic_export(
context,
filepath=filepath,
selected=True,
flatten=False
)
with bpy.context.temp_override(**context):
# We export the abc
bpy.ops.wm.alembic_export(
filepath=filepath,
selected=True,
flatten=False
)
plugin.deselect_all()

View file

@ -50,19 +50,19 @@ class ExtractCamera(publish.Extractor, publish.OptionalPyblishPluginMixin):
scale_length = bpy.context.scene.unit_settings.scale_length
bpy.context.scene.unit_settings.scale_length = 0.01
# We export the fbx
bpy.ops.export_scene.fbx(
context,
filepath=filepath,
use_active_collection=False,
use_selection=True,
bake_anim_use_nla_strips=False,
bake_anim_use_all_actions=False,
add_leaf_bones=False,
armature_nodetype='ROOT',
object_types={'CAMERA'},
bake_anim_simplify_factor=0.0
)
with bpy.context.temp_override(**context):
# We export the fbx
bpy.ops.export_scene.fbx(
filepath=filepath,
use_active_collection=False,
use_selection=True,
bake_anim_use_nla_strips=False,
bake_anim_use_all_actions=False,
add_leaf_bones=False,
armature_nodetype='ROOT',
object_types={'CAMERA'},
bake_anim_simplify_factor=0.0
)
bpy.context.scene.unit_settings.scale_length = scale_length

View file

@ -57,15 +57,15 @@ class ExtractFBX(publish.Extractor, publish.OptionalPyblishPluginMixin):
scale_length = bpy.context.scene.unit_settings.scale_length
bpy.context.scene.unit_settings.scale_length = 0.01
# We export the fbx
bpy.ops.export_scene.fbx(
context,
filepath=filepath,
use_active_collection=False,
use_selection=True,
mesh_smooth_type='FACE',
add_leaf_bones=False
)
with bpy.context.temp_override(**context):
# We export the fbx
bpy.ops.export_scene.fbx(
filepath=filepath,
use_active_collection=False,
use_selection=True,
mesh_smooth_type='FACE',
add_leaf_bones=False
)
bpy.context.scene.unit_settings.scale_length = scale_length

View file

@ -153,17 +153,20 @@ class ExtractAnimationFBX(
override = plugin.create_blender_context(
active=root, selected=[root, armature])
bpy.ops.export_scene.fbx(
override,
filepath=filepath,
use_active_collection=False,
use_selection=True,
bake_anim_use_nla_strips=False,
bake_anim_use_all_actions=False,
add_leaf_bones=False,
armature_nodetype='ROOT',
object_types={'EMPTY', 'ARMATURE'}
)
with bpy.context.temp_override(**override):
# We export the fbx
bpy.ops.export_scene.fbx(
filepath=filepath,
use_active_collection=False,
use_selection=True,
bake_anim_use_nla_strips=False,
bake_anim_use_all_actions=False,
add_leaf_bones=False,
armature_nodetype='ROOT',
object_types={'EMPTY', 'ARMATURE'}
)
armature.name = armature_name
asset_group.name = asset_group_name
root.select_set(True)

View file

@ -80,17 +80,18 @@ class ExtractLayout(publish.Extractor, publish.OptionalPyblishPluginMixin):
override = plugin.create_blender_context(
active=asset, selected=[asset, obj])
bpy.ops.export_scene.fbx(
override,
filepath=filepath,
use_active_collection=False,
use_selection=True,
bake_anim_use_nla_strips=False,
bake_anim_use_all_actions=False,
add_leaf_bones=False,
armature_nodetype='ROOT',
object_types={'EMPTY', 'ARMATURE'}
)
with bpy.context.temp_override(**override):
# We export the fbx
bpy.ops.export_scene.fbx(
filepath=filepath,
use_active_collection=False,
use_selection=True,
bake_anim_use_nla_strips=False,
bake_anim_use_all_actions=False,
add_leaf_bones=False,
armature_nodetype='ROOT',
object_types={'EMPTY', 'ARMATURE'}
)
obj.name = armature_name
asset.name = asset_group_name
asset.select_set(False)

View file

@ -9,6 +9,8 @@ class CollectClipEffects(pyblish.api.InstancePlugin):
label = "Collect Clip Effects Instances"
families = ["clip"]
effect_categories = []
def process(self, instance):
family = "effect"
effects = {}
@ -70,29 +72,62 @@ class CollectClipEffects(pyblish.api.InstancePlugin):
subset_split.insert(0, "effect")
name = "".join(subset_split)
effect_categories = {
x["name"]: x["effect_classes"] for x in self.effect_categories
}
# create new instance and inherit data
data = {}
for key, value in instance.data.items():
if "clipEffectItems" in key:
category_by_effect = {"": ""}
for key, values in effect_categories.items():
for cls in values:
category_by_effect[cls] = key
effects_categorized = {k: {} for k in effect_categories.keys()}
effects_categorized[""] = {}
for key, value in effects.items():
if key == "assignTo":
continue
data[key] = value
# change names
data["subset"] = name
data["family"] = family
data["families"] = [family]
data["name"] = data["subset"] + "_" + data["asset"]
data["label"] = "{} - {}".format(
data['asset'], data["subset"]
)
data["effects"] = effects
# Some classes can have a number in them. Like Text2.
found_cls = ""
for cls in category_by_effect.keys():
if cls in value["class"]:
found_cls = cls
# create new instance
_instance = instance.context.create_instance(**data)
self.log.info("Created instance `{}`".format(_instance))
self.log.debug("instance.data `{}`".format(_instance.data))
effects_categorized[category_by_effect[found_cls]][key] = value
categories = list(effects_categorized.keys())
for category in categories:
if not effects_categorized[category]:
effects_categorized.pop(category)
continue
effects_categorized[category]["assignTo"] = effects["assignTo"]
for category, effects in effects_categorized.items():
name = "".join(subset_split)
name += category.capitalize()
# create new instance and inherit data
data = {}
for key, value in instance.data.items():
if "clipEffectItems" in key:
continue
data[key] = value
# change names
data["subset"] = name
data["family"] = family
data["families"] = [family]
data["name"] = data["subset"] + "_" + data["asset"]
data["label"] = "{} - {}".format(
data['asset'], data["subset"]
)
data["effects"] = effects
# create new instance
_instance = instance.context.create_instance(**data)
self.log.info("Created instance `{}`".format(_instance))
self.log.debug("instance.data `{}`".format(_instance.data))
def test_overlap(self, effect_t_in, effect_t_out):
covering_exp = bool(

View file

@ -16,8 +16,9 @@ class FbxLoader(load.LoaderPlugin):
order = -10
families = ["staticMesh", "fbx"]
representations = ["fbx"]
families = ["*"]
representations = ["*"]
extensions = {"fbx"}
def load(self, context, name=None, namespace=None, data=None):

View file

@ -44,17 +44,17 @@ XML_CHAR_REF_REGEX_HEX = re.compile(r"&#x?[0-9a-fA-F]+;")
ARRAY_TYPE_REGEX = re.compile(r"^(int|float|string)\[\d+\]$")
IMAGE_EXTENSIONS = {
".ani", ".anim", ".apng", ".art", ".bmp", ".bpg", ".bsave", ".cal",
".cin", ".cpc", ".cpt", ".dds", ".dpx", ".ecw", ".exr", ".fits",
".flic", ".flif", ".fpx", ".gif", ".hdri", ".hevc", ".icer",
".icns", ".ico", ".cur", ".ics", ".ilbm", ".jbig", ".jbig2",
".jng", ".jpeg", ".jpeg-ls", ".jpeg", ".2000", ".jpg", ".xr",
".jpeg", ".xt", ".jpeg-hdr", ".kra", ".mng", ".miff", ".nrrd",
".ora", ".pam", ".pbm", ".pgm", ".ppm", ".pnm", ".pcx", ".pgf",
".pictor", ".png", ".psd", ".psb", ".psp", ".qtvr", ".ras",
".rgbe", ".logluv", ".tiff", ".sgi", ".tga", ".tiff", ".tiff/ep",
".tiff/it", ".ufo", ".ufp", ".wbmp", ".webp", ".xbm", ".xcf",
".xpm", ".xwd"
".ani", ".anim", ".apng", ".art", ".bmp", ".bpg", ".bsave",
".cal", ".cin", ".cpc", ".cpt", ".dds", ".dpx", ".ecw", ".exr",
".fits", ".flic", ".flif", ".fpx", ".gif", ".hdri", ".hevc",
".icer", ".icns", ".ico", ".cur", ".ics", ".ilbm", ".jbig", ".jbig2",
".jng", ".jpeg", ".jpeg-ls", ".jpeg-hdr", ".2000", ".jpg",
".kra", ".logluv", ".mng", ".miff", ".nrrd", ".ora",
".pam", ".pbm", ".pgm", ".ppm", ".pnm", ".pcx", ".pgf",
".pictor", ".png", ".psd", ".psb", ".psp", ".qtvr",
".ras", ".rgbe", ".sgi", ".tga",
".tif", ".tiff", ".tiff/ep", ".tiff/it", ".ufo", ".ufp",
".wbmp", ".webp", ".xr", ".xt", ".xbm", ".xcf", ".xpm", ".xwd"
}
VIDEO_EXTENSIONS = {

View file

@ -410,9 +410,9 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
"""
hierarchy_queue = collections.deque()
hierarchy_queue.append(hierarchy_context)
hierarchy_queue.append(copy.deepcopy(hierarchy_context))
while hierarchy_queue:
item = hierarchy_context.popleft()
item = hierarchy_queue.popleft()
if asset_name in item:
return item[asset_name].get("tasks") or {}

View file

@ -30,8 +30,7 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin):
if not AYON_SERVER_ENABLED:
return
hierarchy_context = context.data.get("hierarchyContext")
if not hierarchy_context:
if not context.data.get("hierarchyContext"):
self.log.debug("Skipping ExtractHierarchyToAYON")
return

View file

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
__version__ = "3.18.5-nightly.1"
__version__ = "3.18.5-nightly.3"

View file

@ -307,9 +307,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--nukeassist"],
"darwin": [],
"linux": []
"linux": ["--nukeassist"]
},
"environment": "{}",
"use_python_2": false
@ -329,9 +329,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--nukeassist"],
"darwin": [],
"linux": []
"linux": ["--nukeassist"]
},
"environment": "{}",
"use_python_2": false
@ -351,9 +351,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--nukeassist"],
"darwin": [],
"linux": []
"linux": ["--nukeassist"]
},
"environment": "{}",
"use_python_2": false
@ -382,9 +382,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--nukex"],
"darwin": [],
"linux": []
"linux": ["--nukex"]
},
"environment": "{}",
"use_python_2": false
@ -404,9 +404,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--nukex"],
"darwin": [],
"linux": []
"linux": ["--nukex"]
},
"environment": "{}",
"use_python_2": false
@ -426,9 +426,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--nukex"],
"darwin": [],
"linux": []
"linux": ["--nukex"]
},
"environment": "{}",
"use_python_2": false
@ -457,9 +457,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--studio"],
"darwin": [],
"linux": []
"linux": ["--studio"]
},
"environment": "{}",
"use_python_2": false
@ -479,9 +479,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--studio"],
"darwin": [],
"linux": []
"linux": ["--studio"]
},
"environment": "{}",
"use_python_2": false
@ -501,9 +501,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--studio"],
"darwin": [],
"linux": []
"linux": ["--studio"]
},
"environment": "{}",
"use_python_2": false
@ -532,9 +532,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--hiero"],
"darwin": [],
"linux": []
"linux": ["--hiero"]
},
"environment": "{}",
"use_python_2": false
@ -554,9 +554,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--hiero"],
"darwin": [],
"linux": []
"linux": ["--hiero"]
},
"environment": "{}",
"use_python_2": false
@ -576,9 +576,9 @@
]
},
"arguments": {
"windows": [],
"windows": ["--hiero"],
"darwin": [],
"linux": []
"linux": ["--hiero"]
},
"environment": "{}",
"use_python_2": false

View file

@ -1 +1 @@
__version__ = "0.1.3"
__version__ = "0.1.4"

View file

@ -1,5 +1,7 @@
from pydantic import Field
from ayon_server.settings import BaseSettingsModel
from pydantic import Field, validator
from ayon_server.settings import (
BaseSettingsModel, ensure_unique_names, normalize_name
)
class CollectInstanceVersionModel(BaseSettingsModel):
@ -9,6 +11,30 @@ class CollectInstanceVersionModel(BaseSettingsModel):
)
class CollectClipEffectsDefModel(BaseSettingsModel):
_layout = "expanded"
name: str = Field("", title="Name")
effect_classes: list[str] = Field(
default_factory=list, title="Effect Classes"
)
@validator("name")
def validate_name(cls, value):
"""Ensure name does not contain weird characters"""
return normalize_name(value)
class CollectClipEffectsModel(BaseSettingsModel):
effect_categories: list[CollectClipEffectsDefModel] = Field(
default_factory=list, title="Effect Categories"
)
@validator("effect_categories")
def validate_unique_outputs(cls, value):
ensure_unique_names(value)
return value
class ExtractReviewCutUpVideoModel(BaseSettingsModel):
enabled: bool = Field(
True,
@ -25,6 +51,10 @@ class PublishPuginsModel(BaseSettingsModel):
default_factory=CollectInstanceVersionModel,
title="Collect Instance Version"
)
CollectClipEffects: CollectClipEffectsModel = Field(
default_factory=CollectClipEffectsModel,
title="Collect Clip Effects"
)
"""# TODO: enhance settings with host api:
Rename class name and plugin name
to match title (it makes more sense)
@ -44,5 +74,8 @@ DEFAULT_PUBLISH_PLUGIN_SETTINGS = {
"tags_addition": [
"review"
]
},
"CollectClipEffectsModel": {
"effect_categories": []
}
}

View file

@ -1 +1 @@
__version__ = "0.1.1"
__version__ = "0.1.2"