Merge branch 'release/3.15.x' into feature/OP-3845_nuke-convert-to-new-publisher

This commit is contained in:
Jakub Trllo 2022-12-20 15:24:22 +01:00
commit b4d29d0160
27 changed files with 573 additions and 77 deletions

View file

@ -0,0 +1,82 @@
import bpy
from openpype.hosts.blender.api import plugin
def append_workfile(context, fname, do_import):
asset = context['asset']['name']
subset = context['subset']['name']
group_name = plugin.asset_name(asset, subset)
# We need to preserve the original names of the scenes, otherwise,
# if there are duplicate names in the current workfile, the imported
# scenes will be renamed by Blender to avoid conflicts.
original_scene_names = []
with bpy.data.libraries.load(fname) as (data_from, data_to):
for attr in dir(data_to):
if attr == "scenes":
for scene in data_from.scenes:
original_scene_names.append(scene)
setattr(data_to, attr, getattr(data_from, attr))
current_scene = bpy.context.scene
for scene, s_name in zip(data_to.scenes, original_scene_names):
scene.name = f"{group_name}_{s_name}"
if do_import:
collection = bpy.data.collections.new(f"{group_name}_{s_name}")
for obj in scene.objects:
collection.objects.link(obj)
current_scene.collection.children.link(collection)
for coll in scene.collection.children:
collection.children.link(coll)
class AppendBlendLoader(plugin.AssetLoader):
"""Append workfile in Blender (unmanaged)
Warning:
The loaded content will be unmanaged and is *not* visible in the
scene inventory. It's purely intended to merge content into your scene
so you could also use it as a new base.
"""
representations = ["blend"]
families = ["*"]
label = "Append Workfile"
order = 9
icon = "arrow-circle-down"
color = "#775555"
def load(self, context, name=None, namespace=None, data=None):
append_workfile(context, self.fname, False)
# We do not containerize imported content, it remains unmanaged
return
class ImportBlendLoader(plugin.AssetLoader):
"""Import workfile in the current Blender scene (unmanaged)
Warning:
The loaded content will be unmanaged and is *not* visible in the
scene inventory. It's purely intended to merge content into your scene
so you could also use it as a new base.
"""
representations = ["blend"]
families = ["*"]
label = "Import Workfile"
order = 9
icon = "arrow-circle-down"
color = "#775555"
def load(self, context, name=None, namespace=None, data=None):
append_workfile(context, self.fname, True)
# We do not containerize imported content, it remains unmanaged
return

View file

@ -1,5 +1,5 @@
import os
from Qt import QtWidgets
from qtpy import QtWidgets
from copy import deepcopy
from pprint import pformat
from openpype.tools.utils.host_tools import HostToolsHelper

View file

