Exemple #1
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch the DCC that will automatically
        load Toolkit and the engine when the DCC starts.

        :param str exec_path: Path to executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.

        :returns: A :class:`LaunchInformation` instance.
        """
        # TODO: Get the startup project from settings somewhere, for now hardcoded
        # Otherwise, leave it empty and the project selection window will appear
        # (the command-line arguments are forwarded to the new instance of Unreal Editor)
        unreal_project = ""
        args = args + unreal_project
        required_env = {}
        # Creating a QApplication in Unreal on Mac crashes it, so disable the
        # SG TK integration for now, just run the executable with its args. This
        # allows to launch Unreal from tk-desktop or submit turntable renders
        # from Maya to Unreal, without the integration crashing Unreal.
        if sys.platform == "darwin":
            self.logger.warning(
                "SG TK Unreal integration is not available on Mac.")
            return LaunchInformation(exec_path, args, required_env)

        # Usually DCCs have an environment variable for plugins that need to be loaded.
        # Here we're adding ourselves to that list. We add ourselves to the existing one
        # in fact so we play nice with the current environment.
        required_env["UNREAL_PATH"] = self._join_paths_with_existing_env_paths(
            "UNREAL_PATH", os.path.join(self.disk_location, "startup"))

        # Add std context and site info to the env. This will add stuff like which site to
        # connect to, what context to load, etc.
        required_env.update(self.get_standard_plugin_environment())

        # Signals which engine instance from the environment is going to be used.
        required_env["SHOTGUN_ENGINE"] = self.engine_name

        # Set the bootstrap location in the environment variable that will be used by the Unreal Shotgun plugin
        # startup script
        bootstrap_script = os.path.join(self.disk_location, "plugins", "basic",
                                        "bootstrap.py")
        # From UE5, the UE_SHOTGRID_BOOTSTRAP environment variable is supported.
        # We still need to support UE_SHOTGUN_BOOTSTRAP for previous UE versions.
        required_env["UE_SHOTGUN_BOOTSTRAP"] = bootstrap_script
        required_env["UE_SHOTGRID_BOOTSTRAP"] = bootstrap_script
        # UE5 Python ignores PYTHONPATH and only uses UE_PYTHONPATH
        # blindly copy what was set so modules (e.g. SG TK core) are found
        # when bootstrapping.
        required_env["UE_PYTHONPATH"] = os.environ.get("PYTHONPATH") or ""
        self.logger.debug("Executable path: %s", exec_path)
        self.logger.debug("Launch environment: %s",
                          pprint.pformat(required_env))
        self.logger.debug("Launch arguments: %s", args)

        return LaunchInformation(exec_path, args, required_env)
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Photoshop so that will automatically
        load Toolkit after startup.

        :param str exec_path: Path to Maya executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """

        # find the bootstrap script and import it.
        # note: all the business logic for how to launch is
        #       located in the python/startup folder to be compatible
        #       with older versions of the launch workflow
        bootstrap_python_path = os.path.join(self.disk_location, "python",
                                             "startup")
        (file_obj, filename, desc) = imp.find_module("bootstrap",
                                                     [bootstrap_python_path])
        bootstrap = imp.load_module("bootstrap", file_obj, filename, desc)

        # determine all environment variables
        required_env = bootstrap.compute_environment()

        # Add std context and site info to the env
        std_env = self.get_standard_plugin_environment()
        required_env.update(std_env)

        if file_to_open:
            # If we have a file to open, add it to the end of the args so Photoshop opens the file.
            # By providing the file as an arg, this will ensure that on Windows, Photoshop will open the file
            # in a pre-existing Photoshop session if one is found.
            args = " ".join([args, file_to_open])

        return LaunchInformation(exec_path, args, required_env)
Exemple #3
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Natron in that will automatically
        load Toolkit and the tk-natron engine when Natron starts.

        :param str exec_path: Path to Natron executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                            launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's init.py file when Natron starts up
        startup_path = os.path.join(self.disk_location, "resources", "Katana")

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing Natron Launch via Toolkit Classic methodology ...")
        required_env["TANK_ENGINE"] = self.engine_name
        required_env["TANK_CONTEXT"] = sgtk.context.serialize(self.context)
        required_env["PYTHONPATH"] = os.environ["PYTHONPATH"]
        required_env["KATANA_RESOURCES"] = startup_path

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        args = '"%s"' % startup_path
        return LaunchInformation(exec_path, args, required_env)
Exemple #4
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch 3DEqualizer4 in that will automatically
        load Toolkit and the tk-3de4 engine when 3DEqualizer starts.

        :param str exec_path: Path to 3DEqualizer4 executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's startup/*.py files when 3DEqualizer starts up
        # by appending it to the env PYTHON_CUSTOM_SCRIPTS_3DE4.
        startup_path = os.path.join(self.disk_location, 'startup')

        # Get path to temp menu folder, and add it to the environment.
        menufolder = tempfile.mkdtemp(prefix='tk-3de4_')
        required_env['TK_3DE4_MENU_DIR'] = menufolder

        required_env['PYTHON_CUSTOM_SCRIPTS_3DE4'] = os.pathsep.join(
            [x for x in os.getenv('PYTHON_CUSTOM_SCRIPTS_3DE4', '').split(os.pathsep) if x]
            + [startup_path, menufolder])

        # Add context information info to the env.
        required_env['TANK_CONTEXT'] = sgtk.Context.serialize(self.context)

        # open a file
        if file_to_open:
            args += ' {}'.format(subprocess.list2cmdline(('-open', file_to_open)))

        return LaunchInformation(exec_path, args, required_env)
