Ejemplo n.º 1
0
def launch(*subprocess_args):
    """Starts the websocket server that will be hosted
       in the Photoshop extension.
    """
    from avalon import api, photoshop

    api.install(photoshop)
    sys.excepthook = safe_excepthook
    # Launch Photoshop and the websocket server.
    process = subprocess.Popen(subprocess_args, stdout=subprocess.PIPE)

    websocket_server = WebServerTool()
    # Add Websocket route
    websocket_server.add_route("*", "/ws/", WebSocketAsync)
    # Add after effects route to websocket handler
    route_name = 'Photoshop'
    print("Adding {} route".format(route_name))
    WebSocketAsync.add_route(
        route_name,
        PhotoshopRoute  # keep same name as in extension
    )
    websocket_server.start_server()

    while True:
        if process.poll() is not None:
            print("Photoshop process is not alive. Exiting")
            websocket_server.stop()
            sys.exit(1)
        try:
            _stub = photoshop.stub()
            if _stub:
                break
        except Exception:
            time.sleep(0.5)

    # Wait for application launch to show Workfiles.
    if os.environ.get("AVALON_PHOTOSHOP_WORKFILES_ON_LAUNCH", True):
        if os.getenv("WORKFILES_SAVE_AS"):
            workfiles.show(save=False)
        else:
            workfiles.show()

    # Photoshop could be closed immediately, withou workfile selection
    try:
        if photoshop.stub():
            api.emit("application.launched")

        self.callback_queue = queue.Queue()
        while True:
            main_thread_listen(process, websocket_server)

    except ConnectionNotEstablishedYet:
        pass
    finally:
        # Wait on Photoshop to close before closing the websocket server
        process.wait()
        websocket_server.stop()
Ejemplo n.º 2
0
    def process(self, instance):
        errored_plugins = get_errored_plugins_from_data(instance.context)
        if errored_plugins:
            raise RuntimeError(
                "Skipping incrementing current file because publishing failed."
            )

        scene_path = version_up(instance.context.data["currentFile"])
        _, ext = os.path.splitext(scene_path)
        photoshop.stub().saveAs(scene_path, ext[1:], True)

        self.log.info("Incremented workfile to: {}".format(scene_path))
Ejemplo n.º 3
0
    def process(self, context, plugin):

        # Get the errored instances
        failed = []
        for result in context.data["results"]:
            if (result["error"] is not None and result["instance"] is not None
                    and result["instance"] not in failed):
                failed.append(result["instance"])

        # Apply pyblish.logic to get the instances for the plug-in
        instances = pyblish.api.instances_by_plugin(failed, plugin)
        stub = photoshop.stub()
        for instance in instances:
            self.log.info("validate_naming instance {}".format(instance))
            name = instance.data["name"].replace(" ", "_")
            name = name.replace(instance.data["family"], '')
            instance[0].Name = name
            data = stub.read(instance[0])
            data["subset"] = "image" + name
            stub.imprint(instance[0], data)

            name = stub.PUBLISH_ICON + name
            stub.rename_layer(instance.data["uuid"], name)

        return True
Ejemplo n.º 4
0
    def is_host_connected():
        """Returns True if connected, False if app is not running at all."""
        if ConsoleTrayApp.process.poll() is not None:
            return False
        try:
            _stub = photoshop.stub()

            if _stub:
                return True
        except Exception:
            pass

        return None
Ejemplo n.º 5
0
    def process(self, instance):

        staging_dir = self.staging_dir(instance)
        self.log.info("Outputting image to {}".format(staging_dir))

        # Perform extraction
        stub = photoshop.stub()
        files = {}
        with photoshop.maintained_selection():
            self.log.info("Extracting %s" % str(list(instance)))
            with photoshop.maintained_visibility():
                # Hide all other layers.
                extract_ids = set([ll.id for ll in stub.
                                   get_layers_in_layers([instance[0]])])

                for layer in stub.get_layers():
                    # limit unnecessary calls to client
                    if layer.visible and layer.id not in extract_ids:
                        stub.set_visible(layer.id, False)

                save_options = []
                if "png" in self.formats:
                    save_options.append('png')
                if "jpg" in self.formats:
                    save_options.append('jpg')

                file_basename = os.path.splitext(
                    stub.get_active_document_name()
                )[0]
                for extension in save_options:
                    _filename = "{}.{}".format(file_basename, extension)
                    files[extension] = _filename

                    full_filename = os.path.join(staging_dir, _filename)
                    stub.saveAs(full_filename, extension, True)

        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}")
