Esempio n. 1
0
    def create_mipmaps_for_seq(self, source_paths, target_seq_path):
        """
        Given a list of files, convert each to a mipmap file and save to target path.

        :param source_paths:        list of source image files
        :param target_seq_path:     path (with an seq field if source is an image sequence)
                                    where the mipmaps should be written

        :returns:                   list of created mipmap paths
        """
        publisher = self.parent
        mipmap_paths = []

        for source_path in source_paths:
            frame = publisher.util.get_frame_number(source_path)
            if frame:
                target_path = publisher.util.get_path_for_frame(
                    target_seq_path, frame)
                if not target_path:
                    # We do not want the conversion of multiple images to overwrite
                    # a single target path. Something is wrong with the configuration.
                    raise TankError("Source path: {} contains a frame number, "
                                    "but target path: {} does not.".format(
                                        source_path, target_path))
            else:
                target_path = target_seq_path

            if not self._create_mipmap(source_path, target_path):
                self.logger.warning("Mipmap not created for: {}. "
                                    "Touching empty file.".format(target_path))
                open(target_path, 'a').close()
            else:
                mipmap_paths.append(target_path)

        return mipmap_paths
    def __get_tk_path_from_flame_plate_path(self, flame_path):
        """
		Given a xxx.[1234-1234].exr style Flame plate path,
		return the equivalent, normalized tk path, e.g. xxx.%04d.exr
		
		:param flame_path: Flame style plate path (must match the plate template)
		:returns: tk equivalent
		"""
        template = self._app.sgtk.template_from_path(flame_path)

        if template is None:
            # the path does not match any template. This shouldn't happen since these
            # paths were all generated by the shotgun integration, however is possible because
            # of some known bugs in flame, where updated paths returned by flame hooks are not being
            # used by the flame system. A typical example is when a sequence name contains a space or
            # other special character - the toolkit template system will adjust the path to replace
            # spaces with underscores. These adjusted paths are returned to Flame but are not picked
            # up, resulting in the paths returned here not actually being valid.
            raise TankError(
                "The path '%s' does not match any template in the Toolkit configuration. "
                "This sometimes happens if Flame sequences or clips contain special characters "
                "such as slashes or spaces." % flame_path)

        fields = template.get_fields(flame_path)
        fields["SEQ"] = "FORMAT: %d"
        fields["flame.frame"] = "FORMAT: %d"
        return template.apply_fields(fields)
Esempio n. 3
0
    def _resolve_work_path_template(self, properties, path):
        """
        Resolve work_path_template from the properties.
        The signature uses properties, so that it can resolve the template even if the item object hasn't been created.

        :param properties: properties that have/will be used to build item object.
        :param path: path to be used to get the templates, using template_from_path.
        :return: Name of the template.
        """

        work_path_template = properties.get("work_path_template")

        # If defined, add the work_path_template to the item's properties
        if work_path_template:
            work_tmpl = self.parent.get_template_by_name(work_path_template)
            if not work_tmpl:
                # this template was not found in the template config!
                raise TankError("The template '%s' does not exist!" %
                                work_path_template)

        # Else see if the path matches an existing template
        else:
            # let's try to check if this path fits into any known template
            work_tmpl = self.sgtk.template_from_path(path)
            if not work_tmpl:
                # this path doesn't map to any known templates!
                self.logger.warning(
                    "Cannot find a matching template for path: %s" % path)
            else:
                # update the field with correct value so that we can use it everytime for this item
                work_path_template = work_tmpl.name

        return work_path_template
