diff --git a/engine.py b/engine.py index d189cd7..bd2bd75 100644 --- a/engine.py +++ b/engine.py @@ -19,7 +19,7 @@ import logging import traceback from functools import wraps -from distutils.version import LooseVersion +from distutils.version import LooseVersion import tank from tank.log import LogManager @@ -36,8 +36,7 @@ # when Substance Painter software version is above the tested one. SHOW_COMP_DLG = "SGTK_COMPATIBILITY_DIALOG_SHOWN" -MINIMUM_SUPPORTED_VERSION = "2018.3" - +MINIMUM_SUPPORTED_VERSION = "2018.3" def to_new_version_system(version): @@ -81,6 +80,7 @@ def display_error(msg): t = time.asctime(time.localtime()) print("%s - Shotgun Error | Substance Painter engine | %s " % (t, msg)) + def display_warning(msg): t = time.asctime(time.localtime()) print("%s - Shotgun Warning | Substance Painter engine | %s " % (t, msg)) @@ -90,6 +90,7 @@ def display_info(msg): t = time.asctime(time.localtime()) print("%s - Shotgun Info | Substance Painter engine | %s " % (t, msg)) + def display_debug(msg): if os.environ.get("TK_DEBUG") == "1": t = time.asctime(time.localtime()) @@ -97,10 +98,11 @@ def display_debug(msg): # methods to support the state when the engine cannot start up -# for example if a non-tank file is loaded in Substance Painter we load the +# for example if a non-tank file is loaded in Substance Painter we load the # project context if exists, so we give a chance to the user to at least # do the basics operations. + def refresh_engine(scene_name, prev_context): """ refresh the current engine @@ -141,14 +143,15 @@ def refresh_engine(scene_name, prev_context): try: # could not detect context from path, will use the project context # for menus if it exists - ctx = engine.sgtk.context_from_entity_dictionary( - engine.context.project) - message = ("Shotgun Substance Painter Engine could not detect " - "the context\n from the project loaded. " - "Shotgun menus will be reset \n" - "to the project '%s' " - "context." - "\n" % engine.context.project.get('name')) + ctx = engine.sgtk.context_from_entity_dictionary(engine.context.project) + message = ( + "Shotgun Substance Painter Engine could not detect " + "the context\n from the project loaded. " + "Shotgun menus will be reset \n" + "to the project '%s' " + "context." + "\n" % engine.context.project.get("name") + ) engine.show_warning(message) except tank.TankError, e: @@ -164,7 +167,7 @@ def refresh_engine(scene_name, prev_context): engine.create_shotgun_menu(disabled=True) engine.show_error(message) return - + if ctx != engine.context: engine.change_context(ctx) @@ -203,9 +206,12 @@ def show_message(self, msg, level="info"): """ if self._qt_app_central_widget: from sgtk.platform.qt5 import QtWidgets, QtGui, QtCore - level_icon = {"info": QtWidgets.QMessageBox.Information, - "error": QtWidgets.QMessageBox.Critical, - "warning": QtWidgets.QMessageBox.Warning} + + level_icon = { + "info": QtWidgets.QMessageBox.Information, + "error": QtWidgets.QMessageBox.Critical, + "warning": QtWidgets.QMessageBox.Warning, + } dlg = QtWidgets.QMessageBox(self._qt_app_central_widget) dlg.setIcon(level_icon[level]) @@ -256,7 +262,9 @@ def __toggle_debug_logging(self): Toggles global debug logging on and off in the log manager. This will affect all logging across all of toolkit. """ - self.logger.debug("calling substance painer with debug: %s" % LogManager().global_debug) + self.logger.debug( + "calling substance painer with debug: %s" % LogManager().global_debug + ) # flip debug logging LogManager().global_debug = not LogManager().global_debug @@ -267,15 +275,13 @@ def __open_log_folder(self): """ Opens the file system folder where log files are being stored. """ - self.log_info("Log folder is located in '%s'" % - LogManager().log_folder) + self.log_info("Log folder is located in '%s'" % LogManager().log_folder) if self.has_ui: # only import QT if we have a UI from sgtk.platform.qt import QtGui, QtCore - url = QtCore.QUrl.fromLocalFile( - LogManager().log_folder - ) + + url = QtCore.QUrl.fromLocalFile(LogManager().log_folder) status = QtGui.QDesktopServices.openUrl(url) if not status: self.log_error("Failed to open folder!") @@ -295,10 +301,11 @@ def __register_open_log_folder_command(self): { "short_name": "open_log_folder", "icon": icon_path, - "description": ("Opens the folder where log files are " - "being stored."), - "type": "context_menu" - } + "description": ( + "Opens the folder where log files are " "being stored." + ), + "type": "context_menu", + }, ) def __register_reload_command(self): @@ -307,12 +314,15 @@ def __register_reload_command(self): running apps are registered via a dev descriptor. """ from tank.platform import restart + self.register_command( "Reload and Restart", restart, - {"short_name": "restart", - "icon": self.__get_platform_resource_path("reload_256.png"), - "type": "context_menu"} + { + "short_name": "restart", + "icon": self.__get_platform_resource_path("reload_256.png"), + "type": "context_menu", + }, ) @property @@ -358,31 +368,33 @@ def process_request(self, method, **kwargs): This method takes care of requests from the dcc app. """ self.logger.info("process_request. method: %s | kwargs: %s" % (method, kwargs)) - + if method == "DISPLAY_MENU": menu_position = None - clicked_info = kwargs.get('clickedPosition') + clicked_info = kwargs.get("clickedPosition") if clicked_info: - menu_position = [clicked_info['x'], clicked_info['y']] + menu_position = [clicked_info["x"], clicked_info["y"]] self.display_menu(pos=menu_position) - + if method == "NEW_PROJECT_CREATED": path = kwargs.get("path") change_context = self.get_setting("change_context_on_new_project", False) if change_context: refresh_engine(path, self.context) else: - self.logger.info("change_context_on_new_project is off so context won't be changed.") - + self.logger.info( + "change_context_on_new_project is off so context won't be changed." + ) + if method == "PROJECT_OPENED": path = kwargs.get("path") refresh_engine(path, self.context) if method == "QUIT": - if self. _qt_app: + if self._qt_app: self.destroy_engine() - self. _qt_app.quit() + self._qt_app.quit() if method in self._event_callbacks: self.logger.info("About to run callbacks for %s" % method) @@ -413,7 +425,7 @@ def pre_app_init(self): self.init_qt_app() - port = os.environ['SGTK_SUBSTANCEPAINTER_ENGINE_PORT'] + port = os.environ["SGTK_SUBSTANCEPAINTER_ENGINE_PORT"] url = "ws://localhost:%s" % port engine_client_class = self.tk_substancepainter.application.EngineClient @@ -422,9 +434,11 @@ def pre_app_init(self): # check that we are running an ok version of Substance Painter current_os = sys.platform if current_os not in ["darwin", "win32", "linux64"]: - raise tank.TankError("The current platform is not supported!" - " Supported platforms " - "are Mac, Linux 64 and Windows 64.") + raise tank.TankError( + "The current platform is not supported!" + " Supported platforms " + "are Mac, Linux 64 and Windows 64." + ) # default menu name is Shotgun but this can be overridden # in the configuration to be sgtk in case of conflicts @@ -432,13 +446,12 @@ def pre_app_init(self): if self.get_setting("use_sgtk_as_menu_name", False): self._menu_name = "Sgtk" - painter_version_str = self._dcc_app.get_application_version() # New version system was introduced in version 2020.1, that became # version 6.1.0, so we need to do some magic to normalize versions. # https://docs.substance3d.com/spdoc/version-2020-1-6-1-0-194216357.html - painter_version = to_new_version_system(painter_version_str) + painter_version = to_new_version_system(painter_version_str) painter_min_supported_version = to_new_version_system(MINIMUM_SUPPORTED_VERSION) if painter_version < painter_min_supported_version: @@ -468,9 +481,7 @@ def pre_app_init(self): # check against the compatibility_dialog_min_version # setting - min_version_str = self.get_setting( - "compatibility_dialog_min_version" - ) + min_version_str = self.get_setting("compatibility_dialog_min_version") min_version = to_new_version_system(min_version_str) if painter_version < min_version: @@ -509,7 +520,8 @@ def create_shotgun_menu(self, disabled=False): if self.has_ui: # create our menu handler self._menu_generator = self.tk_substancepainter.MenuGenerator( - self, self._menu_name) + self, self._menu_name + ) self._qt_app.setActiveWindow(self._menu_generator.menu_handle) self._menu_generator.create_menu(disabled=disabled) @@ -529,7 +541,7 @@ def init_qt_app(self): Initializes if not done already the QT Application for the engine. """ from sgtk.platform.qt5 import QtWidgets, QtGui - + if not QtWidgets.QApplication.instance(): self._qt_app = QtWidgets.QApplication(sys.argv) self._qt_app.setWindowIcon(QtGui.QIcon(self.icon_256)) @@ -538,10 +550,10 @@ def init_qt_app(self): self._qt_app_central_widget = QtWidgets.QWidget() self._qt_app_main_window.setCentralWidget(self._qt_app_central_widget) self._qt_app.setQuitOnLastWindowClosed(False) - + # Make the QApplication use the dark theme. Must be called after the QApplication is instantiated self._initialize_dark_look_and_feel() - + else: self._qt_app = QtWidgets.QApplication.instance() @@ -555,7 +567,7 @@ def post_app_init(self): # Run a series of app instance commands at startup. self._run_app_instance_commands() - + # Create the shotgun menu self.create_shotgun_menu() @@ -606,7 +618,8 @@ def _run_app_instance_commands(self): # Add entry 'command name: command function' to the command # dictionary of this app instance. cmd_dict = app_instance_commands.setdefault( - app_instance.instance_name, {}) + app_instance.instance_name, {} + ) cmd_dict[cmd_name] = value["callback"] # Run the series of app instance commands listed in the @@ -625,13 +638,19 @@ def _run_app_instance_commands(self): self.logger.warning( "%s configuration setting 'run_at_startup' requests app" " '%s' that is not installed.", - self.name, app_instance_name) + self.name, + app_instance_name, + ) else: if not setting_cmd_name: # Run all commands of the given app instance. for (cmd_name, command_function) in cmd_dict.iteritems(): - msg = ("%s startup running app '%s' command '%s'.", - self.name, app_instance_name, cmd_name) + msg = ( + "%s startup running app '%s' command '%s'.", + self.name, + app_instance_name, + cmd_name, + ) self.logger.debug(msg) command_function() @@ -640,20 +659,26 @@ def _run_app_instance_commands(self): # 'run_at_startup' setting. command_function = cmd_dict.get(setting_cmd_name) if command_function: - msg = ("%s startup running app '%s' command '%s'.", - self.name, app_instance_name, setting_cmd_name) + msg = ( + "%s startup running app '%s' command '%s'.", + self.name, + app_instance_name, + setting_cmd_name, + ) self.logger.debug(msg) command_function() else: - known_commands = ', '.join( - "'%s'" % name for name in cmd_dict) + known_commands = ", ".join("'%s'" % name for name in cmd_dict) self.logger.warning( "%s configuration setting 'run_at_startup' " "requests app '%s' unknown command '%s'. " "Known commands: %s", - self.name, app_instance_name, - setting_cmd_name, known_commands) + self.name, + app_instance_name, + setting_cmd_name, + known_commands, + ) def destroy_engine(self): """ @@ -661,7 +686,6 @@ def destroy_engine(self): """ self.logger.debug("%s: Destroying...", self) - def _get_dialog_parent(self): """ Get the QWidget parent for all dialogs created through @@ -669,7 +693,6 @@ def _get_dialog_parent(self): """ return self._qt_app_main_window - @property def has_ui(self): """ @@ -694,8 +717,7 @@ def _emit_log_message(self, handler, record): # where "basename" is the leaf part of the logging record name, # for example "tk-multi-shotgunpanel" or "qt_importer". if record.levelno < logging.INFO: - formatter = logging.Formatter( - "Debug: Shotgun %(basename)s: %(message)s") + formatter = logging.Formatter("Debug: Shotgun %(basename)s: %(message)s") else: formatter = logging.Formatter("Shotgun %(basename)s: %(message)s") @@ -715,7 +737,6 @@ def _emit_log_message(self, handler, record): # Display the message in Substance Painter script editor in a thread safe manner. self.async_execute_in_main_thread(fct, msg) - def close_windows(self): """ Closes the various windows (dialogs, panels, etc.) opened by the @@ -737,5 +758,6 @@ def close_windows(self): dialog.close() except Exception, exception: traceback.print_exc() - self.logger.error("Cannot close dialog %s: %s", - dialog_window_title, exception) + self.logger.error( + "Cannot close dialog %s: %s", dialog_window_title, exception + ) diff --git a/hooks/tk-multi-breakdown/tk-substancepainter_scene_operations.py b/hooks/tk-multi-breakdown/tk-substancepainter_scene_operations.py index 14c2bdb..758af22 100644 --- a/hooks/tk-multi-breakdown/tk-substancepainter_scene_operations.py +++ b/hooks/tk-multi-breakdown/tk-substancepainter_scene_operations.py @@ -142,9 +142,7 @@ def scan_scene(self): { "type": "file", "path": ref_path, - "node": SubstancePainterResource( - res_info, in_use, nice_name - ), + "node": SubstancePainterResource(res_info, in_use, nice_name), } ) diff --git a/hooks/tk-multi-loader2/tk-substancepainter_actions.py b/hooks/tk-multi-loader2/tk-substancepainter_actions.py index fb48185..4553f1a 100644 --- a/hooks/tk-multi-loader2/tk-substancepainter_actions.py +++ b/hooks/tk-multi-loader2/tk-substancepainter_actions.py @@ -115,17 +115,14 @@ def generate_actions(self, sg_publish_data, actions, ui_area): app = self.parent app.log_debug( "Generate actions called for UI element %s. " - "Actions: %s. Publish Data: %s" - % (ui_area, actions, sg_publish_data) + "Actions: %s. Publish Data: %s" % (ui_area, actions, sg_publish_data) ) published_file_type = sg_publish_data["published_file_type"]["name"] app.log_debug("published_file_type: %s" % published_file_type) # check Published File Type Name: - available_actions = publishedfile_type_to_actions.get( - published_file_type - ) + available_actions = publishedfile_type_to_actions.get(published_file_type) action_instances = [] diff --git a/hooks/tk-multi-publish2/basic/collector.py b/hooks/tk-multi-publish2/basic/collector.py index 3346a55..6a6e17c 100644 --- a/hooks/tk-multi-publish2/basic/collector.py +++ b/hooks/tk-multi-publish2/basic/collector.py @@ -99,14 +99,10 @@ def process_current_session(self, settings, parent_item): """ # create an item representing the current substance painter session - item = self.collect_current_substancepainter_session( - settings, parent_item - ) + item = self.collect_current_substancepainter_session(settings, parent_item) if item: - publish_as_folder_setting = settings.get( - "Publish Textures as Folder" - ) + publish_as_folder_setting = settings.get("Publish Textures as Folder") if publish_as_folder_setting and publish_as_folder_setting.value: resource_items = self.collect_textures_as_folder(settings, item) else: @@ -122,16 +118,13 @@ def get_export_path(self, settings): work_template_setting.value ) - self.logger.debug( - "Work template defined for Substance Painter collection." - ) + self.logger.debug("Work template defined for Substance Painter collection.") work_export_template = None work_export_template_setting = settings.get("Work Export Template") if work_export_template_setting: self.logger.debug( - "Work Export template settings: %s" - % work_export_template_setting + "Work Export template settings: %s" % work_export_template_setting ) work_export_template = publisher.engine.get_template_by_name( @@ -163,8 +156,7 @@ def collect_textures_as_folder(self, settings, parent_item): engine.show_busy( "Exporting textures", - "Texture are being exported so they can " - "be published.\n\nPlease wait...", + "Texture are being exported so they can " "be published.\n\nPlease wait...", ) map_export_info = engine.app.export_document_maps(export_path) @@ -202,8 +194,7 @@ def collect_textures(self, settings, parent_item): engine.show_busy( "Exporting textures", - "Texture are being exported so they can " - "be published.\n\nPlease wait...", + "Texture are being exported so they can " "be published.\n\nPlease wait...", ) map_export_info = engine.app.export_document_maps(export_path) @@ -211,9 +202,7 @@ def collect_textures(self, settings, parent_item): self.logger.debug("Collecting exported textures...") - icon_path = os.path.join( - self.disk_location, os.pardir, "icons", "texture.png" - ) + icon_path = os.path.join(self.disk_location, os.pardir, "icons", "texture.png") for texture_set_name, texture_set in map_export_info.iteritems(): for texture_id, texture_file in texture_set.iteritems(): @@ -254,15 +243,11 @@ def collect_current_substancepainter_session(self, settings, parent_item): # create the session item for the publish hierarchy session_item = parent_item.create_item( - "substancepainter.session", - "Substance Painter Session", - display_name, + "substancepainter.session", "Substance Painter Session", display_name, ) # get the icon path to display for this item - icon_path = os.path.join( - self.disk_location, os.pardir, "icons", "session.png" - ) + icon_path = os.path.join(self.disk_location, os.pardir, "icons", "session.png") session_item.set_icon_from_path(icon_path) # if a work template is defined, add it to the item properties so diff --git a/hooks/tk-multi-publish2/basic/publish_session.py b/hooks/tk-multi-publish2/basic/publish_session.py index 23e516f..1eded1f 100644 --- a/hooks/tk-multi-publish2/basic/publish_session.py +++ b/hooks/tk-multi-publish2/basic/publish_session.py @@ -42,9 +42,7 @@ def description(self): contain simple html for formatting. """ - loader_url = ( - "https://support.shotgunsoftware.com/hc/en-us/articles/219033078" - ) + loader_url = "https://support.shotgunsoftware.com/hc/en-us/articles/219033078" return """ Publishes the file to Shotgun. A Publish entry will be @@ -115,9 +113,7 @@ def settings(self): """ # inherit the settings from the base publish plugin - base_settings = ( - super(SubstancePainterSessionPublishPlugin, self).settings or {} - ) + base_settings = super(SubstancePainterSessionPublishPlugin, self).settings or {} # settings specific to this class substancepainter_publish_settings = { @@ -190,8 +186,7 @@ def accept(self, settings, item): ) self.logger.info( - "Substance Painter '%s' plugin accepted the current session." - % (self.name,) + "Substance Painter '%s' plugin accepted the current session." % (self.name,) ) return {"accepted": True, "checked": True} @@ -246,9 +241,7 @@ def validate(self, settings, item): }, ) else: - self.logger.debug( - "Work template configured and matches session file." - ) + self.logger.debug("Work template configured and matches session file.") else: self.logger.debug("No work template configured.") @@ -327,12 +320,10 @@ def publish(self, settings, item): ] = _substancepainter_find_additional_session_dependencies() # let the base class register the publish - super(SubstancePainterSessionPublishPlugin, self).publish( - settings, item - ) - item.properties.sg_publish_path = item.properties.sg_publish_data[ - "path" - ]["local_path"] + super(SubstancePainterSessionPublishPlugin, self).publish(settings, item) + item.properties.sg_publish_path = item.properties.sg_publish_data["path"][ + "local_path" + ] def finalize(self, settings, item): """ @@ -346,9 +337,7 @@ def finalize(self, settings, item): """ # do the base class finalization - super(SubstancePainterSessionPublishPlugin, self).finalize( - settings, item - ) + super(SubstancePainterSessionPublishPlugin, self).finalize(settings, item) # bump the session file to the next version self._save_to_next_version(item.properties["path"], item, _save_session) diff --git a/hooks/tk-multi-publish2/basic/publish_texture.py b/hooks/tk-multi-publish2/basic/publish_texture.py index 14dc24a..0872506 100644 --- a/hooks/tk-multi-publish2/basic/publish_texture.py +++ b/hooks/tk-multi-publish2/basic/publish_texture.py @@ -43,9 +43,7 @@ def description(self): contain simple html for formatting. """ - loader_url = ( - "https://support.shotgunsoftware.com/hc/en-us/articles/219033078" - ) + loader_url = "https://support.shotgunsoftware.com/hc/en-us/articles/219033078" return """ Publishes the file to Shotgun. A Publish entry will be @@ -116,7 +114,9 @@ def settings(self): """ # inherit the settings from the base publish plugin - base_settings = super(SubstancePainterTexturesPublishPlugin, self).settings or {} + base_settings = ( + super(SubstancePainterTexturesPublishPlugin, self).settings or {} + ) # settings specific to this class substancepainter_publish_settings = { @@ -178,8 +178,7 @@ def accept(self, settings, item): item.context_change_allowed = False self.logger.info( - "Substance Painter '%s' plugin accepted to publish textures." - % (self.name,) + "Substance Painter '%s' plugin accepted to publish textures." % (self.name,) ) return {"accepted": True, "checked": True} @@ -199,7 +198,9 @@ def validate(self, settings, item): # populate the publish template on the item if found publish_template_setting = settings.get("Publish Template") - publish_template = publisher.engine.get_template_by_name(publish_template_setting.value) + publish_template = publisher.engine.get_template_by_name( + publish_template_setting.value + ) if publish_template: item.properties["publish_template"] = publish_template else: @@ -209,13 +210,14 @@ def validate(self, settings, item): path = item.properties["path"] if not os.path.isfile(path): - error_msg = "Validation failed. Texture path does not exist on disk. %s" % path + error_msg = ( + "Validation failed. Texture path does not exist on disk. %s" % path + ) self.logger.error(error_msg) raise Exception(error_msg) return True - def publish(self, settings, item): """ Executes the publish logic for the given item and settings. @@ -229,7 +231,7 @@ def publish(self, settings, item): publisher = self.parent publish_template = item.properties["publish_template"] - publish_type = item.properties["publish_type"] + publish_type = item.properties["publish_type"] src = item.properties["path"] _, filename = os.path.split(src) filenamefile, extension = os.path.splitext(filename) @@ -239,14 +241,16 @@ def publish(self, settings, item): ctx_fields = self.parent.context.as_template_fields(publish_template) fields.update(ctx_fields) - context_entity_type = self.parent.context.entity['type'] + context_entity_type = self.parent.context.entity["type"] publish_name = context_entity_type + "_" + filenamefile - existing_publishes = self._find_publishes(self.parent.context, publish_name, publish_type) + existing_publishes = self._find_publishes( + self.parent.context, publish_name, publish_type + ) version = max([p["version_number"] for p in existing_publishes] or [0]) + 1 fields["version"] = version fields["channel"] = filenamefile - fields["extension"] = extension[1:] # no dot + fields["extension"] = extension[1:] # no dot publish_path = publish_template.apply_fields(fields) publish_path = sgtk.util.ShotgunPath.normalize(publish_path) @@ -255,7 +259,7 @@ def publish(self, settings, item): # make sure destination folder exists ensure_folder_exists(publish_dir) - sgtk.util.filesystem.copy_file(src, publish_path) + sgtk.util.filesystem.copy_file(src, publish_path) self.logger.info("A Publish will be created in Shotgun and linked to:") self.logger.info(" %s" % (publish_path,)) @@ -265,13 +269,15 @@ def publish(self, settings, item): # add dependencies dependency_paths = [] if "sg_publish_path" in item.parent.properties: - self.logger.debug("Added dependency: %s" % item.parent.properties.sg_publish_path) + self.logger.debug( + "Added dependency: %s" % item.parent.properties.sg_publish_path + ) dependency_paths.append(item.parent.properties.sg_publish_path) self.logger.info("Registering publish...") publish_data = { - "tk": publisher.sgtk, + "tk": publisher.sgtk, "context": item.context, "comment": item.description, "path": publish_path, @@ -289,15 +295,14 @@ def publish(self, settings, item): "action_show_more_info": { "label": "Publish Data", "tooltip": "Show the complete Publish data dictionary", - "text": "
%s
" % (pprint.pformat(publish_data),) + "text": "
%s
" % (pprint.pformat(publish_data),), } - } + }, ) # create the publish and stash it in the item properties for other # plugins to use. - item.properties["sg_publish_data"] = sgtk.util.register_publish( - **publish_data) + item.properties["sg_publish_data"] = sgtk.util.register_publish(**publish_data) # inject the publish path such that children can refer to it when # updating dependency information @@ -308,7 +313,6 @@ def publish(self, settings, item): # now that we've published. keep a handle on the path that was published item.properties["path"] = publish_path - def finalize(self, settings, item): """ Execute the finalization pass. This pass executes once all the publish @@ -340,28 +344,32 @@ def _find_publishes(self, ctx, publish_name, publish_type): publish_type_field = "published_file_type.PublishedFileType.code" else: publish_type_field = "tank_type.TankType.code" - + # construct filters from the context: filters = [["project", "is", ctx.project]] if ctx.entity: filters.append(["entity", "is", ctx.entity]) if ctx.task: filters.append(["task", "is", ctx.task]) - + # add in name & type: if publish_name: filters.append(["name", "is", publish_name]) if publish_type: filters.append([publish_type_field, "is", publish_type]) - + # retrieve a list of all matching publishes from Shotgun: sg_publishes = [] try: query_fields = ["version_number"] - sg_publishes = self.parent.shotgun.find(publish_entity_type, filters, query_fields) + sg_publishes = self.parent.shotgun.find( + publish_entity_type, filters, query_fields + ) except Exception, e: - self.logger.error("Failed to find publishes of type '%s', called '%s', for context %s: %s" - % (publish_name, publish_type, ctx, e)) + self.logger.error( + "Failed to find publishes of type '%s', called '%s', for context %s: %s" + % (publish_name, publish_type, ctx, e) + ) return sg_publishes @@ -379,4 +387,3 @@ def _export_path(): path = path.encode("utf-8") return path - diff --git a/hooks/tk-multi-publish2/basic/publish_textures.py b/hooks/tk-multi-publish2/basic/publish_textures.py index c8cfeee..532656a 100644 --- a/hooks/tk-multi-publish2/basic/publish_textures.py +++ b/hooks/tk-multi-publish2/basic/publish_textures.py @@ -43,9 +43,7 @@ def description(self): contain simple html for formatting. """ - loader_url = ( - "https://support.shotgunsoftware.com/hc/en-us/articles/219033078" - ) + loader_url = "https://support.shotgunsoftware.com/hc/en-us/articles/219033078" return """ Publishes the file to Shotgun. A Publish entry will be @@ -116,7 +114,9 @@ def settings(self): """ # inherit the settings from the base publish plugin - base_settings = super(SubstancePainterTexturesPublishPlugin, self).settings or {} + base_settings = ( + super(SubstancePainterTexturesPublishPlugin, self).settings or {} + ) # settings specific to this class substancepainter_publish_settings = { @@ -199,7 +199,9 @@ def validate(self, settings, item): # populate the publish template on the item if found publish_template_setting = settings.get("Publish Template") - publish_template = publisher.engine.get_template_by_name(publish_template_setting.value) + publish_template = publisher.engine.get_template_by_name( + publish_template_setting.value + ) if publish_template: item.properties["publish_template"] = publish_template else: @@ -229,7 +231,6 @@ def validate(self, settings, item): return True - def publish(self, settings, item): """ Executes the publish logic for the given item and settings. @@ -243,17 +244,19 @@ def publish(self, settings, item): publisher = self.parent publish_template = item.properties["publish_template"] - publish_type = item.properties["publish_type"] + publish_type = item.properties["publish_type"] # Get fields from the current context fields = {} ctx_fields = self.parent.context.as_template_fields(publish_template) fields.update(ctx_fields) - context_entity_type = self.parent.context.entity['type'] + context_entity_type = self.parent.context.entity["type"] publish_name = context_entity_type + "_textures" - existing_publishes = self._find_publishes(self.parent.context, publish_name, publish_type) + existing_publishes = self._find_publishes( + self.parent.context, publish_name, publish_type + ) version = max([p["version_number"] for p in existing_publishes] or [0]) + 1 fields["version"] = version @@ -268,7 +271,7 @@ def publish(self, settings, item): for src in textures: _, filenamefile = os.path.split(src) dst = os.path.join(publish_path, filenamefile) - sgtk.util.filesystem.copy_file(src, dst) + sgtk.util.filesystem.copy_file(src, dst) self.logger.info("A Publish will be created in Shotgun and linked to:") self.logger.info(" %s" % (publish_path,)) @@ -278,7 +281,9 @@ def publish(self, settings, item): # add dependencies dependency_paths = [] if "sg_publish_path" in item.parent.properties: - self.logger.debug("Added dependency: %s" % item.parent.properties.sg_publish_path) + self.logger.debug( + "Added dependency: %s" % item.parent.properties.sg_publish_path + ) dependency_paths.append(item.parent.properties.sg_publish_path) self.logger.info("Registering publish...") @@ -302,15 +307,14 @@ def publish(self, settings, item): "action_show_more_info": { "label": "Publish Data", "tooltip": "Show the complete Publish data dictionary", - "text": "
%s
" % (pprint.pformat(publish_data),) + "text": "
%s
" % (pprint.pformat(publish_data),), } - } + }, ) # create the publish and stash it in the item properties for other # plugins to use. - item.properties["sg_publish_data"] = sgtk.util.register_publish( - **publish_data) + item.properties["sg_publish_data"] = sgtk.util.register_publish(**publish_data) # inject the publish path such that children can refer to it when # updating dependency information @@ -321,7 +325,6 @@ def publish(self, settings, item): # now that we've published. keep a handle on the path that was published item.properties["path"] = publish_path - def finalize(self, settings, item): """ Execute the finalization pass. This pass executes once all the publish @@ -353,28 +356,32 @@ def _find_publishes(self, ctx, publish_name, publish_type): publish_type_field = "published_file_type.PublishedFileType.code" else: publish_type_field = "tank_type.TankType.code" - + # construct filters from the context: filters = [["project", "is", ctx.project]] if ctx.entity: filters.append(["entity", "is", ctx.entity]) if ctx.task: filters.append(["task", "is", ctx.task]) - + # add in name & type: if publish_name: filters.append(["name", "is", publish_name]) if publish_type: filters.append([publish_type_field, "is", publish_type]) - + # retrieve a list of all matching publishes from Shotgun: sg_publishes = [] try: query_fields = ["version_number"] - sg_publishes = self.parent.shotgun.find(publish_entity_type, filters, query_fields) + sg_publishes = self.parent.shotgun.find( + publish_entity_type, filters, query_fields + ) except Exception, e: - self.logger.error("Failed to find publishes of type '%s', called '%s', for context %s: %s" - % (publish_name, publish_type, ctx, e)) + self.logger.error( + "Failed to find publishes of type '%s', called '%s', for context %s: %s" + % (publish_name, publish_type, ctx, e) + ) return sg_publishes diff --git a/hooks/tk-multi-publish2/basic/start_version_control.py b/hooks/tk-multi-publish2/basic/start_version_control.py index e8bf708..7155988 100644 --- a/hooks/tk-multi-publish2/basic/start_version_control.py +++ b/hooks/tk-multi-publish2/basic/start_version_control.py @@ -34,9 +34,7 @@ def icon(self): """ # look for icon one level up from this hook's folder in "icons" folder - return os.path.join( - self.disk_location, os.pardir, "icons", "version_up.png" - ) + return os.path.join(self.disk_location, os.pardir, "icons", "version_up.png") @property def name(self): @@ -134,9 +132,7 @@ def accept(self, settings, item): "Substance Painter '%s' plugin rejected the current session..." % (self.name,) ) - self.logger.info( - " There is already a version number in the file..." - ) + self.logger.info(" There is already a version number in the file...") self.logger.info(" Substance Painter file path: %s" % (path,)) return {"accepted": False} else: @@ -263,23 +259,17 @@ def _get_version_number(self, path, item): work_template = item.properties.get("work_template") if work_template: if work_template.validate(path): - self.logger.debug( - "Using work template to determine version number." - ) + self.logger.debug("Using work template to determine version number.") work_fields = work_template.get_fields(path) if "version" in work_fields: version_number = work_fields.get("version") else: self.logger.debug("Work template did not match path") else: - self.logger.debug( - "Work template unavailable for version extraction." - ) + self.logger.debug("Work template unavailable for version extraction.") if version_number is None: - self.logger.debug( - "Using path info hook to determine version number." - ) + self.logger.debug("Using path info hook to determine version number.") version_number = publisher.util.get_version_number(path) return version_number diff --git a/python/tk_substancepainter/application.py b/python/tk_substancepainter/application.py index 4e88c90..fdb941f 100644 --- a/python/tk_substancepainter/application.py +++ b/python/tk_substancepainter/application.py @@ -65,9 +65,7 @@ def send_and_receive(self, command, **kwargs): # self.log_debug("send_and_receive: message %s" % command) # exit the loop if timeout happens - timeout_timer = QtCore.QTimer( - parent=QtCore.QCoreApplication.instance() - ) + timeout_timer = QtCore.QTimer(parent=QtCore.QCoreApplication.instance()) loop = QtCore.QEventLoop() @@ -79,9 +77,7 @@ def await_for_response(result): loop.quit() # self.log_debug("in the loop...") - self.send_text_message( - command, callback=await_for_response, **kwargs - ) + self.send_text_message(command, callback=await_for_response, **kwargs) timeout_timer.timeout.connect(loop.quit) timeout_timer.start(5 * 1000.0) @@ -155,9 +151,7 @@ def on_text_message_received(self, message): self.callbacks[message_id](result) del self.callbacks[message_id] - def send_text_message( - self, command, message_id=None, callback=None, **kwargs - ): + def send_text_message(self, command, message_id=None, callback=None, **kwargs): if self.client.state() in ( QAbstractSocket.SocketState.ClosingState, QAbstractSocket.SocketState.UnconnectedState, @@ -168,9 +162,7 @@ def send_text_message( return # wait until connected - while ( - self.client.state() == QAbstractSocket.SocketState.ConnectingState - ): + while self.client.state() == QAbstractSocket.SocketState.ConnectingState: QCoreApplication.processEvents() # self.log_debug("client: waiting state: %s" % self.client.state()) time.sleep(self.wait_period) @@ -183,12 +175,7 @@ def send_text_message( self.callbacks[message_id] = callback message = json.dumps( - { - "jsonrpc": "2.0", - "method": command, - "params": kwargs, - "id": message_id, - } + {"jsonrpc": "2.0", "method": command, "params": kwargs, "id": message_id,} ) # self.log_debug("client: send_message: %s" % message) @@ -251,9 +238,7 @@ def broadcast_event(self, event_name): self.send_text_message(event_name) def execute(self, statement_str): - result = self.send_and_receive( - "EXECUTE_STATEMENT", statement=statement_str - ) + result = self.send_and_receive("EXECUTE_STATEMENT", statement=statement_str) return result def extract_thumbnail(self, filename): @@ -298,9 +283,7 @@ def run_once_finished_exporting_maps(**kwargs): ) self.log_debug("Starting map export...") - result = self.send_and_receive( - "EXPORT_DOCUMENT_MAPS", destination=destination - ) + result = self.send_and_receive("EXPORT_DOCUMENT_MAPS", destination=destination) while self.__export_results is None: self.log_debug("Waiting for maps to be exported ...") diff --git a/python/tk_substancepainter/menu_generation.py b/python/tk_substancepainter/menu_generation.py index 5409e1d..e438910 100644 --- a/python/tk_substancepainter/menu_generation.py +++ b/python/tk_substancepainter/menu_generation.py @@ -1,11 +1,11 @@ # Copyright (c) 2013 Shotgun Software Inc. -# +# # CONFIDENTIAL AND PROPRIETARY -# -# This work is provided "AS IS" and subject to the Shotgun Pipeline Toolkit +# +# This work is provided "AS IS" and subject to the Shotgun Pipeline Toolkit # Source Code License included in this distribution package. See LICENSE. -# By accessing, using, copying or modifying this work you indicate your -# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights +# By accessing, using, copying or modifying this work you indicate your +# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights # not expressly granted therein are reserved by Shotgun Software Inc. """ @@ -25,6 +25,7 @@ from tank.platform.qt5 import QtWidgets, QtGui, QtCore, QtWebSockets, QtNetwork + class MenuGenerator(object): """ Menu generation functionality. @@ -34,7 +35,7 @@ def __init__(self, engine, menu_name): self._engine = engine self._menu_name = menu_name self._dialogs = [] - + self._widget = QtWidgets.QWidget() self._handle = QtWidgets.QMenu(self._menu_name, self._widget) self._ui_cache = [] @@ -47,15 +48,14 @@ def hide(self): self.menu_handle.hide() def show(self, pos=None): - pos = QtGui.QCursor.pos() if pos is None else QtCore.QPoint(pos[0], - pos[1]) + pos = QtGui.QCursor.pos() if pos is None else QtCore.QPoint(pos[0], pos[1]) qApp = QtWidgets.QApplication.instance() - #qApp.setWindowState(QtCore.Qt.WindowActive) + # qApp.setWindowState(QtCore.Qt.WindowActive) self.menu_handle.activateWindow() self.menu_handle.raise_() self.menu_handle.exec_(pos) - + def create_menu(self, disabled=False): """ Render the entire Shotgun menu. @@ -90,8 +90,10 @@ def create_menu(self, disabled=False): # scan through all menu items for cmd in menu_items: - if (cmd.get_app_instance_name() == app_instance_name and - cmd.name == menu_name): + if ( + cmd.get_app_instance_name() == app_instance_name + and cmd.name == menu_name + ): # found our match! cmd.add_command_to_menu(self.menu_handle) # mark as a favourite item @@ -171,8 +173,7 @@ def _add_context_menu(self): # Add the menu item only when there are some file system locations. if ctx.filesystem_locations: - self._add_menu_item("Jump to File System", - ctx_menu, self._jump_to_fs) + self._add_menu_item("Jump to File System", ctx_menu, self._jump_to_fs) # divider (apps may register entries below this divider) self._add_divider(ctx_menu) @@ -286,8 +287,9 @@ def get_documentation_url_str(self): doc_url = app.documentation_url # deal with nuke's inability to handle unicode. #fail if doc_url.__class__ == unicode: - doc_url = unicodedata.normalize( - 'NFKD', doc_url).encode('ascii', 'ignore') + doc_url = unicodedata.normalize("NFKD", doc_url).encode( + "ascii", "ignore" + ) return doc_url return None @@ -315,12 +317,12 @@ def add_command_to_menu(self, menu): # already have sub menu parent_menu = sub_menu else: - parent_menu = self.parent._add_sub_menu( - item_label, parent_menu) + parent_menu = self.parent._add_sub_menu(item_label, parent_menu) # self._execute_deferred) - self.parent._add_menu_item(parts[-1], parent_menu, - self.callback, self.properties) + self.parent._add_menu_item( + parts[-1], parent_menu, self.callback, self.properties + ) def _find_sub_menu_item(self, menu, label): """ diff --git a/startup/bootstrap.py b/startup/bootstrap.py index 80f06ca..b05592a 100644 --- a/startup/bootstrap.py +++ b/startup/bootstrap.py @@ -44,6 +44,7 @@ def start_toolkit_classic(): the tk-substancepainter engine and environment. """ import sgtk + logger = sgtk.LogManager.get_logger(__name__) logger.debug("Launching toolkit in classic mode.") @@ -65,24 +66,27 @@ def start_toolkit_classic(): # Deserialize the environment context context = sgtk.context.deserialize(env_context) except Exception, e: - msg = ("Shotgun: Could not create context! Shotgun Pipeline Toolkit" - " will be disabled. Details: %s" % e) + msg = ( + "Shotgun: Could not create context! Shotgun Pipeline Toolkit" + " will be disabled. Details: %s" % e + ) etype, value, tb = sys.exc_info() - msg += ''.join(traceback.format_exception(etype, value, tb)) + msg += "".join(traceback.format_exception(etype, value, tb)) display_error(logger, msg) return try: # Start up the toolkit engine from the environment data - logger.debug("Launching engine instance '%s' for context %s" % - (env_engine, env_context)) + logger.debug( + "Launching engine instance '%s' for context %s" % (env_engine, env_context) + ) engine = sgtk.platform.start_engine(env_engine, context.sgtk, context) logger.debug("Current engine '%s'" % sgtk.platform.current_engine()) except Exception, e: msg = "Shotgun: Could not start engine. Details: %s" % e etype, value, tb = sys.exc_info() - msg += ''.join(traceback.format_exception(etype, value, tb)) + msg += "".join(traceback.format_exception(etype, value, tb)) display_error(logger, msg) return @@ -111,12 +115,14 @@ def start_toolkit(): file_to_open = os.environ.get("SGTK_FILE_TO_OPEN") if file_to_open: msg = "Shotgun: Opening '%s'..." % file_to_open - # TODO load a project if specified + # TODO load a project if specified # .App.loadProject(file_to_open) # Clean up temp env variables. del_vars = [ - "SGTK_ENGINE", "SGTK_CONTEXT", "SGTK_FILE_TO_OPEN", + "SGTK_ENGINE", + "SGTK_CONTEXT", + "SGTK_FILE_TO_OPEN", ] for var in del_vars: if var in os.environ: @@ -124,9 +130,14 @@ def start_toolkit(): def setup_environment(): - SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH = os.environ['SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH'] + SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH = os.environ[ + "SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH" + ] - if SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH and SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH not in sys.path: + if ( + SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH + and SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH not in sys.path + ): sys.path.insert(0, SGTK_SUBSTANCEPAINTER_SGTK_MODULE_PATH)