Exemple #5
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares the given software for launch

        :param str exec_path: Path to DCC executable to launch

        :param str args: Command line arguments as strings

        :param str file_to_open: (optional) Full path name of a file to open on
            launch

        :returns: :class:`LaunchInformation` instance
        """

        # construct the path to the engine's python directory and add it to sys
        # path. this provides us access to the bootstrap module which contains
        # helper methods for constructing the proper environment based on the
        # bootstrap scanario.
        tk_houdini_python_path = os.path.join(
            self.disk_location,
            "python",
        )
        sys.path.insert(0, tk_houdini_python_path)

        from tk_houdini import bootstrap

        # Check the engine settings to see whether any plugins have been
        # specified to load.
        launch_plugins = self.get_setting("launch_builtin_plugins")
        if launch_plugins:

            # Prepare the launch environment with variables required by the
            # plugin bootstrap.
            self.logger.debug("Launch plugins: %s" % (launch_plugins, ))
            required_env = bootstrap.get_plugin_startup_env(launch_plugins)

            # Add context and site info
            required_env.update(self.get_standard_plugin_environment())

        else:

            # pull the env var names from the bootstrap module
            engine_env = bootstrap.g_sgtk_engine_env
            context_env = bootstrap.g_sgtk_context_env

            # Prepare the launch environment with variables required by the
            # classic bootstrap.
            required_env = bootstrap.get_classic_startup_env()
            required_env[engine_env] = self.engine_name
            required_env[context_env] = sgtk.context.serialize(self.context)

        # populate the file to open env. Note this env variable name existed
        # pre software launch setup.
        if file_to_open:
            file_to_open_env = bootstrap.g_sgtk_file_to_open_env
            required_env[file_to_open_env] = file_to_open

        self.logger.debug("Launch environment: %s" % (required_env, ))

        return LaunchInformation(exec_path, args, required_env)
Exemple #6
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch 3DEqualizer4 in that will automatically
        load Toolkit and the tk-3de4 engine when 3DEqualizer starts.

        :param str exec_path: Path to 3DEqualizer4 executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's startup/*.py files when 3DEqualizer starts up
        # by appending it to the env PYTHON_CUSTOM_SCRIPTS_3DE4.
        startup_path = os.path.join(self.disk_location, "startup")
        #sgtk.util.append_path_to_env_var("PYTHON_CUSTOM_SCRIPTS_3DE4", startup_path)
        os.environ["PYTHON_CUSTOM_SCRIPTS_3DE4"] = startup_path
        required_env["PYTHON_CUSTOM_SCRIPTS_3DE4"] = os.environ[
            "PYTHON_CUSTOM_SCRIPTS_3DE4"]

        # Add context information info to the env.
        required_env["TANK_CONTEXT"] = sgtk.Context.serialize(self.context)

        # open a file
        if file_to_open:
            args += " {}".format(
                subprocess.list2cmdline(("-open", file_to_open)))

        return LaunchInformation(exec_path, args, required_env)
Exemple #7
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Photoshop so that will automatically
        load Toolkit after startup.

        :param str exec_path: Path to Maya executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        # todo - add support for the file_to_open parameter.

        # find the bootstrap script and import it.
        # note: all the business logic for how to launch is
        #       located in the python/startup folder to be compatible
        #       with older versions of the launch workflow
        bootstrap_python_path = os.path.join(self.disk_location, "python",
                                             "startup")
        sys.path.insert(0, bootstrap_python_path)
        import bootstrap

        # determine all environment variables
        required_env = bootstrap.compute_environment()
        # copy the extension across to the deploy folder
        bootstrap.ensure_extension_up_to_date()

        # Add std context and site info to the env
        std_env = self.get_standard_plugin_environment()
        required_env.update(std_env)

        return LaunchInformation(exec_path, args, required_env)
Exemple #8
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Clarisse in that will automatically
        load Toolkit and the tk-clarisse engine when Clarisse starts.

        :param str exec_path: Path to Clarisse executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                 launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's userSetup.py file when Clarisse starts up
        # by appending it to the env PYTHONPATH.
        startup_path = os.path.join(self.disk_location, "startup",
                                    "userSetup.py")
        sgtk.util.append_path_to_env_var("CLARISSE_STARTUP_SCRIPT",
                                         startup_path)
        required_env["CLARISSE_STARTUP_SCRIPT"] = os.environ[
            "CLARISSE_STARTUP_SCRIPT"]

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing Clarisse Launch via Toolkit Classic methodology ...")
        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        return LaunchInformation(exec_path, args, required_env)
Exemple #9
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Provides the bare minimum prepare_launch.
        Makes no changes other than to provide the standard environment.
        """

        # Add std context and site info to the env.
        required_env = self.get_standard_plugin_environment()

        return LaunchInformation(exec_path, args, required_env)
Exemple #10
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch VRED in that will automatically load
        Toolkit and the tk-vred engine when VRED starts.

        :param str exec_path: Path to VRED executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Command line arguments
        args += " -insecure_python"

        if os.getenv("DISABLE_VRED_OPENGL", "0") == "1":
            args += " -no_opengl"

        if os.getenv("ENABLE_VRED_CONSOLE", "0") == "1":
            args += " -console"

        # Register plugins
        plugin_dir = os.path.join(self.disk_location, "plugins", "Shotgun")
        vred_plugins_dir = os.path.join(os.path.dirname(exec_path), "Scripts")

        # be sure to not override the VRED_SCRIPT_PLUGINS environment variable if it's already declared
        if "VRED_SCRIPT_PLUGINS" in os.environ.keys():
            required_env["VRED_SCRIPT_PLUGINS"] = "{};{};{}".format(
                plugin_dir, vred_plugins_dir,
                os.environ["VRED_SCRIPT_PLUGINS"])
        else:
            required_env["VRED_SCRIPT_PLUGINS"] = "{};{}".format(
                plugin_dir, vred_plugins_dir)

        # SHOTGUN_ENABLE is an extra environment variable required by VRED
        required_env["SHOTGUN_ENABLE"] = "1"

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug("Preparing VRED Launch...")
        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        # Add the `file to open` to the launch environment
        if file_to_open:
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        # Add VRED executable path as an environment variable to be used by the translators
        required_env["TK_VRED_EXECPATH"] = exec_path

        # Add VRED version to control API imports in hooks
        raw_version = _get_windows_version(exec_path, self.logger)
        required_env["TK_VRED_VERSION"] = self._map_version_year(raw_version)

        return LaunchInformation(exec_path, args, required_env)