Esempio n. 4
0
    def get_publish_template(self, settings, item):
        """
        Retrieves and and validates the publish template from the settings.

        :param settings: Dictionary of Settings. The keys are strings, matching
            the keys returned in the settings property. The values are `Setting`
            instances.
        :param item: Item to process

        :returns: A template representing the publish path of the item or
            None if no template could be identified.
        """
        publisher = self.parent

        publish_template = item.get_property("publish_template")
        if publish_template:
            return publish_template

        publish_template = None
        publish_template_setting = settings.get("Publish Template")

        if publish_template_setting and publish_template_setting.value:
            publish_template = publisher.engine.get_template_by_name(
                publish_template_setting.value)
            if not publish_template:
                raise TankError(
                    "Missing Publish Template in templates.yml: %s " %
                    publish_template_setting.value)

        # cache it for later use
        item.properties["publish_template"] = publish_template

        return publish_template
    def execute(self, path, context):
        """
        Bootstrap launches VRED Presenter

        :param path: full path to the published file
        :param context: context object representing the publish
        """
        tk = self.parent.sgtk
        software_launcher = sgtk.platform.create_engine_launcher(tk, context, "tk-vred")
        software_versions = software_launcher.scan_for_presenter()
        presenter_versions = []
        for version in software_versions:
            if re.search("Presenter", version.product):
                presenter_versions.append(version)
        presenter_version = presenter_versions[-1]
        launch_info = software_launcher.prepare_launch(presenter_version.path, "")
        env = os.environ.copy()
        for k in launch_info.environment:
            if k == "SGTK_CONTEXT":
                env[k] = sgtk.context.serialize(context)
            else:
                env[k] = str(launch_info.environment[k])
        try:
            launched = subprocess.Popen(
                [launch_info.path, launch_info.args, path], env=env
            )
        except RuntimeError:
            raise TankError(
                "Unable to launch VRED Presenter in context "
                "%r for file %s." % (context, path)
            )
        if launched:
            return True
        else:
            return False
Esempio n. 6
0
    def get_layer_name_template(self, settings, item):
        """
        Retrieves and and validates the Layer Name Template, used to build
        a name for the individual layers that will be published.

        :param settings: Dictionary of Settings. The keys are strings, matching
            the keys returned in the settings property. The values are `Setting`
            instances.
        :param item: Item to process

        :returns: A template representing the Layer Name template of the item or
            None if no template could be identified.
        """
        publisher = self.parent

        layer_name_template = item.get_property("layer_name_template")
        if layer_name_template:
            return layer_name_template

        layer_name_template = None
        layer_name_template_setting = settings.get("Layer Name Template")

        if layer_name_template_setting and layer_name_template_setting.value:
            layer_name_template = publisher.engine.get_template_by_name(
                layer_name_template_setting.value)
            if not layer_name_template:
                raise TankError(
                    "Missing Layer Name Template in templates.yml: %s " %
                    layer_name_template_setting.value)

        # cache it for later use
        item.properties["layer_name_template"] = layer_name_template

        return layer_name_template
Esempio n. 7
0
    def get_dcc_versions(self, env, fields, work_template, publish_template):
        # version is used so we need to find the latest version - this means 
        # searching for files...
        # need a file key to find all versions so lets build it:
        file_versions = None
        file_key = FileItem.build_file_key(fields, work_template,
                                           env.version_compare_ignore_fields)
        key = str(env) + str(fields) + str(work_template) + str(publish_template)
        if self._file_model:
            cached = self._file_model._search_cache._cache.get(key)
            if cached:
                file_versions = cached 


            # file_versions = self._file_model.get_cached_file_versions(file_key, env, clean_only=True)
        if file_versions is None:
            # fall back to finding the files manually - this will be slower!  
            try:
                finder = FileFinder()
                files = finder.find_files(work_template,
                                          publish_template,
                                          env.context,
                                          file_key) or []
            except TankError, e:
                raise TankError("Failed to find files for this work area: %s" % e)


            file_versions = [f.version for f in files]
            self._file_model._search_cache._cache[key] = file_versions
