diff --git a/openpype/hosts/blender/api/ops.py b/openpype/hosts/blender/api/ops.py index a73ef0133a..3069c3e1c9 100644 --- a/openpype/hosts/blender/api/ops.py +++ b/openpype/hosts/blender/api/ops.py @@ -306,6 +306,17 @@ class LaunchManager(LaunchQtApp): self._window.refresh() +class LaunchLibrary(LaunchQtApp): + """Launch Library Loader.""" + + bl_idname = "wm.library_loader" + bl_label = "Library..." + _tool_name = "libraryloader" + + def before_window_show(self): + self._window.refresh() + + class LaunchWorkFiles(LaunchQtApp): """Launch Avalon Work Files.""" @@ -365,6 +376,7 @@ class TOPBAR_MT_avalon(bpy.types.Menu): icon_value=pyblish_menu_icon_id, ) layout.operator(LaunchManager.bl_idname, text="Manage...") + layout.operator(LaunchLibrary.bl_idname, text="Library...") layout.separator() layout.operator(LaunchWorkFiles.bl_idname, text="Work Files...") # TODO (jasper): maybe add 'Reload Pipeline', 'Reset Frame Range' and @@ -382,6 +394,7 @@ classes = [ LaunchLoader, LaunchPublisher, LaunchManager, + LaunchLibrary, LaunchWorkFiles, TOPBAR_MT_avalon, ] diff --git a/openpype/hosts/flame/api/menu.py b/openpype/hosts/flame/api/menu.py index 8b4bfd4550..7f1a6a24e2 100644 --- a/openpype/hosts/flame/api/menu.py +++ b/openpype/hosts/flame/api/menu.py @@ -110,19 +110,19 @@ class FlameMenuProjectConnect(_FlameMenuApp): menu = deepcopy(self.menu) menu['actions'].append({ - "name": "Workfiles ...", + "name": "Workfiles...", "execute": lambda x: self.tools_helper.show_workfiles() }) menu['actions'].append({ - "name": "Load ...", + "name": "Load...", "execute": lambda x: self.tools_helper.show_loader() }) menu['actions'].append({ - "name": "Manage ...", + "name": "Manage...", "execute": lambda x: self.tools_helper.show_scene_inventory() }) menu['actions'].append({ - "name": "Library ...", + "name": "Library...", "execute": lambda x: self.tools_helper.show_library_loader() }) return menu @@ -164,24 +164,27 @@ class FlameMenuTimeline(_FlameMenuApp): menu = deepcopy(self.menu) menu['actions'].append({ - "name": "Create ...", + "name": "Create...", "execute": lambda x: callback_selection( x, self.tools_helper.show_creator) }) menu['actions'].append({ - "name": "Publish ...", + "name": "Publish...", "execute": lambda x: callback_selection( x, self.tools_helper.show_publish) }) menu['actions'].append({ - "name": "Load ...", + "name": "Load...", "execute": lambda x: self.tools_helper.show_loader() }) menu['actions'].append({ - "name": "Manage ...", + "name": "Manage...", "execute": lambda x: self.tools_helper.show_scene_inventory() }) - + menu['actions'].append({ + "name": "Library...", + "execute": lambda x: self.tools_helper.show_library_loader() + }) return menu def refresh(self, *args, **kwargs): diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 5d2efb4911..d1c01163b1 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -54,13 +54,13 @@ class OpenPypeMenu(QtWidgets.QWidget): ) self.render_mode_widget = None self.setWindowTitle("OpenPype") - workfiles_btn = QtWidgets.QPushButton("Workfiles ...", self) - create_btn = QtWidgets.QPushButton("Create ...", self) - publish_btn = QtWidgets.QPushButton("Publish ...", self) - load_btn = QtWidgets.QPushButton("Load ...", self) - inventory_btn = QtWidgets.QPushButton("Inventory ...", self) - libload_btn = QtWidgets.QPushButton("Library ...", self) - rendermode_btn = QtWidgets.QPushButton("Set render mode ...", self) + workfiles_btn = QtWidgets.QPushButton("Workfiles...", self) + create_btn = QtWidgets.QPushButton("Create...", self) + publish_btn = QtWidgets.QPushButton("Publish...", self) + load_btn = QtWidgets.QPushButton("Load...", self) + inventory_btn = QtWidgets.QPushButton("Inventory...", self) + libload_btn = QtWidgets.QPushButton("Library...", self) + rendermode_btn = QtWidgets.QPushButton("Set render mode...", self) duplicate_with_inputs_btn = QtWidgets.QPushButton( "Duplicate with input connections", self ) diff --git a/openpype/hosts/hiero/api/menu.py b/openpype/hosts/hiero/api/menu.py index 5aaab7a2e5..306bef87ca 100644 --- a/openpype/hosts/hiero/api/menu.py +++ b/openpype/hosts/hiero/api/menu.py @@ -72,7 +72,7 @@ def menu_install(): menu.addSeparator() - workfiles_action = menu.addAction("Work Files ...") + workfiles_action = menu.addAction("Work Files...") workfiles_action.setIcon(QtGui.QIcon("icons:Position.png")) workfiles_action.triggered.connect(launch_workfiles_app) @@ -82,30 +82,36 @@ def menu_install(): menu.addSeparator() - publish_action = menu.addAction("Publish ...") + publish_action = menu.addAction("Publish...") publish_action.setIcon(QtGui.QIcon("icons:Output.png")) publish_action.triggered.connect( lambda *args: publish(hiero.ui.mainWindow()) ) - creator_action = menu.addAction("Create ...") + creator_action = menu.addAction("Create...") creator_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png")) creator_action.triggered.connect( lambda: host_tools.show_creator(parent=main_window) ) - loader_action = menu.addAction("Load ...") + loader_action = menu.addAction("Load...") loader_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png")) loader_action.triggered.connect( lambda: host_tools.show_loader(parent=main_window) ) - sceneinventory_action = menu.addAction("Manage ...") + sceneinventory_action = menu.addAction("Manage...") sceneinventory_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png")) sceneinventory_action.triggered.connect( lambda: host_tools.show_scene_inventory(parent=main_window) ) + library_action = menu.addAction("Library...") + library_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png")) + library_action.triggered.connect( + lambda: host_tools.show_library_loader(parent=main_window) + ) + if os.getenv("OPENPYPE_DEVELOP"): menu.addSeparator() reload_action = menu.addAction("Reload pipeline") diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml index bc4a2e809a..b8c7f93d76 100644 --- a/openpype/hosts/houdini/startup/MainMenuCommon.xml +++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml @@ -5,7 +5,7 @@ - + - + + + + + + - + - - + + +host_tools.show_library_loader(parent=parent) +]]> - + +]]> @@ -63,7 +73,8 @@ host_tools.show_workfiles(parent) import hou from openpype.tools.utils import host_tools parent = hou.qt.mainWindow() -host_tools.show_experimental_tools_dialog(parent)]]> +host_tools.show_experimental_tools_dialog(parent) +]]> diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index c47187666b..fbbc39f98f 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -183,7 +183,12 @@ def _install_menu(): "Manage...", lambda: host_tools.show_scene_inventory(parent=main_window) ) - + menu.addCommand( + "Library...", + lambda: host_tools.show_library_loader( + parent=main_window + ) + ) menu.addSeparator() menu.addCommand( "Set Resolution", diff --git a/openpype/hosts/nuke/plugins/create/create_write_prerender.py b/openpype/hosts/nuke/plugins/create/create_write_prerender.py index 3285e5f92d..761439fdb2 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_prerender.py +++ b/openpype/hosts/nuke/plugins/create/create_write_prerender.py @@ -98,13 +98,13 @@ class CreateWritePrerender(plugin.OpenPypeCreator): "/{subset}.{frame}.{ext}")}) self.log.info("write_data: {}".format(write_data)) - + reviewable = self.presets.get("reviewable") write_node = create_write_node( self.data["subset"], write_data, input=selected_node, prenodes=[], - review=False, + review=reviewable, linked_knobs=["channels", "___", "first", "last", "use_limit"]) # relinking to collected connections diff --git a/openpype/hosts/resolve/api/menu.py b/openpype/hosts/resolve/api/menu.py index 0d5930d275..9e0dd12376 100644 --- a/openpype/hosts/resolve/api/menu.py +++ b/openpype/hosts/resolve/api/menu.py @@ -54,15 +54,15 @@ class OpenPypeMenu(QtWidgets.QWidget): ) self.setWindowTitle("OpenPype") - workfiles_btn = QtWidgets.QPushButton("Workfiles ...", self) - create_btn = QtWidgets.QPushButton("Create ...", self) - publish_btn = QtWidgets.QPushButton("Publish ...", self) - load_btn = QtWidgets.QPushButton("Load ...", self) - inventory_btn = QtWidgets.QPushButton("Inventory ...", self) - subsetm_btn = QtWidgets.QPushButton("Subset Manager ...", self) - libload_btn = QtWidgets.QPushButton("Library ...", self) + workfiles_btn = QtWidgets.QPushButton("Workfiles...", self) + create_btn = QtWidgets.QPushButton("Create...", self) + publish_btn = QtWidgets.QPushButton("Publish...", self) + load_btn = QtWidgets.QPushButton("Load...", self) + inventory_btn = QtWidgets.QPushButton("Inventory...", self) + subsetm_btn = QtWidgets.QPushButton("Subset Manager...", self) + libload_btn = QtWidgets.QPushButton("Library...", self) experimental_btn = QtWidgets.QPushButton( - "Experimental tools ...", self + "Experimental tools...", self ) # rename_btn = QtWidgets.QPushButton("Rename", self) # set_colorspace_btn = QtWidgets.QPushButton( diff --git a/openpype/hosts/tvpaint/api/communication_server.py b/openpype/hosts/tvpaint/api/communication_server.py index c8d6d3b458..e9c5f4c73e 100644 --- a/openpype/hosts/tvpaint/api/communication_server.py +++ b/openpype/hosts/tvpaint/api/communication_server.py @@ -586,7 +586,10 @@ class BaseCommunicator: "additional_libraries" ) additional_libs_folder = additional_libs_folder.replace("\\", "/") - if additional_libs_folder not in os.environ["PATH"]: + if ( + os.path.exists(additional_libs_folder) + and additional_libs_folder not in os.environ["PATH"] + ): os.environ["PATH"] += (os.pathsep + additional_libs_folder) # Path to TVPaint's plugins folder (where we want to add our plugin) diff --git a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_code/CMakeLists.txt b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_code/CMakeLists.txt index ecd94acc99..c221eb0431 100644 --- a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_code/CMakeLists.txt +++ b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_code/CMakeLists.txt @@ -10,31 +10,42 @@ set(IP_ENABLE_DOCTEST OFF) if(MSVC) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) add_definitions(-D_CRT_SECURE_NO_WARNINGS) + # Define WIN64 or WIN32 for TVPaint SDK + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message("64bit") + add_definitions(-DWIN64) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + message("32bit") + add_definitions(-DWIN32) + endif() endif() # TODO better options option(BOOST_ROOT "Path to root of Boost" "") -option(OPENSSL_INCLUDE "OpenSSL include path" "") +option(OPENSSL_INCLUDE "OpenSSL include path" "") option(OPENSSL_LIB_DIR "OpenSSL lib path" "") option(WEBSOCKETPP_INCLUDE "Websocketpp include path" "") -option(WEBSOCKETPP_LIB_DIR "Websocketpp lib path" "") option(JSONRPCPP_INCLUDE "Jsonrpcpp include path" "") -find_package(Boost 1.72.0 COMPONENTS random) +# Use static boost libraries +set(Boost_USE_STATIC_LIBS ON) + +find_package(Boost COMPONENTS random chrono date_time regex REQUIRED) include_directories( "${TVPAINT_SDK_INCLUDE}" "${OPENSSL_INCLUDE}" "${WEBSOCKETPP_INCLUDE}" "${JSONRPCPP_INCLUDE}" - "${Boost_INCLUDE_DIR}" + "${Boost_INCLUDE_DIRS}" ) + link_directories( "${OPENSSL_LIB_DIR}" - "${WEBSOCKETPP_LIB_DIR}" + "${Boost_LIBRARY_DIRS}" ) add_library(jsonrpcpp INTERFACE) diff --git a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x64/additional_libraries/boost_random-vc142-mt-x64-1_72.dll b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x64/additional_libraries/boost_random-vc142-mt-x64-1_72.dll deleted file mode 100644 index 46bd533b72..0000000000 Binary files a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x64/additional_libraries/boost_random-vc142-mt-x64-1_72.dll and /dev/null differ diff --git a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x64/plugin/OpenPypePlugin.dll b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x64/plugin/OpenPypePlugin.dll index 293a7b19b0..f7f5119ef3 100644 Binary files a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x64/plugin/OpenPypePlugin.dll and b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x64/plugin/OpenPypePlugin.dll differ diff --git a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x86/additional_libraries/boost_random-vc142-mt-x32-1_72.dll b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x86/additional_libraries/boost_random-vc142-mt-x32-1_72.dll deleted file mode 100644 index ccf2fd8562..0000000000 Binary files a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x86/additional_libraries/boost_random-vc142-mt-x32-1_72.dll and /dev/null differ diff --git a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x86/plugin/OpenPypePlugin.dll b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x86/plugin/OpenPypePlugin.dll index 9671d8a27b..f35e3ffe86 100644 Binary files a/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x86/plugin/OpenPypePlugin.dll and b/openpype/hosts/tvpaint/tvpaint_plugin/plugin_files/windows_x86/plugin/OpenPypePlugin.dll differ diff --git a/openpype/modules/default_modules/ftrack/plugins/publish/integrate_ftrack_instances.py b/openpype/modules/default_modules/ftrack/plugins/publish/integrate_ftrack_instances.py index 8399e19184..cff7cd32cb 100644 --- a/openpype/modules/default_modules/ftrack/plugins/publish/integrate_ftrack_instances.py +++ b/openpype/modules/default_modules/ftrack/plugins/publish/integrate_ftrack_instances.py @@ -23,6 +23,7 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): "setdress": "setdress", "pointcache": "cache", "render": "render", + "prerender": "render", "render2d": "render", "nukescript": "comp", "write": "render", @@ -51,6 +52,9 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): if not asset_type and family_low in self.family_mapping: asset_type = self.family_mapping[family_low] + self.log.debug(self.family_mapping) + self.log.debug(family_low) + # Ignore this instance if neither "ftrackFamily" or a family mapping is # found. if not asset_type: diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index 1474ad103d..00ce65705a 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -292,7 +292,8 @@ ], "families": [ "write", - "render" + "render", + "prerender" ], "task_types": [], "tasks": [], @@ -353,6 +354,7 @@ "setdress": "setdress", "pointcache": "cache", "render": "render", + "prerender": "render", "render2d": "render", "nukescript": "comp", "write": "render", diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index c3e229b8e8..5a819e6904 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -32,7 +32,8 @@ "Fg01", "Branch01", "Part01" - ] + ], + "reviewable": false } }, "publish": { diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json b/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json index 22cb8a4ea3..9ab5fc65fb 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json @@ -131,6 +131,11 @@ "object_type": { "type": "text" } + }, + { + "type": "boolean", + "key": "reviewable", + "label": "Add reviewable toggle" } ] } diff --git a/openpype/settings/handlers.py b/openpype/settings/handlers.py index 4ad175168c..9f2b46d758 100644 --- a/openpype/settings/handlers.py +++ b/openpype/settings/handlers.py @@ -995,7 +995,7 @@ class MongoSettingsHandler(SettingsHandler): # QUESTION cache? if version == LEGACY_SETTINGS_VERSION: return self.collection.find_one({ - "type": PROJECT_SETTINGS_KEY, + "type": PROJECT_ANATOMY_KEY, "is_default": True }) @@ -1003,7 +1003,7 @@ class MongoSettingsHandler(SettingsHandler): version = self._current_version return self.collection.find_one({ - "type": self._project_settings_key, + "type": self._project_anatomy_key, "is_default": True, "version": version }) diff --git a/openpype/tools/settings/local_settings/apps_widget.py b/openpype/tools/settings/local_settings/apps_widget.py index 344979218a..c1f350fcbc 100644 --- a/openpype/tools/settings/local_settings/apps_widget.py +++ b/openpype/tools/settings/local_settings/apps_widget.py @@ -11,15 +11,12 @@ from openpype.tools.utils import PlaceholderLineEdit class AppVariantWidget(QtWidgets.QWidget): exec_placeholder = "< Specific path for this machine >" - def __init__(self, group_label, variant_name, variant_entity, parent): + def __init__( + self, group_label, variant_name, variant_label, variant_entity, parent + ): super(AppVariantWidget, self).__init__(parent) self.executable_input_widget = None - variant_label = variant_entity.label - if variant_label is None: - parent_entity = variant_entity.parent - if hasattr(parent_entity, "get_key_label"): - variant_label = parent_entity.get_key_label(variant_name) if not variant_label: variant_label = variant_name @@ -107,15 +104,15 @@ class AppVariantWidget(QtWidgets.QWidget): class AppGroupWidget(QtWidgets.QWidget): - def __init__(self, group_entity, parent): + def __init__(self, group_entity, group_label, parent, dynamic=False): super(AppGroupWidget, self).__init__(parent) + variants_entity = group_entity["variants"] valid_variants = {} - for key, entity in group_entity["variants"].items(): + for key, entity in variants_entity.items(): if "enabled" not in entity or entity["enabled"].value: valid_variants[key] = entity - group_label = group_entity.label expading_widget = ExpandingWidget(group_label, self) content_widget = QtWidgets.QWidget(expading_widget) content_layout = QtWidgets.QVBoxLayout(content_widget) @@ -126,8 +123,16 @@ class AppGroupWidget(QtWidgets.QWidget): if "executables" not in variant_entity: continue + variant_label = variant_entity.label + if dynamic and hasattr(variants_entity, "get_key_label"): + variant_label = variants_entity.get_key_label(variant_name) + variant_widget = AppVariantWidget( - group_label, variant_name, variant_entity, content_widget + group_label, + variant_name, + variant_label, + variant_entity, + content_widget ) widgets_by_variant_name[variant_name] = variant_widget content_layout.addWidget(variant_widget) @@ -171,6 +176,20 @@ class LocalApplicationsWidgets(QtWidgets.QWidget): self.content_layout = layout + def _filter_group_entity(self, entity): + if not entity["enabled"].value: + return False + + # Check if has enabled any variant + for variant_entity in entity["variants"].values(): + if ( + "enabled" not in variant_entity + or variant_entity["enabled"].value + ): + return True + + return False + def _reset_app_widgets(self): while self.content_layout.count() > 0: item = self.content_layout.itemAt(0) @@ -181,34 +200,34 @@ class LocalApplicationsWidgets(QtWidgets.QWidget): self.widgets_by_group_name.clear() app_items = {} + additional_apps = set() + additional_apps_entity = None for key, entity in self.system_settings_entity["applications"].items(): if key != "additional_apps": app_items[key] = entity continue + additional_apps_entity = entity for _key, _entity in entity.items(): app_items[_key] = _entity + additional_apps.add(_key) for key, entity in app_items.items(): - # Filter not enabled app groups - if not entity["enabled"].value: + if not self._filter_group_entity(entity): continue - # Check if has enabled any variant - enabled_variant = False - for variant_entity in entity["variants"].values(): - if ( - "enabled" not in variant_entity - or variant_entity["enabled"].value - ): - enabled_variant = True - break + dynamic = key in additional_apps + group_label = None + if dynamic and hasattr(additional_apps_entity, "get_key_label"): + group_label = additional_apps_entity.get_key_label(key) - if not enabled_variant: - continue + if not group_label: + group_label = entity.label + if not group_label: + group_label = key # Create App group specific widget and store it by the key - group_widget = AppGroupWidget(entity, self) + group_widget = AppGroupWidget(entity, group_label, self, dynamic) if group_widget.widgets_by_variant_name: self.widgets_by_group_name[key] = group_widget self.content_layout.addWidget(group_widget) diff --git a/openpype/tools/settings/local_settings/window.py b/openpype/tools/settings/local_settings/window.py index 3fbf841ce7..fb47e69a17 100644 --- a/openpype/tools/settings/local_settings/window.py +++ b/openpype/tools/settings/local_settings/window.py @@ -9,6 +9,7 @@ from openpype.settings.lib import ( ) from openpype.tools.settings import CHILD_OFFSET from openpype.api import ( + Logger, SystemSettings, ProjectSettings ) @@ -32,7 +33,7 @@ from .constants import ( LOCAL_APPS_KEY ) -log = logging.getLogger(__name__) +log = Logger.get_logger(__name__) class LocalSettingsWidget(QtWidgets.QWidget): @@ -250,6 +251,9 @@ class LocalSettingsWindow(QtWidgets.QWidget): self._settings_widget.update_local_settings(value) except Exception as exc: + log.warning( + "Failed to create local settings window", exc_info=True + ) error_msg = str(exc) crashed = error_msg is not None