Exemple #11
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Cinema in that will automatically
        load Toolkit and the tk-cinema engine when Cinema starts.

        :param str exec_path: Path to Cinema executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                 launch.
        :returns: :class:`LaunchInformation` instance
        """

        required_env = {}

        # Run the engine's userSetup.py file when Cinema starts up
        # by appending it to the env PYTHONPATH.
        startup_path = os.path.join(self.disk_location, "startup")

        sgtk.util.append_path_to_env_var("g_additionalModulePath",
                                         startup_path)
        required_env["g_additionalModulePath"] = os.environ[
            "g_additionalModulePath"]

        if 'R23' in exec_path:
            # Get Qt Site - when launching from Shotgun Desktop this should
            # point to the installs lib/site-packages directory.
            try:
                from sgtk.platform.qt import QtCore
                qt_site = os.path.dirname(os.path.dirname(QtCore.__file__))
                sgtk.util.append_path_to_env_var("PYTHONPATH", qt_site)
            except ImportError:
                pass

        sgtk.util.append_path_to_env_var("PYTHONPATH",
                                         os.path.join(startup_path, 'libs'))
        required_env["PYTHONPATH"] = os.environ["PYTHONPATH"]
        required_env["C4DPYTHONPATH37"] = os.environ["PYTHONPATH"]  # R23
        required_env["C4DPYTHONPATH39"] = os.environ["PYTHONPATH"]  # R24

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing Cinema Launch via Toolkit Classic methodology ...")
        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        return LaunchInformation(exec_path, args, required_env)
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Blender in that will automatically
        load Toolkit and the tk-blender engine when Blender starts.

        :param str exec_path: Path to Blender executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                 launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's startup file file when Blender starts up
        # by appending it to the env PYTHONPATH.
        scripts_path = os.path.join(self.disk_location, "resources", "scripts")

        startup_path = os.path.join(scripts_path, "startup", "Shotgun_menu.py")

        args += "-P " + startup_path

        required_env["BLENDER_USER_SCRIPTS"] = scripts_path

        if not os.environ.get("PYSIDE2_PYTHONPATH"):
            pyside2_python_path = os.path.join(self.disk_location, "python",
                                               "ext")
            required_env["PYSIDE2_PYTHONPATH"] = pyside2_python_path

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing Blender Launch via Toolkit Classic methodology ...")

        required_env["SGTK_MODULE_PATH"] = sgtk.get_sgtk_module_path().replace(
            "\\", "/")

        engine_startup_path = os.path.join(self.disk_location, "startup",
                                           "bootstrap.py")

        required_env["SGTK_BLENDER_ENGINE_STARTUP"] = engine_startup_path
        required_env["SGTK_BLENDER_ENGINE_PYTHON"] = sys.executable.replace(
            "\\", "/")

        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        return LaunchInformation(exec_path, args, required_env)
Exemple #13
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Fusion in that will automatically
        load Toolkit and the tk-fusion engine when Fusion starts.

        :param str exec_path: Path to Fusion executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                            launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's init.py file when Fusion starts up
        # startup_path = os.path.join(self.disk_location, "startup", "init.py")
        startup_path = os.path.join(
            self.disk_location, "startup", "plugins", "Profile", "master.prefs"
        )

        sgtk.util.append_path_to_env_var(
            "FUSION9_MasterPrefs", startup_path
        )
        sgtk.util.append_path_to_env_var(
            "FUSION16_MasterPrefs", startup_path
        )
        sgtk.util.append_path_to_env_var(
             "FUSION_PYTHON27_HOME", "C:/Program Files/Shotgun/Python")

        required_env["FUSION9_MasterPrefs"] = os.environ[
            "FUSION9_MasterPrefs"
        ]
        required_env["FUSION16_MasterPrefs"] = os.environ[
            "FUSION9_MasterPrefs"
        ]        
        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing Fusion Launch via Toolkit Classic methodology ...")
        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        args = '"%s"' % startup_path
        return LaunchInformation(exec_path, args, required_env)
Exemple #14
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares the given software for launch.

        :param str exec_path: Path to DCC executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}
        startup_path = os.path.join(self.disk_location, "startup")
        sgtk.util.append_path_to_env_var("PYTHONPATH", startup_path)
        required_env["PYTHONPATH"] = os.environ["PYTHONPATH"]
        if file_to_open:
            required_env["FILE_TO_OPEN"] = file_to_open

        return LaunchInformation(exec_path, args, required_env)
Exemple #15
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares the given software for launch

        :param str exec_path: Path to DCC executable to launch

        :param str args: Command line arguments as strings

        :param str file_to_open: (optional) Full path name of a file to open on
            launch

        :returns: :class:`LaunchInformation` instance
        """
        launch_plugins = self.get_setting("launch_builtin_plugins")

        if launch_plugins:
            self.logger.debug("Launch plugins: %s", launch_plugins)

            # Get Nuke environment for plugin launch.
            required_env, required_args = self._get_plugin_startup_env(
                launch_plugins, exec_path, args, file_to_open
            )

            # Add std context and site info to the env.
            required_env.update(self.get_standard_plugin_environment())

            # Make sure we are picking the right engine.
            required_env["SHOTGUN_ENGINE"] = self.engine_name
        else:
            self.logger.debug(
                "Preparing Nuke Launch via Toolkit Classic methodology ..."
            )

            # Get Nuke environment for Toolkit Classic launch.
            required_env, required_args = self._get_classic_startup_env(
                self.disk_location, exec_path, args, file_to_open
            )
            # Add context information info to the env.
            required_env["TANK_CONTEXT"] = sgtk.Context.serialize(self.context)
            required_env["TANK_ENGINE"] = self.engine_name

        self.logger.debug("Launch environment: %s",
                          pprint.pformat(required_env))
        self.logger.debug("Launch arguments: %s", required_args)

        return LaunchInformation(exec_path, required_args, required_env)