@ -5,10 +5,10 @@ from copy import deepcopy
from xml.etree import ElementTree as ET
import qargparse
from Qt import QtCore, QtWidgets
from qtpy import QtCore, QtWidgets
from openpype import style
from openpype.lib import Logger
from openpype.lib import Logger, StringTemplate
from openpype.pipeline import LegacyCreator, LoaderPlugin
from openpype.settings import get_current_project_settings
@ -775,6 +775,11 @@ class OpenClipSolver(flib.MediaInfoFile):
self.feed_colorspace = feed_data.get("colorspace")
self.log.debug("feed_version_name: {}".format(self.feed_version_name))
# layer rename variables
self.layer_rename_template = feed_data["layer_rename_template"]
self.layer_rename_patterns = feed_data["layer_rename_patterns"]
self.context_data = feed_data["context_data"]
# derivate other feed variables
self.feed_basename = os.path.basename(feed_path)
self.feed_dir = os.path.dirname(feed_path)
@ -813,9 +818,11 @@ class OpenClipSolver(flib.MediaInfoFile):
def _create_new_open_clip(self):
self.log.info("Building new openClip")
self.log.debug(">> self.clip_data: {}".format(self.clip_data))
for tmp_xml_track in self.clip_data.iter("track"):
# solve track (layer) name
self._rename_track_name(tmp_xml_track)
tmp_xml_feeds = tmp_xml_track.find('feeds')
tmp_xml_feeds.set('currentVersion', self.feed_version_name)
@ -850,6 +857,48 @@ class OpenClipSolver(flib.MediaInfoFile):
if uid == track_uid:
return xml_track
def _rename_track_name(self, xml_track_data):
layer_uid = xml_track_data.get("uid")
name_obj = xml_track_data.find("name")
layer_name = name_obj.text
if (
self.layer_rename_patterns
and not any(
re.search(lp_.lower(), layer_name.lower())
for lp_ in self.layer_rename_patterns
)
):
return
formating_data = self._update_formating_data(
layerName=layer_name,
layerUID=layer_uid
)
name_obj.text = StringTemplate(
self.layer_rename_template
).format(formating_data)
def _update_formating_data(self, **kwargs):
""" Updating formating data for layer rename
Attributes:
key=value (optional): will be included to formating data
as {key: value}
Returns:
dict: anatomy context data for formating
"""
self.log.debug(">> self.clip_data: {}".format(self.clip_data))
clip_name_obj = self.clip_data.find("name")
data = {
"originalBasename": clip_name_obj.text
}
# include version context data
data.update(self.context_data)
# include input kwargs data
data.update(kwargs)
return data
def _update_open_clip(self):
self.log.info("Updating openClip ..")
@ -857,11 +906,12 @@ class OpenClipSolver(flib.MediaInfoFile):
out_xml = out_xml.getroot()
self.log.debug(">> out_xml: {}".format(out_xml))
self.log.debug(">> self.clip_data: {}".format(self.clip_data))
# loop tmp tracks
updated_any = False
for tmp_xml_track in self.clip_data.iter("track"):
# solve track (layer) name
self._rename_track_name(tmp_xml_track)
# get tmp track uid
tmp_track_uid = tmp_xml_track.get("uid")
self.log.debug(">> tmp_track_uid: {}".format(tmp_track_uid))

View file