Esempio n. 8
0
    def _on_browse_for_publishes(self, new_project_form):
        """
        Called when the user clicks the 'Add Publishes' button in the new
        project form.  Opens the loader so that the user can select a publish
        to be loaded into the new project.

        :param new_project_form:    The new project form that the button was
                                    clicked in
        """
        loader_app = self._app.engine.apps.get("tk-multi-loader2")
        if not loader_app:
            raise TankError(
                "The tk-multi-loader2 app needs to be available to browse for publishes!"
            )

        # browse for publishes:
        publish_types = self._app.get_setting("publish_types")
        selected_publishes = loader_app.open_publish(
            "Select Published Geometry", "Select", publish_types)

        # make sure we keep this list of publishes unique:
        current_ids = set([p["id"] for p in self.__new_project_publishes])
        for sg_publish in selected_publishes:
            publish_id = sg_publish.get("id")
            if publish_id != None and publish_id not in current_ids:
                current_ids.add(publish_id)
                self.__new_project_publishes.append(sg_publish)

        # update new project form with selected geometry:
        new_project_form.update_publishes(self.__new_project_publishes)
Esempio n. 9
0
    def add_task(
        self,
        cbl,
        priority=None,
        group=None,
        upstream_task_ids=None,
        task_args=None,
        task_kwargs=None,
    ):
        """
        Add a new task to the queue.  A task is a callable method/class together with any arguments that
        should be passed to the callable when it is called.

        :param cbl:                 The callable function/class to call when executing the task
        :param priority:            The priority this task should be run with.  Tasks with higher priority
                                    are run first.
        :param group:               The group this task belongs to.  Task groups can be used to simplify task
                                    management (e.g. stop a whole group, be notified when a group is complete)
        :param upstream_task_ids:   A list of any upstream tasks that should be completed before this task
                                    is run.  The results from any upstream tasks are appended to the kwargs
                                    for this task.
        :param task_args:           A list of unnamed parameters to be passed to the callable when running the
                                    task
        :param task_kwargs:         A dictionary of named parameters to be passed to the callable when running
                                    the task
        :returns:                   A unique id representing the task.
        """
        if not callable(cbl):
            raise TankError(
                "The task function, method or object '%s' must be callable!" % cbl
            )

        upstream_task_ids = set(upstream_task_ids or [])

        # create a new task instance:
        task_id = self._next_task_id
        self._next_task_id += 1
        new_task = BackgroundTask(task_id, cbl, group, priority, task_args, task_kwargs)

        # add the task to the pending queue:
        # If priority is None, then use 0 so when we sort we're only comparing integers.
        # Python 3 raises an error when comparing int with NoneType.
        self._pending_tasks_by_priority.setdefault(priority or 0, []).append(new_task)

        # add tasks to various look-ups:
        self._tasks_by_id[new_task.uid] = new_task
        self._group_task_map.setdefault(group, set()).add(new_task.uid)

        # keep track of the task dependencies:
        self._upstream_task_map[new_task.uid] = upstream_task_ids
        for us_task_id in upstream_task_ids:
            self._downstream_task_map.setdefault(us_task_id, set()).add(new_task.uid)

        self._low_level_debug_log("Added Task %s to the queue" % new_task)

        # and start the next task:
        self._start_tasks()

        return new_task.uid
Esempio n. 10
0
def find_change_containing(p4, path):
    """
    Find the current change that the specified path is in.
    """
    try:
        p4_res = p4.run_fstat(path)
    except P4Exception, e:
        raise TankError("Perforce: %s" % (p4.errors[0] if p4.errors else e))
Esempio n. 11
0
 def _update_item_thumbnail(self, pixmap):
     """
     Update the currently selected item with the given
     thumbnail pixmap
     """
     if not self._current_item:
         raise TankError("No current item set!")
     self._current_item.thumbnail = pixmap
Esempio n. 12
0
    def batch_version_number(self):
        """
        Return the version number associated with the batch file
        """
        if not self.has_batch_export:
            raise TankError("Cannot get batch path - no batch metadata found!")

        return int(self._flame_batch_data["versionNumber"])
    def _get_hook_value(self, method_name, hook_key):
        """
        Validate that value is correct and return it
        """

        if method_name not in self._hook_data:
            raise TankError("Unknown shotgun_fields hook method %s" %
                            method_name)

        data = self._hook_data[method_name]

        if hook_key not in data:
            raise TankError("Hook shotgun_fields.%s does not return "
                            "required dictionary key '%s'!" %
                            (method_name, hook_key))

        return data[hook_key]