Exemple #16
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Krita in that will automatically
        load Toolkit and the tk-krita engine when Krita starts.

        :param str exec_path: Path to Krita executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's userSetup.py file when Maya starts up
        # by appending it to the env PYTHONPATH.
        startup_path = os.path.join(self.disk_location, "startup")
        sgtk.util.append_path_to_env_var("PYTHONPATH", startup_path)
        required_env["SG_PYTHONPATH"] = os.environ["PYTHONPATH"]

        return LaunchInformation(exec_path, args, required_env)
Exemple #17
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch After Effects so that will automatically
        load Toolkit after startup.

        :param str exec_path: Path to Maya executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """

        # determine all environment variables
        required_env = self.compute_environment()

        # Add std context and site info to the env
        std_env = self.get_standard_plugin_environment()
        required_env.update(std_env)

        return LaunchInformation(exec_path, args, required_env)
Exemple #18
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch the DCC that will automatically
        load Toolkit and the engine when the DCC starts.

        :param str exec_path: Path to executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.

        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}
        # Usually DCCs have an environment variable for plugins that need to be loaded.
        # Here we're adding ourselves to that list. We add ourselves to the existing one
        # in fact so we play nice with the current environment.
        required_env["UNREAL_PATH"] = self._join_paths_with_existing_env_paths(
            "UNREAL_PATH", os.path.join(self.disk_location, "startup"))

        # Add std context and site info to the env. This will add stuff like which site to
        # connect to, what context to load, etc.
        required_env.update(self.get_standard_plugin_environment())

        # Signals which engine instance from the environment is going to be used.
        required_env["SHOTGUN_ENGINE"] = self.engine_name

        # TODO: Get the startup project from settings somewhere, for now hardcoded
        # Otherwise, leave it empty and the project selection window will appear
        # (the command-line arguments are forwarded to the new instance of Unreal Editor)
        unreal_project = ""
        args = args + unreal_project

        # Set the bootstrap location in the environment variable that will be used by the Unreal Shotgun startup script
        bootstrap_script = os.path.join(self.disk_location, "plugins", "basic",
                                        "bootstrap.py")
        required_env["UE_SHOTGUN_BOOTSTRAP"] = bootstrap_script

        self.logger.debug("Executable path: %s", exec_path)
        self.logger.debug("Launch environment: %s",
                          pprint.pformat(required_env))
        self.logger.debug("Launch arguments: %s", args)

        return LaunchInformation(exec_path, args, required_env)
Exemple #19
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch in that will automatically
        load Toolkit and the engine when the application starts.

        :param str exec_path: Path to application executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                            launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        resources_plugins_path = os.path.join(self.disk_location, "resources",
                                              "plugins")
        required_env["SBS_DESIGNER_PYTHON_PATH"] = os.path.join(
            resources_plugins_path, "shotgun_bridge")

        # Run the engine's init.py file when the application starts up
        startup_path = os.path.join(self.disk_location, "startup", "init.py")
        required_env[
            "SGTK_SUBSTANCEDESIGNER_ENGINE_STARTUP"] = startup_path.replace(
                "\\", "/")

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing %s Launch via Toolkit Classic methodology ..." %
            APPLICATION_NAME)

        required_env["SGTK_ENGINE"] = ENGINE_NAME
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)
        required_env[
            "SGTK_SUBSTANCEDESIGNER_SGTK_MODULE_PATH"] = get_sgtk_module_path(
            )

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        os.chdir(os.path.dirname(os.path.dirname(exec_path)))
        return LaunchInformation(path=exec_path, environ=required_env)
Exemple #20
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Premiere so that will automatically
        load Toolkit after startup.

        :param str exec_path: Path to Maya executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """

        # determine all environment variables
        required_env = self.compute_environment()

        # Add std context and site info to the env
        std_env = self.get_standard_plugin_environment()
        required_env.update(std_env)

        # override with default project file
        args = os.path.join(self.disk_location, "resources", "Untitled.prproj")

        return LaunchInformation(exec_path, args, required_env)
