Merge pull request #3649 from BigRoy/loader_show_containers_in_scene

This commit is contained in:
Milan Kolar 2022-09-14 12:55:43 +02:00 committed by GitHub
commit be79e8b786
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 129 additions and 55 deletions

View file

@ -0,0 +1,28 @@
from Qt import QtWidgets, QtGui, QtCore
class LoadedInSceneDelegate(QtWidgets.QStyledItemDelegate):
"""Delegate for Loaded in Scene state columns.
Shows "yes" or "no" for True or False values
Colorizes green or dark grey based on True or False values
"""
def __init__(self, *args, **kwargs):
super(LoadedInSceneDelegate, self).__init__(*args, **kwargs)
self._colors = {
True: QtGui.QColor(80, 170, 80),
False: QtGui.QColor(90, 90, 90)
}
def displayText(self, value, locale):
return "yes" if value else "no"
def initStyleOption(self, option, index):
super(LoadedInSceneDelegate, self).initStyleOption(option, index)
# Colorize based on value
value = index.data(QtCore.Qt.DisplayRole)
color = self._colors[bool(value)]
option.palette.setBrush(QtGui.QPalette.Text, color)

View file

@ -17,6 +17,7 @@ from openpype.client import (
get_representations
)
from openpype.pipeline import (
registered_host,
HeroVersionType,
schema,
)
@ -24,6 +25,7 @@ from openpype.pipeline import (
from openpype.style import get_default_entity_icon_color
from openpype.tools.utils.models import TreeModel, Item
from openpype.tools.utils import lib
from openpype.host import ILoadHost
from openpype.modules import ModulesManager
from openpype.tools.utils.constants import (
@ -136,6 +138,7 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
"duration",
"handles",
"step",
"loaded_in_scene",
"repre_info"
]
@ -150,6 +153,7 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
"duration": "Duration",
"handles": "Handles",
"step": "Step",
"loaded_in_scene": "In scene",
"repre_info": "Availability"
}
@ -231,8 +235,14 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
self._doc_fetching_stop = False
self._doc_payload = {}
self.doc_fetched.connect(self._on_doc_fetched)
self._host = registered_host()
self._loaded_representation_ids = set()
# Refresh loaded scene containers only every 3 seconds at most
self._host_loaded_refresh_timeout = 3
self._host_loaded_refresh_time = 0
self.doc_fetched.connect(self._on_doc_fetched)
self.refresh()
def get_item_by_id(self, item_id):
@ -474,6 +484,27 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
last_versions_by_subset_id[subset_id] = hero_version
# Check loaded subsets
loaded_subset_ids = set()
ids = self._loaded_representation_ids
if ids:
if self._doc_fetching_stop:
return
# Get subset ids from loaded representations in workfile
# todo: optimize with aggregation query to distinct subset id
representations = get_representations(project_name,
representation_ids=ids,
fields=["parent"])
version_ids = set(repre["parent"] for repre in representations)
versions = get_versions(project_name,
version_ids=version_ids,
fields=["parent"])
loaded_subset_ids = set(version["parent"] for version in versions)
if self._doc_fetching_stop:
return
repre_info_by_version_id = {}
if self.sync_server.enabled:
versions_by_id = {}
@ -501,7 +532,8 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
"subset_docs_by_id": subset_docs_by_id,
"subset_families": subset_families,
"last_versions_by_subset_id": last_versions_by_subset_id,
"repre_info_by_version_id": repre_info_by_version_id
"repre_info_by_version_id": repre_info_by_version_id,
"subsets_loaded_by_id": loaded_subset_ids
}
self.doc_fetched.emit()
@ -533,6 +565,20 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
self.doc_fetched.emit()
return
# Collect scene container representations to compare loaded state
# This runs in the main thread because it involves the host DCC
if self._host:
time_since_refresh = time.time() - self._host_loaded_refresh_time
if time_since_refresh > self._host_loaded_refresh_timeout:
if isinstance(self._host, ILoadHost):
containers = self._host.get_containers()
else:
containers = self._host.ls()
repre_ids = {con.get("representation") for con in containers}
self._loaded_representation_ids = repre_ids
self._host_loaded_refresh_time = time.time()
self.fetch_subset_and_version()
def _on_doc_fetched(self):
@ -554,6 +600,10 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
"repre_info_by_version_id"
)
subsets_loaded_by_id = self._doc_payload.get(
"subsets_loaded_by_id"
)
if (
asset_docs_by_id is None
or subset_docs_by_id is None
@ -568,7 +618,8 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
asset_docs_by_id,
subset_docs_by_id,
last_versions_by_subset_id,
repre_info_by_version_id
repre_info_by_version_id,
subsets_loaded_by_id
)
self.endResetModel()
self.refreshed.emit(True)
@ -596,8 +647,12 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
return merge_group
def _fill_subset_items(
self, asset_docs_by_id, subset_docs_by_id, last_versions_by_subset_id,
repre_info_by_version_id
self,
asset_docs_by_id,
subset_docs_by_id,
last_versions_by_subset_id,
repre_info_by_version_id,
subsets_loaded_by_id
):
_groups_tuple = self.groups_config.split_subsets_for_groups(
subset_docs_by_id.values(), self._grouping
@ -621,6 +676,35 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
"index": self.index(group_item.row(), 0)
}
def _add_subset_item(subset_doc, parent_item, parent_index):
last_version = last_versions_by_subset_id.get(
subset_doc["_id"]
)
# do not show subset without version
if not last_version:
return
data = copy.deepcopy(subset_doc)
data["subset"] = subset_doc["name"]
asset_id = subset_doc["parent"]
data["asset"] = asset_docs_by_id[asset_id]["name"]
data["last_version"] = last_version
data["loaded_in_scene"] = subset_doc["_id"] in subsets_loaded_by_id
# Sync server data
data.update(
self._get_last_repre_info(repre_info_by_version_id,
last_version["_id"]))
item = Item()
item.update(data)
self.add_child(item, parent_item)
index = self.index(item.row(), 0, parent_index)
self.set_version(index, last_version)
subset_counter = 0
for group_name, subset_docs_by_name in subset_docs_by_group.items():
parent_item = group_item_by_name[group_name]["item"]
@ -643,31 +727,9 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
_parent_index = parent_index
for subset_doc in subset_docs:
asset_id = subset_doc["parent"]
data = copy.deepcopy(subset_doc)
data["subset"] = subset_name
data["asset"] = asset_docs_by_id[asset_id]["name"]
last_version = last_versions_by_subset_id.get(
subset_doc["_id"]
)
data["last_version"] = last_version
# do not show subset without version
if not last_version:
continue
data.update(
self._get_last_repre_info(repre_info_by_version_id,
last_version["_id"]))
item = Item()
item.update(data)
self.add_child(item, _parent_item)
index = self.index(item.row(), 0, _parent_index)
self.set_version(index, last_version)
_add_subset_item(subset_doc,
parent_item=_parent_item,
parent_index=_parent_index)
for subset_name in sorted(subset_docs_without_group.keys()):
subset_docs = subset_docs_without_group[subset_name]
@ -682,31 +744,9 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
subset_counter += 1
for subset_doc in subset_docs:
asset_id = subset_doc["parent"]
data = copy.deepcopy(subset_doc)
data["subset"] = subset_name
data["asset"] = asset_docs_by_id[asset_id]["name"]
last_version = last_versions_by_subset_id.get(
subset_doc["_id"]
)
data["last_version"] = last_version
# do not show subset without version
if not last_version:
continue
data.update(
self._get_last_repre_info(repre_info_by_version_id,
last_version["_id"]))
item = Item()
item.update(data)
self.add_child(item, parent_item)
index = self.index(item.row(), 0, parent_index)
self.set_version(index, last_version)
_add_subset_item(subset_doc,
parent_item=parent_item,
parent_index=parent_index)
def data(self, index, role):
if not index.isValid():

View file

@ -58,6 +58,7 @@ from .model import (
ITEM_ID_ROLE
)
from . import lib
from .delegates import LoadedInSceneDelegate
from openpype.tools.utils.constants import (
LOCAL_PROVIDER_ROLE,
@ -169,6 +170,7 @@ class SubsetWidget(QtWidgets.QWidget):
("duration", 60),
("handles", 55),
("step", 10),
("loaded_in_scene", 25),
("repre_info", 65)
)
@ -234,6 +236,10 @@ class SubsetWidget(QtWidgets.QWidget):
column = model.Columns.index("repre_info")
view.setItemDelegateForColumn(column, avail_delegate)
loaded_in_scene_delegate = LoadedInSceneDelegate(view)
column = model.Columns.index("loaded_in_scene")
view.setItemDelegateForColumn(column, loaded_in_scene_delegate)
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addLayout(top_bar_layout)