From f763479a6412fbcf9ece933fc3f2b99151086629 Mon Sep 17 00:00:00 2001 From: Michel Fedde <35878897+Neintonine@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:08:11 +0100 Subject: [PATCH] adds select feature to editor --- docu/planned_features.md | 2 +- src/__init__.py | 15 ++++++- src/menu/id_mask_select_menu.py | 12 ++++++ src/operators/create_id_mask.py | 2 +- src/operators/id_editor_paint.py | 4 +- src/operators/id_mask_select.py | 71 ++++++++++++++++++++++++++++++++ src/panels/id_mask_editor.py | 7 +++- 7 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 src/menu/id_mask_select_menu.py create mode 100644 src/operators/id_mask_select.py diff --git a/docu/planned_features.md b/docu/planned_features.md index 547bd7a..e138f59 100644 --- a/docu/planned_features.md +++ b/docu/planned_features.md @@ -2,5 +2,5 @@ ### ID Mask - Editor - [ ] A way to automatically get already used colors, f.E. you already did it by hand -- [ ] Select by color +- [X] Select by color - [ ] Update after color change \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index d04dfa1..db9cacb 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,9 +1,11 @@ import bpy +from src.menu import id_mask_select_menu from src.operators.create_id_mask import CreateIDMaskOperator from src.operators.id_editor_create_id import IDEDITOR_CreateIDOperator from src.operators.id_editor_paint import IDEDITOR_PaintIDMaskOperator from src.operators.id_editor_remove_id import IDEDITOR_RemoveIDOperator +from src.operators.id_mask_select import IDEDITOR_SelectIDMaskOperator from src.panels.id_mask_editor_id_list import IDMaskEditorIDList from src.properties.id_mask_editor_value_properties import IDMaskEditorValueProperties from . panels.bake_panel_options import BakeToIDOptionsPanel @@ -38,21 +40,32 @@ classes = ( IDMaskEditorIDList, IDEDITOR_CreateIDOperator, IDEDITOR_RemoveIDOperator, - IDEDITOR_PaintIDMaskOperator + IDEDITOR_PaintIDMaskOperator, + IDEDITOR_SelectIDMaskOperator ) +menu_additions = [ + id_mask_select_menu +] def register(): for cls in classes: bpy.utils.register_class(cls) + for menu in menu_additions: + menu.register() + setattr(bpy.types.Scene, 'bake_to_id_props', bpy.props.PointerProperty(type=BakeToIDProperties)) setattr(bpy.types.Mesh, 'id_mask_editor_properties', bpy.props.PointerProperty(type=IDMaskEditorProperties)) def unregister(): + for menu in reversed(menu_additions): + menu.unregister() + for cls in reversed(classes): bpy.utils.unregister_class(cls) + del bpy.types.Scene.bake_to_id_props diff --git a/src/menu/id_mask_select_menu.py b/src/menu/id_mask_select_menu.py new file mode 100644 index 0000000..48212bb --- /dev/null +++ b/src/menu/id_mask_select_menu.py @@ -0,0 +1,12 @@ +import bpy + +from src.operators.id_mask_select import IDEDITOR_SelectIDMaskOperator + +def id_mask_select_menu_function(self, context): + self.layout.operator(IDEDITOR_SelectIDMaskOperator.bl_idname).isCalledFromEditor = False + +def register(): + bpy.types.VIEW3D_MT_select_edit_mesh.append(id_mask_select_menu_function) + +def unregister(): + bpy.types.VIEW3D_MT_select_edit_mesh.remove(id_mask_select_menu_function) \ No newline at end of file diff --git a/src/operators/create_id_mask.py b/src/operators/create_id_mask.py index de8652d..6c0e3a5 100644 --- a/src/operators/create_id_mask.py +++ b/src/operators/create_id_mask.py @@ -3,7 +3,7 @@ import bpy class CreateIDMaskOperator(bpy.types.Operator): bl_idname = "id_mask_editor.create_id_mask_attribute" - bl_label = "" + bl_label = "Create ID Mask - Attribute" bl_options = {'INTERNAL'} @classmethod diff --git a/src/operators/id_editor_paint.py b/src/operators/id_editor_paint.py index a8c97b5..944f912 100644 --- a/src/operators/id_editor_paint.py +++ b/src/operators/id_editor_paint.py @@ -2,8 +2,7 @@ import bpy class IDEDITOR_PaintIDMaskOperator(bpy.types.Operator): bl_idname = "id_mask_editor.paint_id_mask" - bl_label = "Paint" - bl_options = {'INTERNAL'} + bl_label = "Paint ID Mask" def execute(self, context): obj = context.active_object @@ -24,7 +23,6 @@ class IDEDITOR_PaintIDMaskOperator(bpy.types.Operator): color_attribute = mesh.color_attributes.get(properties.target_attribute) - selected_polygons = [] for polygon in mesh.polygons: if not polygon.select: continue diff --git a/src/operators/id_mask_select.py b/src/operators/id_mask_select.py new file mode 100644 index 0000000..811c872 --- /dev/null +++ b/src/operators/id_mask_select.py @@ -0,0 +1,71 @@ +import bpy + + +class IDEDITOR_SelectIDMaskOperator(bpy.types.Operator): + bl_idname = "id_mask_editor.select_id_mask" + bl_label = "Select by ID Mask" + bl_description = "Selects the faces of the active object, based on current ID mask" + + isCalledFromEditor: bpy.props.BoolProperty(default=False) + + @classmethod + def poll(cls, context): + obj = context.active_object + if obj.type != 'MESH': + return False + + if not obj.data: + return False + + mesh = obj.data + properties = mesh.id_mask_editor_properties + + if not properties.target_attribute: + return False + + return True + + def execute(self, context): + obj = context.active_object + + old_mode = bpy.context.object.mode + if old_mode != "OBJECT": + bpy.ops.object.mode_set(mode='OBJECT', toggle=False) + + mesh = obj.data + properties = mesh.id_mask_editor_properties + color_attribute = mesh.color_attributes.get(properties.target_attribute) + + test_color = self.get_test_color(properties, mesh, color_attribute) + if not test_color: + if old_mode != "OBJECT": + bpy.ops.object.mode_set(mode=old_mode, toggle=False) + + return {'FINISHED'} + + for polygon in mesh.polygons: + polygon_color = self.get_color_from_polygon(color_attribute, polygon) + + if test_color[0] != polygon_color[0] or test_color[1] != polygon_color[1] or test_color[2] != polygon_color[2]: + continue + + polygon.select = True + + if old_mode != "OBJECT": + bpy.ops.object.mode_set(mode=old_mode, toggle=False) + + return {'FINISHED'} + + def get_test_color(self, properties, mesh, color_attribute): + if self.isCalledFromEditor: + color = properties.possible_ids[properties.active_id].color + return (color.r, color.g, color.b, 1.0) + + if mesh.polygons.active: + return self.get_color_from_polygon(color_attribute, mesh.polygons[mesh.polygons.active]) + + return None + + def get_color_from_polygon(self, attribute, polygon): + color = attribute.data[polygon.loop_indices[0]].color + return (color[0], color[1], color[2], 1.0) \ No newline at end of file diff --git a/src/panels/id_mask_editor.py b/src/panels/id_mask_editor.py index f1fd474..51a7709 100644 --- a/src/panels/id_mask_editor.py +++ b/src/panels/id_mask_editor.py @@ -4,6 +4,7 @@ from src.operators.create_id_mask import CreateIDMaskOperator from src.operators.id_editor_create_id import IDEDITOR_CreateIDOperator from src.operators.id_editor_paint import IDEDITOR_PaintIDMaskOperator from src.operators.id_editor_remove_id import IDEDITOR_RemoveIDOperator +from src.operators.id_mask_select import IDEDITOR_SelectIDMaskOperator from src.types.colors import get_color @@ -55,7 +56,11 @@ class IDMaskEditorPanel(bpy.types.Panel): row = layout.row() col = row.column() - col.operator(IDEDITOR_PaintIDMaskOperator.bl_idname, icon='VPAINT_HLT') + button_row = col.row() + button_row.operator(IDEDITOR_PaintIDMaskOperator.bl_idname, text='Paint', icon='VPAINT_HLT') + button_row.operator(IDEDITOR_SelectIDMaskOperator.bl_idname, text='Select', icon='SELECT_SET').isCalledFromEditor = True + + col.template_list( 'IDMaskEditorIDList', 'IDMaskEditorIDList',