Esempio n. 14
0
    def _get_entity(self):
        """
        Returns the most relevant playback entity (as a sg std dict) for the current context
        """

        # figure out the context for Screening Room
        # first try to get a version
        # if that fails try to get the current entity
        rv_context = None
        task = self.context.task
        if task:
            # look for versions matching this task!
            self.logger.debug("Looking for versions connected to %s..." % task)
            filters = [["sg_task", "is", task]]
            order = [{"field_name": "created_at", "direction": "desc"}]
            fields = ["id"]
            version = self.shotgun.find_one("Version",
                                            filters=filters,
                                            fields=fields,
                                            order=order)
            if version:
                # got a version
                rv_context = version

        if rv_context is None and self.context.entity:
            # fall back on entity
            # try to extract a version (because versions are launched in a really nice way
            # in Screening Room, while entities are not so nice...)
            self.logger.debug("Looking for versions connected to %s..." %
                              self.context.entity)
            filters = [["entity", "is", self.context.entity]]
            order = [{"field_name": "created_at", "direction": "desc"}]
            fields = ["id"]
            version = self.shotgun.find_one("Version",
                                            filters=filters,
                                            fields=fields,
                                            order=order)

            if version:
                # got a version
                rv_context = version
            else:
                # no versions, fall back onto just the entity
                rv_context = self.context.entity

        if rv_context is None:
            # fall back on project
            rv_context = self.context.project

        if rv_context is None:
            raise TankError(
                "Not able to figure out a current context to launch screening room for!"
            )

        self.logger.debug("Closest match to current context is %s" %
                          rv_context)

        return rv_context
Esempio n. 15
0
def submit_change(p4, change):
    """
    Submit the specified change
    """
    try:
        change_spec = p4.fetch_change("-o", str(change))
        p4.run_submit(change_spec)
    except P4Exception, e:
        raise TankError("Perforce: %s" % (p4.errors[0] if p4.errors else e))
Esempio n. 16
0
 def shotgun_version_id(self):
     """
     Returns the ShotGrid id for the version associated with this segment, if there is one.
     """
     if not self.has_shotgun_version:
         raise TankError(
             "Cannot get ShotGrid version id for segment - no version associated!"
         )
     return self._shotgun_version_id
Esempio n. 17
0
    def batch_path(self):
        """
        Return the flame batch export path for this shot
        """
        if not self.has_batch_export:
            raise TankError("Cannot get batch path - no batch metadata found!")

        return os.path.join(self._flame_batch_data.get("destinationPath"),
                            self._flame_batch_data.get("resolvedPath"))
 def _get_active_document(self):
     """
     Returns the currently open document in Photoshop.
     Raises an exeption if no document is active.
     """
     doc = photoshop.app.activeDocument
     if doc is None:
         raise TankError("There is no currently active document!")
     return doc
Esempio n. 19
0
    def pre_app_init(self):
        """
        Engine construction/setup done before any apps are initialized
        """
        self.log_debug("%s: Initializing..." % self)

        # check that this version of Mari is supported:
        MIN_VERSION = (2, 6, 1)  # completely unsupported below this!
        MAX_VERSION = (3, 0)  # untested above this so display a warning

        mari_version = mari.app.version()
        if (mari_version.major() < MIN_VERSION[0]
                or (mari_version.major() == MIN_VERSION[0]
                    and mari_version.minor() < MIN_VERSION[1])):
            # this is a completely unsupported version of Mari!
            raise TankError(
                "This version of Mari (%d.%dv%d) is not supported by Shotgun Toolkit.  The"
                "minimum required version is %d.%dv%d." %
                (mari_version.major(), mari_version.minor(),
                 mari_version.revision(), MIN_VERSION[0], MIN_VERSION[1],
                 MIN_VERSION[2]))
        elif (mari_version.major() > MAX_VERSION[0]
              or (mari_version.major() == MAX_VERSION[0]
                  and mari_version.minor() > MAX_VERSION[1])):
            # this is an untested version of Mari
            msg = (
                "The Shotgun Pipeline Toolkit has not yet been fully tested with Mari %d.%dv%d. "
                "You can continue to use the Toolkit but you may experience bugs or "
                "instability.  Please report any issues you see to [email protected]"
                % (mari_version.major(), mari_version.minor(),
                   mari_version.revision()))

            if (self.has_ui
                    and "SGTK_MARI_VERSION_WARNING_SHOWN" not in os.environ
                    and mari_version.major() >=
                    self.get_setting("compatibility_dialog_min_version")):
                # show the warning dialog the first time:
                mari.utils.message(msg, "Shotgun")
                os.environ["SGTK_MARI_VERSION_WARNING_SHOWN"] = "1"

            self.log_warning(msg)

        try:
            self.log_user_attribute_metric(
                "Mari version",
                "%s.%s.%s" % (mari_version.major(), mari_version.minor(),
                              mari_version.revision()))
        except:
            # ignore all errors. ex: using a core that doesn't support metrics
            pass

        # cache handles to the various manager instances:
        tk_mari = self.import_module("tk_mari")
        self.__geometry_mgr = tk_mari.GeometryManager()
        self.__project_mgr = tk_mari.ProjectManager()
        self.__metadata_mgr = tk_mari.MetadataManager()
