yyc12345
84e7e8380f
- now grouping, ungrouping clear groups operators will show a report at the bottom of blender to indicate their work have done. - disable fix material, 3ds max align, select by virtools group operators in edit mode to prevent any possible undefined behavior.
207 lines
7.9 KiB
Python
207 lines
7.9 KiB
Python
import bpy
|
|
import enum
|
|
from . import PROP_virtools_group
|
|
from . import UTIL_functions
|
|
|
|
#region Select by Group
|
|
|
|
class SelectMode(enum.IntEnum):
|
|
Set = enum.auto()
|
|
Extend = enum.auto()
|
|
Subtract = enum.auto()
|
|
Difference = enum.auto()
|
|
Intersect = enum.auto()
|
|
_g_SelectModeDesc: dict[SelectMode, tuple[str, str, str]] = {
|
|
SelectMode.Set: ('Set', 'Sets a new selection.', 'SELECT_SET'),
|
|
SelectMode.Extend: ('Extend', 'Adds newly selected items to the existing selection.', 'SELECT_EXTEND'),
|
|
SelectMode.Subtract: ('Subtract', 'Removes newly selected items from the existing selection.', 'SELECT_SUBTRACT'),
|
|
SelectMode.Difference: ('Invert', 'Inverts the selection.', 'SELECT_DIFFERENCE'),
|
|
SelectMode.Intersect: ('Intersect', 'Selects items that intersect with the existing selection.', 'SELECT_INTERSECT')
|
|
}
|
|
_g_EnumHelper_SelectMode: UTIL_functions.EnumPropHelper = UTIL_functions.EnumPropHelper(
|
|
SelectMode,
|
|
lambda x: str(x.value),
|
|
lambda x: SelectMode(int(x)),
|
|
lambda x: _g_SelectModeDesc[x][0],
|
|
lambda x: _g_SelectModeDesc[x][1],
|
|
lambda x: _g_SelectModeDesc[x][2]
|
|
)
|
|
|
|
class BBP_OT_select_object_by_virtools_group(bpy.types.Operator, PROP_virtools_group.SharedGroupNameInputProperties):
|
|
"""Select Objects by Virtools Group"""
|
|
bl_idname = "bbp.select_object_by_virtools_group"
|
|
bl_label = "Select by Virtools Group"
|
|
bl_options = {'UNDO'}
|
|
|
|
selection_mode: bpy.props.EnumProperty(
|
|
name = "Mode",
|
|
description = "Selection mode",
|
|
items = _g_EnumHelper_SelectMode.generate_items(),
|
|
default = _g_EnumHelper_SelectMode.to_selection(SelectMode.Intersect)
|
|
) # type: ignore
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return UTIL_functions.is_in_object_mode()
|
|
|
|
def invoke(self, context, event):
|
|
wm = context.window_manager
|
|
return wm.invoke_props_dialog(self)
|
|
|
|
def execute(self, context):
|
|
_select_object_by_virtools_group(
|
|
self.general_get_group_name(),
|
|
_g_EnumHelper_SelectMode.get_selection(self.selection_mode)
|
|
)
|
|
return {'FINISHED'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.label(text='Selection Mode')
|
|
sublayout = layout.column() # make selection expand vertically, not horizontal.
|
|
sublayout.prop(self, 'selection_mode', expand = True)
|
|
|
|
layout.separator()
|
|
layout.label(text='Group Parameters')
|
|
self.draw_group_name_input(layout)
|
|
|
|
def _select_object_by_virtools_group(group_name: str, mode: SelectMode) -> None:
|
|
match(mode):
|
|
case SelectMode.Set:
|
|
# iterate all objects and directly set
|
|
for obj in bpy.context.scene.objects:
|
|
# check group and decide whether select this obj
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
obj.select_set(gp.contain_group(group_name))
|
|
case SelectMode.Extend:
|
|
# also iterate all objects
|
|
for obj in bpy.context.scene.objects:
|
|
# but only increase selection, for selected object, skip check
|
|
if obj.select_get(): continue
|
|
# if not selected, check whether add it.
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
if gp.contain_group(group_name):
|
|
obj.select_set(True)
|
|
case SelectMode.Subtract:
|
|
# subtract only involving selected item. so we get selected objest first
|
|
# and copy it (because we need modify it)
|
|
# and iterate it to reduce useless operations
|
|
selected = bpy.context.selected_objects[:]
|
|
for obj in selected:
|
|
# remove matched only
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
if gp.contain_group(group_name):
|
|
obj.select_set(False)
|
|
case SelectMode.Difference:
|
|
# construct a selected obj set for convenient operations
|
|
selected_set = set(bpy.context.selected_objects)
|
|
# iterate all objects
|
|
for obj in bpy.context.scene.objects:
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
# use xor to select
|
|
# in_selected XOR in_group
|
|
obj.select_set((obj in selected_set) ^ gp.contain_group(group_name))
|
|
case SelectMode.Intersect:
|
|
# like subtract, only iterate selected obj
|
|
selected = bpy.context.selected_objects[:]
|
|
for obj in selected:
|
|
# but remove not matched
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
if not gp.contain_group(group_name):
|
|
obj.select_set(False)
|
|
case _:
|
|
raise UTIL_functions.BBPException('invalid selection mode')
|
|
|
|
#endregion
|
|
|
|
#region Objects Group Opers
|
|
|
|
class BBP_OT_add_objects_virtools_group(bpy.types.Operator, PROP_virtools_group.SharedGroupNameInputProperties):
|
|
"""Grouping Selected Objects"""
|
|
bl_idname = "bbp.add_objects_virtools_group"
|
|
bl_label = "Grouping Objects"
|
|
bl_options = {'UNDO'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return len(bpy.context.selected_objects) != 0
|
|
|
|
def invoke(self, context, event):
|
|
wm = context.window_manager
|
|
return wm.invoke_props_dialog(self)
|
|
|
|
def execute(self, context):
|
|
group_name: str = self.general_get_group_name()
|
|
for obj in bpy.context.selected_objects:
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
gp.add_group(group_name)
|
|
self.report({'INFO'}, "Grouping objects successfully.")
|
|
return {'FINISHED'}
|
|
|
|
def draw(self, context):
|
|
self.draw_group_name_input(self.layout)
|
|
|
|
class BBP_OT_rm_objects_virtools_group(bpy.types.Operator, PROP_virtools_group.SharedGroupNameInputProperties):
|
|
"""Ungrouping Selected Objects"""
|
|
bl_idname = "bbp.rm_objects_virtools_group"
|
|
bl_label = "Ungrouping Objects"
|
|
bl_options = {'UNDO'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return len(bpy.context.selected_objects) != 0
|
|
|
|
def invoke(self, context, event):
|
|
wm = context.window_manager
|
|
return wm.invoke_props_dialog(self)
|
|
|
|
def execute(self, context):
|
|
group_name: str = self.general_get_group_name()
|
|
for obj in bpy.context.selected_objects:
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
gp.remove_group(group_name)
|
|
self.report({'INFO'}, "Ungrouping objects successfully.")
|
|
return {'FINISHED'}
|
|
|
|
def draw(self, context):
|
|
self.draw_group_name_input(self.layout)
|
|
|
|
class BBP_OT_clear_objects_virtools_group(bpy.types.Operator):
|
|
"""Clear Virtools Groups on Selected Objects"""
|
|
bl_idname = "bbp.clear_objects_virtools_group"
|
|
bl_label = "Clear All Groups"
|
|
bl_options = {'UNDO'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return len(bpy.context.selected_objects) != 0
|
|
|
|
def invoke(self, context, event):
|
|
wm = context.window_manager
|
|
return wm.invoke_confirm(self, event)
|
|
|
|
def execute(self, context):
|
|
# iterate object
|
|
for obj in bpy.context.selected_objects:
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
|
gp.clear_groups()
|
|
self.report({'INFO'}, "Clear objects groups successfully.")
|
|
return {'FINISHED'}
|
|
|
|
#endregion
|
|
|
|
def register() -> None:
|
|
bpy.utils.register_class(BBP_OT_select_object_by_virtools_group)
|
|
|
|
bpy.utils.register_class(BBP_OT_add_objects_virtools_group)
|
|
bpy.utils.register_class(BBP_OT_rm_objects_virtools_group)
|
|
bpy.utils.register_class(BBP_OT_clear_objects_virtools_group)
|
|
|
|
def unregister() -> None:
|
|
bpy.utils.unregister_class(BBP_OT_clear_objects_virtools_group)
|
|
bpy.utils.unregister_class(BBP_OT_rm_objects_virtools_group)
|
|
bpy.utils.unregister_class(BBP_OT_add_objects_virtools_group)
|
|
|
|
bpy.utils.unregister_class(BBP_OT_select_object_by_virtools_group)
|
|
|