fix issue. add feat.
- add ignored bmesh update function in flatten uv - finish select by group, add, rm, clear group functions.
This commit is contained in:
parent
c5ce6e8a2c
commit
20aba6c273
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -2,5 +2,6 @@
|
||||
*.png binary
|
||||
# our generated mesh should be save as binary
|
||||
*.bin binary
|
||||
# the compressed json data should be binary
|
||||
# the raw json data should be binary
|
||||
# although i edit it manually
|
||||
bbp_ng/raw_jsons/*.json binary
|
||||
|
198
bbp_ng/OP_OBJECT_virtools_group.py
Normal file
198
bbp_ng/OP_OBJECT_virtools_group.py
Normal file
@ -0,0 +1,198 @@
|
||||
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)
|
||||
)
|
||||
|
||||
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')
|
||||
layout.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(self, 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)
|
||||
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(self, 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)
|
||||
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(self, 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()
|
||||
return {'FINISHED'}
|
||||
|
||||
#endregion
|
||||
|
||||
def register():
|
||||
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():
|
||||
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)
|
||||
|
@ -301,6 +301,8 @@ def _real_flatten_uv(mesh: bpy.types.Mesh, reference_edge: int, scale_data: _Fla
|
||||
# just get abs for the u component
|
||||
_set_face_vertex_uv(face, uv_layer, idx, (abs(ppuv.x), ppuv.y))
|
||||
|
||||
# show the updates in the viewport
|
||||
bmesh.update_edit_mesh(mesh)
|
||||
# return process result
|
||||
return no_processed_count
|
||||
|
||||
|
@ -290,7 +290,7 @@ class BBP_UL_virtools_groups(bpy.types.UIList):
|
||||
def draw_item(self, context, layout: bpy.types.UILayout, data, item: BBP_PG_virtools_group, icon, active_data, active_propname):
|
||||
layout.label(text = item.group_name, translate = False, icon_value = _get_group_icon_by_name(item.group_name))
|
||||
|
||||
class BBP_OT_add_virtools_groups(bpy.types.Operator, SharedGroupNameInputProperties):
|
||||
class BBP_OT_add_virtools_group(bpy.types.Operator, SharedGroupNameInputProperties):
|
||||
"""Add a Virtools Group for Active Object."""
|
||||
bl_idname = "bbp.add_virtools_groups"
|
||||
bl_label = "Add to Virtools Groups"
|
||||
@ -313,7 +313,7 @@ class BBP_OT_add_virtools_groups(bpy.types.Operator, SharedGroupNameInputPropert
|
||||
def draw(self, context):
|
||||
self.draw_group_name_input(self.layout)
|
||||
|
||||
class BBP_OT_rm_virtools_groups(bpy.types.Operator):
|
||||
class BBP_OT_rm_virtools_group(bpy.types.Operator):
|
||||
"""Remove a Virtools Group for Active Object."""
|
||||
bl_idname = "bbp.rm_virtools_groups"
|
||||
bl_label = "Remove from Virtools Groups"
|
||||
@ -389,8 +389,8 @@ class BBP_PT_virtools_groups(bpy.types.Panel):
|
||||
)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator(BBP_OT_add_virtools_groups.bl_idname, icon='ADD', text="")
|
||||
col.operator(BBP_OT_rm_virtools_groups.bl_idname, icon='REMOVE', text="")
|
||||
col.operator(BBP_OT_add_virtools_group.bl_idname, icon='ADD', text="")
|
||||
col.operator(BBP_OT_rm_virtools_group.bl_idname, icon='REMOVE', text="")
|
||||
col.separator()
|
||||
col.operator(BBP_OT_clear_virtools_groups.bl_idname, icon='TRASH', text="")
|
||||
|
||||
@ -400,8 +400,8 @@ def register():
|
||||
# register all classes
|
||||
bpy.utils.register_class(BBP_PG_virtools_group)
|
||||
bpy.utils.register_class(BBP_UL_virtools_groups)
|
||||
bpy.utils.register_class(BBP_OT_add_virtools_groups)
|
||||
bpy.utils.register_class(BBP_OT_rm_virtools_groups)
|
||||
bpy.utils.register_class(BBP_OT_add_virtools_group)
|
||||
bpy.utils.register_class(BBP_OT_rm_virtools_group)
|
||||
bpy.utils.register_class(BBP_OT_clear_virtools_groups)
|
||||
bpy.utils.register_class(BBP_PT_virtools_groups)
|
||||
|
||||
@ -416,7 +416,7 @@ def unregister():
|
||||
|
||||
bpy.utils.unregister_class(BBP_PT_virtools_groups)
|
||||
bpy.utils.unregister_class(BBP_OT_clear_virtools_groups)
|
||||
bpy.utils.unregister_class(BBP_OT_rm_virtools_groups)
|
||||
bpy.utils.unregister_class(BBP_OT_add_virtools_groups)
|
||||
bpy.utils.unregister_class(BBP_OT_rm_virtools_group)
|
||||
bpy.utils.unregister_class(BBP_OT_add_virtools_group)
|
||||
bpy.utils.unregister_class(BBP_UL_virtools_groups)
|
||||
bpy.utils.unregister_class(BBP_PG_virtools_group)
|
||||
|
@ -33,7 +33,7 @@ from . import PROP_preferences, PROP_ptrprop_resolver, PROP_virtools_material, P
|
||||
from . import OP_IMPORT_bmfile, OP_EXPORT_bmfile, OP_IMPORT_virtools, OP_EXPORT_virtools
|
||||
from . import OP_UV_flatten_uv, OP_UV_rail_uv
|
||||
from . import OP_ADDS_component, OP_ADDS_bme
|
||||
from . import OP_OBJECT_legacy_align
|
||||
from . import OP_OBJECT_legacy_align, OP_OBJECT_virtools_group
|
||||
|
||||
#region Menu
|
||||
|
||||
@ -46,9 +46,15 @@ class BBP_MT_View3DMenu(bpy.types.Menu):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text = 'UV', icon = 'UV')
|
||||
layout.operator(OP_UV_flatten_uv.BBP_OT_flatten_uv.bl_idname)
|
||||
layout.operator(OP_UV_rail_uv.BBP_OT_rail_uv.bl_idname)
|
||||
layout.separator()
|
||||
layout.label(text = 'Align', icon = 'SNAP_ON')
|
||||
layout.operator(OP_OBJECT_legacy_align.BBP_OT_legacy_align.bl_idname)
|
||||
layout.separator()
|
||||
layout.label(text = 'Select', icon = 'SELECT_SET')
|
||||
layout.operator(OP_OBJECT_virtools_group.BBP_OT_select_object_by_virtools_group.bl_idname)
|
||||
|
||||
class BBP_MT_AddBmeMenu(bpy.types.Menu):
|
||||
"""Add Ballance Floor"""
|
||||
@ -95,27 +101,44 @@ class BBP_MT_AddComponentsMenu(bpy.types.Menu):
|
||||
|
||||
MenuDrawer_t = typing.Callable[[typing.Any, typing.Any], None]
|
||||
|
||||
def menu_drawer_import(self, context):
|
||||
def menu_drawer_import(self, context) -> None:
|
||||
layout: bpy.types.UILayout = self.layout
|
||||
layout.operator(OP_IMPORT_bmfile.BBP_OT_import_bmfile.bl_idname, text = "Ballance Map (.bmx)")
|
||||
layout.operator(OP_IMPORT_virtools.BBP_OT_import_virtools.bl_idname, text = "Virtools File (.nmo/.cmo/.vmo) (experimental)")
|
||||
|
||||
def menu_drawer_export(self, context):
|
||||
def menu_drawer_export(self, context) -> None:
|
||||
layout: bpy.types.UILayout = self.layout
|
||||
layout.operator(OP_EXPORT_bmfile.BBP_OT_export_bmfile.bl_idname, text = "Ballance Map (.bmx)")
|
||||
layout.operator(OP_EXPORT_virtools.BBP_OT_export_virtools.bl_idname, text = "Virtools File (.nmo/.cmo/.vmo) (experimental)")
|
||||
|
||||
def menu_drawer_view3d(self, context):
|
||||
def menu_drawer_view3d(self, context) -> None:
|
||||
layout: bpy.types.UILayout = self.layout
|
||||
layout.menu(BBP_MT_View3DMenu.bl_idname)
|
||||
|
||||
def menu_drawer_add(self, context):
|
||||
def menu_drawer_add(self, context) -> None:
|
||||
layout: bpy.types.UILayout = self.layout
|
||||
layout.separator()
|
||||
layout.label(text="Ballance")
|
||||
layout.menu(BBP_MT_AddBmeMenu.bl_idname, icon='MESH_CUBE')
|
||||
layout.menu(BBP_MT_AddRailMenu.bl_idname, icon='MESH_CIRCLE')
|
||||
layout.menu(BBP_MT_AddComponentsMenu.bl_idname, icon='MESH_ICOSPHERE')
|
||||
|
||||
def menu_drawer_grouping(self, context) -> None:
|
||||
layout: bpy.types.UILayout = self.layout
|
||||
layout.separator()
|
||||
|
||||
# NOTE: because outline context may change operator context
|
||||
# so it will cause no popup window when click operator in outline.
|
||||
# thus we create a sub layout and set its operator context as 'INVOKE_DEFAULT'
|
||||
# thus, all operators can pop up normally.
|
||||
col = layout.column()
|
||||
col.operator_context = 'INVOKE_DEFAULT'
|
||||
|
||||
col.label(text="Virtools Group")
|
||||
col.operator(OP_OBJECT_virtools_group.BBP_OT_add_objects_virtools_group.bl_idname, icon = 'ADD', text = "Group into...")
|
||||
col.operator(OP_OBJECT_virtools_group.BBP_OT_rm_objects_virtools_group.bl_idname, icon = 'REMOVE', text = "Ungroup from...")
|
||||
col.operator(OP_OBJECT_virtools_group.BBP_OT_clear_objects_virtools_group.bl_idname, icon = 'TRASH', text = "Clear All Groups")
|
||||
|
||||
#endregion
|
||||
|
||||
#region Register and Unregister.
|
||||
@ -141,6 +164,10 @@ g_BldMenus: tuple[MenuEntry, ...] = (
|
||||
MenuEntry(bpy.types.TOPBAR_MT_file_import, True, menu_drawer_import),
|
||||
MenuEntry(bpy.types.TOPBAR_MT_file_export, True, menu_drawer_export),
|
||||
MenuEntry(bpy.types.VIEW3D_MT_add, True, menu_drawer_add),
|
||||
|
||||
# register double (for 2 menus)
|
||||
MenuEntry(bpy.types.VIEW3D_MT_object_context_menu, True, menu_drawer_grouping),
|
||||
MenuEntry(bpy.types.OUTLINER_MT_object, True, menu_drawer_grouping),
|
||||
)
|
||||
|
||||
def register() -> None:
|
||||
@ -166,6 +193,7 @@ def register() -> None:
|
||||
OP_ADDS_bme.register()
|
||||
|
||||
OP_OBJECT_legacy_align.register()
|
||||
OP_OBJECT_virtools_group.register()
|
||||
|
||||
# register other classes
|
||||
for cls in g_BldClasses:
|
||||
@ -188,6 +216,7 @@ def unregister() -> None:
|
||||
bpy.utils.unregister_class(cls)
|
||||
|
||||
# unregister modules
|
||||
OP_OBJECT_virtools_group.unregister()
|
||||
OP_OBJECT_legacy_align.unregister()
|
||||
|
||||
OP_ADDS_bme.unregister()
|
||||
|
Loading…
Reference in New Issue
Block a user