Ejemplo n.º 6
0
    def process(self, context, plugin):

        # Get the errored instances
        failed = []
        for result in context.data["results"]:
            if (result["error"] is not None and result["instance"] is not None
                    and result["instance"] not in failed):
                failed.append(result["instance"])

        # Apply pyblish.logic to get the instances for the plug-in
        instances = pyblish.api.instances_by_plugin(failed, plugin)
        stub = photoshop.stub()
        for instance in instances:
            data = stub.read(instance[0])

            data["asset"] = os.environ["AVALON_ASSET"]
            stub.imprint(instance[0], data)
Ejemplo n.º 7
0
    def process(self, context):
        stub = photoshop.stub()
        layers = stub.get_layers()
        layers_meta = stub.get_layers_metadata()
        instance_names = []
        for layer in layers:
            layer_data = stub.read(layer, layers_meta)

            # Skip layers without metadata.
            if layer_data is None:
                continue

            # Skip containers.
            if "container" in layer_data["id"]:
                continue

            # child_layers = [*layer.Layers]
            # self.log.debug("child_layers {}".format(child_layers))
            # if not child_layers:
            #     self.log.info("%s skipped, it was empty." % layer.Name)
            #     continue

            instance = context.create_instance(layer_data["subset"])
            instance.append(layer)
            instance.data.update(layer_data)
            instance.data["families"] = self.families_mapping[
                layer_data["family"]]
            instance.data["publish"] = layer.visible
            instance_names.append(layer_data["subset"])

            # Produce diagnostic message for any graphical
            # user interface interested in visualising it.
            self.log.info("Found: \"%s\" " % instance.data["name"])
            self.log.info("instance: {} ".format(instance.data))

        if len(instance_names) != len(set(instance_names)):
            self.log.warning("Duplicate instances found. " +
                             "Remove unwanted via SubsetManager")
Ejemplo n.º 8
0
    def process(self):
        groups = []
        layers = []
        create_group = False

        stub = photoshop.stub()
        if (self.options or {}).get("useSelection"):
            multiple_instances = False
            selection = stub.get_selected_layers()
            self.log.info("selection {}".format(selection))
            if len(selection) > 1:
                # Ask user whether to create one image or image per selected
                # item.
                msg_box = Qt.QtWidgets.QMessageBox()
                msg_box.setIcon(Qt.QtWidgets.QMessageBox.Warning)
                msg_box.setText("Multiple layers selected."
                                "\nDo you want to make one image per layer?")
                msg_box.setStandardButtons(Qt.QtWidgets.QMessageBox.Yes
                                           | Qt.QtWidgets.QMessageBox.No
                                           | Qt.QtWidgets.QMessageBox.Cancel)
                ret = msg_box.exec_()
                if ret == Qt.QtWidgets.QMessageBox.Yes:
                    multiple_instances = True
                elif ret == Qt.QtWidgets.QMessageBox.Cancel:
                    return

                if multiple_instances:
                    for item in selection:
                        if item.group:
                            groups.append(item)
                        else:
                            layers.append(item)
                else:
                    group = stub.group_selected_layers(self.name)
                    groups.append(group)

            elif len(selection) == 1:
                # One selected item. Use group if its a LayerSet (group), else
                # create a new group.
                if selection[0].group:
                    groups.append(selection[0])
                else:
                    layers.append(selection[0])
            elif len(selection) == 0:
                # No selection creates an empty group.
                create_group = True
        else:
            create_group = True

        if create_group:
            group = stub.create_group(self.name)
            groups.append(group)

        for layer in layers:
            stub.select_layers([layer])
            group = stub.group_selected_layers(layer.name)
            groups.append(group)

        for group in groups:
            long_names = []
            if group.long_name:
                for directory in group.long_name[::-1]:
                    name = directory.replace(stub.PUBLISH_ICON, '').\
                                      replace(stub.LOADED_ICON, '')
                    long_names.append(name)

            self.data.update({"subset": "image" + group.name})
            self.data.update({"uuid": str(group.id)})
            self.data.update({"long_name": "_".join(long_names)})
            stub.imprint(group, self.data)
            # reusing existing group, need to rename afterwards
            if not create_group:
                stub.rename_layer(group.id, stub.PUBLISH_ICON + group.name)
