Merge branch 'develop' into feature/OP-3879_Change-extractor-usage-in-maya

This commit is contained in:
Jakub Trllo 2022-09-12 09:52:55 +02:00
commit ad81d94de6
74 changed files with 1312 additions and 753 deletions

View file

@ -1,6 +1,19 @@
import os
import bpy
import pyblish.api
from openpype.pipeline import legacy_io
from openpype.hosts.blender.api import workio
class SaveWorkfiledAction(pyblish.api.Action):
"""Save Workfile."""
label = "Save Workfile"
on = "failed"
icon = "save"
def process(self, context, plugin):
bpy.ops.wm.avalon_workfiles()
class CollectBlenderCurrentFile(pyblish.api.ContextPlugin):
@ -8,12 +21,52 @@ class CollectBlenderCurrentFile(pyblish.api.ContextPlugin):
order = pyblish.api.CollectorOrder - 0.5
label = "Blender Current File"
hosts = ['blender']
hosts = ["blender"]
actions = [SaveWorkfiledAction]
def process(self, context):
"""Inject the current working file"""
current_file = bpy.data.filepath
context.data['currentFile'] = current_file
current_file = workio.current_file()
assert current_file != '', "Current file is empty. " \
"Save the file before continuing."
context.data["currentFile"] = current_file
assert current_file, (
"Current file is empty. Save the file before continuing."
)
folder, file = os.path.split(current_file)
filename, ext = os.path.splitext(file)
task = legacy_io.Session["AVALON_TASK"]
data = {}
# create instance
instance = context.create_instance(name=filename)
subset = "workfile" + task.capitalize()
data.update({
"subset": subset,
"asset": os.getenv("AVALON_ASSET", None),
"label": subset,
"publish": True,
"family": "workfile",
"families": ["workfile"],
"setMembers": [current_file],
"frameStart": bpy.context.scene.frame_start,
"frameEnd": bpy.context.scene.frame_end,
})
data["representations"] = [{
"name": ext.lstrip("."),
"ext": ext.lstrip("."),
"files": file,
"stagingDir": folder,
}]
instance.data.update(data)
self.log.info("Collected instance: {}".format(file))
self.log.info("Scene path: {}".format(current_file))
self.log.info("staging Dir: {}".format(folder))
self.log.info("subset: {}".format(subset))

View file

@ -2,12 +2,12 @@ import os
import bpy
from openpype import api
from openpype.pipeline import publish
from openpype.hosts.blender.api import plugin
from openpype.hosts.blender.api.pipeline import AVALON_PROPERTY
class ExtractABC(api.Extractor):
class ExtractABC(publish.Extractor):
"""Extract as ABC."""
label = "Extract ABC"

View file

@ -2,10 +2,10 @@ import os
import bpy
import openpype.api
from openpype.pipeline import publish
class ExtractBlend(openpype.api.Extractor):
class ExtractBlend(publish.Extractor):
"""Extract a blend file."""
label = "Extract Blend"

View file

@ -2,10 +2,10 @@ import os
import bpy
import openpype.api
from openpype.pipeline import publish
class ExtractBlendAnimation(openpype.api.Extractor):
class ExtractBlendAnimation(publish.Extractor):
"""Extract a blend file."""
label = "Extract Blend"

View file

@ -2,11 +2,11 @@ import os
import bpy
from openpype import api
from openpype.pipeline import publish
from openpype.hosts.blender.api import plugin
class ExtractCamera(api.Extractor):
class ExtractCamera(publish.Extractor):
"""Extract as the camera as FBX."""
label = "Extract Camera"

View file

@ -2,12 +2,12 @@ import os
import bpy
from openpype import api
from openpype.pipeline import publish
from openpype.hosts.blender.api import plugin
from openpype.hosts.blender.api.pipeline import AVALON_PROPERTY
class ExtractFBX(api.Extractor):
class ExtractFBX(publish.Extractor):
"""Extract as FBX."""
label = "Extract FBX"

View file

