mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
502 lines
13 KiB
Python
502 lines
13 KiB
Python
import logging
|
|
import warnings
|
|
|
|
import ayon_api
|
|
|
|
from ayon_core.settings import get_studio_settings, get_project_settings
|
|
from ayon_core.pipeline.plugin_discover import (
|
|
discover,
|
|
register_plugin,
|
|
register_plugin_path,
|
|
deregister_plugin,
|
|
deregister_plugin_path
|
|
)
|
|
|
|
from .load.utils import get_representation_path_from_context
|
|
|
|
|
|
class LauncherActionSelection:
|
|
"""Object helper to pass selection to actions.
|
|
|
|
Object support backwards compatibility for 'session' from OpenPype where
|
|
environment variable keys were used to define selection.
|
|
|
|
Args:
|
|
project_name (str): Selected project name.
|
|
folder_id (str): Selected folder id.
|
|
task_id (str): Selected task id.
|
|
folder_path (Optional[str]): Selected folder path.
|
|
task_name (Optional[str]): Selected task name.
|
|
project_entity (Optional[dict[str, Any]]): Project entity.
|
|
folder_entity (Optional[dict[str, Any]]): Folder entity.
|
|
task_entity (Optional[dict[str, Any]]): Task entity.
|
|
|
|
"""
|
|
def __init__(
|
|
self,
|
|
project_name,
|
|
folder_id,
|
|
task_id,
|
|
workfile_id,
|
|
folder_path=None,
|
|
task_name=None,
|
|
project_entity=None,
|
|
folder_entity=None,
|
|
task_entity=None,
|
|
workfile_entity=None,
|
|
project_settings=None,
|
|
):
|
|
self._project_name = project_name
|
|
self._folder_id = folder_id
|
|
self._task_id = task_id
|
|
self._workfile_id = workfile_id
|
|
|
|
self._folder_path = folder_path
|
|
self._task_name = task_name
|
|
|
|
self._project_entity = project_entity
|
|
self._folder_entity = folder_entity
|
|
self._task_entity = task_entity
|
|
self._workfile_entity = workfile_entity
|
|
|
|
self._project_settings = project_settings
|
|
|
|
def __getitem__(self, key):
|
|
warnings.warn(
|
|
(
|
|
"Using deprecated access to selection data. Please use"
|
|
" attributes and methods"
|
|
" defined by 'LauncherActionSelection'."
|
|
),
|
|
category=DeprecationWarning
|
|
)
|
|
if key in {"AYON_PROJECT_NAME", "AVALON_PROJECT"}:
|
|
return self.project_name
|
|
if key in {"AYON_FOLDER_PATH", "AVALON_ASSET"}:
|
|
return self.folder_path
|
|
if key in {"AYON_TASK_NAME", "AVALON_TASK"}:
|
|
return self.task_name
|
|
raise KeyError(f"Key: {key} not found")
|
|
|
|
def __iter__(self):
|
|
for key in self.keys():
|
|
yield key
|
|
|
|
def __contains__(self, key):
|
|
warnings.warn(
|
|
(
|
|
"Using deprecated access to selection data. Please use"
|
|
" attributes and methods"
|
|
" defined by 'LauncherActionSelection'."
|
|
),
|
|
category=DeprecationWarning
|
|
)
|
|
# Fake missing keys check for backwards compatibility
|
|
if key in {
|
|
"AYON_PROJECT_NAME",
|
|
"AVALON_PROJECT",
|
|
}:
|
|
return self._project_name is not None
|
|
if key in {
|
|
"AYON_FOLDER_PATH",
|
|
"AVALON_ASSET",
|
|
}:
|
|
return self._folder_id is not None
|
|
if key in {
|
|
"AYON_TASK_NAME",
|
|
"AVALON_TASK",
|
|
}:
|
|
return self._task_id is not None
|
|
return False
|
|
|
|
def get(self, key, default=None):
|
|
"""
|
|
|
|
Deprecated:
|
|
Added for backwards compatibility with older actions.
|
|
|
|
"""
|
|
warnings.warn(
|
|
(
|
|
"Using deprecated access to selection data. Please use"
|
|
" attributes and methods"
|
|
" defined by 'LauncherActionSelection'."
|
|
),
|
|
category=DeprecationWarning
|
|
)
|
|
try:
|
|
return self[key]
|
|
except KeyError:
|
|
return default
|
|
|
|
def items(self):
|
|
"""
|
|
|
|
Deprecated:
|
|
Added for backwards compatibility with older actions.
|
|
|
|
"""
|
|
for key, value in (
|
|
("AYON_PROJECT_NAME", self.project_name),
|
|
("AYON_FOLDER_PATH", self.folder_path),
|
|
("AYON_TASK_NAME", self.task_name),
|
|
):
|
|
if value is not None:
|
|
yield (key, value)
|
|
|
|
def keys(self):
|
|
"""
|
|
|
|
Deprecated:
|
|
Added for backwards compatibility with older actions.
|
|
|
|
"""
|
|
for key, _ in self.items():
|
|
yield key
|
|
|
|
def values(self):
|
|
"""
|
|
|
|
Deprecated:
|
|
Added for backwards compatibility with older actions.
|
|
|
|
"""
|
|
for _, value in self.items():
|
|
yield value
|
|
|
|
def get_project_name(self):
|
|
"""Selected project name.
|
|
|
|
Returns:
|
|
Union[str, None]: Selected project name.
|
|
|
|
"""
|
|
return self._project_name
|
|
|
|
def get_folder_id(self):
|
|
"""Selected folder id.
|
|
|
|
Returns:
|
|
Union[str, None]: Selected folder id.
|
|
|
|
"""
|
|
return self._folder_id
|
|
|
|
def get_folder_path(self):
|
|
"""Selected folder path.
|
|
|
|
Returns:
|
|
Union[str, None]: Selected folder path.
|
|
|
|
"""
|
|
if self._folder_id is None:
|
|
return None
|
|
if self._folder_path is None:
|
|
self._folder_path = self.folder_entity["path"]
|
|
return self._folder_path
|
|
|
|
def get_task_id(self):
|
|
"""Selected task id.
|
|
|
|
Returns:
|
|
Union[str, None]: Selected task id.
|
|
|
|
"""
|
|
return self._task_id
|
|
|
|
def get_task_name(self):
|
|
"""Selected task name.
|
|
|
|
Returns:
|
|
Union[str, None]: Selected task name.
|
|
|
|
"""
|
|
if self._task_id is None:
|
|
return None
|
|
if self._task_name is None:
|
|
self._task_name = self.task_entity["name"]
|
|
return self._task_name
|
|
|
|
def get_workfile_id(self):
|
|
"""Selected workfile id.
|
|
|
|
Returns:
|
|
Union[str, None]: Selected workfile id.
|
|
|
|
"""
|
|
return self._workfile_id
|
|
|
|
def get_project_entity(self):
|
|
"""Project entity for the selection.
|
|
|
|
Returns:
|
|
Union[dict[str, Any], None]: Project entity.
|
|
|
|
"""
|
|
if self._project_name is None:
|
|
return None
|
|
if self._project_entity is None:
|
|
self._project_entity = ayon_api.get_project(self._project_name)
|
|
return self._project_entity
|
|
|
|
def get_folder_entity(self):
|
|
"""Folder entity for the selection.
|
|
|
|
Returns:
|
|
Union[dict[str, Any], None]: Folder entity.
|
|
|
|
"""
|
|
if self._project_name is None or self._folder_id is None:
|
|
return None
|
|
if self._folder_entity is None:
|
|
self._folder_entity = ayon_api.get_folder_by_id(
|
|
self._project_name, self._folder_id
|
|
)
|
|
return self._folder_entity
|
|
|
|
def get_task_entity(self):
|
|
"""Task entity for the selection.
|
|
|
|
Returns:
|
|
Union[dict[str, Any], None]: Task entity.
|
|
|
|
"""
|
|
if (
|
|
self._project_name is None
|
|
or self._task_id is None
|
|
):
|
|
return None
|
|
if self._task_entity is None:
|
|
self._task_entity = ayon_api.get_task_by_id(
|
|
self._project_name, self._task_id
|
|
)
|
|
return self._task_entity
|
|
|
|
def get_workfile_entity(self):
|
|
"""Workfile entity for the selection.
|
|
|
|
Returns:
|
|
Union[dict[str, Any], None]: Workfile entity.
|
|
|
|
"""
|
|
if (
|
|
self._project_name is None
|
|
or self._workfile_id is None
|
|
):
|
|
return None
|
|
if self._workfile_entity is None:
|
|
self._workfile_entity = ayon_api.get_workfile_info_by_id(
|
|
self._project_name, self._workfile_id
|
|
)
|
|
return self._workfile_entity
|
|
|
|
def get_project_settings(self):
|
|
"""Project settings for the selection.
|
|
|
|
Returns:
|
|
dict[str, Any]: Project settings or studio settings if
|
|
project is not selected.
|
|
|
|
"""
|
|
if self._project_settings is None:
|
|
if self._project_name is None:
|
|
settings = get_studio_settings()
|
|
else:
|
|
settings = get_project_settings(self._project_name)
|
|
self._project_settings = settings
|
|
return self._project_settings
|
|
|
|
@property
|
|
def is_project_selected(self):
|
|
"""Return whether a project is selected.
|
|
|
|
Returns:
|
|
bool: Whether a project is selected.
|
|
|
|
"""
|
|
return self._project_name is not None
|
|
|
|
@property
|
|
def is_folder_selected(self):
|
|
"""Return whether a folder is selected.
|
|
|
|
Returns:
|
|
bool: Whether a folder is selected.
|
|
|
|
"""
|
|
return self._folder_id is not None
|
|
|
|
@property
|
|
def is_task_selected(self):
|
|
"""Return whether a task is selected.
|
|
|
|
Returns:
|
|
bool: Whether a task is selected.
|
|
|
|
"""
|
|
return self._task_id is not None
|
|
|
|
@property
|
|
def is_workfile_selected(self):
|
|
"""Return whether a task is selected.
|
|
|
|
Returns:
|
|
bool: Whether a task is selected.
|
|
|
|
"""
|
|
return self._workfile_id is not None
|
|
|
|
project_name = property(get_project_name)
|
|
folder_id = property(get_folder_id)
|
|
task_id = property(get_task_id)
|
|
workfile_id = property(get_workfile_id)
|
|
folder_path = property(get_folder_path)
|
|
task_name = property(get_task_name)
|
|
|
|
project_entity = property(get_project_entity)
|
|
folder_entity = property(get_folder_entity)
|
|
task_entity = property(get_task_entity)
|
|
workfile_entity = property(get_workfile_entity)
|
|
|
|
|
|
class LauncherAction(object):
|
|
"""A custom action available"""
|
|
name = None
|
|
label = None
|
|
icon = None
|
|
color = None
|
|
order = 0
|
|
|
|
log = logging.getLogger("LauncherAction")
|
|
log.propagate = True
|
|
|
|
def is_compatible(self, selection):
|
|
"""Return whether the class is compatible with the Session.
|
|
|
|
Args:
|
|
selection (LauncherActionSelection): Data with selection.
|
|
|
|
"""
|
|
return True
|
|
|
|
def process(self, selection, **kwargs):
|
|
"""Process the action.
|
|
|
|
Args:
|
|
selection (LauncherActionSelection): Data with selection.
|
|
**kwargs: Additional arguments.
|
|
|
|
"""
|
|
pass
|
|
|
|
|
|
class InventoryAction(object):
|
|
"""A custom action for the scene inventory tool
|
|
|
|
If registered the action will be visible in the Right Mouse Button menu
|
|
under the submenu "Actions".
|
|
|
|
"""
|
|
|
|
label = None
|
|
icon = None
|
|
color = None
|
|
order = 0
|
|
|
|
log = logging.getLogger("InventoryAction")
|
|
log.propagate = True
|
|
|
|
@staticmethod
|
|
def is_compatible(container):
|
|
"""Override function in a custom class
|
|
|
|
This method is specifically used to ensure the action can operate on
|
|
the container.
|
|
|
|
Args:
|
|
container(dict): the data of a loaded asset, see host.ls()
|
|
|
|
Returns:
|
|
bool
|
|
"""
|
|
return bool(container.get("objectName"))
|
|
|
|
def process(self, containers):
|
|
"""Override function in a custom class
|
|
|
|
This method will receive all containers even those which are
|
|
incompatible. It is advised to create a small filter along the lines
|
|
of this example:
|
|
|
|
valid_containers = filter(self.is_compatible(c) for c in containers)
|
|
|
|
The return value will need to be a True-ish value to trigger
|
|
the data_changed signal in order to refresh the view.
|
|
|
|
You can return a list of container names to trigger GUI to select
|
|
treeview items.
|
|
|
|
You can return a dict to carry extra GUI options. For example:
|
|
{
|
|
"objectNames": [container names...],
|
|
"options": {"mode": "toggle",
|
|
"clear": False}
|
|
}
|
|
Currently workable GUI options are:
|
|
- clear (bool): Clear current selection before selecting by action.
|
|
Default `True`.
|
|
- mode (str): selection mode, use one of these:
|
|
"select", "deselect", "toggle". Default is "select".
|
|
|
|
Args:
|
|
containers (list): list of dictionaries
|
|
|
|
Return:
|
|
bool, list or dict
|
|
|
|
"""
|
|
return True
|
|
|
|
@classmethod
|
|
def filepath_from_context(cls, context):
|
|
return get_representation_path_from_context(context)
|
|
|
|
|
|
# Launcher action
|
|
def discover_launcher_actions():
|
|
return discover(LauncherAction)
|
|
|
|
|
|
def register_launcher_action(plugin):
|
|
return register_plugin(LauncherAction, plugin)
|
|
|
|
|
|
def register_launcher_action_path(path):
|
|
return register_plugin_path(LauncherAction, path)
|
|
|
|
|
|
# Inventory action
|
|
def discover_inventory_actions():
|
|
actions = discover(InventoryAction)
|
|
filtered_actions = []
|
|
for action in actions:
|
|
if action is not InventoryAction:
|
|
filtered_actions.append(action)
|
|
|
|
return filtered_actions
|
|
|
|
|
|
def register_inventory_action(plugin):
|
|
return register_plugin(InventoryAction, plugin)
|
|
|
|
|
|
def deregister_inventory_action(plugin):
|
|
deregister_plugin(InventoryAction, plugin)
|
|
|
|
|
|
def register_inventory_action_path(path):
|
|
return register_plugin_path(InventoryAction, path)
|
|
|
|
|
|
def deregister_inventory_action_path(path):
|
|
return deregister_plugin_path(InventoryAction, path)
|