Ejemplo n.º 9
0
 def process(self, context):
     context.data["currentFile"] = os.path.normpath(
         photoshop.stub().get_active_document_full_name()).replace(
             "\\", "/")
Ejemplo n.º 10
0
from avalon import api, photoshop
import os
import re

stub = photoshop.stub()


class ImageLoader(api.Loader):
    """Load images

    Stores the imported asset in a container named after the asset.
    """

    families = ["image", "render"]
    representations = ["*"]

    def load(self, context, name=None, namespace=None, data=None):
        layer_name = self._get_unique_layer_name(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 photoshop.containerise(name, namespace, layer, context,
                                      self.__class__.__name__)

    def update(self, container, representation):
        """ Switch asset or change version """
        layer = container.pop("layer")
Ejemplo n.º 11
0
    def process(self, instance):
        staging_dir = self.staging_dir(instance)
        self.log.info("Outputting image to {}".format(staging_dir))

        stub = photoshop.stub()

        layers = []
        for image_instance in instance.context:
            if image_instance.data["family"] != "image":
                continue
            layers.append(image_instance[0])

        # Perform extraction
        output_image = "{}.jpg".format(
            os.path.splitext(stub.get_active_document_name())[0])
        output_image_path = os.path.join(staging_dir, output_image)
        with photoshop.maintained_visibility():
            # Hide all other layers.
            extract_ids = set(
                [ll.id for ll in stub.get_layers_in_layers(layers)])
            self.log.info("extract_ids {}".format(extract_ids))
            for layer in stub.get_layers():
                # limit unnecessary calls to client
                if layer.visible and layer.id not in extract_ids:
                    stub.set_visible(layer.id, False)

            stub.saveAs(output_image_path, 'jpg', True)

        ffmpeg_path = pype.lib.get_ffmpeg_tool_path("ffmpeg")

        instance.data["representations"].append({
            "name": "jpg",
            "ext": "jpg",
            "files": output_image,
            "stagingDir": staging_dir
        })
        instance.data["stagingDir"] = staging_dir

        # Generate thumbnail.
        thumbnail_path = os.path.join(staging_dir, "thumbnail.jpg")
        args = [
            "{}".format(ffmpeg_path), "-y", "-i", output_image_path, "-vf",
            "scale=300:-1", "-vframes", "1", thumbnail_path
        ]
        output = pype.lib.run_subprocess(args)

        instance.data["representations"].append({
            "name":
            "thumbnail",
            "ext":
            "jpg",
            "files":
            os.path.basename(thumbnail_path),
            "stagingDir":
            staging_dir,
            "tags": ["thumbnail"]
        })
        # Generate mov.
        mov_path = os.path.join(staging_dir, "review.mov")
        args = [
            ffmpeg_path, "-y", "-i", output_image_path, "-vf",
            "pad=ceil(iw/2)*2:ceil(ih/2)*2", "-vframes", "1", mov_path
        ]
        output = pype.lib.run_subprocess(args)
        self.log.debug(output)
        instance.data["representations"].append({
            "name":
            "mov",
            "ext":
            "mov",
            "files":
            os.path.basename(mov_path),
            "stagingDir":
            staging_dir,
            "frameStart":
            1,
            "frameEnd":
            1,
            "fps":
            25,
            "preview":
            True,
            "tags": ["review", "ftrackreview"]
        })

        # Required for extract_review plugin (L222 onwards).
        instance.data["frameStart"] = 1
        instance.data["frameEnd"] = 1
        instance.data["fps"] = 25

        self.log.info(f"Extracted {instance} to {staging_dir}")
Ejemplo n.º 12
0
 def process(self, instance):
     photoshop.stub().save()