@ -5,12 +5,12 @@ import bpy
import bpy_extras
import bpy_extras.anim_utils
from openpype import api
from openpype.pipeline import publish
from openpype.hosts.blender.api import plugin
from openpype.hosts.blender.api.pipeline import AVALON_PROPERTY
class ExtractAnimationFBX(api.Extractor):
class ExtractAnimationFBX(publish.Extractor):
"""Extract as animation."""
label = "Extract FBX"

View file

@ -6,12 +6,12 @@ import bpy_extras
import bpy_extras.anim_utils
from openpype.client import get_representation_by_name
from openpype.pipeline import publish
from openpype.hosts.blender.api import plugin
from openpype.hosts.blender.api.pipeline import AVALON_PROPERTY
import openpype.api
class ExtractLayout(openpype.api.Extractor):
class ExtractLayout(publish.Extractor):
"""Extract a layout."""
label = "Extract Layout"

View file

@ -1,113 +0,0 @@
import os
import collections
from pprint import pformat
import pyblish.api
from openpype.client import (
get_subsets,
get_last_versions,
get_representations
)
from openpype.pipeline import legacy_io
class AppendCelactionAudio(pyblish.api.ContextPlugin):
label = "Colect Audio for publishing"
order = pyblish.api.CollectorOrder + 0.1
def process(self, context):
self.log.info('Collecting Audio Data')
asset_doc = context.data["assetEntity"]
# get all available representations
subsets = self.get_subsets(
asset_doc,
representations=["audio", "wav"]
)
self.log.info(f"subsets is: {pformat(subsets)}")
if not subsets.get("audioMain"):
raise AttributeError("`audioMain` subset does not exist")
reprs = subsets.get("audioMain", {}).get("representations", [])
self.log.info(f"reprs is: {pformat(reprs)}")
repr = next((r for r in reprs), None)
if not repr:
raise "Missing `audioMain` representation"
self.log.info(f"representation is: {repr}")
audio_file = repr.get('data', {}).get('path', "")
if os.path.exists(audio_file):
context.data["audioFile"] = audio_file
self.log.info(
'audio_file: {}, has been added to context'.format(audio_file))
else:
self.log.warning("Couldn't find any audio file on Ftrack.")
def get_subsets(self, asset_doc, representations):
"""
Query subsets with filter on name.
The method will return all found subsets and its defined version
and subsets. Version could be specified with number. Representation
can be filtered.
Arguments:
asset_doct (dict): Asset (shot) mongo document
representations (list): list for all representations
Returns:
dict: subsets with version and representations in keys
"""
# Query all subsets for asset
project_name = legacy_io.active_project()
subset_docs = get_subsets(
project_name, asset_ids=[asset_doc["_id"]], fields=["_id"]
)
# Collect all subset ids
subset_ids = [
subset_doc["_id"]
for subset_doc in subset_docs
]
# Check if we found anything
assert subset_ids, (
"No subsets found. Check correct filter. "
"Try this for start `r'.*'`: asset: `{}`"
).format(asset_doc["name"])
last_versions_by_subset_id = get_last_versions(
project_name, subset_ids, fields=["_id", "parent"]
)
version_docs_by_id = {}
for version_doc in last_versions_by_subset_id.values():
version_docs_by_id[version_doc["_id"]] = version_doc
repre_docs = get_representations(
project_name,
version_ids=version_docs_by_id.keys(),
representation_names=representations
)
repre_docs_by_version_id = collections.defaultdict(list)
for repre_doc in repre_docs:
version_id = repre_doc["parent"]
repre_docs_by_version_id[version_id].append(repre_doc)
output_dict = {}
for version_id, repre_docs in repre_docs_by_version_id.items():
version_doc = version_docs_by_id[version_id]
subset_id = version_doc["parent"]
subset_doc = last_versions_by_subset_id[subset_id]
# Store queried docs by subset name
output_dict[subset_doc["name"]] = {
"representations": repre_docs,
"version": version_doc
}
return output_dict

View file