class ProjectManager(object):
    """
    Handle all Mari project management
    """
    def __init__(self, app):
        """
        Construction
        
        :param app:    The Application instance that created this instance
        """
        self._app = app
        self.__new_project_publishes = []
        self.__project_name_template = self._app.get_template(
            "template_new_project_name")

    def create_new_project(self, name_part, sg_publish_data):
        """
        Create a new project in the current Toolkit context and seed it
        with the specified geometry
        
        :param name:                The name to use in the project_name template when 
                                    generating the project name
        :param sg_publish_data:     List of the initial geometry publishes to load for 
                                    into the new project.  Each entry in the list is a
                                    Shotgun entity dictionary
        :returns:                   The new Mari project instance if successful or None 
                                    if not
        :raises:                    TankError if something went wrong at any stage!
        """
        # create the project name:
        name_result = self._generate_new_project_name(name_part)
        project_name = name_result.get("project_name")
        if not project_name:
            raise TankError("Failed to determine the project name: %s" %
                            name_result.get("message"))

        # use a hook to retrieve the project creation settings to use:
        hook_res = {}
        try:
            hook_res = self._app.execute_hook_method(
                "get_project_creation_args_hook",
                "get_project_creation_args",
                sg_publish_data=sg_publish_data)
            if hook_res == None:
                hook_res = {}
            elif not isinstance(hook_res, dict):
                raise TankError(
                    "get_project_creation_args_hook returned unexpected type!")
        except TankError, e:
            raise TankError(
                "Failed to get project creation args from hook: %s" % e)
        except Exception, e:
            self._app.log_exception(
                "Failed to get project creation args from hook!")
            raise TankError(
                "Failed to get project creation args from hook: %s" % e)
Esempio n. 21
0
    def flame_minor_version(self):
        """
        Returns Flame's minor version number as a string.
        
        :returns: String (e.g. '2')
        """
        if self._flame_version is None:
            raise TankError("No Flame DCC version specified!")

        return self._flame_version["minor"]
    def _get_publish_name(self, item, task_settings):
        """
        Get the publish name for the supplied item.

        :param item: The item to determine the publish version for

        Uses the path info hook to retrieve the publish name.
        """

        publisher = self.parent

        # Start with the item's fields
        fields = copy.copy(item.properties.get("fields", {}))

        publish_name_template = task_settings.get("publish_name_template")
        publish_name = None

        # First check if we have a publish_name_template defined and attempt to
        # get the publish name from that
        if publish_name_template:

            pub_tmpl = publisher.get_template_by_name(publish_name_template)
            if not pub_tmpl:
                # this template was not found in the template config!
                raise TankError("The Template '%s' does not exist!" %
                                publish_name_template)

            # First get the fields from the context
            try:
                fields.update(item.context.as_template_fields(pub_tmpl))
            except TankError, e:
                self.logger.debug(
                    "Unable to get context fields for publish_name_template.")

            missing_keys = pub_tmpl.missing_keys(fields, True)
            if missing_keys:
                raise TankError(
                    "Cannot resolve publish_name_template (%s). Missing keys: %s"
                    % (publish_name_template, pprint.pformat(missing_keys)))

            publish_name = pub_tmpl.apply_fields(fields)
            self.logger.debug(
                "Retrieved publish_name via publish_name_template.")
