Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Inch <mythologylover75@gmail.com>2020-08-11 07:19:34 +0300
committerRyan Inch <mythologylover75@gmail.com>2020-08-11 07:19:34 +0300
commit559fbf908ba8721f4c9e72b6dc7c3bfa0863479f (patch)
tree4d2e48cce576ea04f6099bbe5445e38fe1bcdbcd
parent1d1bb1a707554ce51696d85d2feb9718e34a0220 (diff)
Collection Manager: Add Holdout & Indirect Only. Task: T69577
Add support for the Holdout and Indirect Only RTOs.
-rw-r--r--object_collection_manager/__init__.py8
-rw-r--r--object_collection_manager/internals.py22
-rw-r--r--object_collection_manager/operator_utils.py130
-rw-r--r--object_collection_manager/operators.py209
-rw-r--r--object_collection_manager/ui.py68
5 files changed, 413 insertions, 24 deletions
diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py
index 49bd0de9..d7b312a5 100644
--- a/object_collection_manager/__init__.py
+++ b/object_collection_manager/__init__.py
@@ -22,7 +22,7 @@ bl_info = {
"name": "Collection Manager",
"description": "Manage collections and their objects",
"author": "Ryan Inch",
- "version": (2, 13, 0),
+ "version": (2, 14, 0),
"blender": (2, 80, 0),
"location": "View3D - Object Mode (Shortcut - M)",
"warning": '', # used for warning icon and text in addons panel
@@ -77,6 +77,8 @@ class CollectionManagerProperties(PropertyGroup):
show_hide_viewport: BoolProperty(default=True, name="[VV] Hide in Viewport")
show_disable_viewport: BoolProperty(default=False, name="[DV] Disable in Viewports")
show_render: BoolProperty(default=False, name="[RR] Disable in Renders")
+ show_holdout: BoolProperty(default=False, name="[HH] Holdout")
+ show_indirect_only: BoolProperty(default=False, name="[IO] Indirect Only")
align_local_ops: BoolProperty(default=False, name="Align Local Options",
description="Align local options in a column to the right")
@@ -108,6 +110,10 @@ classes = (
operators.CMUnDisableViewportAllOperator,
operators.CMDisableRenderOperator,
operators.CMUnDisableRenderAllOperator,
+ operators.CMHoldoutOperator,
+ operators.CMUnHoldoutAllOperator,
+ operators.CMIndirectOnlyOperator,
+ operators.CMUnIndirectOnlyAllOperator,
operators.CMNewCollectionOperator,
operators.CMRemoveCollectionOperator,
operators.CMRemoveEmptyCollectionsOperator,
diff --git a/object_collection_manager/internals.py b/object_collection_manager/internals.py
index 857e73aa..163e9804 100644
--- a/object_collection_manager/internals.py
+++ b/object_collection_manager/internals.py
@@ -53,12 +53,16 @@ rto_history = {
"disable": {},
"disable_all": {},
"render": {},
- "render_all": {}
+ "render_all": {},
+ "holdout": {},
+ "holdout_all": {},
+ "indirect": {},
+ "indirect_all": {},
}
expand_history = {
"target": "",
- "history": []
+ "history": [],
}
phantom_history = {
@@ -70,12 +74,16 @@ phantom_history = {
"hide_history": {},
"disable_history": {},
"render_history": {},
+ "holdout_history": {},
+ "indirect_history": {},
"exclude_all_history": [],
"select_all_history": [],
"hide_all_history": [],
"disable_all_history": [],
- "render_all_history": []
+ "render_all_history": [],
+ "holdout_all_history": [],
+ "indirect_all_history": [],
}
copy_buffer = {
@@ -317,7 +325,9 @@ def update_col_name(self, context):
"select",
"hide",
"disable",
- "render"
+ "render",
+ "holdout",
+ "indirect",
]
orig_targets = {
@@ -584,6 +594,8 @@ def generate_state():
"hide": [],
"disable": [],
"render": [],
+ "holdout": [],
+ "indirect": [],
}
for name, laycol in layer_collections.items():
@@ -593,6 +605,8 @@ def generate_state():
state["hide"].append(laycol["ptr"].hide_viewport)
state["disable"].append(laycol["ptr"].collection.hide_viewport)
state["render"].append(laycol["ptr"].collection.hide_render)
+ state["holdout"].append(laycol["ptr"].holdout)
+ state["indirect"].append(laycol["ptr"].indirect_only)
return state
diff --git a/object_collection_manager/operator_utils.py b/object_collection_manager/operator_utils.py
index ed7fce09..6f7ee83b 100644
--- a/object_collection_manager/operator_utils.py
+++ b/object_collection_manager/operator_utils.py
@@ -36,12 +36,67 @@ rto_path = {
"select": "collection.hide_select",
"hide": "hide_viewport",
"disable": "collection.hide_viewport",
- "render": "collection.hide_render"
+ "render": "collection.hide_render",
+ "holdout": "holdout",
+ "indirect": "indirect_only",
+ }
+
+set_off_on = {
+ "exclude": {
+ "off": True,
+ "on": False
+ },
+ "select": {
+ "off": True,
+ "on": False
+ },
+ "hide": {
+ "off": True,
+ "on": False
+ },
+ "disable": {
+ "off": True,
+ "on": False
+ },
+ "render": {
+ "off": True,
+ "on": False
+ },
+ "holdout": {
+ "off": False,
+ "on": True
+ },
+ "indirect": {
+ "off": False,
+ "on": True
+ }
+ }
+
+get_off_on = {
+ False: {
+ "exclude": "on",
+ "select": "on",
+ "hide": "on",
+ "disable": "on",
+ "render": "on",
+ "holdout": "off",
+ "indirect": "off",
+ },
+
+ True: {
+ "exclude": "off",
+ "select": "off",
+ "hide": "off",
+ "disable": "off",
+ "render": "off",
+ "holdout": "on",
+ "indirect": "on",
+ }
}
def get_rto(layer_collection, rto):
- if rto in ["exclude", "hide"]:
+ if rto in ["exclude", "hide", "holdout", "indirect"]:
return getattr(layer_collection, rto_path[rto])
else:
@@ -50,7 +105,7 @@ def get_rto(layer_collection, rto):
def set_rto(layer_collection, rto, value):
- if rto in ["exclude", "hide"]:
+ if rto in ["exclude", "hide", "holdout", "indirect"]:
setattr(layer_collection, rto_path[rto], value)
else:
@@ -76,13 +131,16 @@ def apply_to_children(parent, apply_function):
def isolate_rto(cls, self, view_layer, rto, *, children=False):
+ off = set_off_on[rto]["off"]
+ on = set_off_on[rto]["on"]
+
laycol_ptr = layer_collections[self.name]["ptr"]
target = rto_history[rto][view_layer]["target"]
history = rto_history[rto][view_layer]["history"]
# get active collections
active_layer_collections = [x["ptr"] for x in layer_collections.values()
- if not get_rto(x["ptr"], rto)]
+ if get_rto(x["ptr"], rto) == on]
# check if previous state should be restored
if cls.isolated and self.name == target:
@@ -100,7 +158,7 @@ def isolate_rto(cls, self, view_layer, rto, *, children=False):
active_layer_collections[0].name == self.name):
# activate all collections
for item in layer_collections.values():
- set_rto(item["ptr"], rto, False)
+ set_rto(item["ptr"], rto, on)
# reset target and history
del rto_history[rto][view_layer]
@@ -130,15 +188,15 @@ def isolate_rto(cls, self, view_layer, rto, *, children=False):
# isolate collection
for item in layer_collections.values():
if item["name"] != laycol_ptr.name:
- set_rto(item["ptr"], rto, True)
+ set_rto(item["ptr"], rto, off)
- set_rto(laycol_ptr, rto, False)
+ set_rto(laycol_ptr, rto, on)
- if rto != "exclude":
+ if rto not in ["exclude", "holdout", "indirect"]:
# activate all parents
laycol = layer_collections[self.name]
while laycol["id"] != 0:
- set_rto(laycol["ptr"], rto, False)
+ set_rto(laycol["ptr"], rto, on)
laycol = laycol["parent"]
if children:
@@ -156,7 +214,7 @@ def isolate_rto(cls, self, view_layer, rto, *, children=False):
apply_to_children(laycol_ptr, restore_child_states)
- else:
+ elif rto == "exclude":
# deactivate all children
def deactivate_all_children(layer_collection):
set_rto(layer_collection, rto, True)
@@ -183,6 +241,9 @@ def toggle_children(self, view_layer, rto):
def activate_all_rtos(view_layer, rto):
+ off = set_off_on[rto]["off"]
+ on = set_off_on[rto]["on"]
+
history = rto_history[rto+"_all"][view_layer]
# if not activated, activate all
@@ -190,12 +251,12 @@ def activate_all_rtos(view_layer, rto):
keep_history = False
for item in reversed(list(layer_collections.values())):
- if get_rto(item["ptr"], rto) == True:
+ if get_rto(item["ptr"], rto) == off:
keep_history = True
history.append(get_rto(item["ptr"], rto))
- set_rto(item["ptr"], rto, False)
+ set_rto(item["ptr"], rto, on)
if not keep_history:
history.clear()
@@ -233,12 +294,22 @@ def copy_rtos(view_layer, rto):
# copy
copy_buffer["RTO"] = rto
for laycol in layer_collections.values():
- copy_buffer["values"].append(get_rto(laycol["ptr"], rto))
+ copy_buffer["values"].append(get_off_on[
+ get_rto(laycol["ptr"], rto)
+ ][
+ rto
+ ]
+ )
else:
# paste
for x, laycol in enumerate(layer_collections.values()):
- set_rto(laycol["ptr"], rto, copy_buffer["values"][x])
+ set_rto(laycol["ptr"],
+ rto,
+ set_off_on[rto][
+ copy_buffer["values"][x]
+ ]
+ )
# clear rto history
rto_history[rto].pop(view_layer, None)
@@ -254,18 +325,41 @@ def swap_rtos(view_layer, rto):
# get A
swap_buffer["A"]["RTO"] = rto
for laycol in layer_collections.values():
- swap_buffer["A"]["values"].append(get_rto(laycol["ptr"], rto))
+ swap_buffer["A"]["values"].append(get_off_on[
+ get_rto(laycol["ptr"], rto)
+ ][
+ rto
+ ]
+ )
else:
# get B
swap_buffer["B"]["RTO"] = rto
for laycol in layer_collections.values():
- swap_buffer["B"]["values"].append(get_rto(laycol["ptr"], rto))
+ swap_buffer["B"]["values"].append(get_off_on[
+ get_rto(laycol["ptr"], rto)
+ ][
+ rto
+ ]
+ )
# swap A with B
for x, laycol in enumerate(layer_collections.values()):
- set_rto(laycol["ptr"], swap_buffer["A"]["RTO"], swap_buffer["B"]["values"][x])
- set_rto(laycol["ptr"], swap_buffer["B"]["RTO"], swap_buffer["A"]["values"][x])
+ set_rto(laycol["ptr"], swap_buffer["A"]["RTO"],
+ set_off_on[
+ swap_buffer["A"]["RTO"]
+ ][
+ swap_buffer["B"]["values"][x]
+ ]
+ )
+
+ set_rto(laycol["ptr"], swap_buffer["B"]["RTO"],
+ set_off_on[
+ swap_buffer["B"]["RTO"]
+ ][
+ swap_buffer["A"]["values"][x]
+ ]
+ )
# clear rto history
diff --git a/object_collection_manager/operators.py b/object_collection_manager/operators.py
index 7509d3f2..ff1bbf95 100644
--- a/object_collection_manager/operators.py
+++ b/object_collection_manager/operators.py
@@ -909,6 +909,211 @@ class CMUnDisableRenderAllOperator(Operator):
return {'FINISHED'}
+class CMHoldoutOperator(Operator):
+ bl_label = "[HH] Holdout"
+ bl_description = (
+ " * Shift+LMB - Isolate/Restore.\n"
+ " * Shift+Ctrl+LMB - Isolate nested/Restore.\n"
+ " * Ctrl+LMB - Toggle nested.\n"
+ " * Alt+LMB - Discard history"
+ )
+ bl_idname = "view3d.holdout_collection"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ name: StringProperty()
+
+ # static class var
+ isolated = False
+
+ def invoke(self, context, event):
+ global rto_history
+ cls = CMHoldoutOperator
+
+ modifiers = get_modifiers(event)
+ view_layer = context.view_layer.name
+ laycol_ptr = layer_collections[self.name]["ptr"]
+
+ if not view_layer in rto_history["holdout"]:
+ rto_history["holdout"][view_layer] = {"target": "", "history": []}
+
+ if modifiers == {"alt"}:
+ del rto_history["holdout"][view_layer]
+ cls.isolated = False
+
+ elif modifiers == {"shift"}:
+ isolate_rto(cls, self, view_layer, "holdout")
+
+ elif modifiers == {"ctrl"}:
+ toggle_children(self, view_layer, "holdout")
+
+ cls.isolated = False
+
+ elif modifiers == {"ctrl", "shift"}:
+ isolate_rto(cls, self, view_layer, "holdout", children=True)
+
+ else:
+ # toggle holdout
+
+ # reset holdout history
+ del rto_history["holdout"][view_layer]
+
+ # toggle holdout of collection in viewport
+ laycol_ptr.holdout = not laycol_ptr.holdout
+
+ cls.isolated = False
+
+ # reset holdout all history
+ if view_layer in rto_history["holdout_all"]:
+ del rto_history["holdout_all"][view_layer]
+
+ return {'FINISHED'}
+
+
+class CMUnHoldoutAllOperator(Operator):
+ bl_label = "[HH Global] Holdout"
+ bl_description = (
+ " * LMB - Enable all/Restore.\n"
+ " * Shift+LMB - Invert.\n"
+ " * Ctrl+LMB - Copy/Paste RTOs.\n"
+ " * Ctrl+Alt+LMB - Swap RTOs.\n"
+ " * Alt+LMB - Discard history"
+ )
+ bl_idname = "view3d.un_holdout_all_collections"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def invoke(self, context, event):
+ global rto_history
+
+ view_layer = context.view_layer.name
+ modifiers = get_modifiers(event)
+
+ if not view_layer in rto_history["holdout_all"]:
+ rto_history["holdout_all"][view_layer] = []
+
+ if modifiers == {"alt"}:
+ # clear all states
+ del rto_history["holdout_all"][view_layer]
+ clear_copy("holdout")
+ clear_swap("holdout")
+
+ elif modifiers == {"ctrl"}:
+ copy_rtos(view_layer, "holdout")
+
+ elif modifiers == {"ctrl", "alt"}:
+ swap_rtos(view_layer, "holdout")
+
+ elif modifiers == {"shift"}:
+ invert_rtos(view_layer, "holdout")
+
+ else:
+ activate_all_rtos(view_layer, "holdout")
+
+ return {'FINISHED'}
+
+
+class CMIndirectOnlyOperator(Operator):
+ bl_label = "[IO] Indirect Only"
+ bl_description = (
+ " * Shift+LMB - Isolate/Restore.\n"
+ " * Shift+Ctrl+LMB - Isolate nested/Restore.\n"
+ " * Ctrl+LMB - Toggle nested.\n"
+ " * Alt+LMB - Discard history"
+ )
+ bl_idname = "view3d.indirect_only_collection"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ name: StringProperty()
+
+ # static class var
+ isolated = False
+
+ def invoke(self, context, event):
+ global rto_history
+ cls = CMIndirectOnlyOperator
+
+ modifiers = get_modifiers(event)
+ view_layer = context.view_layer.name
+ laycol_ptr = layer_collections[self.name]["ptr"]
+
+ if not view_layer in rto_history["indirect"]:
+ rto_history["indirect"][view_layer] = {"target": "", "history": []}
+
+
+ if modifiers == {"alt"}:
+ del rto_history["indirect"][view_layer]
+ cls.isolated = False
+
+ elif modifiers == {"shift"}:
+ isolate_rto(cls, self, view_layer, "indirect")
+
+ elif modifiers == {"ctrl"}:
+ toggle_children(self, view_layer, "indirect")
+
+ cls.isolated = False
+
+ elif modifiers == {"ctrl", "shift"}:
+ isolate_rto(cls, self, view_layer, "indirect", children=True)
+
+ else:
+ # toggle indirect only
+
+ # reset indirect history
+ del rto_history["indirect"][view_layer]
+
+ # toggle indirect only of collection
+ laycol_ptr.indirect_only = not laycol_ptr.indirect_only
+
+ cls.isolated = False
+
+ # reset indirect all history
+ if view_layer in rto_history["indirect_all"]:
+ del rto_history["indirect_all"][view_layer]
+
+ return {'FINISHED'}
+
+
+class CMUnIndirectOnlyAllOperator(Operator):
+ bl_label = "[IO Global] Indirect Only"
+ bl_description = (
+ " * LMB - Enable all/Restore.\n"
+ " * Shift+LMB - Invert.\n"
+ " * Ctrl+LMB - Copy/Paste RTOs.\n"
+ " * Ctrl+Alt+LMB - Swap RTOs.\n"
+ " * Alt+LMB - Discard history"
+ )
+ bl_idname = "view3d.un_indirect_only_all_collections"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def invoke(self, context, event):
+ global rto_history
+
+ view_layer = context.view_layer.name
+ modifiers = get_modifiers(event)
+
+ if not view_layer in rto_history["indirect_all"]:
+ rto_history["indirect_all"][view_layer] = []
+
+ if modifiers == {"alt"}:
+ # clear all states
+ del rto_history["indirect_all"][view_layer]
+ clear_copy("indirect")
+ clear_swap("indirect")
+
+ elif modifiers == {"ctrl"}:
+ copy_rtos(view_layer, "indirect")
+
+ elif modifiers == {"ctrl", "alt"}:
+ swap_rtos(view_layer, "indirect")
+
+ elif modifiers == {"shift"}:
+ invert_rtos(view_layer, "indirect")
+
+ else:
+ activate_all_rtos(view_layer, "indirect")
+
+ return {'FINISHED'}
+
+
class CMRemoveCollectionOperator(Operator):
'''Remove Collection'''
bl_label = "Remove Collection"
@@ -1112,6 +1317,8 @@ class CMPhantomModeOperator(Operator):
"hide": layer_collection.hide_viewport,
"disable": layer_collection.collection.hide_viewport,
"render": layer_collection.collection.hide_render,
+ "holdout": layer_collection.holdout,
+ "indirect": layer_collection.indirect_only,
}
apply_to_children(view_layer.layer_collection, save_visibility_state)
@@ -1132,6 +1339,8 @@ class CMPhantomModeOperator(Operator):
layer_collection.hide_viewport = phantom_laycol["hide"]
layer_collection.collection.hide_viewport = phantom_laycol["disable"]
layer_collection.collection.hide_render = phantom_laycol["render"]
+ layer_collection.holdout = phantom_laycol["holdout"]
+ layer_collection.indirect_only = phantom_laycol["indirect"]
apply_to_children(view_layer.layer_collection, restore_visibility_state)
diff --git a/object_collection_manager/ui.py b/object_collection_manager/ui.py
index 7858e5bf..0f2703cb 100644
--- a/object_collection_manager/ui.py
+++ b/object_collection_manager/ui.py
@@ -302,6 +302,44 @@ class CollectionManager(Operator):
global_rto_row.operator("view3d.un_disable_render_all_collections", text="", icon=icon, depress=depress)
+ if cm.show_holdout:
+ holdout_all_history = rto_history["holdout_all"].get(view_layer.name, [])
+ depress = True if len(holdout_all_history) else False
+ icon = 'HOLDOUT_ON'
+ buffers = [False, False]
+
+ if copy_buffer["RTO"] == "holdout":
+ icon = copy_icon
+ buffers[0] = True
+
+ if swap_buffer["A"]["RTO"] == "holdout":
+ icon = swap_icon
+ buffers[1] = True
+
+ if buffers[0] and buffers[1]:
+ icon = copy_swap_icon
+
+ global_rto_row.operator("view3d.un_holdout_all_collections", text="", icon=icon, depress=depress)
+
+ if cm.show_indirect_only:
+ indirect_all_history = rto_history["indirect_all"].get(view_layer.name, [])
+ depress = True if len(indirect_all_history) else False
+ icon = 'INDIRECT_ONLY_ON'
+ buffers = [False, False]
+
+ if copy_buffer["RTO"] == "indirect":
+ icon = copy_icon
+ buffers[0] = True
+
+ if swap_buffer["A"]["RTO"] == "indirect":
+ icon = swap_icon
+ buffers[1] = True
+
+ if buffers[0] and buffers[1]:
+ icon = copy_swap_icon
+
+ global_rto_row.operator("view3d.un_indirect_only_all_collections", text="", icon=icon, depress=depress)
+
# treeview
layout.row().template_list("CM_UL_items", "",
cm, "cm_list_collection",
@@ -381,7 +419,7 @@ class CollectionManager(Operator):
else:
- for rto in ["exclude", "select", "hide", "disable", "render"]:
+ for rto in ["exclude", "select", "hide", "disable", "render", "holdout", "indirect"]:
if new_state[rto] != collection_state[rto]:
if view_layer.name in rto_history[rto]:
del rto_history[rto][view_layer.name]
@@ -628,6 +666,32 @@ class CM_UL_items(UIList):
emboss=highlight, depress=highlight)
prop.name = item.name
+ if cm.show_holdout:
+ holdout_history_base = rto_history["holdout"].get(view_layer.name, {})
+ holdout_target = holdout_history_base.get("target", "")
+ holdout_history = holdout_history_base.get("history", [])
+
+ highlight = bool(holdout_history and holdout_target == item.name)
+ icon = ('HOLDOUT_ON' if laycol["ptr"].holdout else
+ 'HOLDOUT_OFF')
+
+ prop = row.operator("view3d.holdout_collection", text="", icon=icon,
+ emboss=highlight, depress=highlight)
+ prop.name = item.name
+
+ if cm.show_indirect_only:
+ indirect_history_base = rto_history["indirect"].get(view_layer.name, {})
+ indirect_target = indirect_history_base.get("target", "")
+ indirect_history = indirect_history_base.get("history", [])
+
+ highlight = bool(indirect_history and indirect_target == item.name)
+ icon = ('INDIRECT_ONLY_ON' if laycol["ptr"].indirect_only else
+ 'INDIRECT_ONLY_OFF')
+
+ prop = row.operator("view3d.indirect_only_collection", text="", icon=icon,
+ emboss=highlight, depress=highlight)
+ prop.name = item.name
+
row = s2
@@ -751,6 +815,8 @@ class CMDisplayOptionsPanel(Panel):
row.prop(cm, "show_hide_viewport", icon='HIDE_OFF', icon_only=True)
row.prop(cm, "show_disable_viewport", icon='RESTRICT_VIEW_OFF', icon_only=True)
row.prop(cm, "show_render", icon='RESTRICT_RENDER_OFF', icon_only=True)
+ row.prop(cm, "show_holdout", icon='HOLDOUT_ON', icon_only=True)
+ row.prop(cm, "show_indirect_only", icon='INDIRECT_ONLY_ON', icon_only=True)
layout.separator()