@ -51,7 +51,8 @@ from .pipeline import (
)
from .menu import (
FlameMenuProjectConnect,
FlameMenuTimeline
FlameMenuTimeline,
FlameMenuUniversal
)
from .plugin import (
Creator,
@ -131,6 +132,7 @@ __all__ = [
# menu
"FlameMenuProjectConnect",
"FlameMenuTimeline",
"FlameMenuUniversal",
# plugin
"Creator",

View file

@ -201,3 +201,53 @@ class FlameMenuTimeline(_FlameMenuApp):
if self.flame:
self.flame.execute_shortcut('Rescan Python Hooks')
self.log.info('Rescan Python Hooks')
class FlameMenuUniversal(_FlameMenuApp):
# flameMenuProjectconnect app takes care of the preferences dialog as well
def __init__(self, framework):
_FlameMenuApp.__init__(self, framework)
def __getattr__(self, name):
def method(*args, **kwargs):
project = self.dynamic_menu_data.get(name)
if project:
self.link_project(project)
return method
def build_menu(self):
if not self.flame:
return []
menu = deepcopy(self.menu)
menu['actions'].append({
"name": "Load...",
"execute": lambda x: self.tools_helper.show_loader()
})
menu['actions'].append({
"name": "Manage...",
"execute": lambda x: self.tools_helper.show_scene_inventory()
})
menu['actions'].append({
"name": "Library...",
"execute": lambda x: self.tools_helper.show_library_loader()
})
return menu
def refresh(self, *args, **kwargs):
self.rescan()
def rescan(self, *args, **kwargs):
if not self.flame:
try:
import flame
self.flame = flame
except ImportError:
self.flame = None
if self.flame:
self.flame.execute_shortcut('Rescan Python Hooks')
self.log.info('Rescan Python Hooks')

View file

@ -361,6 +361,8 @@ class PublishableClip:
index_from_segment_default = False
use_shot_name_default = False
include_handles_default = False
retimed_handles_default = True
retimed_framerange_default = True
def __init__(self, segment, **kwargs):
self.rename_index = kwargs["rename_index"]
@ -496,6 +498,14 @@ class PublishableClip:
"audio", {}).get("value") or False
self.include_handles = self.ui_inputs.get(
"includeHandles", {}).get("value") or self.include_handles_default
self.retimed_handles = (
self.ui_inputs.get("retimedHandles", {}).get("value")
or self.retimed_handles_default
)
self.retimed_framerange = (
self.ui_inputs.get("retimedFramerange", {}).get("value")
or self.retimed_framerange_default
)
# build subset name from layer name
if self.subset_name == "[ track name ]":

View file

@ -276,6 +276,22 @@ class CreateShotClip(opfapi.Creator):
"target": "tag",
"toolTip": "By default handles are excluded", # noqa
"order": 3
},
"retimedHandles": {
"value": True,
"type": "QCheckBox",
"label": "Retimed handles",
"target": "tag",
"toolTip": "By default handles are retimed.", # noqa
"order": 4
},
"retimedFramerange": {
"value": True,
"type": "QCheckBox",
"label": "Retimed framerange",
"target": "tag",
"toolTip": "By default framerange is retimed.", # noqa
"order": 5
}
}
}

View file