Esempio n. 23
0
def _prepare_flame_flare_launch(engine_name, context, app_path, app_args):
    """
    Flame specific pre-launch environment setup.

    :param engine_name: The name of the engine being launched (tk-flame or tk-flare)
    :param context: The context that the application is being launched in
    :param app_path: Path to DCC executable or launch script
    :param app_args: External app arguments

    :returns: Tuple (app_path, app_args) Potentially modified app_path or
              app_args value, depending on preparation requirements for
              flame.
    """
    # Retrieve the TK Application instance from the current bundle
    tk_app = sgtk.platform.current_bundle()

    # find the path to the engine on disk where the startup script can be found:
    engine_path = sgtk.platform.get_engine_path(engine_name, tk_app.sgtk, context)
    if engine_path is None:
        raise TankError("Path to '%s' engine could not be found." % engine_name)

    # find bootstrap file located in the engine and load that up
    startup_path = os.path.join(engine_path, "python", "startup", "bootstrap.py")
    if not os.path.exists(startup_path):
        raise Exception("Cannot find bootstrap script '%s'" % startup_path)

    python_path = os.path.dirname(startup_path)

    # add our bootstrap location to the pythonpath
    sys.path.insert(0, python_path)
    try:
        import bootstrap
        (app_path, new_args) = bootstrap.bootstrap(engine_name, context, app_path, app_args)

    except Exception, e:
        tk_app.log_exception("Error executing engine bootstrap script.")

        if tk_app.engine.has_ui:
            # got UI support. Launch dialog with nice message
            not_found_dialog = tk_app.import_module("not_found_dialog")
            not_found_dialog.show_generic_error_dialog(tk_app, str(e))

        raise TankError("Error executing bootstrap script. Please see log for details.")
Esempio n. 24
0
def add_to_change(p4, change, file_paths):
    """
    Add the specified files to the specified change
    """
    try:
        # use reopen command which works with local file paths.
        # fetch/modify/save_change only works with depot paths!
        p4.run_reopen("-c", str(change), file_paths)
    except P4Exception, e:
        raise TankError("Perforce: %s" % (p4.errors[0] if p4.errors else e))
