Merge branch 'develop' into feature/OP-1841_Experimental-options

This commit is contained in:
iLLiCiTiT 2021-10-21 14:54:09 +02:00
commit 9339d398b9
24 changed files with 519 additions and 212 deletions

View file

@ -4,7 +4,6 @@ import copy
import argparse
from avalon import io
from avalon.tools import publish
import pyblish.api
import pyblish.util
@ -13,6 +12,7 @@ from openpype.api import Logger
import openpype
import openpype.hosts.celaction
from openpype.hosts.celaction import api as celaction
from openpype.tools.utils import host_tools
log = Logger().get_logger("Celaction_cli_publisher")
@ -82,7 +82,7 @@ def main():
pyblish.api.register_host(publish_host)
return publish.show()
return host_tools.show_publish()
if __name__ == "__main__":

View file

@ -1,8 +1,6 @@
from .pipeline import (
install,
uninstall,
publish,
launch_workfiles_app
uninstall
)
from .utils import (
@ -22,12 +20,9 @@ __all__ = [
# pipeline
"install",
"uninstall",
"publish",
"launch_workfiles_app",
# utils
"setup",
"get_resolve_module",
# lib
"get_additional_data",

View file

@ -3,19 +3,7 @@ import sys
from Qt import QtWidgets, QtCore
from .pipeline import (
publish,
launch_workfiles_app
)
from avalon.tools import (
creator,
sceneinventory,
)
from openpype.tools import (
loader,
libraryloader
)
from openpype.tools.utils import host_tools
from openpype.hosts.fusion.scripts import (
set_rendermode,
@ -36,7 +24,7 @@ def load_stylesheet():
class Spacer(QtWidgets.QWidget):
def __init__(self, height, *args, **kwargs):
super(self.__class__, self).__init__(*args, **kwargs)
super(Spacer, self).__init__(*args, **kwargs)
self.setFixedHeight(height)
@ -53,7 +41,7 @@ class Spacer(QtWidgets.QWidget):
class OpenPypeMenu(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(self.__class__, self).__init__(*args, **kwargs)
super(OpenPypeMenu, self).__init__(*args, **kwargs)
self.setObjectName("OpenPypeMenu")
@ -117,27 +105,27 @@ class OpenPypeMenu(QtWidgets.QWidget):
def on_workfile_clicked(self):
print("Clicked Workfile")
launch_workfiles_app()
host_tools.show_workfiles()
def on_create_clicked(self):
print("Clicked Create")
creator.show()
host_tools.show_creator()
def on_publish_clicked(self):
print("Clicked Publish")
publish(None)
host_tools.show_publish()
def on_load_clicked(self):
print("Clicked Load")
loader.show(use_context=True)
host_tools.show_loader(use_context=True)
def on_inventory_clicked(self):
print("Clicked Inventory")
sceneinventory.show()
host_tools.show_scene_inventory()
def on_libload_clicked(self):
print("Clicked Library")
libraryloader.show()
host_tools.show_library_loader()
def on_rendernode_clicked(self):
from avalon import style

View file

@ -3,7 +3,6 @@ Basic avalon integration
"""
import os
from openpype.tools import workfiles
from avalon import api as avalon
from pyblish import api as pyblish
from openpype.api import Logger
@ -98,14 +97,3 @@ def on_pyblish_instance_toggled(instance, new_value, old_value):
current = attrs["TOOLB_PassThrough"]
if current != passthrough:
tool.SetAttrs({"TOOLB_PassThrough": passthrough})
def launch_workfiles_app(*args):
workdir = os.environ["AVALON_WORKDIR"]
workfiles.show(workdir)
def publish(parent):
"""Shorthand to publish from within host"""
from avalon.tools import publish
return publish.show(parent)

View file

@ -3,17 +3,14 @@
import os
from pathlib import Path
import logging
import re
from openpype import lib
from openpype.api import (get_current_project_settings)
import openpype.hosts.harmony
import pyblish.api
from avalon import io, harmony
import avalon.api
import avalon.tools.sceneinventory
log = logging.getLogger("openpype.hosts.harmony")

View file

@ -2,6 +2,7 @@ import os
import sys
import hiero.core
from openpype.api import Logger
from openpype.tools.utils import host_tools
from avalon.api import Session
from hiero.ui import findMenuAction
@ -41,8 +42,6 @@ def menu_install():
apply_colorspace_project, apply_colorspace_clips
)
# here is the best place to add menu
from avalon.tools import creator, sceneinventory
from openpype.tools import loader
from avalon.vendor.Qt import QtGui
menu_name = os.environ['AVALON_LABEL']
@ -87,15 +86,15 @@ def menu_install():
creator_action = menu.addAction("Create ...")
creator_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png"))
creator_action.triggered.connect(creator.show)
creator_action.triggered.connect(host_tools.show_creator)
loader_action = menu.addAction("Load ...")
loader_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png"))
loader_action.triggered.connect(loader.show)
loader_action.triggered.connect(host_tools.show_loader)
sceneinventory_action = menu.addAction("Manage ...")
sceneinventory_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png"))
sceneinventory_action.triggered.connect(sceneinventory.show)
sceneinventory_action.triggered.connect(host_tools.show_scene_inventory)
menu.addSeparator()
if os.getenv("OPENPYPE_DEVELOP"):

View file

@ -4,13 +4,12 @@ Basic avalon integration
import os
import contextlib
from collections import OrderedDict
from avalon.tools import publish as _publish
from openpype.tools import workfiles
from avalon.pipeline import AVALON_CONTAINER_ID
from avalon import api as avalon
from avalon import schema
from pyblish import api as pyblish
from openpype.api import Logger
from openpype.tools.utils import host_tools
from . import lib, menu, events
log = Logger().get_logger(__name__)
@ -211,15 +210,13 @@ def update_container(track_item, data=None):
def launch_workfiles_app(*args):
''' Wrapping function for workfiles launcher '''
workdir = os.environ["AVALON_WORKDIR"]
# show workfile gui
workfiles.show(workdir)
host_tools.show_workfiles()
def publish(parent):
"""Shorthand to publish from within host"""
return _publish.show(parent)
return host_tools.show_publish(parent)
@contextlib.contextmanager

View file

@ -7,24 +7,30 @@
<scriptItem id="avalon_create">
<label>Create ...</label>
<scriptCode><![CDATA[
from avalon.tools import creator
creator.show()
import hou
from openpype.tools.utils import host_tools
parent = hou.qt.mainWindow()
host_tools.show_creator(parent)
]]></scriptCode>
</scriptItem>
<scriptItem id="avalon_load">
<label>Load ...</label>
<scriptCode><![CDATA[
from openpype.tools import loader
loader.show(use_context=True)
import hou
from openpype.tools.utils import host_tools
parent = hou.qt.mainWindow()
host_tools.show_loader(parent=parent, use_context=True)
]]></scriptCode>
</scriptItem>
<scriptItem id="avalon_manage">
<label>Manage ...</label>
<scriptCode><![CDATA[
from avalon.tools import cbsceneinventory
cbsceneinventory.show()
import hou
from openpype.tools.utils import host_tools
parent = hou.qt.mainWindow()
host_tools.show_scene_inventory(parent)
]]></scriptCode>
</scriptItem>
@ -32,9 +38,9 @@ cbsceneinventory.show()
<label>Publish ...</label>
<scriptCode><![CDATA[
import hou
from avalon.tools import publish
from openpype.tools.utils import host_tools
parent = hou.qt.mainWindow()
publish.show(parent)
host_tools.show_publish(parent)
]]></scriptCode>
</scriptItem>
@ -43,9 +49,10 @@ publish.show(parent)
<scriptItem id="workfiles">
<label>Work Files ...</label>
<scriptCode><![CDATA[
import hou, os
from openpype.tools import workfiles
workfiles.show(os.environ["AVALON_WORKDIR"])
import hou
from openpype.tools.utils import host_tools
parent = hou.qt.mainWindow()
host_tools.show_workfiles(parent)
]]></scriptCode>
</scriptItem>

View file

@ -8,7 +8,7 @@ from avalon import api as avalon
from avalon import pipeline
from avalon.maya import suspended_refresh
from avalon.maya.pipeline import IS_HEADLESS
from openpype.tools import workfiles
from openpype.tools.utils import host_tools
from pyblish import api as pyblish
from openpype.lib import any_outdated
import openpype.hosts.maya
@ -208,16 +208,12 @@ def on_init(_):
launch_workfiles = os.environ.get("WORKFILES_STARTUP")
if launch_workfiles:
safe_deferred(launch_workfiles_app)
safe_deferred(host_tools.show_workfiles)
if not IS_HEADLESS:
safe_deferred(override_toolbox_ui)
def launch_workfiles_app():
workfiles.show(os.environ["AVALON_WORKDIR"])
def on_before_save(return_code, _):
"""Run validation for scene's FPS prior to saving"""
return lib.validate_fps()

View file

@ -1,10 +1,16 @@
"""A set of commands that install overrides to Maya's UI"""
import os
import logging
from functools import partial
import maya.cmds as mc
import maya.mel as mel
from functools import partial
import os
import logging
from avalon.maya import pipeline
from openpype.api import resources
from openpype.tools.utils import host_tools
log = logging.getLogger(__name__)
@ -69,39 +75,8 @@ def override_component_mask_commands():
def override_toolbox_ui():
"""Add custom buttons in Toolbox as replacement for Maya web help icon."""
inventory = None
loader = None
launch_workfiles_app = None
mayalookassigner = None
try:
import avalon.tools.sceneinventory as inventory
except Exception:
log.warning("Could not import SceneInventory tool")
try:
import openpype.tools.loader as loader
except Exception:
log.warning("Could not import Loader tool")
try:
from avalon.maya.pipeline import launch_workfiles_app
except Exception:
log.warning("Could not import Workfiles tool")
try:
from openpype.tools import mayalookassigner
except Exception:
log.warning("Could not import Maya Look assigner tool")
from openpype.api import resources
icons = resources.get_resource("icons")
if not any((
mayalookassigner, launch_workfiles_app, loader, inventory
)):
return
# Ensure the maya web icon on toolbox exists
web_button = "ToolBox|MainToolboxLayout|mayaWebButton"
if not mc.iconTextButton(web_button, query=True, exists=True):
@ -120,14 +95,23 @@ def override_toolbox_ui():
# Create our controls
background_color = (0.267, 0.267, 0.267)
controls = []
if mayalookassigner:
look_assigner = None
try:
look_assigner = host_tools.get_tool_by_name(
"lookassigner",
parent=pipeline._parent
)
except Exception:
log.warning("Couldn't create Look assigner window.", exc_info=True)
if look_assigner is not None:
controls.append(
mc.iconTextButton(
"pype_toolbox_lookmanager",
annotation="Look Manager",
label="Look Manager",
image=os.path.join(icons, "lookmanager.png"),
command=lambda: mayalookassigner.show(),
command=host_tools.show_look_assigner,
bgc=background_color,
width=icon_size,
height=icon_size,
@ -135,50 +119,53 @@ def override_toolbox_ui():
)
)
if launch_workfiles_app:
controls.append(
mc.iconTextButton(
"pype_toolbox_workfiles",
annotation="Work Files",
label="Work Files",
image=os.path.join(icons, "workfiles.png"),
command=lambda: launch_workfiles_app(),
bgc=background_color,
width=icon_size,
height=icon_size,
parent=parent
)
controls.append(
mc.iconTextButton(
"pype_toolbox_workfiles",
annotation="Work Files",
label="Work Files",
image=os.path.join(icons, "workfiles.png"),
command=lambda: host_tools.show_workfiles(
parent=pipeline._parent
),
bgc=background_color,
width=icon_size,
height=icon_size,
parent=parent
)
)
if loader:
controls.append(
mc.iconTextButton(
"pype_toolbox_loader",
annotation="Loader",
label="Loader",
image=os.path.join(icons, "loader.png"),
command=lambda: loader.show(use_context=True),
bgc=background_color,
width=icon_size,
height=icon_size,
parent=parent
)
controls.append(
mc.iconTextButton(
"pype_toolbox_loader",
annotation="Loader",
label="Loader",
image=os.path.join(icons, "loader.png"),
command=lambda: host_tools.show_loader(
parent=pipeline._parent, use_context=True
),
bgc=background_color,
width=icon_size,
height=icon_size,
parent=parent
)
)
if inventory:
controls.append(
mc.iconTextButton(
"pype_toolbox_manager",
annotation="Inventory",
label="Inventory",
image=os.path.join(icons, "inventory.png"),
command=lambda: inventory.show(),
bgc=background_color,
width=icon_size,
height=icon_size,
parent=parent
)
controls.append(
mc.iconTextButton(
"pype_toolbox_manager",
annotation="Inventory",
label="Inventory",
image=os.path.join(icons, "inventory.png"),
command=lambda: host_tools.show_scene_inventory(
parent=pipeline._parent
),
bgc=background_color,
width=icon_size,
height=icon_size,
parent=parent
)
)
# Add the buttons on the bottom and stack
# them above each other with side padding

View file

@ -2,13 +2,15 @@ import sys
import os
import logging
from avalon.vendor.Qt import QtWidgets, QtGui
from avalon.maya import pipeline
from openpype.api import BuildWorkfile
import maya.cmds as cmds
from openpype.settings import get_project_settings
from Qt import QtWidgets, QtGui
self = sys.modules[__name__]
import maya.cmds as cmds
from avalon.maya import pipeline
from openpype.api import BuildWorkfile
from openpype.settings import get_project_settings
from openpype.tools.utils import host_tools
log = logging.getLogger(__name__)
@ -36,25 +38,15 @@ def deferred():
)
def add_look_assigner_item():
import mayalookassigner
cmds.menuItem(
"Look assigner",
parent=pipeline._menu,
command=lambda *args: mayalookassigner.show()
command=lambda *args: host_tools.show_look_assigner(
pipeline._parent
)
)
def modify_workfiles():
from openpype.tools import workfiles
def launch_workfiles_app(*_args, **_kwargs):
workfiles.show(
os.path.join(
cmds.workspace(query=True, rootDirectory=True),
cmds.workspace(fileRuleEntry="scene")
),
parent=pipeline._parent
)
# Find the pipeline menu
top_menu = _get_menu()
@ -75,7 +67,7 @@ def deferred():
cmds.menuItem(
"Work Files",
parent=pipeline._menu,
command=launch_workfiles_app,
command=lambda *args: host_tools.show_workfiles(pipeline._parent),
insertAfter=after_action
)

View file

@ -244,17 +244,17 @@ class CollectMayaRender(pyblish.api.ContextPlugin):
# metadata file will be located in top-most common
# directory.
# TODO: use `os.path.commonpath()` after switch to Python 3
publish_meta_path = os.path.normpath(publish_meta_path)
common_publish_meta_path = os.path.splitdrive(
publish_meta_path)[0]
if common_publish_meta_path:
common_publish_meta_path += os.path.sep
for part in publish_meta_path.split("/"):
for part in publish_meta_path.replace(
common_publish_meta_path, "").split(os.path.sep):
common_publish_meta_path = os.path.join(
common_publish_meta_path, part)
if part == expected_layer_name:
break
common_publish_meta_path = common_publish_meta_path.replace(
"\\", "/")
self.log.info(
"Publish meta path: {}".format(common_publish_meta_path))

View file

@ -7,7 +7,6 @@ from collections import OrderedDict
from avalon import api, io, lib
from openpype.tools import workfiles
import avalon.nuke
from avalon.nuke import lib as anlib
from avalon.nuke import (
@ -24,7 +23,7 @@ from openpype.api import (
get_current_project_settings,
ApplicationManager
)
from openpype.tools.utils import host_tools
import nuke
from .utils import set_context_favorites
@ -1662,7 +1661,7 @@ def launch_workfiles_app():
if not opnl.workfiles_launched:
opnl.workfiles_launched = True
workfiles.show(os.environ["AVALON_WORKDIR"])
host_tools.show_workfiles()
def process_workfile_builder():

View file

@ -4,7 +4,7 @@ from avalon.api import Session
from .lib import WorkfileSettings
from openpype.api import Logger, BuildWorkfile, get_current_project_settings
from openpype.tools import workfiles
from openpype.tools.utils import host_tools
log = Logger().get_logger(__name__)
@ -25,7 +25,7 @@ def install():
menu.removeItem(rm_item[1].name())
menu.addCommand(
name,
workfiles.show,
host_tools.show_workfiles,
index=2
)
menu.addSeparator(index=3)

View file

@ -8,15 +8,7 @@ from .pipeline import (
launch_workfiles_app
)
from avalon.tools import (
creator,
sceneinventory,
subsetmanager
)
from openpype.tools import (
loader,
libraryloader,
)
from openpype.tools.utils import host_tools
def load_stylesheet():
@ -32,7 +24,7 @@ def load_stylesheet():
class Spacer(QtWidgets.QWidget):
def __init__(self, height, *args, **kwargs):
super(self.__class__, self).__init__(*args, **kwargs)
super(Spacer, self).__init__(*args, **kwargs)
self.setFixedHeight(height)
@ -49,7 +41,7 @@ class Spacer(QtWidgets.QWidget):
class OpenPypeMenu(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(self.__class__, self).__init__(*args, **kwargs)
super(OpenPypeMenu, self).__init__(*args, **kwargs)
self.setObjectName("OpenPypeMenu")
@ -119,7 +111,7 @@ class OpenPypeMenu(QtWidgets.QWidget):
def on_create_clicked(self):
print("Clicked Create")
creator.show()
host_tools.show_creator()
def on_publish_clicked(self):
print("Clicked Publish")
@ -127,19 +119,19 @@ class OpenPypeMenu(QtWidgets.QWidget):
def on_load_clicked(self):
print("Clicked Load")
loader.show(use_context=True)
host_tools.show_loader(use_context=True)
def on_inventory_clicked(self):
print("Clicked Inventory")
sceneinventory.show()
host_tools.show_scene_inventory()
def on_subsetm_clicked(self):
print("Clicked Subset Manager")
subsetmanager.show()
host_tools.show_subset_manager()
def on_libload_clicked(self):
print("Clicked Library")
libraryloader.show()
host_tools.show_library_loader()
def on_rename_clicked(self):
print("Clicked Rename")

View file

@ -4,7 +4,6 @@ Basic avalon integration
import os
import contextlib
from collections import OrderedDict
from openpype.tools import workfiles
from avalon import api as avalon
from avalon import schema
from avalon.pipeline import AVALON_CONTAINER_ID
@ -12,6 +11,7 @@ from pyblish import api as pyblish
from openpype.api import Logger
from . import lib
from . import PLUGINS_DIR
from openpype.tools.utils import host_tools
log = Logger().get_logger(__name__)
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
@ -212,14 +212,12 @@ def update_container(timeline_item, data=None):
def launch_workfiles_app(*args):
workdir = os.environ["AVALON_WORKDIR"]
workfiles.show(workdir)
host_tools.show_workfiles()
def publish(parent):
"""Shorthand to publish from within host"""
from avalon.tools import publish
return publish.show(parent)
return host_tools.show_publish()
@contextlib.contextmanager

View file

@ -38,7 +38,10 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
# Enable minimize and maximize for app
self.setWindowTitle(self.tool_title)
self.setWindowFlags(QtCore.Qt.Window)
window_flags = QtCore.Qt.Window
if not parent:
window_flags |= QtCore.Qt.WindowStaysOnTopHint
self.setWindowFlags(window_flags)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
if icon is not None:
self.setWindowIcon(icon)

View file

@ -51,7 +51,10 @@ class LoaderWindow(QtWidgets.QDialog):
self.family_config_cache = lib.FamilyConfigCache(io)
# Enable minimize and maximize for app
self.setWindowFlags(QtCore.Qt.Window)
window_flags = QtCore.Qt.Window
if not parent:
window_flags |= QtCore.Qt.WindowStaysOnTopHint
self.setWindowFlags(window_flags)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
body = QtWidgets.QWidget()

View file

@ -786,7 +786,10 @@ class ThumbnailWidget(QtWidgets.QLabel):
def scale_pixmap(self, pixmap):
return pixmap.scaled(
self.width(), self.height(), QtCore.Qt.KeepAspectRatio
self.width(),
self.height(),
QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation
)
def set_thumbnail(self, entity=None):

View file

@ -0,0 +1,357 @@
"""Single access point to all tools usable in hosts.
It is possible to create `HostToolsHelper` in host implementaion or
use singleton approach with global functions (using helper anyway).
"""
import avalon.api
class HostToolsHelper:
"""Create and cache tool windows in memory.
Almost all methods expect parent widget but the parent is used only on
first tool creation.
Class may also contain tools that are available only for one or few hosts.
"""
def __init__(self, parent=None):
self._log = None
# Global parent for all tools (may and may not be set)
self._parent = parent
# Prepare attributes for all tools
self._workfiles_tool = None
self._loader_tool = None
self._creator_tool = None
self._subset_manager_tool = None
self._scene_inventory_tool = None
self._library_loader_tool = None
self._look_assigner_tool = None
@property
def log(self):
if self._log is None:
from openpype.api import Logger
self._log = Logger.get_logger(self.__class__.__name__)
return self._log
def get_workfiles_tool(self, parent):
"""Create, cache and return workfiles tool window."""
if self._workfiles_tool is None:
from avalon import style
from openpype.tools.workfiles.app import (
Window, validate_host_requirements
)
# Host validation
host = avalon.api.registered_host()
validate_host_requirements(host)
workfiles_window = Window(parent=parent)
workfiles_window.setStyleSheet(style.load_stylesheet())
self._workfiles_tool = workfiles_window
return self._workfiles_tool
def show_workfiles(self, parent=None, use_context=None, save=None):
"""Workfiles tool for changing context and saving workfiles."""
if use_context is None:
use_context = True
if save is None:
save = True
workfiles_tool = self.get_workfiles_tool(parent)
if use_context:
context = {
"asset": avalon.api.Session["AVALON_ASSET"],
"silo": avalon.api.Session["AVALON_SILO"],
"task": avalon.api.Session["AVALON_TASK"]
}
workfiles_tool.set_context(context)
if save:
workfiles_tool.set_save_enabled(save)
workfiles_tool.refresh()
workfiles_tool.show()
# Pull window to the front.
workfiles_tool.raise_()
workfiles_tool.activateWindow()
def get_loader_tool(self, parent):
"""Create, cache and return loader tool window."""
if self._loader_tool is None:
from avalon import style
from openpype.tools.loader import LoaderWindow
loader_window = LoaderWindow(parent=parent or self._parent)
loader_window.setStyleSheet(style.load_stylesheet())
self._loader_tool = loader_window
return self._loader_tool
def show_loader(self, parent=None, use_context=None):
"""Loader tool for loading representations."""
if use_context is None:
use_context = False
loader_tool = self.get_loader_tool(parent)
if use_context:
context = {"asset": avalon.api.Session["AVALON_ASSET"]}
loader_tool.set_context(context, refresh=True)
else:
loader_tool.refresh()
loader_tool.show()
loader_tool.raise_()
loader_tool.activateWindow()
loader_tool.refresh()
def get_creator_tool(self, parent):
"""Create, cache and return creator tool window."""
if self._creator_tool is None:
from avalon import style
from avalon.tools.creator.app import Window
creator_window = Window(parent=parent or self._parent)
creator_window.setStyleSheet(style.load_stylesheet())
self._creator_tool = creator_window
return self._creator_tool
def show_creator(self, parent=None):
"""Show tool to create new instantes for publishing."""
creator_tool = self.get_creator_tool(parent)
creator_tool.refresh()
creator_tool.show()
# Pull window to the front.
creator_tool.raise_()
creator_tool.activateWindow()
def get_subset_manager_tool(self, parent):
"""Create, cache and return subset manager tool window."""
if self._subset_manager_tool is None:
from avalon import style
from avalon.tools.subsetmanager import Window
subset_manager_window = Window(parent=parent or self._parent)
subset_manager_window.setStyleSheet(style.load_stylesheet())
self._subset_manager_tool = subset_manager_window
return self._subset_manager_tool
def show_subset_manager(self, parent=None):
"""Show tool display/remove existing created instances."""
subset_manager_tool = self.get_subset_manager_tool(parent)
subset_manager_tool.show()
# Pull window to the front.
subset_manager_tool.raise_()
subset_manager_tool.activateWindow()
def get_scene_inventory_tool(self, parent):
"""Create, cache and return scene inventory tool window."""
if self._scene_inventory_tool is None:
from avalon import style
from avalon.tools.sceneinventory.app import Window
scene_inventory_window = Window(parent=parent or self._parent)
scene_inventory_window.setStyleSheet(style.load_stylesheet())
self._scene_inventory_tool = scene_inventory_window
return self._scene_inventory_tool
def show_scene_inventory(self, parent=None):
"""Show tool maintain loaded containers."""
scene_inventory_tool = self.get_scene_inventory_tool(parent)
scene_inventory_tool.show()
scene_inventory_tool.refresh()
# Pull window to the front.
scene_inventory_tool.raise_()
scene_inventory_tool.activateWindow()
def get_library_loader_tool(self, parent):
"""Create, cache and return library loader tool window."""
if self._library_loader_tool is None:
from avalon import style
from openpype.tools.libraryloader import LibraryLoaderWindow
library_window = LibraryLoaderWindow(
parent=parent or self._parent
)
library_window.setStyleSheet(style.load_stylesheet())
self._library_loader_tool = library_window
return self._library_loader_tool
def show_library_loader(self, parent=None):
"""Loader tool for loading representations from library project."""
library_loader_tool = self.get_library_loader_tool(parent)
library_loader_tool.show()
library_loader_tool.raise_()
library_loader_tool.activateWindow()
library_loader_tool.refresh()
def show_publish(self, parent=None):
"""Publish UI."""
from avalon.tools import publish
publish.show(parent)
def get_look_assigner_tool(self, parent):
"""Create, cache and return look assigner tool window."""
if self._look_assigner_tool is None:
from avalon import style
import mayalookassigner
mayalookassigner_window = mayalookassigner.App(parent)
mayalookassigner_window.setStyleSheet(style.load_stylesheet())
self._look_assigner_tool = mayalookassigner_window
return self._look_assigner_tool
def show_look_assigner(self, parent=None):
"""Look manager is Maya specific tool for look management."""
look_assigner_tool = self.get_look_assigner_tool(parent)
look_assigner_tool.show()
def get_tool_by_name(self, tool_name, parent=None, *args, **kwargs):
"""Show tool by it's name.
This is helper for
"""
if tool_name == "workfiles":
return self.get_workfiles_tool(parent, *args, **kwargs)
elif tool_name == "loader":
return self.get_loader_tool(parent, *args, **kwargs)
elif tool_name == "libraryloader":
return self.get_library_loader_tool(parent, *args, **kwargs)
elif tool_name == "creator":
return self.get_creator_tool(parent, *args, **kwargs)
elif tool_name == "subsetmanager":
return self.get_subset_manager_tool(parent, *args, **kwargs)
elif tool_name == "sceneinventory":
return self.get_scene_inventory_tool(parent, *args, **kwargs)
elif tool_name == "lookassigner":
return self.get_look_assigner_tool(parent, *args, **kwargs)
elif tool_name == "publish":
self.log.info("Can't return publish tool window.")
else:
self.log.warning(
"Can't show unknown tool name: \"{}\"".format(tool_name)
)
def show_tool_by_name(self, tool_name, parent=None, *args, **kwargs):
"""Show tool by it's name.
This is helper for
"""
if tool_name == "workfiles":
self.show_workfiles(parent, *args, **kwargs)
elif tool_name == "loader":
self.show_loader(parent, *args, **kwargs)
elif tool_name == "libraryloader":
self.show_library_loader(parent, *args, **kwargs)
elif tool_name == "creator":
self.show_creator(parent, *args, **kwargs)
elif tool_name == "subsetmanager":
self.show_subset_manager(parent, *args, **kwargs)
elif tool_name == "sceneinventory":
self.show_scene_inventory(parent, *args, **kwargs)
elif tool_name == "lookassigner":
self.show_look_assigner(parent, *args, **kwargs)
elif tool_name == "publish":
self.show_publish(parent, *args, **kwargs)
else:
self.log.warning(
"Can't show unknown tool name: \"{}\"".format(tool_name)
)
class _SingletonPoint:
"""Singleton access to host tools.
Some hosts don't have ability to create 'HostToolsHelper' object anc can
only register function callbacks. For those cases is created this singleton
point where 'HostToolsHelper' is created "in shared memory".
"""
helper = None
@classmethod
def _create_helper(cls):
if cls.helper is None:
cls.helper = HostToolsHelper()
@classmethod
def show_tool_by_name(cls, tool_name, parent=None, *args, **kwargs):
cls._create_helper()
cls.helper.show_tool_by_name(tool_name, parent, *args, **kwargs)
@classmethod
def get_tool_by_name(cls, tool_name, parent=None, *args, **kwargs):
cls._create_helper()
return cls.helper.get_tool_by_name(tool_name, parent, *args, **kwargs)
# Function callbacks using singleton acces point
def get_tool_by_name(tool_name, parent=None, *args, **kwargs):
return _SingletonPoint.get_tool_by_name(tool_name, parent, *args, **kwargs)
def show_tool_by_name(tool_name, parent=None, *args, **kwargs):
_SingletonPoint.show_tool_by_name(tool_name, parent, *args, **kwargs)
def show_workfiles(parent=None, use_context=None, save=None):
_SingletonPoint.show_tool_by_name(
"workfiles", parent, use_context=use_context, save=save
)
def show_loader(parent=None, use_context=None):
_SingletonPoint.show_tool_by_name(
"loader", parent, use_context=use_context
)
def show_library_loader(parent=None):
_SingletonPoint.show_tool_by_name("libraryloader", parent)
def show_creator(parent=None):
_SingletonPoint.show_tool_by_name("creator", parent)
def show_subset_manager(parent=None):
_SingletonPoint.show_tool_by_name("subsetmanager", parent)
def show_scene_inventory(parent=None):
_SingletonPoint.show_tool_by_name("sceneinventory", parent)
def show_look_assigner(parent=None):
_SingletonPoint.show_tool_by_name("lookassigner", parent)
def show_publish(parent=None):
_SingletonPoint.show_tool_by_name("publish", parent)

View file

@ -944,7 +944,10 @@ class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent=parent)
self.setWindowTitle(self.title)
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.WindowCloseButtonHint)
window_flags = QtCore.Qt.Window | QtCore.Qt.WindowCloseButtonHint
if not parent:
window_flags |= QtCore.Qt.WindowStaysOnTopHint
self.setWindowFlags(window_flags)
# Create pages widget and set it as central widget
pages_widget = QtWidgets.QStackedWidget(self)
@ -1015,6 +1018,9 @@ class Window(QtWidgets.QMainWindow):
"""
def set_save_enabled(self, enabled):
self.files_widget.btn_save.setEnabled(enabled)
def on_task_changed(self):
# Since we query the disk give it slightly more delay
tools_lib.schedule(self._on_task_changed, 100, channel="mongo")
@ -1187,7 +1193,7 @@ def show(root=None, debug=False, parent=None, use_context=True, save=True):
}
window.set_context(context)
window.files_widget.btn_save.setEnabled(save)
window.set_save_enabled(save)
window.show()
window.setStyleSheet(style.load_stylesheet())

View file

@ -27,7 +27,7 @@ def get_release_type_github(Log, github_token):
return "minor"
if any(label in labels for label in patch_labels):
return "path"
return "patch"
return None

View file

@ -116,8 +116,8 @@ module.exports = {
// Optional: Algolia search parameters
searchParameters: {},
},
googleAnalytics: {
trackingID: 'G-HHJZ9VF0FG',
gtag: {
trackingID: 'G-DTKXMFENFY',
// Optional fields.
anonymizeIP: false, // Should IPs be anonymized?
},

View file

@ -2175,11 +2175,11 @@ autoprefixer@^10.0.2, autoprefixer@^10.2.5:
postcss-value-parser "^4.1.0"
axios@^0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
follow-redirects "^1.10.0"
follow-redirects "^1.14.0"
babel-loader@^8.2.2:
version "8.2.2"
@ -3982,10 +3982,10 @@ flux@^4.0.1:
fbemitter "^3.0.0"
fbjs "^3.0.0"
follow-redirects@^1.0.0, follow-redirects@^1.10.0:
version "1.13.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==
follow-redirects@^1.0.0, follow-redirects@^1.14.0:
version "1.14.4"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
for-in@^1.0.2:
version "1.0.2"