@ -1,3 +1,4 @@
from copy import deepcopy
import os
import flame
from pprint import pformat
@ -25,6 +26,14 @@ class LoadClip(opfapi.ClipLoader):
reel_name = "Loaded"
clip_name_template = "{asset}_{subset}<_{output}>"
""" Anatomy keys from version context data and dynamically added:
- {layerName} - original layer name token
- {layerUID} - original layer UID token
- {originalBasename} - original clip name taken from file
"""
layer_rename_template = "{asset}_{subset}<_{output}>"
layer_rename_patterns = []
def load(self, context, name, namespace, options):
# get flame objects
@ -38,8 +47,16 @@ class LoadClip(opfapi.ClipLoader):
version_name = version.get("name", None)
colorspace = self.get_colorspace(context)
# in case output is not in context replace key to representation
if not context["representation"]["context"].get("output"):
self.clip_name_template = self.clip_name_template.replace(
"output", "representation")
self.layer_rename_template = self.layer_rename_template.replace(
"output", "representation")
formating_data = deepcopy(context["representation"]["context"])
clip_name = StringTemplate(self.clip_name_template).format(
context["representation"]["context"])
formating_data)
# convert colorspace with ocio to flame mapping
# in imageio flame section
@ -62,6 +79,9 @@ class LoadClip(opfapi.ClipLoader):
"path": self.fname.replace("\\", "/"),
"colorspace": colorspace,
"version": "v{:0>3}".format(version_name),
"layer_rename_template": self.layer_rename_template,
"layer_rename_patterns": self.layer_rename_patterns,
"context_data": formating_data
}
self.log.debug(pformat(
loading_context

View file

@ -25,6 +25,14 @@ class LoadClipBatch(opfapi.ClipLoader):
reel_name = "OP_LoadedReel"
clip_name_template = "{batch}_{asset}_{subset}<_{output}>"
""" Anatomy keys from version context data and dynamically added:
- {layerName} - original layer name token
- {layerUID} - original layer UID token
- {originalBasename} - original clip name taken from file
"""
layer_rename_template = "{asset}_{subset}<_{output}>"
layer_rename_patterns = []
def load(self, context, name, namespace, options):
# get flame objects
@ -39,7 +47,10 @@ class LoadClipBatch(opfapi.ClipLoader):
# in case output is not in context replace key to representation
if not context["representation"]["context"].get("output"):
self.clip_name_template.replace("output", "representation")
self.clip_name_template = self.clip_name_template.replace(
"output", "representation")
self.layer_rename_template = self.layer_rename_template.replace(
"output", "representation")
formating_data = deepcopy(context["representation"]["context"])
formating_data["batch"] = self.batch.name.get_value()
@ -69,6 +80,9 @@ class LoadClipBatch(opfapi.ClipLoader):
"path": self.fname.replace("\\", "/"),
"colorspace": colorspace,
"version": "v{:0>3}".format(version_name),
"layer_rename_template": self.layer_rename_template,
"layer_rename_patterns": self.layer_rename_patterns,
"context_data": formating_data
}
self.log.debug(pformat(
loading_context

View file

@ -1,4 +1,4 @@
from Qt import QtWidgets, QtCore
from qtpy import QtWidgets, QtCore
import uiwidgets
import app_utils

View file

@ -1,4 +1,4 @@
from Qt import QtWidgets, QtCore
from qtpy import QtWidgets, QtCore
class FlameLabel(QtWidgets.QLabel):

View file

@ -1,6 +1,6 @@
from __future__ import print_function
import sys
from Qt import QtWidgets
from qtpy import QtWidgets
from pprint import pformat
import atexit

View file

@ -1,7 +1,7 @@
import logging
from scriptsmenu import scriptsmenu
from Qt import QtWidgets
from qtpy import QtWidgets
log = logging.getLogger(__name__)

View file

@ -15,7 +15,11 @@ import secrets
import shutil
import hiero
from Qt import QtWidgets, QtCore, QtXml
from qtpy import QtWidgets, QtCore
try:
from PySide import QtXml
except ImportError:
from PySide2 import QtXml
from openpype.client import get_project
from openpype.settings import get_project_settings

View file

@ -43,7 +43,7 @@ def menu_install():
"""
from Qt import QtGui
from qtpy import QtGui
from . import (
publish, launch_workfiles_app, reload_config,
apply_colorspace_project, apply_colorspace_clips

View file

@ -5,7 +5,7 @@ from copy import deepcopy
import hiero
from Qt import QtWidgets, QtCore
from qtpy import QtWidgets, QtCore
import qargparse
from openpype.settings import get_current_project_settings

View file

@ -3,7 +3,7 @@ import tempfile
from pprint import pformat
import pyblish.api
from Qt.QtGui import QPixmap
from qtpy.QtGui import QPixmap
import hiero.ui

View file

@ -11,7 +11,7 @@ import contextlib
from collections import OrderedDict
import nuke
from Qt import QtCore, QtWidgets
from qtpy import QtCore, QtWidgets
from openpype.client import (
get_project,
@ -130,7 +130,6 @@ class Context:
def get_main_window():
"""Acquire Nuke's main window"""
if Context.main_window is None:
from Qt import QtWidgets
top_widgets = QtWidgets.QApplication.topLevelWidgets()
name = "Foundry::UI::DockMainWindow"
@ -740,7 +739,10 @@ def get_created_node_imageio_setting_legacy(nodeclass, creator, subset):
if (
onode["subsets"]
and not any(re.search(s, subset) for s in onode["subsets"])
and not any(
re.search(s.lower(), subset.lower())
for s in onode["subsets"]
)
):
continue
@ -823,7 +825,8 @@ def get_imageio_node_override_setting(
# find matching override node
override_imageio_node = None
for onode in override_nodes:
log.info(onode)
log.debug("__ onode: {}".format(onode))
log.debug("__ subset: {}".format(subset))
if node_class not in onode["nukeNodeClass"]:
continue
@ -832,7 +835,10 @@ def get_imageio_node_override_setting(
if (
onode["subsets"]
and not any(re.search(s, subset) for s in onode["subsets"])
and not any(
re.search(s.lower(), subset.lower())
for s in onode["subsets"]
)
):
continue