Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1726 from pypeclub/feature/636-add-reference-from…
Browse files Browse the repository at this point in the history
…-sequence-PS

PS - added loader from sequence
  • Loading branch information
kalisp authored Jun 23, 2021
2 parents cfdd04a + aea7d53 commit a79af86
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 26 deletions.
26 changes: 26 additions & 0 deletions openpype/hosts/photoshop/plugins/lib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import re


def get_unique_layer_name(layers, asset_name, subset_name):
"""
Gets all layer names and if 'asset_name_subset_name' is present, it
increases suffix by 1 (eg. creates unique layer name - for Loader)
Args:
layers (list) of dict with layers info (name, id etc.)
asset_name (string):
subset_name (string):
Returns:
(string): name_00X (without version)
"""
name = "{}_{}".format(asset_name, subset_name)
names = {}
for layer in layers:
layer_name = re.sub(r'_\d{3}$', '', layer.name)
if layer_name in names.keys():
names[layer_name] = names[layer_name] + 1
else:
names[layer_name] = 1
occurrences = names.get(name, 0)

return "{}_{:0>3d}".format(name, occurrences + 1)
33 changes: 7 additions & 26 deletions openpype/hosts/photoshop/plugins/load/load_image.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from avalon import api, photoshop
import os
import re

from avalon import api, photoshop

from openpype.hosts.photoshop.plugins.lib import get_unique_layer_name

stub = photoshop.stub()


Expand All @@ -15,8 +17,9 @@ class ImageLoader(api.Loader):
representations = ["*"]

def load(self, context, name=None, namespace=None, data=None):
layer_name = self._get_unique_layer_name(context["asset"]["name"],
name)
layer_name = get_unique_layer_name(stub.get_layers(),
context["asset"]["name"],
name)
with photoshop.maintained_selection():
layer = stub.import_smart_object(self.fname, layer_name)

Expand Down Expand Up @@ -69,25 +72,3 @@ def remove(self, container):

def switch(self, container, representation):
self.update(container, representation)

def _get_unique_layer_name(self, asset_name, subset_name):
"""
Gets all layer names and if 'name' is present in them, increases
suffix by 1 (eg. creates unique layer name - for Loader)
Args:
name (string): in format asset_subset
Returns:
(string): name_00X (without version)
"""
name = "{}_{}".format(asset_name, subset_name)
names = {}
for layer in stub.get_layers():
layer_name = re.sub(r'_\d{3}$', '', layer.name)
if layer_name in names.keys():
names[layer_name] = names[layer_name] + 1
else:
names[layer_name] = 1
occurrences = names.get(name, 0)

return "{}_{:0>3d}".format(name, occurrences + 1)
98 changes: 98 additions & 0 deletions openpype/hosts/photoshop/plugins/load/load_image_from_sequence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import os

from avalon import api
from avalon import photoshop
from avalon.pipeline import get_representation_path_from_context
from avalon.vendor import qargparse

from openpype.lib import Anatomy
from openpype.hosts.photoshop.plugins.lib import get_unique_layer_name

stub = photoshop.stub()


class ImageFromSequenceLoader(api.Loader):
""" Load specifing image from sequence
Used only as quick load of reference file from a sequence.
Plain ImageLoader picks first frame from sequence.
Loads only existing files - currently not possible to limit loaders
to single select - multiselect. If user selects multiple repres, list
for all of them is provided, but selection is only single file.
This loader will be triggered multiple times, but selected name will
match only to proper path.
Loader doesnt do containerization as there is currently no data model
of 'frame of rendered files' (only rendered sequence), update would be
difficult.
"""

families = ["render"]
representations = ["*"]
options = []

def load(self, context, name=None, namespace=None, data=None):
if data.get("frame"):
self.fname = os.path.join(os.path.dirname(self.fname),
data["frame"])
if not os.path.exists(self.fname):
return

stub = photoshop.stub()
layer_name = get_unique_layer_name(stub.get_layers(),
context["asset"]["name"],
name)

with photoshop.maintained_selection():
layer = stub.import_smart_object(self.fname, layer_name)

self[:] = [layer]
namespace = namespace or layer_name

return namespace

@classmethod
def get_options(cls, repre_contexts):
"""
Returns list of files for selected 'repre_contexts'.
It returns only files with same extension as in context as it is
expected that context points to sequence of frames.
Returns:
(list) of qargparse.Choice
"""
files = []
for context in repre_contexts:
fname = get_representation_path_from_context(context)
_, file_extension = os.path.splitext(fname)

for file_name in os.listdir(os.path.dirname(fname)):
if not file_name.endswith(file_extension):
continue
files.append(file_name)

# return selection only if there is something
if not files or len(files) <= 1:
return []

return [
qargparse.Choice(
"frame",
label="Select specific file",
items=files,
default=0,
help="Which frame should be loaded?"
)
]

def update(self, container, representation):
"""No update possible, not containerized."""
pass

def remove(self, container):
"""No update possible, not containerized."""
pass

0 comments on commit a79af86

Please sign in to comment.