Open in... Latest work file version

Can I configure Shotgun Create to open the latest working file of the task being reviewed.

I.e. click open in nuke and it opens the latest version for that task program chosen.

2 Likes

I would also love to be able to do this! My artists all think that this should be the default.

2 Likes

It’s not always easy to know what the latest file is. What happens if you have two files with different names but the same version number?

However, if your workflow allows you to make assumptions about what the latest file is then you should be able to implement it opening the latest file on startup. I’m putting together an example, I’ll hopefully have it posted tomorrow.

1 Like

You make a good point, re: knowing what the latest file is. My old configuration would not have made this possible, but my new one does where I manage shot names with the {Shot} identifier rather than {name} - handling it for the user.

2 Likes

OK I’ve put an example together. It is just that, and example, it works, but it will likely need tweaking to make it more robust.
You need to take over the app_launch.py hook of the tk-multi-launchapp .

Then replace the script contents with the following:

import os
import re
import sys
import tank
import sgtk


class AppLaunch(tank.Hook):

    def execute(self, app_path, app_args, version, engine_name, **kwargs):

        engine = sgtk.platform.current_engine()

        if engine_name == "tk-nuke" and engine.context.task is not None:
            self.logger.debug("Finding latest file to load on startup ...")

            # Get the settings for the workfiles app in the environment we will be launchig Nuke in.
            # This is so we can find out the publish and work templates it would use.
            app_settings = sgtk.platform.find_app_settings(engine_name,
                                                           'tk-multi-workfiles2',
                                                           engine.sgtk,
                                                           engine.context)

            # extracting the templates from the app settings
            publish_template = app_settings[0]['settings']['template_publish']
            work_template = app_settings[0]['settings']['template_work']

            # Now get the latest work and publish file along with the version number for each
            work_file, work_file_version = self.get_next_version(engine.sgtk, engine.context, publish_template)
            publish_file, publish_file_version = self.get_next_version(engine.sgtk, engine.context, work_template)

            # Figure out which of the latest publish and work file is the highest version and use that.
            # In the situation where both are the same, use the work file
            file_to_open = work_file if work_file_version >= publish_file_version else publish_file
            # Now add the file path to the Nuke launch args. If you were doing this for software other than nuke
            # Then you will need to handle it in the way in which that software expects the arg to be passed.
            app_args = "{0} {1}".format(file_to_open, app_args)

        system = sys.platform

        if system == "linux2":
            # on linux, we just run the executable directly
            cmd = "%s %s &" % (app_path, app_args)

        elif system == "darwin":
            # If we're on OS X, then we have two possibilities: we can be asked
            # to launch an application bundle using the "open" command, or we
            # might have been given an executable that we need to treat like
            # any other Unix-style command. The best way we have to know whether
            # we're in one situation or the other is to check the app path we're
            # being asked to launch; if it's a .app, we use the "open" command,
            # and if it's not then we treat it like a typical, Unix executable.
            if app_path.endswith(".app"):
                # The -n flag tells the OS to launch a new instance even if one is
                # already running. The -a flag specifies that the path is an
                # application and supports both the app bundle form or the full
                # executable form.
                cmd = "open -n -a \"%s\"" % (app_path)
                if app_args:
                    cmd += " --args %s" % app_args
            else:
                cmd = "%s %s &" % (app_path, app_args)

        elif system == "win32":
            # on windows, we run the start command in order to avoid
            # any command shells popping up as part of the application launch.
            cmd = "start /B \"App\" \"%s\" %s" % (app_path, app_args)

        # run the command to launch the app
        exit_code = os.system(cmd)

        return {
            "command": cmd,
            "return_code": exit_code
        }

    def get_next_version(self, tk, context, template_name, ):
        """
        Get the highest version file found on disk for a given template
        :param tk:
        :param template_name:
        :return:
        """
        template = tk.templates[template_name]
        fields = context.as_template_fields(template)

        # Get a list of existing file paths on disk that match the template and provided fields
        # Skip the version field as we want to find all versions, not a specific version.
        skip_fields = ["version"]
        file_paths = tk.paths_from_template(
            template,
            fields,
            skip_fields,
            skip_missing_optional_keys=True
        )
        # now loop over the files and find the highest version file
        latest_file = None
        highest_version = 0
        for a_file in file_paths:
            # extract the values from the path so we can read the version.
            path_fields = template.get_fields(a_file)
            if path_fields["version"] > highest_version:
                highest_version = path_fields["version"]
                latest_file = a_file
        return latest_file, highest_version
2 Likes

Also, if the latest file is a PublishedFile, then really it should be copied to the working directory so that it can be worked on. This guide might be helpful with trying to add that behaviour.

1 Like