Exemple #21
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares the given software for launch

        :param str exec_path: Path to DCC executable to launch

        :param str args: Command line arguments as strings

        :param str file_to_open: (optional) Full path name of a file to open on
            launch

        :returns: :class:`LaunchInformation` instance
        """
        # flame comes with toolkit built-in, so no need to
        # run any startup logic.

        env = {
            "SHOTGUN_SITE": self.sgtk.shotgun_url,
            "SHOTGUN_ENTITY_ID": str(self.context.project["id"]),
            "SHOTGUN_ENTITY_TYPE": str(self.context.project["type"]),
            "SHOTGUN_ENTITY_NAME": str(self.context.project["name"])
        }

        return LaunchInformation(exec_path, args, env)
Exemple #22
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch in that will automatically
        load Toolkit and the engine when the application starts.

        :param str exec_path: Path to application executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                            launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's init.py file when the application starts up
        resources_plugins_path = os.path.join(self.disk_location, "startup")
        required_env["RUMBA_USER_PLUGINS"] = (
            os.environ.get("RUMBA_USER_PLUGINS", "")
            + os.pathsep
            + resources_plugins_path
        )

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing %s Launch via Toolkit Classic methodology ..." % APPLICATION_NAME
        )

        required_env["SGTK_ENGINE"] = ENGINE_NAME
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)
        required_env["SGTK_MODULE_PATH"] = get_sgtk_module_path()

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        return LaunchInformation(path=exec_path, args=args, environ=required_env)
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch 3dsMax in that will automatically
        load Toolkit and the tk-3dsmaxplus engine when 3dsMax starts.

        :param str exec_path: Path to 3dsMax executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        # This is a fix for PySide problems in 2017+ versions of Max. Now that
        # Max ships with a full install of PySide, we need to ensure that dlls
        # for the native Max install are sourced. If we don't do this, we end
        # up with dlls loaded from SG Desktop's bin and we have a mismatch that
        # results in complete breakage.
        max_root = os.path.dirname(exec_path)
        sgtk.util.prepend_path_to_env_var("PATH", max_root)

        required_env = {}

        startup_file = os.path.join(self.disk_location, "python", "startup",
                                    "bootstrap.py")
        new_args = "-U PythonHost \"%s\"" % startup_file

        if args:
            args = "%s %s" % (args, new_args)
        else:
            args = new_args

        # Check the engine settings to see whether any plugins have been
        # specified to load.
        find_plugins = self.get_setting("launch_builtin_plugins")
        if find_plugins:
            self.logger.debug(
                "Plugins found from 'launch_builtin_plugins': %s" %
                find_plugins)

            # Keep track of the specific list of Toolkit plugins to load when
            # launching 3dsMax. This list is passed through the environment and
            # used by the startup/bootstrap.py file.
            load_max_plugins = []

            for find_plugin in find_plugins:
                load_plugin = os.path.join(self.disk_location, "plugins",
                                           find_plugin)
                if os.path.exists(load_plugin):
                    self.logger.debug(
                        "Preparing to launch builtin plugin '%s'" %
                        load_plugin)
                    load_max_plugins.append(load_plugin)
                else:
                    # Report the missing plugin directory
                    self.logger.warning(
                        "Resolved plugin path '%s' does not exist!" %
                        load_plugin)

            required_env["SGTK_LOAD_MAX_PLUGINS"] = os.pathsep.join(
                load_max_plugins)

            # Add context and site info
            std_env = self.get_standard_plugin_environment()
            required_env.update(std_env)

        else:
            # Prepare the launch environment with variables required by the
            # classic bootstrap approach.
            self.logger.debug(
                "Preparing 3dsMax Launch via Toolkit Classic methodology ...")
            required_env["TANK_ENGINE"] = self.engine_name
            required_env["TANK_CONTEXT"] = self.context.serialize(
                use_json=True)

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        return LaunchInformation(exec_path, args, required_env)
Exemple #24
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Maya in that will automatically
        load Toolkit and the tk-maya engine when Maya starts.

        :param str exec_path: Path to Maya executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        # Run the engine's userSetup.py file when Maya starts up
        # by appending it to the env PYTHONPATH.
        startup_path = os.path.join(self.disk_location, "startup")
        sgtk.util.append_path_to_env_var("PYTHONPATH", startup_path)
        required_env["PYTHONPATH"] = os.environ["PYTHONPATH"]

        # Check the engine settings to see whether any plugins have been
        # specified to load.
        find_plugins = self.get_setting("launch_builtin_plugins")
        if find_plugins:
            # Parse the specified comma-separated list of plugins
            self.logger.debug(
                "Plugins found from 'launch_builtin_plugins': %s" %
                find_plugins)

            # Keep track of the specific list of Toolkit plugins to load when
            # launching Maya. This list is passed through the environment and
            # used by the startup/userSetup.py file.
            load_maya_plugins = []

            # Add Toolkit plugins to load to the MAYA_MODULE_PATH environment
            # variable so the Maya loadPlugin command can find them.
            maya_module_paths = os.environ.get("MAYA_MODULE_PATH") or []
            if maya_module_paths:
                maya_module_paths = maya_module_paths.split(os.pathsep)

            for find_plugin in find_plugins:
                load_plugin = os.path.join(self.disk_location, "plugins",
                                           find_plugin)
                if os.path.exists(load_plugin):
                    # If the plugin path exists, add it to the list of MAYA_MODULE_PATHS
                    # so Maya can find it and to the list of SGTK_LOAD_MAYA_PLUGINS so
                    # the startup's userSetup.py file knows what plugins to load.
                    self.logger.debug(
                        "Preparing to launch builtin plugin '%s'" %
                        load_plugin)
                    load_maya_plugins.append(load_plugin)
                    if load_plugin not in maya_module_paths:
                        # Insert at beginning of list to give priority to toolkit plugins
                        # launched from the desktop app over standalone ones whose
                        # path is already part of the MAYA_MODULE_PATH env var
                        maya_module_paths.insert(0, load_plugin)
                else:
                    # Report the missing plugin directory
                    self.logger.warning(
                        "Resolved plugin path '%s' does not exist!" %
                        load_plugin)

            # Add MAYA_MODULE_PATH and SGTK_LOAD_MAYA_PLUGINS to the launch
            # environment.
            required_env["MAYA_MODULE_PATH"] = os.pathsep.join(
                maya_module_paths)
            required_env["SGTK_LOAD_MAYA_PLUGINS"] = os.pathsep.join(
                load_maya_plugins)

            # Add context and site info
            std_env = self.get_standard_plugin_environment()
            required_env.update(std_env)

        else:
            # Prepare the launch environment with variables required by the
            # classic bootstrap approach.
            self.logger.debug(
                "Preparing Maya Launch via Toolkit Classic methodology ...")
            required_env["SGTK_ENGINE"] = self.engine_name
            required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        return LaunchInformation(exec_path, args, required_env)
Exemple #25
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch SubstancePainter in that will automatically
        load Toolkit and the tk-substancepainter engine when SubstancePainter starts.

        :param str exec_path: Path to SubstancePainter executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                            launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        resources_plugins_path = os.path.join(self.disk_location, "resources",
                                              "plugins")

        # Run the engine's init.py file when SubstancePainter starts up
        # TODO, maybe start engine here
        startup_path = os.path.join(self.disk_location, "startup",
                                    "bootstrap.py")

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing SubstancePainter Launch via Toolkit Classic methodology ..."
        )

        required_env[
            "SGTK_SUBSTANCEPAINTER_ENGINE_STARTUP"] = startup_path.replace(
                "\\", "/")

        required_env[
            "SGTK_SUBSTANCEPAINTER_ENGINE_PYTHON"] = sys.executable.replace(
                "\\", "/")

        required_env[
            "SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH"] = sgtk.get_sgtk_module_path(
            )

        required_env["SGTK_SUBSTANCEPAINTER_ENGINE_PORT"] = str(
            get_free_port())

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        # First big disclaimer: qml does not support environment variables for safety reasons
        # the only way to pass information inside substance painter is to actually encode
        # as a string and trick the program to think it is opening a substance painter project
        # The reason why this works is because inside substance painter the original file is
        # used with an URL, ie. //file/serve/filename, so we add to the URL using & to pass
        # our now fake environment variables.
        # Only the startup script, the location of python and potentially the file to open
        # are needed.
        args = ""
        args = ["%s=%s" % (k, v) for k, v in required_env.iteritems()]
        args = '"&%s"' % "&".join(args)
        logger.info("running %s" % args)

        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        # ensure scripts are up to date on the substance painter side

        # Platform-specific plug-in paths

        if sys.platform == "win32":
            import ctypes.wintypes

            CSIDL_PERSONAL = 5  # My Documents
            SHGFP_TYPE_CURRENT = 0  # Get current My Documents folder, not default value

            path_buffer = ctypes.create_unicode_buffer(
                ctypes.wintypes.MAX_PATH)
            ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None,
                                                   SHGFP_TYPE_CURRENT,
                                                   path_buffer)

            user_scripts_path = path_buffer.value + r"\Allegorithmic\Substance Painter\plugins"

        else:
            user_scripts_path = os.path.expanduser(
                r"~/Documents/Allegorithmic/Substance Painter/plugins")

        ensure_scripts_up_to_date(resources_plugins_path, user_scripts_path)

        # args = '&SGTK_SUBSTANCEPAINTER_ENGINE_STARTUP=%s;SGTK_SUBSTANCEPAINTER_ENGINE_PYTHON=%s' % (startup_path, sys.executable)
        return LaunchInformation(exec_path, args, required_env)
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares the given software for launch

        :param str exec_path: Path to DCC executable to launch
        :param str args: Command line arguments as strings
        :param str file_to_open: (optional) Full path name of a file to open on
            launch

        :returns: :class:`LaunchInformation` instance
        """
        use_builtin_plugin = self.get_setting("use_builtin_plugin")

        # If there is a plugin to launch with, we don't have much in the
        # way of prep work to do.
        if use_builtin_plugin:
            # flame comes with toolkit built-in, so no need to
            # run any startup logic.
            self.logger.debug("Using the builtin plugin on Flame launch.")
            env = {
                "SHOTGUN_SITE": self.sgtk.shotgun_url,
                "SHOTGUN_ENTITY_ID": str(self.context.project["id"]),
                "SHOTGUN_ENTITY_TYPE": str(self.context.project["type"]),
                "SHOTGUN_ENTITY_NAME": str(self.context.project["name"])
            }
        else:
            self.logger.debug("Using the legacy bootstrap on Flame launch.")

            # We have a list of environment variables that we need to
            # gather and return. These are various bits of data that
            # the python/startup/app_launcher.py script uses during
            # its bootstrapping of SGTK during launch.
            env = {
                "TOOLKIT_ENGINE_NAME": self.engine_name,
                "TOOLKIT_CONTEXT": sgtk.context.serialize(self.context)
            }

            # We also need to store the various components of the Flame
            # version in the environment. The app_launcher.py script that
            # launches and bootstraps SGTK registers these with the engine,
            # and the engine then logs metrics about what version of Flame
            # has been launched.
            #
            # The exec_path is likely a path to the .app that will be launched.
            # What we need instead of is the fully-qualified path to the Flame
            # startApplication executable, which is what we'll extract the
            # version components from. Examples of what this path can be and
            # how it's parsed can be found in the docstring of _get_flame_version
            # method.
            self.logger.debug("Flame app executable: %s", exec_path)
            if exec_path.endswith(".app"):
                # The flame executable contained withing the .app will be a
                # symlink to the startApplication path we're interested in.
                flame_path = os.path.join(exec_path, "Contents", "MacOS",
                                          "flame")
                app_path = os.path.realpath(flame_path)
            else:
                app_path = os.path.realpath(exec_path)

            if app_path != exec_path:
                self.logger.debug(
                    "Flame app executable has been flattened. The flattened "
                    "path that will be parsed and used at launch time is: %s",
                    app_path)

            self.logger.debug(
                "Parsing Flame (%s) to determine Flame version...", app_path)
            major, minor, patch, version_str = self._get_flame_version(
                app_path)
            self.logger.debug("Found Flame version: %s", version_str)

            env.update(
                dict(
                    TOOLKIT_FLAME_VERSION=version_str,
                    TOOLKIT_FLAME_MAJOR_VERSION=str(major),
                    TOOLKIT_FLAME_MINOR_VERSION=str(minor),
                    TOOLKIT_FLAME_PATCH_VERSION=str(patch),
                ))

            # The install root of Flame is also used by the app_launcher
            # script, which registers it with the engine after bootstrapping.
            # The path is used by the engine when submitting render jobs
            # to Backburner.
            match = re.search("(^.*)/(fla[mr]e[^_]*_[^/]+)/bin", app_path)
            if match:
                env["TOOLKIT_FLAME_INSTALL_ROOT"] = match.group(1)
                app_folder = match.group(2)
                wiretap_path = os.path.join(
                    env["TOOLKIT_FLAME_INSTALL_ROOT"],
                    app_folder,
                    "python",
                )
                self.logger.debug("Adding wiretap root path to PYTHONPATH: %s",
                                  wiretap_path)
                sgtk.util.prepend_path_to_env_var("PYTHONPATH", wiretap_path)
            else:
                raise TankError(
                    "Cannot extract install root from the path: %s" % app_path)

            # The Python executable bundled with Flame is used by the engine
            # when submitting Backburner jobs.
            env["TOOLKIT_FLAME_PYTHON_BINARY"] = "%s/python/%s/bin/python" % (
                env["TOOLKIT_FLAME_INSTALL_ROOT"], version_str)

            # We need to override the exec_path and args that will be used
            # to launch Flame. We launch using the Python bundled with Flame
            # and the app_launcher.py script bundled with the engine. That
            # app_launcher script will do some prep work prior to launching
            # Flame itself.
            #
            # <flame python> <tk-flame>/python/startup/app_launcher.py dcc_path dcc_args
            #
            launch_script = os.path.join(
                os.path.dirname(__file__),
                "python",
                "startup",
                "app_launcher.py",
            )
            exec_path = env["TOOLKIT_FLAME_PYTHON_BINARY"]
            args = "'%s' %s %s" % (launch_script, app_path, args)

        return LaunchInformation(exec_path, args, env)
