Panel update + fix for remove function so it doesn't remove all instances

This commit is contained in:
Nero Frame 13 committed 2026-10-28 11:03:16 +01:00
1 parent fbc7ac18e4
commit 3f87904cd1
5 files changed
+182 -159

No files matched your search

+171 -41
View File
@@ -3,11 +3,11 @@ import textwrap
import bpy
from .. import config, rename, shot_viewer, tools_ops
from ..core import CheckContext, Severity, checks_for_context, contexts, runner
from ..core.runner import Status
from ..scene_manager import ipc
from ..scene_manager import library as sm_library
from ..scene_manager import operators as sm
from ..core import CheckContext, Severity, checks_for_context, contexts, runner
from ..core.runner import Status
from .operators import EXPANDED
STATUS_ICONS = {
@@ -244,7 +244,18 @@ class _RenamePanel:
class WTD_UL_shots(bpy.types.UIList):
"""Camera markers of the scene, in time order."""
def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
def draw_item(
self,
context,
layout,
data,
item,
icon,
active_data,
active_property,
index=0,
flt_flag=0,
):
start, end = shot_viewer.shot_range(item)
split = layout.split(factor=0.4)
split.label(text=item.name, icon="MARKER_HLT")
@@ -256,7 +267,10 @@ class WTD_UL_shots(bpy.types.UIList):
markers = getattr(data, propname)
ordered = [marker.as_pointer() for marker in shot_viewer.shots(data)]
position = {pointer: index for index, pointer in enumerate(ordered)}
flags = [self.bitflag_filter_item if marker.as_pointer() in position else 0 for marker in markers]
flags = [
self.bitflag_filter_item if marker.as_pointer() in position else 0
for marker in markers
]
if self.filter_name:
by_name = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, markers, "name"
@@ -294,13 +308,33 @@ class _ShotViewerPanel:
row = layout.row(align=True)
row.scale_y = 1.4
row.enabled = has_shots
row.operator(shot_viewer.WTD_OT_shot_viewer_step.bl_idname, text="Previous", icon="TRIA_LEFT").step = -1
row.operator(shot_viewer.WTD_OT_shot_viewer_step.bl_idname, text="Next", icon="TRIA_RIGHT").step = 1
row.operator(
shot_viewer.WTD_OT_shot_viewer_step.bl_idname,
text="Previous",
icon="TRIA_LEFT",
).step = -1
row.operator(
shot_viewer.WTD_OT_shot_viewer_step.bl_idname,
text="Next",
icon="TRIA_RIGHT",
).step = 1
row = layout.row()
row.template_list("WTD_UL_shots", "", scene, "timeline_markers", settings, "shot_index", rows=5)
row.template_list(
"WTD_UL_shots",
"",
scene,
"timeline_markers",
settings,
"shot_index",
rows=5,
)
col = row.column(align=True)
col.operator(shot_viewer.WTD_OT_shot_viewer_new_shot.bl_idname, text="", icon="ADD")
col.operator(shot_viewer.WTD_OT_shot_viewer_delete_shot.bl_idname, text="", icon="REMOVE")
col.operator(
shot_viewer.WTD_OT_shot_viewer_new_shot.bl_idname, text="", icon="ADD"
)
col.operator(
shot_viewer.WTD_OT_shot_viewer_delete_shot.bl_idname, text="", icon="REMOVE"
)
if not has_shots:
layout.label(text="No camera marker yet: add a shot with +", icon="INFO")
layout.prop(settings, "loop_shot")
@@ -355,8 +389,14 @@ class _SceneManagerPanel:
layout.prop(scene.wtd_scene_manager, "context_oid", text="", icon="SEQUENCE")
row = layout.row(align=True)
row.operator(sm.WTD_OT_scene_use_current_oid.bl_idname, text="Libreflow Oid", icon="IMPORT")
row.operator(sm.WTD_OT_scene_pick_shot.bl_idname, text="Pick Shot", icon="VIEWZOOM")
row.operator(
sm.WTD_OT_scene_use_current_oid.bl_idname,
text="Libreflow Oid",
icon="IMPORT",
)
row.operator(
sm.WTD_OT_scene_pick_shot.bl_idname, text="Pick Shot", icon="VIEWZOOM"
)
text, valid = sm.context_label(sm.context_oid(scene))
if text:
row = layout.row()
@@ -386,11 +426,17 @@ class _SceneCastingPanel:
row.scale_y = 1.3
row.operator(sm.WTD_OT_scene_load.bl_idname, text="Load Missing", icon="IMPORT")
if sm.missing_files(context.scene):
row.operator(sm.WTD_OT_scene_request.bl_idname, text="Request Missing", icon="URL")
row.operator(
sm.WTD_OT_scene_request.bl_idname, text="Request Missing", icon="URL"
)
row.operator(sm.WTD_OT_scene_refresh.bl_idname, text="", icon="FILE_REFRESH")
casting = sm.STATE.casting.get(oid)
if casting is None:
text = "Not read yet: refresh" if sm.is_shot_context(oid) else "Set a shot as context"
text = (
"Not read yet: refresh"
if sm.is_shot_context(oid)
else "Set a shot as context"
)
layout.label(text=text, icon="INFO")
return
if not casting["assets"]:
@@ -399,36 +445,64 @@ class _SceneCastingPanel:
found = sm_library.all_instances()
col = layout.column(align=True)
for asset in casting["assets"]:
library = sm_library.find_library(asset["file"]["file_oid"]) if asset.get("file") else None
library = (
sm_library.find_library(asset["file"]["file_oid"])
if asset.get("file")
else None
)
have = len(found.get(library.name, [])) if library else 0
want = asset.get("nb_occurences") or 1
error = asset.get("error")
file = sm.file_data(asset["file"]["file_oid"], asset["file"]) if asset.get("file") else None
file = (
sm.file_data(asset["file"]["file_oid"], asset["file"])
if asset.get("file")
else None
)
latest = (file or {}).get("latest") or {}
requested = bool(error) and latest.get("sync_status") == "Requested"
if requested:
error = f"{latest['name']} requested, waiting for the download"
icon = "SORTTIME" if requested else "ERROR" if error else "CHECKMARK" if have >= want else "IMPORT"
icon = (
"SORTTIME"
if requested
else "ERROR"
if error
else "CHECKMARK"
if have >= want
else "IMPORT"
)
row = col.row(align=True)
row.alert = bool(error) and not requested
row.label(text=f"{asset['name']} ({asset.get('asset_type', '')})", icon=icon)
row.label(
text=f"{asset['name']} ({asset.get('asset_type', '')})", icon=icon
)
row.label(text=f"{have}/{want}")
if not error and have < want:
row.operator(sm.WTD_OT_scene_load.bl_idname, text="", icon="IMPORT").asset_oid = asset["oid"]
row.operator(
sm.WTD_OT_scene_load.bl_idname, text="", icon="IMPORT"
).asset_oid = asset["oid"]
if sm.to_request(file):
row.operator(sm.WTD_OT_scene_request.bl_idname, text="", icon="URL").file_oid = file["file_oid"]
row.operator(
sm.WTD_OT_scene_request.bl_idname, text="", icon="URL"
).file_oid = file["file_oid"]
if error:
sub = col.row()
sub.alert = not requested
_wrapped_label(sub, context, error, icon="BLANK1")
cast = {asset["oid"] for asset in casting["assets"]}
extra = [library for library in sm_library.managed_libraries() if library["wtd_asset_oid"] not in cast]
extra = [
library
for library in sm_library.managed_libraries()
if library["wtd_asset_oid"] not in cast
]
if extra:
box = layout.box()
box.label(text="Loaded, no longer cast:", icon="ERROR")
for library in extra:
box.label(text=library.get("wtd_asset_name", library.name), icon="BLANK1")
box.label(
text=library.get("wtd_asset_name", library.name), icon="BLANK1"
)
class _SceneLoadedPanel:
@@ -439,13 +513,17 @@ class _SceneLoadedPanel:
def draw(self, context) -> None:
layout = self.layout
layout.operator(sm.WTD_OT_scene_browse.bl_idname, text="Load Publish...", icon="VIEWZOOM")
layout.operator(
sm.WTD_OT_scene_browse.bl_idname, text="Load...", icon="VIEWZOOM"
)
libraries = sm_library.managed_libraries()
if not libraries:
layout.label(text="Nothing loaded by the Scene Manager", icon="INFO")
return
row = layout.row(align=True)
row.operator(sm.WTD_OT_scene_update.bl_idname, text="Update All", icon="FILE_REFRESH")
row.operator(
sm.WTD_OT_scene_update.bl_idname, text="Update All", icon="FILE_REFRESH"
)
row.operator(sm.WTD_OT_scene_refresh.bl_idname, text="", icon="VIEWZOOM")
found = sm_library.all_instances()
@@ -460,16 +538,29 @@ class _SceneLoadedPanel:
emboss=False,
icon="DOWNARROW_HLT" if expanded else "RIGHTARROW",
).library = library.name
row.label(text=library.get("wtd_asset_name", library.name), icon="LIBRARY_DATA_DIRECT")
row.label(
text=library.get("wtd_asset_name", library.name),
icon="LIBRARY_DATA_DIRECT",
)
version = row.row(align=True)
version.alert = outdated
version.label(text=library.get("wtd_revision", "?"))
if state == "UPDATE":
row.operator(sm.WTD_OT_scene_update.bl_idname, text="", icon="FILE_REFRESH").library = library.name
elif state == "PENDING" and sm.to_request(sm.file_data(library["wtd_file_oid"])):
row.operator(sm.WTD_OT_scene_request.bl_idname, text="", icon="URL").file_oid = library["wtd_file_oid"]
row.operator(sm.WTD_OT_scene_pick_revision.bl_idname, text="", icon="COLLAPSEMENU").library = library.name
row.operator(sm.WTD_OT_scene_remove.bl_idname, text="", icon="X").library = library.name
row.operator(
sm.WTD_OT_scene_update.bl_idname, text="", icon="FILE_REFRESH"
).library = library.name
elif state == "PENDING" and sm.to_request(
sm.file_data(library["wtd_file_oid"])
):
row.operator(
sm.WTD_OT_scene_request.bl_idname, text="", icon="URL"
).file_oid = library["wtd_file_oid"]
row.operator(
sm.WTD_OT_scene_pick_revision.bl_idname, text="", icon="COLLAPSEMENU"
).library = library.name
row.operator(
sm.WTD_OT_scene_remove.bl_idname, text="", icon="X"
).library = library.name
if outdated:
sub = layout.row()
sub.alert = True
@@ -480,23 +571,44 @@ class _SceneLoadedPanel:
for instance in found.get(library.name, []):
is_object = isinstance(instance, bpy.types.Object)
sub = col.row(align=True)
sub.label(text=instance.name, icon="OUTLINER_OB_EMPTY" if is_object else "OUTLINER_COLLECTION")
op = sub.operator(sm.WTD_OT_scene_select_instance.bl_idname, text="", icon="RESTRICT_SELECT_OFF")
sub.label(
text=instance.name,
icon="OUTLINER_OB_EMPTY" if is_object else "OUTLINER_COLLECTION",
)
op = sub.operator(
sm.WTD_OT_scene_select_instance.bl_idname,
text="",
icon="RESTRICT_SELECT_OFF",
)
op.library, op.instance = library.name, instance.name
sub.operator(sm.WTD_OT_scene_remove.bl_idname, text="", icon="X").instance = instance.name
sub.operator(
sm.WTD_OT_scene_remove.bl_idname, text="", icon="X"
).instance = instance.name
lods = sm_library.lods(library, instance)
if lods:
current = sm_library.current_lod(library, instance)
sub = col.row(align=True)
sub.label(text="LOD", icon="BLANK1")
for name in lods:
op = sub.operator(sm.WTD_OT_scene_set_lod.bl_idname, text=name, depress=name == current)
op.lod, op.library, op.instance = name, library.name, instance.name
op = sub.operator(
sm.WTD_OT_scene_set_lod.bl_idname,
text=name,
depress=name == current,
)
op.lod, op.library, op.instance = (
name,
library.name,
instance.name,
)
layout.separator()
row = layout.row(align=True)
row.operator(sm.WTD_OT_scene_update.bl_idname, text="Update Selected").selected = True
row.operator(sm.WTD_OT_scene_remove.bl_idname, text="Remove Selected").selected = True
row.operator(
sm.WTD_OT_scene_update.bl_idname, text="Update Selected"
).selected = True
row.operator(
sm.WTD_OT_scene_remove.bl_idname, text="Remove Selected"
).selected = True
selected = [
(library, instance)
for library, instance in sm_library.selected_instances(context.view_layer)
@@ -506,10 +618,21 @@ class _SceneLoadedPanel:
col = layout.column(align=True)
col.label(text="LOD of Selected")
row = col.row(align=True)
shown = {sm_library.current_lod(library, instance) for library, instance in selected}
names = {name for library, instance in selected for name in sm_library.lods(library, instance)}
shown = {
sm_library.current_lod(library, instance)
for library, instance in selected
}
names = {
name
for library, instance in selected
for name in sm_library.lods(library, instance)
}
for name in sorted(names, key=sm_library.lod_order):
op = row.operator(sm.WTD_OT_scene_set_lod.bl_idname, text=name, depress=shown == {name})
op = row.operator(
sm.WTD_OT_scene_set_lod.bl_idname,
text=name,
depress=shown == {name},
)
op.lod, op.selected = name, True
@@ -523,9 +646,16 @@ class _SceneAssetizePanel:
def draw(self, context) -> None:
layout = self.layout
_wrapped_label(
layout, context, "Publish a local collection of this scene to Libreflow as an asset.", icon="INFO"
layout,
context,
"Publish a local collection of this scene to Libreflow as an asset.",
icon="INFO",
)
layout.operator(
sm.WTD_OT_scene_assetize.bl_idname,
text="Assetize Collection...",
icon="EXPORT",
)
layout.operator(sm.WTD_OT_scene_assetize.bl_idname, text="Assetize Collection...", icon="EXPORT")
class WTD_PT_sanity_view3d(_SanityPanel, bpy.types.Panel):