@ -131,6 +131,10 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
"fps": self.fps,
"workfileFrameStart": workfile_start,
"sourceFirstFrame": int(first_frame),
"notRetimedHandles": (
not marker_data.get("retimedHandles")),
"notRetimedFramerange": (
not marker_data.get("retimedFramerange")),
"path": file_path,
"flameAddTasks": self.add_tasks,
"tasks": {

View file

@ -90,26 +90,38 @@ class ExtractSubsetResources(openpype.api.Extractor):
handle_end = instance.data["handleEnd"]
handles = max(handle_start, handle_end)
include_handles = instance.data.get("includeHandles")
retimed_handles = instance.data.get("retimedHandles")
# get media source range with handles
source_start_handles = instance.data["sourceStartH"]
source_end_handles = instance.data["sourceEndH"]
# retime if needed
if r_speed != 1.0:
source_start_handles = (
instance.data["sourceStart"] - r_handle_start)
source_end_handles = (
source_start_handles
+ (r_source_dur - 1)
+ r_handle_start
+ r_handle_end
)
if retimed_handles:
# handles are retimed
source_start_handles = (
instance.data["sourceStart"] - r_handle_start)
source_end_handles = (
source_start_handles
+ (r_source_dur - 1)
+ r_handle_start
+ r_handle_end
)
else:
# handles are not retimed
source_end_handles = (
source_start_handles
+ (r_source_dur - 1)
+ handle_start
+ handle_end
)
# get frame range with handles for representation range
frame_start_handle = frame_start - handle_start
repre_frame_start = frame_start_handle
if include_handles:
if r_speed == 1.0:
if r_speed == 1.0 or not retimed_handles:
frame_start_handle = frame_start
else:
frame_start_handle = (

View file

@ -73,6 +73,8 @@ def load_apps():
opfapi.FlameMenuProjectConnect(opfapi.CTX.app_framework))
opfapi.CTX.flame_apps.append(
opfapi.FlameMenuTimeline(opfapi.CTX.app_framework))
opfapi.CTX.flame_apps.append(
opfapi.FlameMenuUniversal(opfapi.CTX.app_framework))
opfapi.CTX.app_framework.log.info("Apps are loaded")
@ -191,3 +193,27 @@ def get_timeline_custom_ui_actions():
openpype_install()
return _build_app_menu("FlameMenuTimeline")
def get_batch_custom_ui_actions():
"""Hook to create submenu in batch
Returns:
list: menu object
"""
# install openpype and the host
openpype_install()
return _build_app_menu("FlameMenuUniversal")
def get_media_panel_custom_ui_actions():
"""Hook to create submenu in desktop
Returns:
list: menu object
"""
# install openpype and the host
openpype_install()
return _build_app_menu("FlameMenuUniversal")

View file

@ -0,0 +1,10 @@
from .addon import (
FusionAddon,
FUSION_HOST_DIR,
)
__all__ = (
"FusionAddon",
"FUSION_HOST_DIR",
)

View file

@ -0,0 +1,23 @@
import os
from openpype.modules import OpenPypeModule
from openpype.modules.interfaces import IHostAddon
FUSION_HOST_DIR = os.path.dirname(os.path.abspath(__file__))
class FusionAddon(OpenPypeModule, IHostAddon):
name = "fusion"
host_name = "fusion"
def initialize(self, module_settings):
self.enabled = True
def get_launch_hook_paths(self, app):
if app.host_name != self.host_name:
return []
return [
os.path.join(FUSION_HOST_DIR, "hooks")
]
def get_workfile_extensions(self):
return [".comp"]

View file

@ -18,12 +18,11 @@ from openpype.pipeline import (
deregister_inventory_action_path,
AVALON_CONTAINER_ID,
)
import openpype.hosts.fusion
from openpype.hosts.fusion import FUSION_HOST_DIR
log = Logger.get_logger(__name__)
HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.fusion.__file__))
PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
PLUGINS_DIR = os.path.join(FUSION_HOST_DIR, "plugins")
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
LOAD_PATH = os.path.join(PLUGINS_DIR, "load")

View file

@ -2,13 +2,11 @@
import sys
import os
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
from .pipeline import get_current_comp
def file_extensions():
return HOST_WORKFILE_EXTENSIONS["fusion"]
return [".comp"]
def has_unsaved_changes():

View file