Exemple #27
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Harmony in that will automatically
        load Toolkit and the tk-harmony engine when Harmony starts.

        :param str exec_path: Path to Harmony executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                            launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        resources_packages_path = os.path.join(self.disk_location, "resources",
                                               "packages")

        startup_js_path = os.path.join(self.disk_location, "resources",
                                       "startup", "bootstrap.js")

        # Run the engine's init.py file when Harmony starts up
        # TODO, maybe start engine here
        startup_path = os.path.join(self.disk_location, "startup",
                                    "bootstrap.py")

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing Harmony Launch via Toolkit Classic methodology ...")

        required_env["SGTK_HARMONY_EXEC_PATH"] = exec_path.replace("\\", "/")

        required_env["SGTK_HARMONY_ENGINE_STARTUP"] = startup_path.replace(
            "\\", "/")

        required_env[
            "SGTK_HARMONY_ENGINE_JS_STARTUP"] = startup_js_path.replace(
                "\\", "/")

        required_env["SGTK_HARMONY_ENGINE_PYTHON"] = sys.executable.replace(
            "\\", "/")

        resources_path = os.path.join(DIR_PATH, "resources")
        required_env[
            "SGTK_HARMONY_ENGINE_RESOURCES_PATH"] = resources_path.replace(
                "\\", "/")

        newfile_template_path = os.path.join(resources_path, "templates",
                                             "newfile", "template.xstage")
        required_env[
            "SGTK_HARMONY_NEWFILE_TEMPLATE"] = newfile_template_path.replace(
                "\\", "/")

        required_env["SGTK_HARMONY_MODULE_PATH"] = sgtk.get_sgtk_module_path(
        ).replace("\\", "/")

        required_env["SGTK_HARMONY_ENGINE_HOST"] = "127.0.0.1"
        required_env["SGTK_HARMONY_ENGINE_PORT"] = str(get_free_port())

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        # ensure scripts are up to date on the dccc side
        scripts_path = scripts_path_for_exec(exec_path)
        self.logger.debug("Executable path: %s" % exec_path)
        self.logger.debug("Searching for scripts here: %s" % scripts_path)

        if scripts_path is None:
            message = ("Could not find the scripts path for "
                       "executable: %s\n" % exec_path)
            raise TankEngineInitError(message)

        user_scripts_path = os.path.join(scripts_path, "packages")

        # create scripts folder if it does not exist already
        if not os.path.exists(user_scripts_path):
            os.makedirs(user_scripts_path)

        xtage = os.path.join(
            self.disk_location,
            "resources",
            "templates",
            "startup",
            "template.xstage",
        )
        required_env["SGTK_HARMONY_STARTUP_TEMPLATE"] = xtage.replace(
            "\\", "/")

        args = " -debug"
        args += ' "' + xtage + '"'

        self.logger.debug("Launch info: %s" % args)

        ensure_scripts_up_to_date(resources_packages_path, user_scripts_path)

        return LaunchInformation(exec_path, args, required_env)