Esempio n. 25
0
    def flame_version(self):
        """
        Returns Flame's full version number as a string.
        
        :returns: String (e.g. '2016.1.0.278')
        """
        if self._flame_version is None:
            raise TankError("No Flame DCC version specified!")

        return self._flame_version["full"]
    def _get_actions_for_publish(self, sg_data, ui_area):
        """
        Retrieves the list of actions for a given publish.

        :param sg_data: Publish to retrieve actions for
        :param ui_area: Indicates which part of the UI the request is coming from.
                        Currently one of UI_AREA_MAIN, UI_AREA_DETAILS and UI_AREA_HISTORY
        :return: List of actions.
        """

        # Figure out the type of the publish
        publish_type_dict = sg_data.get(self._publish_type_field)
        if publish_type_dict is None:
            # this publish does not have a type
            publish_type = "undefined"
        else:
            publish_type = publish_type_dict["name"]

        # check if we have logic configured to handle this publish type.
        mappings = self._app.get_setting("action_mappings")
        # returns a structure on the form
        # { "Maya Scene": ["reference", "import"] }
        actions = mappings.get(publish_type, [])

        if len(actions) == 0:
            return []

        # cool so we have one or more actions for this publish type.
        # resolve UI area
        if ui_area == LoaderActionManager.UI_AREA_DETAILS:
            ui_area_str = "details"
        elif ui_area == LoaderActionManager.UI_AREA_HISTORY:
            ui_area_str = "history"
        elif ui_area == LoaderActionManager.UI_AREA_MAIN:
            ui_area_str = "main"
        else:
            raise TankError("Unsupported UI_AREA. Contact support.")

        # convert created_at unix time stamp to shotgun time stamp
        self._fix_timestamp(sg_data)

        action_defs = []
        try:
            # call out to hook to give us the specifics.
            action_defs = self._app.execute_hook_method(
                "actions_hook",
                "generate_actions",
                sg_publish_data=sg_data,
                actions=actions,
                ui_area=ui_area_str,
            )
        except Exception:
            self._app.log_exception("Could not execute generate_actions hook.")

        return action_defs
    def _get_current_project(self):
        """
        Returns the current project based on where in the UI the user clicked
        """

        # get the menu selection from hiero engine
        selection = self.parent.engine.get_menu_selection()

        if len(selection) != 1:
            raise TankError("Please select a single Project!")

        if not isinstance(selection[0], hiero.core.Bin):
            raise TankError("Please select a Hiero Project!")

        project = selection[0].project()
        if project is None:
            # apparently bins can be without projects (child bins I think)
            raise TankError("Please select a Hiero Project!")

        return project
    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item
                                    
                            name:   String
                                    Name to use for the item in the UI
                            
                            description:    String
                                            Description of the item to use in the UI
                                            
                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.
                                            
                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.
                                            
                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """

        items = []

        # get the main scene:
        if not MaxPlus.FileManager.GetFileName():
            raise TankError("Please Save your file before Publishing")

        # create the primary item - 'type' should match the 'primary_scene_item_type':
        items.append({
            "type": "work_file",
            "name": MaxPlus.FileManager.GetFileName()
        })

        # always add a secondary item to allow user to commit all changes to Perforce:
        # Note: only need one of these as it submits all published files
        items.append({
            "type": "perforce_submit",
            "name": "All Published Files"
        })

        return items
    def _get_active_document(self):
        """
        Returns the currently open document in Photoshop.
        Raises an exeption if no document is active.
        """
        doc = self.parent.engine.adobe.get_active_document()

        if not doc:
            raise TankError("There is no active document!")

        return doc
Esempio n. 30
0
    def __init__(self, bundle):
        """
        Constructor
        
        :param bundle: app, engine or framework object to associate the settings with.
        """

        self.__fw = sgtk.platform.current_bundle()

        self.__settings = QtCore.QSettings("Shotgun Software", bundle.name)
        self.__fw.log_debug("Initialized settings manager for '%s'" %
                            bundle.name)

        # now organize various keys

        # studio level settings - base it on the server host name
        _, sg_hostname, _, _, _ = urlparse.urlsplit(self.__fw.sgtk.shotgun_url)
        self.__site_key = sg_hostname

        # project level settings
        pc = self.__fw.sgtk.pipeline_configuration
        self.__project_key = "%s:%s" % (self.__site_key,
                                        pc.get_project_disk_name())

        # config level settings
        self.__pipeline_config_key = "%s:%s" % (self.__project_key,
                                                pc.get_name())

        # instance level settings
        if isinstance(bundle, sgtk.platform.Application):
            # based on the environment name, engine instance name and app instance name
            self.__instance_key = "%s:%s:%s:%s" % (
                self.__pipeline_config_key, bundle.engine.environment["name"],
                bundle.engine.instance_name, bundle.instance_name)
            self.__engine_key = bundle.engine.name

        elif isinstance(bundle, sgtk.platform.Engine):
            # based on the environment name & engine instance name
            self.__instance_key = "%s:%s:%s" % (self.__pipeline_config_key,
                                                bundle.environment["name"],
                                                bundle.instance_name)
            self.__engine_key = bundle.name

        elif isinstance(bundle, sgtk.platform.Framework):
            # based on the environment name & framework name
            self.__instance_key = "%s:%s:%s" % (
                self.__pipeline_config_key, bundle.engine.environment["name"],
                bundle.name)
            self.__engine_key = bundle.engine.name

        else:
            raise TankError("Not sure how to handle bundle type %s. "
                            "Please pass an App, Engine or Framework object." %
                            bundle)