import os import sys import re import json import contextlib import traceback import logging from functools import partial from qtpy import QtWidgets from openpype.pipeline import install_host from openpype.modules import ModulesManager from openpype.tools.utils import host_tools from openpype.tests.lib import is_in_tests from .launch_logic import ProcessLauncher, get_stub log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) def safe_excepthook(*args): traceback.print_exception(*args) def main(*subprocess_args): sys.excepthook = safe_excepthook from openpype.hosts.aftereffects.api import AfterEffectsHost host = AfterEffectsHost() install_host(host) os.environ["OPENPYPE_LOG_NO_COLORS"] = "False" app = QtWidgets.QApplication([]) app.setQuitOnLastWindowClosed(False) launcher = ProcessLauncher(subprocess_args) launcher.start() if os.environ.get("HEADLESS_PUBLISH"): manager = ModulesManager() webpublisher_addon = manager["webpublisher"] launcher.execute_in_main_thread( partial( webpublisher_addon.headless_publish, log, "CloseAE", is_in_tests() ) ) elif os.environ.get("AVALON_PHOTOSHOP_WORKFILES_ON_LAUNCH", True): save = False if os.getenv("WORKFILES_SAVE_AS"): save = True launcher.execute_in_main_thread( lambda: host_tools.show_tool_by_name("workfiles", save=save) ) sys.exit(app.exec_()) @contextlib.contextmanager def maintained_selection(): """Maintain selection during context.""" selection = get_stub().get_selected_items(True, False, False) try: yield selection finally: pass def get_extension_manifest_path(): return os.path.join( os.path.dirname(os.path.abspath(__file__)), "extension", "CSXS", "manifest.xml" ) def get_unique_layer_name(layers, name): """ Gets all layer names and if 'name' is present in them, increases suffix by 1 (eg. creates unique layer name - for Loader) Args: layers (list): of strings, names only name (string): checked value Returns: (string): name_00X (without version) """ names = {} for layer in layers: layer_name = re.sub(r'_\d{3}$', '', layer) if layer_name in names.keys(): names[layer_name] = names[layer_name] + 1 else: names[layer_name] = 1 occurrences = names.get(name, 0) return "{}_{:0>3d}".format(name, occurrences + 1) def get_background_layers(file_url): """ Pulls file name from background json file, enrich with folder url for AE to be able import files. Order is important, follows order in json. Args: file_url (str): abs url of background json Returns: (list): of abs paths to images """ with open(file_url) as json_file: data = json.load(json_file) layers = list() bg_folder = os.path.dirname(file_url) for child in data['children']: if child.get("filename"): layers.append(os.path.join(bg_folder, child.get("filename")). replace("\\", "/")) else: for layer in child['children']: if layer.get("filename"): layers.append(os.path.join(bg_folder, layer.get("filename")). replace("\\", "/")) return layers def get_asset_settings(asset_doc): """Get settings on current asset from database. Returns: dict: Scene data. """ asset_data = asset_doc["data"] fps = asset_data.get("fps") frame_start = asset_data.get("frameStart") frame_end = asset_data.get("frameEnd") handle_start = asset_data.get("handleStart") handle_end = asset_data.get("handleEnd") resolution_width = asset_data.get("resolutionWidth") resolution_height = asset_data.get("resolutionHeight") duration = (frame_end - frame_start + 1) + handle_start + handle_end return { "fps": fps, "frameStart": frame_start, "frameEnd": frame_end, "handleStart": handle_start, "handleEnd": handle_end, "resolutionWidth": resolution_width, "resolutionHeight": resolution_height, "duration": duration }