Exemple #28
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch in that will automatically
        load Toolkit and the engine when the application starts.

        :param str exec_path: Path to application executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on
                                            launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}

        resources_plugins_path = os.path.join(self.disk_location, "resources",
                                              "extensions")

        # Run the engine's init.py file when the application starts up
        startup_path = os.path.join(self.disk_location, "startup", "init.py")
        required_env["SGTK_KRITA_ENGINE_STARTUP"] = startup_path.replace(
            "\\", "/")

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug(
            "Preparing %s Launch via Toolkit Classic methodology ..." %
            APPLICATION_NAME)

        required_env["SGTK_ENGINE"] = ENGINE_NAME
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)
        required_env["SGTK_MODULE_PATH"] = get_sgtk_module_path()

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        # figure out where the shotgun bridge extension should be copied
        user_plugins_root_paths = self.USER_PLUGINS_ROOT_PATH.get(
            "darwin" if sgtk.util.is_macos() else "win32" if sgtk.util.
            is_windows() else "linux" if sgtk.util.is_linux() else [])

        if not user_plugins_root_paths:
            raise NotImplementedError

        scripts_synced = False
        for user_plugins_root_path in user_plugins_root_paths:
            user_plugins_root_path = resolve_path(user_plugins_root_path)
            if os.path.exists(user_plugins_root_path):
                user_plugins_path = os.path.join(user_plugins_root_path,
                                                 "pykrita")
                if not os.path.exists(user_plugins_path):
                    os.makedirs(user_plugins_path)

                ensure_scripts_up_to_date(resources_plugins_path,
                                          user_plugins_path)
                scripts_synced = True

        if not scripts_synced:
            raise sgtk.TankError(
                "Could not find the resources path for Krita. Searched here: %s"
                % user_plugins_root_paths)
        return LaunchInformation(path=exec_path, environ=required_env)
