From c162c335758ef9e1eae6a2069c208ec569b8f885 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Fri, 21 Jun 2024 12:15:41 +0200 Subject: [PATCH] feat(Blenvy): added support for Bevy components to meshes & materials * added a much improved "get current selection in outliner" helper function * added MESH and MATERIAL variants to the type enums * added metadata to both Mesh & Material types * various related tweaks & improvements --- .../bevy_components/components/lists.py | 2 + .../bevy_components/components/maps.py | 2 + .../bevy_components/components/metadata.py | 6 ++- .../bevy_components/components/operators.py | 33 ++++++------ .../add_ons/bevy_components/components/ui.py | 23 +++----- .../bevy_components/propGroups/prop_groups.py | 4 +- tools/blenvy/add_ons/bevy_components/utils.py | 54 ++++++++++++------- 7 files changed, 70 insertions(+), 54 deletions(-) diff --git a/tools/blenvy/add_ons/bevy_components/components/lists.py b/tools/blenvy/add_ons/bevy_components/components/lists.py index 0e93687..d809021 100644 --- a/tools/blenvy/add_ons/bevy_components/components/lists.py +++ b/tools/blenvy/add_ons/bevy_components/components/lists.py @@ -42,6 +42,8 @@ class BLENVY_OT_component_list_actions(Operator): items=( ('OBJECT', "Object", ""), ('COLLECTION', "Collection", ""), + ('MESH', "Mesh", ""), + ('MATERIAL', "Material", ""), ), default="OBJECT" ) # type: ignore diff --git a/tools/blenvy/add_ons/bevy_components/components/maps.py b/tools/blenvy/add_ons/bevy_components/components/maps.py index 7f7f2ce..eb351d4 100644 --- a/tools/blenvy/add_ons/bevy_components/components/maps.py +++ b/tools/blenvy/add_ons/bevy_components/components/maps.py @@ -37,6 +37,8 @@ class BLENVY_OT_component_map_actions(Operator): items=( ('OBJECT', "Object", ""), ('COLLECTION', "Collection", ""), + ('MESH', "Mesh", ""), + ('MATERIAL', "Material", ""), ), default="OBJECT" ) # type: ignore diff --git a/tools/blenvy/add_ons/bevy_components/components/metadata.py b/tools/blenvy/add_ons/bevy_components/components/metadata.py index 2d415b5..da56226 100644 --- a/tools/blenvy/add_ons/bevy_components/components/metadata.py +++ b/tools/blenvy/add_ons/bevy_components/components/metadata.py @@ -61,14 +61,18 @@ class ComponentsMeta(PropertyGroup): @classmethod def register(cls): - # you can add components to both objects & collections + # you can add components to both objects , collections , meshes & materials bpy.types.Object.components_meta = PointerProperty(type=ComponentsMeta) bpy.types.Collection.components_meta = PointerProperty(type=ComponentsMeta) + bpy.types.Mesh.components_meta = PointerProperty(type=ComponentsMeta) + bpy.types.Material.components_meta = PointerProperty(type=ComponentsMeta) @classmethod def unregister(cls): del bpy.types.Object.components_meta del bpy.types.Collection.components_meta + del bpy.types.Mesh.components_meta + del bpy.types.Material.components_meta # remove no longer valid metadata from item def cleanup_invalid_metadata(item): diff --git a/tools/blenvy/add_ons/bevy_components/components/operators.py b/tools/blenvy/add_ons/bevy_components/components/operators.py index 5ce436a..07fb9ee 100644 --- a/tools/blenvy/add_ons/bevy_components/components/operators.py +++ b/tools/blenvy/add_ons/bevy_components/components/operators.py @@ -6,7 +6,7 @@ from bpy.props import (StringProperty, EnumProperty) from .metadata import add_component_from_custom_property, add_component_to_item, apply_customProperty_values_to_item_propertyGroups, apply_propertyGroup_values_to_item_customProperties, apply_propertyGroup_values_to_item_customProperties_for_component, copy_propertyGroup_values_to_another_item, get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_item, remove_component_from_item, rename_component, toggle_component -from ..utils import get_selected_object_or_collection +from ..utils import get_item_by_type, get_selected_item class BLENVY_OT_component_add(Operator): """Add Bevy component to object/collection""" @@ -20,7 +20,7 @@ class BLENVY_OT_component_add(Operator): ) # type: ignore def execute(self, context): - target = get_selected_object_or_collection(context) + target = get_selected_item(context) print("adding component ", self.component_type, "to target '"+target.name+"'") has_component_type = self.component_type != "" @@ -53,6 +53,8 @@ class BLENVY_OT_component_copy(Operator): items=( ('OBJECT', "Object", ""), ('COLLECTION', "Collection", ""), + ('MESH', "Mesh", ""), + ('MATERIAL', "Material", ""), ), default="OBJECT" ) # type: ignore @@ -90,12 +92,14 @@ class BLENVY_OT_component_paste(Operator): def execute(self, context): source_item_name = context.window_manager.copied_source_item_name source_item_type = context.window_manager.copied_source_item_type - if source_item_type == 'Object': + source_item = get_item_by_type(source_item_type, source_item_name) + print("HEEEERRE", source_item_name, source_item_type, source_item) + """if source_item_type == 'Object': source_item = bpy.data.objects.get(source_item_name, None) elif source_item_type == 'Collection': - source_item = bpy.data.collections.get(source_item_name, None) + source_item = bpy.data.collections.get(source_item_name, None)""" - if source_item == None: + if source_item is None: self.report({"ERROR"}, "The source object to copy a component from does not exist") else: component_name = context.window_manager.copied_source_component_name @@ -105,7 +109,7 @@ class BLENVY_OT_component_paste(Operator): else: print("pasting component to item:", source_item, "component name:", str(component_name), "component value:" + str(component_value)) registry = context.window_manager.components_registry - target_item = get_selected_object_or_collection(context) + target_item = get_selected_item(context) copy_propertyGroup_values_to_another_item(source_item, target_item, component_name, registry) return {'FINISHED'} @@ -133,7 +137,9 @@ class BLENVY_OT_component_remove(Operator): items=( ('OBJECT', "Object", ""), ('COLLECTION', "Collection", ""), - ), + ('MESH', "Mesh", ""), + ('MATERIAL', "Material", ""), + ), default="OBJECT" ) # type: ignore @@ -142,10 +148,7 @@ class BLENVY_OT_component_remove(Operator): if self.item_name == "": self.report({"ERROR"}, "The target to remove ("+ self.component_name +") from does not exist") else: - if self.item_type == 'OBJECT': - target = bpy.data.objects[self.item_name] - elif self.item_type == 'COLLECTION': - target = bpy.data.collections[self.item_name] + target = get_item_by_type(self.item_type, self.item_name) print("removing component ", self.component_name, "from object '"+target.name+"'") @@ -260,11 +263,7 @@ class BLENVY_OT_component_rename_component(Operator): if original_name != '' and target_name != '' and original_name != target_name and len(target_items) > 0: for index, item_data in enumerate(target_items): [item_name, item_type] = item_data - item = None - if item_type == "OBJECT": - item = bpy.data.objects[item_name] - elif item_type == "COLLECTION": - item = bpy.data.collections[item_name] + item = get_item_by_type(item_type, item_name) if item and original_name in get_bevy_components(item) or original_name in item: try: @@ -367,7 +366,7 @@ class BLENVY_OT_component_toggle_visibility(Operator): ) # type: ignore def execute(self, context): - target = get_selected_object_or_collection(context) + target = get_selected_item(context) toggle_component(target, self.component_name) return {'FINISHED'} diff --git a/tools/blenvy/add_ons/bevy_components/components/ui.py b/tools/blenvy/add_ons/bevy_components/components/ui.py index d1beee0..9408a39 100644 --- a/tools/blenvy/add_ons/bevy_components/components/ui.py +++ b/tools/blenvy/add_ons/bevy_components/components/ui.py @@ -1,7 +1,7 @@ import json import bpy -from ..utils import get_selection_type +from ..utils import get_selected_item, get_selection_type from .metadata import do_item_custom_properties_have_missing_metadata, get_bevy_components @@ -176,22 +176,17 @@ class BLENVY_PT_components_panel(bpy.types.Panel): layout = self.layout name = "" target_type = "" - object = next(iter(context.selected_objects), None) - collection = context.collection - if object is not None: - name = object.name - target_type = "Object" - elif collection is not None: - name = collection.name - target_type = "Collection" + selected_item = get_selected_item(context) + target_type = get_selection_type(selected_item) + name = selected_item.name if selected_item is not None else '' + # name = context.object.name if context.object is not None else '' layout.label(text=f"Components for {name} ({target_type})") #print("object", context.object, "active", context.active_object, "objects", context.selected_objects) def draw(self, context): - object = next(iter(context.selected_objects), None) - collection = context.collection + selected_item = get_selected_item(context) layout = self.layout # we get & load our component registry @@ -199,10 +194,8 @@ class BLENVY_PT_components_panel(bpy.types.Panel): selected_component = bpy.context.window_manager.blenvy.components.component_selector registry_has_type_infos = registry.has_type_infos() - if object is not None: - draw_component_ui(layout, object, registry, selected_component, registry_has_type_infos, context) - elif collection is not None: - draw_component_ui(layout, collection, registry, selected_component, registry_has_type_infos, context) + if selected_item is not None: + draw_component_ui(layout, selected_item, registry, selected_component, registry_has_type_infos, context) else: layout.label(text ="Select an object to edit its components") diff --git a/tools/blenvy/add_ons/bevy_components/propGroups/prop_groups.py b/tools/blenvy/add_ons/bevy_components/propGroups/prop_groups.py index 735ad3d..3ba245c 100644 --- a/tools/blenvy/add_ons/bevy_components/propGroups/prop_groups.py +++ b/tools/blenvy/add_ons/bevy_components/propGroups/prop_groups.py @@ -4,13 +4,13 @@ import bpy from .conversions_from_prop_group import property_group_value_to_custom_property_value from .process_component import process_component from .utils import update_calback_helper -from ..utils import get_selected_object_or_collection +from ..utils import get_selected_item ## main callback function, fired whenever any property changes, no matter the nesting level def update_component(self, context, definition, component_name): registry = bpy.context.window_manager.components_registry - current_object_or_collection = get_selected_object_or_collection(context) + current_object_or_collection = get_selected_item(context) update_disabled = current_object_or_collection["__disable__update"] if "__disable__update" in current_object_or_collection else False update_disabled = registry.disable_all_object_updates or update_disabled # global settings if update_disabled: diff --git a/tools/blenvy/add_ons/bevy_components/utils.py b/tools/blenvy/add_ons/bevy_components/utils.py index 8de622e..a4efbae 100644 --- a/tools/blenvy/add_ons/bevy_components/utils.py +++ b/tools/blenvy/add_ons/bevy_components/utils.py @@ -22,6 +22,8 @@ class BLENVY_OT_item_select(Operator): items=( ('OBJECT', "Object", ""), ('COLLECTION', "Collection", ""), + ('MESH', "Mesh", ""), + ('MATERIAL', "Material", ""), ), default="OBJECT" ) # type: ignore @@ -53,19 +55,38 @@ class BLENVY_OT_item_select(Operator): return {'FINISHED'} -#FIXME: does not work if object is hidden !! -def get_selected_object_or_collection(context): - target = None - object = next(iter(context.selected_objects), None) - collection = context.collection - if object is not None: - target = object - elif collection is not None: - target = collection - return target +def get_selected_item(context): + selection = None + + #print("original context", context) + def get_outliner_area(): + if bpy.context.area.type!='OUTLINER': + for area in bpy.context.screen.areas: + if area.type == 'OUTLINER': + return area + return None + + area = get_outliner_area() + if area is not None: + region = next(region for region in area.regions if region.type == "WINDOW") + + with bpy.context.temp_override(area=area, region=region): + #print("overriden context", bpy.context) + for obj in bpy.context.selected_ids: + pass#print(f"Selected: {obj.name} - {type(obj)}") + selection = bpy.context.selected_ids[len(bpy.context.selected_ids) - 1] if len(bpy.context.selected_ids)>0 else None #next(iter(bpy.context.selected_ids), None) + print("selection", f"Selected: {selection.name} - {type(selection)}") + + #print("SELECTIONS", context.selected_objects) + return selection def get_selection_type(selection): + #print("bla mesh", isinstance(selection, bpy.types.Mesh), "bli bli", selection.type) + if isinstance(selection, bpy.types.Material): + return 'MATERIAL' + if isinstance(selection, bpy.types.Mesh): + return 'MESH' if isinstance(selection, bpy.types.Object): return 'OBJECT' if isinstance(selection, bpy.types.Collection): @@ -76,18 +97,13 @@ def get_item_by_type(item_type, item_name): if item_type == 'OBJECT': item = bpy.data.objects[item_name] elif item_type == 'COLLECTION': - print("item NAME", item_name) item = bpy.data.collections[item_name] + elif item_type == "MESH": + item = bpy.data.meshes[item_name] + elif item_type == 'MATERIAL': + item = bpy.data.materials[item_name] return item -def get_selected_object_or_collection_by_item_type(context, item_type): - item = None - if item_type == 'OBJECT': - object = next(iter(context.selected_objects), None) - return object - elif item_type == 'COLLECTION': - return context.collection - def add_component_to_ui_list(self, context, _): items = [] type_infos = context.window_manager.components_registry.type_infos