@ -318,10 +318,9 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
@staticmethod
def create_otio_time_range_from_timeline_item_data(track_item):
speed = track_item.playbackSpeed()
timeline = phiero.get_current_sequence()
frame_start = int(track_item.timelineIn())
frame_duration = int((track_item.duration() - 1) / speed)
frame_duration = int(track_item.duration())
fps = timeline.framerate().toFloat()
return hiero_export.create_otio_time_range(

View file

@ -70,7 +70,7 @@ class CollectAssembly(pyblish.api.InstancePlugin):
data[representation_id].append(instance_data)
instance.data["scenedata"] = dict(data)
instance.data["hierarchy"] = list(set(hierarchy_nodes))
instance.data["nodesHierarchy"] = list(set(hierarchy_nodes))
def get_file_rule(self, rule):
return mel.eval('workspace -query -fileRuleEntry "{}"'.format(rule))

View file

@ -32,7 +32,7 @@ class ExtractAssembly(publish.Extractor):
json.dump(instance.data["scenedata"], filepath, ensure_ascii=False)
self.log.info("Extracting point cache ..")
cmds.select(instance.data["hierarchy"])
cmds.select(instance.data["nodesHierarchy"])
# Run basic alembic exporter
extract_alembic(file=hierarchy_path,

View file

@ -48,7 +48,7 @@ class ValidateAssemblyModelTransforms(pyblish.api.InstancePlugin):
from openpype.hosts.maya.api import lib
# Get all transforms in the loaded containers
container_roots = cmds.listRelatives(instance.data["hierarchy"],
container_roots = cmds.listRelatives(instance.data["nodesHierarchy"],
children=True,
type="transform",
fullPath=True)

View file

@ -201,34 +201,6 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
if not instance.data["review"]:
instance.data["useSequenceForReview"] = False
project_name = legacy_io.active_project()
asset_name = instance.data["asset"]
# * Add audio to instance if exists.
# Find latest versions document
last_version_doc = get_last_version_by_subset_name(
project_name, "audioMain", asset_name=asset_name, fields=["_id"]
)
repre_doc = None
if last_version_doc:
# Try to find it's representation (Expected there is only one)
repre_docs = list(get_representations(
project_name, version_ids=[last_version_doc["_id"]]
))
if not repre_docs:
self.log.warning(
"Version document does not contain any representations"
)
else:
repre_doc = repre_docs[0]
# Add audio to instance if representation was found
if repre_doc:
instance.data["audio"] = [{
"offset": 0,
"filename": get_representation_path(repre_doc)
}]
self.log.debug("instance.data: {}".format(pformat(instance.data)))
def is_prerender(self, families):

View file

@ -2,7 +2,8 @@ import pyblish.api
from openpype.pipeline.publish import get_errored_instances_from_context
from openpype.hosts.nuke.api.lib import (
get_write_node_template_attr,
set_node_knobs_from_settings
set_node_knobs_from_settings,
color_gui_to_int
)
from openpype.pipeline import PublishXmlValidationError
@ -76,8 +77,11 @@ class ValidateNukeWriteNode(pyblish.api.InstancePlugin):
# fix type differences
if type(node_value) in (int, float):
value = float(value)
node_value = float(node_value)
if isinstance(value, list):
value = color_gui_to_int(value)
else:
value = float(value)
node_value = float(node_value)
else:
value = str(value)
node_value = str(node_value)

View file

@ -127,11 +127,11 @@ class CollectInstances(pyblish.api.ContextPlugin):
```python
import os
import openpype.api
from avalon import photoshop
from openpype.pipeline import publish
from openpype.hosts.photoshop import api as photoshop
class ExtractImage(openpype.api.Extractor):
class ExtractImage(publish.Extractor):
"""Produce a flattened image file from instance
This plug-in takes into account only the layers in the group.

View file

@ -64,10 +64,15 @@ def maintained_selection():
@contextlib.contextmanager
def maintained_visibility():
"""Maintain visibility during context."""
def maintained_visibility(layers=None):
"""Maintain visibility during context.
Args:
layers (list) of PSItem (used for caching)
"""
visibility = {}
layers = stub().get_layers()
if not layers:
layers = stub().get_layers()
for layer in layers:
visibility[layer.id] = layer.visible
try:

View file

@ -229,10 +229,11 @@ class PhotoshopServerStub:
return self._get_layers_in_layers(parent_ids)
def get_layers_in_layers_ids(self, layers_ids):
def get_layers_in_layers_ids(self, layers_ids, layers=None):
"""Return all layers that belong to layers (might be groups).
Args:
layers_ids <list of Int>
layers <list of PSItem>:
Returns:
@ -240,10 +241,13 @@ class PhotoshopServerStub:
"""
parent_ids = set(layers_ids)
return self._get_layers_in_layers(parent_ids)
return self._get_layers_in_layers(parent_ids, layers)
def _get_layers_in_layers(self, parent_ids):
all_layers = self.get_layers()
def _get_layers_in_layers(self, parent_ids, layers=None):
if not layers:
layers = self.get_layers()
all_layers = layers
ret = []
for layer in all_layers:
@ -394,14 +398,17 @@ class PhotoshopServerStub:
self.hide_all_others_layers_ids(extract_ids)
def hide_all_others_layers_ids(self, extract_ids):
def hide_all_others_layers_ids(self, extract_ids, layers=None):
"""hides all layers that are not part of the list or that are not
children of this list
Args:
extract_ids (list): list of integer that should be visible
layers (list) of PSItem (used for caching)
"""
for layer in self.get_layers():
if not layers:
layers = self.get_layers()
for layer in layers:
if layer.visible and layer.id not in extract_ids:
self.set_visible(layer.id, False)

View file

@ -1,61 +1,99 @@
import os
import openpype.api
import pyblish.api
from openpype.pipeline import publish
from openpype.hosts.photoshop import api as photoshop
class ExtractImage(openpype.api.Extractor):
"""Produce a flattened image file from instance
class ExtractImage(pyblish.api.ContextPlugin):
"""Extract all layers (groups) marked for publish.
This plug-in takes into account only the layers in the group.
Usually publishable instance is created as a wrapper of layer(s). For each
publishable instance so many images as there is 'formats' is created.
Logic tries to hide/unhide layers minimum times.
Called once for all publishable instances.
"""
order = publish.Extractor.order - 0.48
label = "Extract Image"
hosts = ["photoshop"]
families = ["image", "background"]
formats = ["png", "jpg"]
def process(self, instance):
staging_dir = self.staging_dir(instance)
self.log.info("Outputting image to {}".format(staging_dir))
# Perform extraction
def process(self, context):
stub = photoshop.stub()
files = {}
hidden_layer_ids = set()
all_layers = stub.get_layers()
for layer in all_layers:
if not layer.visible:
hidden_layer_ids.add(layer.id)
stub.hide_all_others_layers_ids([], layers=all_layers)
with photoshop.maintained_selection():
self.log.info("Extracting %s" % str(list(instance)))
with photoshop.maintained_visibility():
ids = set()
layer = instance.data.get("layer")
if layer:
ids.add(layer.id)
add_ids = instance.data.pop("ids", None)
if add_ids:
ids.update(set(add_ids))
extract_ids = set([ll.id for ll in stub.
get_layers_in_layers_ids(ids)])
stub.hide_all_others_layers_ids(extract_ids)
with photoshop.maintained_visibility(layers=all_layers):
for instance in context:
if instance.data["family"] not in self.families:
continue
file_basename = os.path.splitext(
stub.get_active_document_name()
)[0]
for extension in self.formats:
_filename = "{}.{}".format(file_basename, extension)
files[extension] = _filename
staging_dir = self.staging_dir(instance)
self.log.info("Outputting image to {}".format(staging_dir))
full_filename = os.path.join(staging_dir, _filename)
stub.saveAs(full_filename, extension, True)
self.log.info(f"Extracted: {extension}")
# Perform extraction
files = {}
ids = set()
layer = instance.data.get("layer")
if layer:
ids.add(layer.id)
add_ids = instance.data.pop("ids", None)
if add_ids:
ids.update(set(add_ids))
extract_ids = set([ll.id for ll in stub.
get_layers_in_layers_ids(ids, all_layers)
if ll.id not in hidden_layer_ids])
representations = []
for extension, filename in files.items():
representations.append({
"name": extension,
"ext": extension,
"files": filename,
"stagingDir": staging_dir
})
instance.data["representations"] = representations
instance.data["stagingDir"] = staging_dir
for extracted_id in extract_ids:
stub.set_visible(extracted_id, True)
self.log.info(f"Extracted {instance} to {staging_dir}")
file_basename = os.path.splitext(
stub.get_active_document_name()
)[0]
for extension in self.formats:
_filename = "{}.{}".format(file_basename,
extension)
files[extension] = _filename
full_filename = os.path.join(staging_dir,
_filename)
stub.saveAs(full_filename, extension, True)
self.log.info(f"Extracted: {extension}")
representations = []
for extension, filename in files.items():
representations.append({
"name": extension,
"ext": extension,
"files": filename,
"stagingDir": staging_dir
})
instance.data["representations"] = representations
instance.data["stagingDir"] = staging_dir
self.log.info(f"Extracted {instance} to {staging_dir}")
for extracted_id in extract_ids:
stub.set_visible(extracted_id, False)
def staging_dir(self, instance):
"""Provide a temporary directory in which to store extracted files
Upon calling this method the staging directory is stored inside
the instance.data['stagingDir']
"""
from openpype.pipeline.publish import get_instance_staging_dir
return get_instance_staging_dir(instance)

View file

@ -2,12 +2,15 @@ import os
import shutil
from PIL import Image
import openpype.api
import openpype.lib
from openpype.lib import (
run_subprocess,
get_ffmpeg_tool_path,
)
from openpype.pipeline import publish
from openpype.hosts.photoshop import api as photoshop
class ExtractReview(openpype.api.Extractor):
class ExtractReview(publish.Extractor):
"""
Produce a flattened or sequence image files from all 'image' instances.
@ -72,7 +75,7 @@ class ExtractReview(openpype.api.Extractor):
})
processed_img_names = [img_list]
ffmpeg_path = openpype.lib.get_ffmpeg_tool_path("ffmpeg")
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
instance.data["stagingDir"] = staging_dir
@ -93,7 +96,7 @@ class ExtractReview(openpype.api.Extractor):
thumbnail_path
]
self.log.debug("thumbnail args:: {}".format(args))
output = openpype.lib.run_subprocess(args)
output = run_subprocess(args)
instance.data["representations"].append({
"name": "thumbnail",
@ -116,7 +119,7 @@ class ExtractReview(openpype.api.Extractor):
mov_path
]
self.log.debug("mov args:: {}".format(args))
output = openpype.lib.run_subprocess(args)
output = run_subprocess(args)
self.log.debug(output)
instance.data["representations"].append({
"name": "mov",

View file

@ -1,11 +1,11 @@
import openpype.api
from openpype.pipeline import publish
from openpype.hosts.photoshop import api as photoshop
class ExtractSaveScene(openpype.api.Extractor):
class ExtractSaveScene(publish.Extractor):
"""Save scene before extraction."""
order = openpype.api.Extractor.order - 0.49
order = publish.Extractor.order - 0.49
label = "Extract Save Scene"
hosts = ["photoshop"]
families = ["workfile"]

View file

@ -17,7 +17,7 @@ def setup(env):
# collect script dirs
if us_env:
log.info(f"Utility Scripts Env: `{us_env}`")
log.info("Utility Scripts Env: `{}`".format(us_env))
us_paths = us_env.split(
os.pathsep) + us_paths
@ -25,13 +25,13 @@ def setup(env):
for path in us_paths:
scripts.update({path: os.listdir(path)})
log.info(f"Utility Scripts Dir: `{us_paths}`")
log.info(f"Utility Scripts: `{scripts}`")
log.info("Utility Scripts Dir: `{}`".format(us_paths))
log.info("Utility Scripts: `{}`".format(scripts))
# make sure no script file is in folder
for s in os.listdir(us_dir):
path = os.path.join(us_dir, s)
log.info(f"Removing `{path}`...")
log.info("Removing `{}`...".format(path))
if os.path.isdir(path):
shutil.rmtree(path, onerror=None)
else:
@ -44,7 +44,7 @@ def setup(env):
# script in script list
src = os.path.join(d, s)
dst = os.path.join(us_dir, s)
log.info(f"Copying `{src}` to `{dst}`...")
log.info("Copying `{}` to `{}`...".format(src, dst))
if os.path.isdir(src):
shutil.copytree(
src, dst, symlinks=False,