Exemple #29
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Unity in that will automatically
        load Toolkit and the tk-unity engine when Unity starts.

        :param str exec_path: Path to Unity executable to launch.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}
        # Add std context and site info to the env. This will add stuff like which site to
        # connect to, what context to load, etc.
        required_env.update(self.get_standard_plugin_environment())

        # This will be read by Bootstrap.cs (com.unity.integrations.shotgrid)
        # from the C# plugin in UI to know where to pick up the
        # Toolkit code.
        required_env["SHOTGRID_UNITY_BOOTSTRAP_LOCATION"] = os.path.join(
            self.disk_location, "plugins", "basic", "bootstrap.py")
        #To be removed when Python Package is integrated properly
        #Code is passing a PySide2 environment variable to Shotgrid unity to use for install
        #A proper integration would simple Pip install Pyside
        from sgtk.util.qt_importer import QtImporter
        pyside_importer = QtImporter()._import_pyside2()
        pysideFilePath = pyside_importer[2].__path__[0]
        pysideFilePath = pysideFilePath.replace("Python", "Python3").replace(
            "python2.7", "python3.7")
        pysideFilePath = os.path.dirname(pysideFilePath)
        required_env["SHOTGRID_UNITY_PYSIDE_LOCATION"] = pysideFilePath

        # Signals which engine instance from the environment is going to be used.
        required_env["SHOTGRID_ENGINE"] = self.engine_name

        # We do not support the file_to_open logic. Its value comes from the
        # launch plug-in when users launch DCCs from a published file.
        # https://github.com/shotgunsoftware/tk-shotgrid-launchpublish
        # https://github.com/shotgunsoftware/tk-config-default2/blob/master/env/publishedfile.yml#L27
        # https://github.com/shotgunsoftware/tk-config-default2/blob/master/env/includes/settings/tk-shotgrid-launchpublish.yml

        #Get user project path with Qt File Dialog
        from sgtk.util.qt_importer import QtImporter
        qt = QtImporter()
        QFileDialog = qt.QtGui.QFileDialog
        QMessageBox = qt.QtGui.QMessageBox
        QApplication = qt.QtGui.QApplication
        QErrorMessage = qt.QtGui.QErrorMessage
        # options for either browse type
        options = [
            QFileDialog.DontResolveSymlinks,
            QFileDialog.ShowDirsOnly,
        ]
        # browse folders specifics
        caption = "Select a Unity Project Directory"
        file_mode = QFileDialog.Directory
        # create the dialog
        file_dialog = QFileDialog(
            parent=QApplication.instance().activeWindow(), caption=caption)
        file_dialog.setLabelText(QFileDialog.Accept, "Select")
        file_dialog.setLabelText(QFileDialog.Reject, "Cancel")
        file_dialog.setFileMode(file_mode)

        # set the appropriate options
        for option in options:
            file_dialog.setOption(option)
        # browse!
        while file_dialog.exec_():
            selected_file_path = file_dialog.selectedFiles()[0]
            if os.path.exists(os.path.join(selected_file_path, "Assets")):
                args += "-projectPath " + selected_file_path
                self.logger.debug("Launch environment: %s",
                                  pprint.pformat(required_env))
                self.logger.debug("Launch arguments: %s", args)
                return LaunchInformation(exec_path, args, required_env)
            else:
                error_message = QErrorMessage()
                error_message.showMessage(
                    "The selected directory does not contain an Unity project. Please select a valid Unity project directory"
                )
                error_message.exec_()
        raise KeyError(
            "User cancelled the Unity project directory selection. Launch aborted"
        )
Exemple #30
0
    def prepare_launch(self, exec_path, args, file_to_open=None):
        """
        Prepares an environment to launch Alias.

        This environment will automatically load Toolkit and the tk-alias engine when
        the program starts.

        :param str exec_path: Path to Alias executable.
        :param str args: Command line arguments as strings.
        :param str file_to_open: (optional) Full path name of a file to open on launch.
        :returns: :class:`LaunchInformation` instance
        """
        required_env = {}
        args = self._clean_args(args)

        # Add flags according to the code_name
        tk_alias_codename = None
        for code_name, data in self.CODE_NAMES.items():
            if code_name in exec_path and data.get("flags"):
                flags = self._clean_args(data.get("flags"))
                if flags not in args:
                    args += " " + flags
                tk_alias_codename = code_name
                break

        # Flag -P (plugins list file)
        plugins_list_file = self._get_plugins_list_file(
            exec_path, tk_alias_codename)
        if plugins_list_file:
            args += ' -P "{0}'.format(plugins_list_file)
            args += '"'

        # Append executable folder to PATH environment variable
        sgtk.util.append_path_to_env_var("PATH",
                                         os.path.dirname(sys.executable))

        # Make the engine startup module to be available when Alias starts up
        # by appending it to the env PYTHONPATH.
        startup_path = os.path.join(self.disk_location, "startup")
        sgtk.util.append_path_to_env_var("PYTHONPATH", startup_path)

        # setup the PYTHONPATH according to Alias version
        self.__setup_pythonpath(tk_alias_codename, exec_path)

        # We're going to append all of this Python process's sys.path to the
        # PYTHONPATH environment variable. This will ensure that we have access
        # to all libraries available in this process. We're appending instead of
        # setting because we don't want to stomp on any PYTHONPATH that might already
        # exist that we want to persist
        sgtk.util.append_path_to_env_var("PYTHONPATH",
                                         os.pathsep.join(sys.path))

        required_env["PYTHONPATH"] = os.environ["PYTHONPATH"]

        # Prepare the launch environment with variables required by the
        # classic bootstrap approach.
        self.logger.debug("Preparing Alias Launch...")
        required_env["SGTK_ENGINE"] = self.engine_name
        required_env["SGTK_CONTEXT"] = sgtk.context.serialize(self.context)

        if file_to_open:
            # Add the file name to open to the launch environment
            required_env["SGTK_FILE_TO_OPEN"] = file_to_open

        # Add executable path and codename
        required_env["TK_ALIAS_EXECPATH"] = exec_path

        if tk_alias_codename:
            tk_alias_codename_lower = tk_alias_codename.lower()
            required_env["TK_ALIAS_VERSION"] = self._get_release_version(
                exec_path, tk_alias_codename).split(".")[0]
        else:
            tk_alias_codename_lower = self.FALLBACK_CODE_NAME.lower()
            required_env["TK_ALIAS_VERSION"] = self._get_release_version(
                exec_path, self.FALLBACK_CODE_NAME).split(".")[0]

        required_env["TK_ALIAS_CODENAME"] = tk_alias_codename_lower

        return LaunchInformation(exec_path, args, required_env)