mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
Merge branch 'develop' into feature/909-define-basic-trait-type-using-dataclasses
This commit is contained in:
commit
51d7cc16af
17 changed files with 242 additions and 77 deletions
|
|
@ -1,12 +1,15 @@
|
||||||
from ayon_api import get_project, get_folder_by_path, get_task_by_name
|
from ayon_api import get_project, get_folder_by_path, get_task_by_name
|
||||||
|
|
||||||
|
from ayon_core.pipeline import Anatomy
|
||||||
|
from ayon_core.pipeline.anatomy import RootMissingEnv
|
||||||
|
|
||||||
from ayon_applications import PreLaunchHook
|
from ayon_applications import PreLaunchHook
|
||||||
|
from ayon_applications.exceptions import ApplicationLaunchFailed
|
||||||
from ayon_applications.utils import (
|
from ayon_applications.utils import (
|
||||||
EnvironmentPrepData,
|
EnvironmentPrepData,
|
||||||
prepare_app_environments,
|
prepare_app_environments,
|
||||||
prepare_context_environments
|
prepare_context_environments
|
||||||
)
|
)
|
||||||
from ayon_core.pipeline import Anatomy
|
|
||||||
|
|
||||||
|
|
||||||
class GlobalHostDataHook(PreLaunchHook):
|
class GlobalHostDataHook(PreLaunchHook):
|
||||||
|
|
@ -67,9 +70,12 @@ class GlobalHostDataHook(PreLaunchHook):
|
||||||
self.data["project_entity"] = project_entity
|
self.data["project_entity"] = project_entity
|
||||||
|
|
||||||
# Anatomy
|
# Anatomy
|
||||||
self.data["anatomy"] = Anatomy(
|
try:
|
||||||
project_name, project_entity=project_entity
|
self.data["anatomy"] = Anatomy(
|
||||||
)
|
project_name, project_entity=project_entity
|
||||||
|
)
|
||||||
|
except RootMissingEnv as exc:
|
||||||
|
raise ApplicationLaunchFailed(str(exc))
|
||||||
|
|
||||||
folder_path = self.data.get("folder_path")
|
folder_path = self.data.get("folder_path")
|
||||||
if not folder_path:
|
if not folder_path:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
ProjectNotSet,
|
ProjectNotSet,
|
||||||
|
RootMissingEnv,
|
||||||
RootCombinationError,
|
RootCombinationError,
|
||||||
TemplateMissingKey,
|
TemplateMissingKey,
|
||||||
AnatomyTemplateUnsolved,
|
AnatomyTemplateUnsolved,
|
||||||
|
|
@ -9,6 +10,7 @@ from .anatomy import Anatomy
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"ProjectNotSet",
|
"ProjectNotSet",
|
||||||
|
"RootMissingEnv",
|
||||||
"RootCombinationError",
|
"RootCombinationError",
|
||||||
"TemplateMissingKey",
|
"TemplateMissingKey",
|
||||||
"AnatomyTemplateUnsolved",
|
"AnatomyTemplateUnsolved",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ class ProjectNotSet(Exception):
|
||||||
"""Exception raised when is created Anatomy without project name."""
|
"""Exception raised when is created Anatomy without project name."""
|
||||||
|
|
||||||
|
|
||||||
|
class RootMissingEnv(KeyError):
|
||||||
|
"""Raised when root requires environment variables which is not filled."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RootCombinationError(Exception):
|
class RootCombinationError(Exception):
|
||||||
"""This exception is raised when templates has combined root types."""
|
"""This exception is raised when templates has combined root types."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@ import os
|
||||||
import platform
|
import platform
|
||||||
import numbers
|
import numbers
|
||||||
|
|
||||||
from ayon_core.lib import Logger
|
from ayon_core.lib import Logger, StringTemplate
|
||||||
from ayon_core.lib.path_templates import FormatObject
|
from ayon_core.lib.path_templates import FormatObject
|
||||||
|
|
||||||
|
from .exceptions import RootMissingEnv
|
||||||
|
|
||||||
|
|
||||||
class RootItem(FormatObject):
|
class RootItem(FormatObject):
|
||||||
"""Represents one item or roots.
|
"""Represents one item or roots.
|
||||||
|
|
@ -21,18 +23,36 @@ class RootItem(FormatObject):
|
||||||
multi root setup otherwise None value is expected.
|
multi root setup otherwise None value is expected.
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent, root_raw_data, name):
|
def __init__(self, parent, root_raw_data, name):
|
||||||
super(RootItem, self).__init__()
|
super().__init__()
|
||||||
self._log = None
|
self._log = None
|
||||||
lowered_platform_keys = {}
|
lowered_platform_keys = {
|
||||||
for key, value in root_raw_data.items():
|
key.lower(): value
|
||||||
lowered_platform_keys[key.lower()] = value
|
for key, value in root_raw_data.items()
|
||||||
|
}
|
||||||
self.raw_data = lowered_platform_keys
|
self.raw_data = lowered_platform_keys
|
||||||
self.cleaned_data = self._clean_roots(lowered_platform_keys)
|
self.cleaned_data = self._clean_roots(lowered_platform_keys)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
self.available_platforms = set(lowered_platform_keys.keys())
|
self.available_platforms = set(lowered_platform_keys.keys())
|
||||||
self.value = lowered_platform_keys.get(platform.system().lower())
|
|
||||||
|
current_platform = platform.system().lower()
|
||||||
|
# WARNING: Using environment variables in roots is not considered
|
||||||
|
# as production safe. Some features may not work as expected, for
|
||||||
|
# example USD resolver or site sync.
|
||||||
|
try:
|
||||||
|
self.value = lowered_platform_keys[current_platform].format_map(
|
||||||
|
os.environ
|
||||||
|
)
|
||||||
|
except KeyError:
|
||||||
|
result = StringTemplate(self.value).format(os.environ.copy())
|
||||||
|
is_are = "is" if len(result.missing_keys) == 1 else "are"
|
||||||
|
missing_keys = ", ".join(result.missing_keys)
|
||||||
|
raise RootMissingEnv(
|
||||||
|
f"Root \"{name}\" requires environment variable/s"
|
||||||
|
f" {missing_keys} which {is_are} not available."
|
||||||
|
)
|
||||||
|
|
||||||
self.clean_value = self._clean_root(self.value)
|
self.clean_value = self._clean_root(self.value)
|
||||||
|
|
||||||
def __format__(self, *args, **kwargs):
|
def __format__(self, *args, **kwargs):
|
||||||
|
|
@ -105,10 +125,10 @@ class RootItem(FormatObject):
|
||||||
|
|
||||||
def _clean_roots(self, raw_data):
|
def _clean_roots(self, raw_data):
|
||||||
"""Clean all values of raw root item values."""
|
"""Clean all values of raw root item values."""
|
||||||
cleaned = {}
|
return {
|
||||||
for key, value in raw_data.items():
|
key: self._clean_root(value)
|
||||||
cleaned[key] = self._clean_root(value)
|
for key, value in raw_data.items()
|
||||||
return cleaned
|
}
|
||||||
|
|
||||||
def path_remapper(self, path, dst_platform=None, src_platform=None):
|
def path_remapper(self, path, dst_platform=None, src_platform=None):
|
||||||
"""Remap path for specific platform.
|
"""Remap path for specific platform.
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ from .workfile import (
|
||||||
get_workdir,
|
get_workdir,
|
||||||
get_custom_workfile_template_by_string_context,
|
get_custom_workfile_template_by_string_context,
|
||||||
get_workfile_template_key_from_context,
|
get_workfile_template_key_from_context,
|
||||||
get_last_workfile
|
get_last_workfile,
|
||||||
|
MissingWorkdirError,
|
||||||
)
|
)
|
||||||
from . import (
|
from . import (
|
||||||
register_loader_plugin_path,
|
register_loader_plugin_path,
|
||||||
|
|
@ -251,7 +252,7 @@ def uninstall_host():
|
||||||
pyblish.api.deregister_discovery_filter(filter_pyblish_plugins)
|
pyblish.api.deregister_discovery_filter(filter_pyblish_plugins)
|
||||||
deregister_loader_plugin_path(LOAD_PATH)
|
deregister_loader_plugin_path(LOAD_PATH)
|
||||||
deregister_inventory_action_path(INVENTORY_PATH)
|
deregister_inventory_action_path(INVENTORY_PATH)
|
||||||
log.info("Global plug-ins unregistred")
|
log.info("Global plug-ins unregistered")
|
||||||
|
|
||||||
deregister_host()
|
deregister_host()
|
||||||
|
|
||||||
|
|
@ -617,7 +618,18 @@ def version_up_current_workfile():
|
||||||
last_workfile_path = get_last_workfile(
|
last_workfile_path = get_last_workfile(
|
||||||
work_root, file_template, data, extensions, True
|
work_root, file_template, data, extensions, True
|
||||||
)
|
)
|
||||||
new_workfile_path = version_up(last_workfile_path)
|
# `get_last_workfile` will return the first expected file version
|
||||||
|
# if no files exist yet. In that case, if they do not exist we will
|
||||||
|
# want to save v001
|
||||||
|
new_workfile_path = last_workfile_path
|
||||||
if os.path.exists(new_workfile_path):
|
if os.path.exists(new_workfile_path):
|
||||||
new_workfile_path = version_up(new_workfile_path)
|
new_workfile_path = version_up(new_workfile_path)
|
||||||
|
|
||||||
|
# Raise an error if the parent folder doesn't exist as `host.save_workfile`
|
||||||
|
# is not supposed/able to create missing folders.
|
||||||
|
parent_folder = os.path.dirname(new_workfile_path)
|
||||||
|
if not os.path.exists(parent_folder):
|
||||||
|
raise MissingWorkdirError(
|
||||||
|
f"Work area directory '{parent_folder}' does not exist.")
|
||||||
|
|
||||||
host.save_workfile(new_workfile_path)
|
host.save_workfile(new_workfile_path)
|
||||||
|
|
|
||||||
|
|
@ -2303,10 +2303,16 @@ class CreateContext:
|
||||||
for plugin_name, plugin_value in item_changes.pop(
|
for plugin_name, plugin_value in item_changes.pop(
|
||||||
"publish_attributes"
|
"publish_attributes"
|
||||||
).items():
|
).items():
|
||||||
|
if plugin_value is None:
|
||||||
|
current_publish[plugin_name] = None
|
||||||
|
continue
|
||||||
plugin_changes = current_publish.setdefault(
|
plugin_changes = current_publish.setdefault(
|
||||||
plugin_name, {}
|
plugin_name, {}
|
||||||
)
|
)
|
||||||
plugin_changes.update(plugin_value)
|
if plugin_changes is None:
|
||||||
|
current_publish[plugin_name] = plugin_value
|
||||||
|
else:
|
||||||
|
plugin_changes.update(plugin_value)
|
||||||
|
|
||||||
item_values.update(item_changes)
|
item_values.update(item_changes)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,29 +160,26 @@ class AttributeValues:
|
||||||
return self._attr_defs_by_key.get(key, default)
|
return self._attr_defs_by_key.get(key, default)
|
||||||
|
|
||||||
def update(self, value):
|
def update(self, value):
|
||||||
changes = {}
|
changes = self._update(value)
|
||||||
for _key, _value in dict(value).items():
|
|
||||||
if _key in self._data and self._data.get(_key) == _value:
|
|
||||||
continue
|
|
||||||
self._data[_key] = _value
|
|
||||||
changes[_key] = _value
|
|
||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
self._parent.attribute_value_changed(self._key, changes)
|
self._parent.attribute_value_changed(self._key, changes)
|
||||||
|
|
||||||
def pop(self, key, default=None):
|
def pop(self, key, default=None):
|
||||||
has_key = key in self._data
|
value, changes = self._pop(key, default)
|
||||||
value = self._data.pop(key, default)
|
if changes:
|
||||||
# Remove attribute definition if is 'UnknownDef'
|
self._parent.attribute_value_changed(self._key, changes)
|
||||||
# - gives option to get rid of unknown values
|
|
||||||
attr_def = self._attr_defs_by_key.get(key)
|
|
||||||
if isinstance(attr_def, UnknownDef):
|
|
||||||
self._attr_defs_by_key.pop(key)
|
|
||||||
self._attr_defs.remove(attr_def)
|
|
||||||
elif has_key:
|
|
||||||
self._parent.attribute_value_changed(self._key, {key: None})
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def set_value(self, value):
|
||||||
|
pop_keys = set(value.keys()) - set(self._data.keys())
|
||||||
|
changes = self._update(value)
|
||||||
|
for key in pop_keys:
|
||||||
|
_, key_changes = self._pop(key, None)
|
||||||
|
changes.update(key_changes)
|
||||||
|
|
||||||
|
if changes:
|
||||||
|
self._parent.attribute_value_changed(self._key, changes)
|
||||||
|
|
||||||
def reset_values(self):
|
def reset_values(self):
|
||||||
self._data = {}
|
self._data = {}
|
||||||
|
|
||||||
|
|
@ -228,6 +225,29 @@ class AttributeValues:
|
||||||
|
|
||||||
return serialize_attr_defs(self._attr_defs)
|
return serialize_attr_defs(self._attr_defs)
|
||||||
|
|
||||||
|
def _update(self, value):
|
||||||
|
changes = {}
|
||||||
|
for key, value in dict(value).items():
|
||||||
|
if key in self._data and self._data.get(key) == value:
|
||||||
|
continue
|
||||||
|
self._data[key] = value
|
||||||
|
changes[key] = value
|
||||||
|
return changes
|
||||||
|
|
||||||
|
def _pop(self, key, default):
|
||||||
|
has_key = key in self._data
|
||||||
|
value = self._data.pop(key, default)
|
||||||
|
# Remove attribute definition if is 'UnknownDef'
|
||||||
|
# - gives option to get rid of unknown values
|
||||||
|
attr_def = self._attr_defs_by_key.get(key)
|
||||||
|
changes = {}
|
||||||
|
if isinstance(attr_def, UnknownDef):
|
||||||
|
self._attr_defs_by_key.pop(key)
|
||||||
|
self._attr_defs.remove(attr_def)
|
||||||
|
elif has_key:
|
||||||
|
changes[key] = None
|
||||||
|
return value, changes
|
||||||
|
|
||||||
|
|
||||||
class CreatorAttributeValues(AttributeValues):
|
class CreatorAttributeValues(AttributeValues):
|
||||||
"""Creator specific attribute values of an instance."""
|
"""Creator specific attribute values of an instance."""
|
||||||
|
|
@ -270,6 +290,23 @@ class PublishAttributes:
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self._data[key]
|
return self._data[key]
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
"""Set value for plugin.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key (str): Plugin name.
|
||||||
|
value (dict[str, Any]): Value to set.
|
||||||
|
|
||||||
|
"""
|
||||||
|
current_value = self._data.get(key)
|
||||||
|
if isinstance(current_value, PublishAttributeValues):
|
||||||
|
current_value.set_value(value)
|
||||||
|
else:
|
||||||
|
self._data[key] = value
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
self.pop(key)
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return key in self._data
|
return key in self._data
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,11 +226,26 @@ class _CacheItems:
|
||||||
thumbnails_cache = ThumbnailsCache()
|
thumbnails_cache = ThumbnailsCache()
|
||||||
|
|
||||||
|
|
||||||
def get_thumbnail_path(project_name, thumbnail_id):
|
def get_thumbnail_path(
|
||||||
|
project_name: str,
|
||||||
|
entity_type: str,
|
||||||
|
entity_id: str,
|
||||||
|
thumbnail_id: str
|
||||||
|
):
|
||||||
"""Get path to thumbnail image.
|
"""Get path to thumbnail image.
|
||||||
|
|
||||||
|
Thumbnail is cached by thumbnail id but is received using entity type and
|
||||||
|
entity id.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
Function 'get_thumbnail_by_id' can't be used because does not work
|
||||||
|
for artists. The endpoint can't validate artist permissions.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
project_name (str): Project where thumbnail belongs to.
|
project_name (str): Project where thumbnail belongs to.
|
||||||
|
entity_type (str): Entity type "folder", "task", "version"
|
||||||
|
and "workfile".
|
||||||
|
entity_id (str): Entity id.
|
||||||
thumbnail_id (Union[str, None]): Thumbnail id.
|
thumbnail_id (Union[str, None]): Thumbnail id.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
@ -251,7 +266,7 @@ def get_thumbnail_path(project_name, thumbnail_id):
|
||||||
# 'get_thumbnail_by_id' did not return output of
|
# 'get_thumbnail_by_id' did not return output of
|
||||||
# 'ServerAPI' method.
|
# 'ServerAPI' method.
|
||||||
con = ayon_api.get_server_api_connection()
|
con = ayon_api.get_server_api_connection()
|
||||||
result = con.get_thumbnail_by_id(project_name, thumbnail_id)
|
result = con.get_thumbnail(project_name, entity_type, entity_id)
|
||||||
|
|
||||||
if result is not None and result.is_valid:
|
if result is not None and result.is_valid:
|
||||||
return _CacheItems.thumbnails_cache.store_thumbnail(
|
return _CacheItems.thumbnails_cache.store_thumbnail(
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ from .path_resolving import (
|
||||||
from .utils import (
|
from .utils import (
|
||||||
should_use_last_workfile_on_launch,
|
should_use_last_workfile_on_launch,
|
||||||
should_open_workfiles_tool_on_launch,
|
should_open_workfiles_tool_on_launch,
|
||||||
|
MissingWorkdirError,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .build_workfile import BuildWorkfile
|
from .build_workfile import BuildWorkfile
|
||||||
|
|
@ -46,6 +47,7 @@ __all__ = (
|
||||||
|
|
||||||
"should_use_last_workfile_on_launch",
|
"should_use_last_workfile_on_launch",
|
||||||
"should_open_workfiles_tool_on_launch",
|
"should_open_workfiles_tool_on_launch",
|
||||||
|
"MissingWorkdirError",
|
||||||
|
|
||||||
"BuildWorkfile",
|
"BuildWorkfile",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,11 @@ from ayon_core.lib import filter_profiles
|
||||||
from ayon_core.settings import get_project_settings
|
from ayon_core.settings import get_project_settings
|
||||||
|
|
||||||
|
|
||||||
|
class MissingWorkdirError(Exception):
|
||||||
|
"""Raised when accessing a work directory not found on disk."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def should_use_last_workfile_on_launch(
|
def should_use_last_workfile_on_launch(
|
||||||
project_name,
|
project_name,
|
||||||
host_name,
|
host_name,
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,50 @@ class ThumbnailsModel:
|
||||||
self._folders_cache.reset()
|
self._folders_cache.reset()
|
||||||
self._versions_cache.reset()
|
self._versions_cache.reset()
|
||||||
|
|
||||||
def get_thumbnail_path(self, project_name, thumbnail_id):
|
def get_thumbnail_paths(
|
||||||
return self._get_thumbnail_path(project_name, thumbnail_id)
|
self,
|
||||||
|
project_name,
|
||||||
|
entity_type,
|
||||||
|
entity_ids,
|
||||||
|
):
|
||||||
|
thumbnail_paths = set()
|
||||||
|
if not project_name or not entity_type or not entity_ids:
|
||||||
|
return thumbnail_paths
|
||||||
|
|
||||||
|
thumbnail_id_by_entity_id = {}
|
||||||
|
if entity_type == "folder":
|
||||||
|
thumbnail_id_by_entity_id = self.get_folder_thumbnail_ids(
|
||||||
|
project_name, entity_ids
|
||||||
|
)
|
||||||
|
|
||||||
|
elif entity_type == "version":
|
||||||
|
thumbnail_id_by_entity_id = self.get_version_thumbnail_ids(
|
||||||
|
project_name, entity_ids
|
||||||
|
)
|
||||||
|
|
||||||
|
if not thumbnail_id_by_entity_id:
|
||||||
|
return thumbnail_paths
|
||||||
|
|
||||||
|
entity_ids_by_thumbnail_id = collections.defaultdict(set)
|
||||||
|
for entity_id, thumbnail_id in thumbnail_id_by_entity_id.items():
|
||||||
|
if not thumbnail_id:
|
||||||
|
continue
|
||||||
|
entity_ids_by_thumbnail_id[thumbnail_id].add(entity_id)
|
||||||
|
|
||||||
|
output = {
|
||||||
|
entity_id: None
|
||||||
|
for entity_id in entity_ids
|
||||||
|
}
|
||||||
|
for thumbnail_id, entity_ids in entity_ids_by_thumbnail_id.items():
|
||||||
|
thumbnail_path = self._get_thumbnail_path(
|
||||||
|
project_name, entity_type, next(iter(entity_ids)), thumbnail_id
|
||||||
|
)
|
||||||
|
if not thumbnail_path:
|
||||||
|
continue
|
||||||
|
for entity_id in entity_ids:
|
||||||
|
output[entity_id] = thumbnail_path
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
def get_folder_thumbnail_ids(self, project_name, folder_ids):
|
def get_folder_thumbnail_ids(self, project_name, folder_ids):
|
||||||
project_cache = self._folders_cache[project_name]
|
project_cache = self._folders_cache[project_name]
|
||||||
|
|
@ -56,7 +98,13 @@ class ThumbnailsModel:
|
||||||
output[version_id] = cache.get_data()
|
output[version_id] = cache.get_data()
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def _get_thumbnail_path(self, project_name, thumbnail_id):
|
def _get_thumbnail_path(
|
||||||
|
self,
|
||||||
|
project_name,
|
||||||
|
entity_type,
|
||||||
|
entity_id,
|
||||||
|
thumbnail_id
|
||||||
|
):
|
||||||
if not thumbnail_id:
|
if not thumbnail_id:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
@ -64,7 +112,12 @@ class ThumbnailsModel:
|
||||||
if thumbnail_id in project_cache:
|
if thumbnail_id in project_cache:
|
||||||
return project_cache[thumbnail_id]
|
return project_cache[thumbnail_id]
|
||||||
|
|
||||||
filepath = get_thumbnail_path(project_name, thumbnail_id)
|
filepath = get_thumbnail_path(
|
||||||
|
project_name,
|
||||||
|
entity_type,
|
||||||
|
entity_id,
|
||||||
|
thumbnail_id
|
||||||
|
)
|
||||||
project_cache[thumbnail_id] = filepath
|
project_cache[thumbnail_id] = filepath
|
||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -733,7 +733,12 @@ class FrontendLoaderController(_BaseLoaderController):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_thumbnail_path(self, project_name, thumbnail_id):
|
def get_thumbnail_paths(
|
||||||
|
self,
|
||||||
|
project_name,
|
||||||
|
entity_type,
|
||||||
|
entity_ids
|
||||||
|
):
|
||||||
"""Get thumbnail path for thumbnail id.
|
"""Get thumbnail path for thumbnail id.
|
||||||
|
|
||||||
This method should get a path to a thumbnail based on thumbnail id.
|
This method should get a path to a thumbnail based on thumbnail id.
|
||||||
|
|
@ -742,10 +747,11 @@ class FrontendLoaderController(_BaseLoaderController):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
project_name (str): Project name.
|
project_name (str): Project name.
|
||||||
thumbnail_id (str): Thumbnail id.
|
entity_type (str): Entity type.
|
||||||
|
entity_ids (set[str]): Entity ids.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Union[str, None]: Thumbnail path or None if not found.
|
dict[str, Union[str, None]]: Thumbnail path by entity id.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -259,9 +259,14 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
||||||
project_name, version_ids
|
project_name, version_ids
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_thumbnail_path(self, project_name, thumbnail_id):
|
def get_thumbnail_paths(
|
||||||
return self._thumbnails_model.get_thumbnail_path(
|
self,
|
||||||
project_name, thumbnail_id
|
project_name,
|
||||||
|
entity_type,
|
||||||
|
entity_ids,
|
||||||
|
):
|
||||||
|
return self._thumbnails_model.get_thumbnail_paths(
|
||||||
|
project_name, entity_type, entity_ids
|
||||||
)
|
)
|
||||||
|
|
||||||
def change_products_group(self, project_name, product_ids, group_name):
|
def change_products_group(self, project_name, product_ids, group_name):
|
||||||
|
|
|
||||||
|
|
@ -501,38 +501,29 @@ class LoaderWindow(QtWidgets.QWidget):
|
||||||
self._update_thumbnails()
|
self._update_thumbnails()
|
||||||
|
|
||||||
def _update_thumbnails(self):
|
def _update_thumbnails(self):
|
||||||
|
# TODO make this threaded and show loading animation while running
|
||||||
project_name = self._selected_project_name
|
project_name = self._selected_project_name
|
||||||
thumbnail_ids = set()
|
entity_type = None
|
||||||
|
entity_ids = set()
|
||||||
if self._selected_version_ids:
|
if self._selected_version_ids:
|
||||||
thumbnail_id_by_entity_id = (
|
entity_ids = set(self._selected_version_ids)
|
||||||
self._controller.get_version_thumbnail_ids(
|
entity_type = "version"
|
||||||
project_name,
|
|
||||||
self._selected_version_ids
|
|
||||||
)
|
|
||||||
)
|
|
||||||
thumbnail_ids = set(thumbnail_id_by_entity_id.values())
|
|
||||||
elif self._selected_folder_ids:
|
elif self._selected_folder_ids:
|
||||||
thumbnail_id_by_entity_id = (
|
entity_ids = set(self._selected_folder_ids)
|
||||||
self._controller.get_folder_thumbnail_ids(
|
entity_type = "folder"
|
||||||
project_name,
|
|
||||||
self._selected_folder_ids
|
|
||||||
)
|
|
||||||
)
|
|
||||||
thumbnail_ids = set(thumbnail_id_by_entity_id.values())
|
|
||||||
|
|
||||||
thumbnail_ids.discard(None)
|
thumbnail_path_by_entity_id = self._controller.get_thumbnail_paths(
|
||||||
|
project_name, entity_type, entity_ids
|
||||||
if not thumbnail_ids:
|
)
|
||||||
self._thumbnails_widget.set_current_thumbnails(None)
|
thumbnail_paths = set(thumbnail_path_by_entity_id.values())
|
||||||
return
|
|
||||||
|
|
||||||
thumbnail_paths = set()
|
|
||||||
for thumbnail_id in thumbnail_ids:
|
|
||||||
thumbnail_path = self._controller.get_thumbnail_path(
|
|
||||||
project_name, thumbnail_id)
|
|
||||||
thumbnail_paths.add(thumbnail_path)
|
|
||||||
thumbnail_paths.discard(None)
|
thumbnail_paths.discard(None)
|
||||||
self._thumbnails_widget.set_current_thumbnail_paths(thumbnail_paths)
|
|
||||||
|
if thumbnail_paths:
|
||||||
|
self._thumbnails_widget.set_current_thumbnail_paths(
|
||||||
|
thumbnail_paths
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._thumbnails_widget.set_current_thumbnails(None)
|
||||||
|
|
||||||
def _on_projects_refresh(self):
|
def _on_projects_refresh(self):
|
||||||
self._refresh_handler.set_project_refreshed()
|
self._refresh_handler.set_project_refreshed()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Package declaring AYON addon 'core' version."""
|
"""Package declaring AYON addon 'core' version."""
|
||||||
__version__ = "1.1.6+dev"
|
__version__ = "1.1.7+dev"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
name = "core"
|
name = "core"
|
||||||
title = "Core"
|
title = "Core"
|
||||||
version = "1.1.6+dev"
|
version = "1.1.7+dev"
|
||||||
|
|
||||||
client_dir = "ayon_core"
|
client_dir = "ayon_core"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "ayon-core"
|
name = "ayon-core"
|
||||||
version = "1.1.6+dev"
|
version = "1.1.7+dev"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Ynput Team <team@ynput.io>"]
|
authors = ["Ynput Team <team@ynput.io>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue