diff --git a/openpype/hooks/pre_mac_launch.py b/openpype/hooks/pre_mac_launch.py new file mode 100644 index 0000000000..3f07ae07db --- /dev/null +++ b/openpype/hooks/pre_mac_launch.py @@ -0,0 +1,34 @@ +import os +from openpype.lib import PreLaunchHook + + +class LaunchWithTerminal(PreLaunchHook): + """Mac specific pre arguments for application. + + Mac applications should be launched using "open" argument which is internal + callbacks to open executable. We also add argument "-a" to tell it's + application open. This is used only for executables ending with ".app". It + is expected that these executables lead to app packages. + """ + order = 1000 + + platforms = ["darwin"] + + def execute(self): + executable = str(self.launch_context.executable) + # Skip executables not ending with ".app" or that are not folder + if not executable.endswith(".app") or not os.path.isdir(executable): + return + + # Check if first argument match executable path + # - Few applications are not executed directly but through OpenPype + # process (Photoshop, AfterEffects, Harmony, ...). These should not + # use `open`. + if self.launch_context.launch_args[0] != executable: + return + + # Tell `open` to pass arguments if there are any + if len(self.launch_context.launch_args) > 1: + self.launch_context.launch_args.insert(1, "--args") + # Prepend open arguments + self.launch_context.launch_args.insert(0, ["open", "-a"]) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index a44c43102f..d82b7cd847 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -440,7 +440,20 @@ class EnvironmentTool: class ApplicationExecutable: + """Representation of executable loaded from settings.""" + def __init__(self, executable): + # On MacOS check if exists path to executable when ends with `.app` + # - it is common that path will lead to "/Applications/Blender" but + # real path is "/Applications/Blender.app" + if ( + platform.system().lower() == "darwin" + and not os.path.exists(executable) + ): + _executable = executable + ".app" + if os.path.exists(_executable): + executable = _executable + self.executable_path = executable def __str__(self): @@ -1177,17 +1190,23 @@ def prepare_context_environments(data): try: workdir = get_workdir_with_workdir_data(workdir_data, anatomy) - if not os.path.exists(workdir): - log.debug( - "Creating workdir folder: \"{}\"".format(workdir) - ) - os.makedirs(workdir) except Exception as exc: raise ApplicationLaunchFailed( "Error in anatomy.format: {}".format(str(exc)) ) + if not os.path.exists(workdir): + log.debug( + "Creating workdir folder: \"{}\"".format(workdir) + ) + try: + os.makedirs(workdir) + except Exception as exc: + raise ApplicationLaunchFailed( + "Couldn't create workdir because: {}".format(str(exc)) + ) + context_env = { "AVALON_PROJECT": project_doc["name"], "AVALON_ASSET": asset_doc["name"],