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
This commit is contained in:
parent
dafd408bd1
commit
c162c33575
|
@ -42,6 +42,8 @@ class BLENVY_OT_component_list_actions(Operator):
|
||||||
items=(
|
items=(
|
||||||
('OBJECT', "Object", ""),
|
('OBJECT', "Object", ""),
|
||||||
('COLLECTION', "Collection", ""),
|
('COLLECTION', "Collection", ""),
|
||||||
|
('MESH', "Mesh", ""),
|
||||||
|
('MATERIAL', "Material", ""),
|
||||||
),
|
),
|
||||||
default="OBJECT"
|
default="OBJECT"
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
|
@ -37,6 +37,8 @@ class BLENVY_OT_component_map_actions(Operator):
|
||||||
items=(
|
items=(
|
||||||
('OBJECT', "Object", ""),
|
('OBJECT', "Object", ""),
|
||||||
('COLLECTION', "Collection", ""),
|
('COLLECTION', "Collection", ""),
|
||||||
|
('MESH', "Mesh", ""),
|
||||||
|
('MATERIAL', "Material", ""),
|
||||||
),
|
),
|
||||||
default="OBJECT"
|
default="OBJECT"
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
|
@ -61,14 +61,18 @@ class ComponentsMeta(PropertyGroup):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
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.Object.components_meta = PointerProperty(type=ComponentsMeta)
|
||||||
bpy.types.Collection.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
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
del bpy.types.Object.components_meta
|
del bpy.types.Object.components_meta
|
||||||
del bpy.types.Collection.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
|
# remove no longer valid metadata from item
|
||||||
def cleanup_invalid_metadata(item):
|
def cleanup_invalid_metadata(item):
|
||||||
|
|
|
@ -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 .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):
|
class BLENVY_OT_component_add(Operator):
|
||||||
"""Add Bevy component to object/collection"""
|
"""Add Bevy component to object/collection"""
|
||||||
|
@ -20,7 +20,7 @@ class BLENVY_OT_component_add(Operator):
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
def execute(self, context):
|
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+"'")
|
print("adding component ", self.component_type, "to target '"+target.name+"'")
|
||||||
|
|
||||||
has_component_type = self.component_type != ""
|
has_component_type = self.component_type != ""
|
||||||
|
@ -53,6 +53,8 @@ class BLENVY_OT_component_copy(Operator):
|
||||||
items=(
|
items=(
|
||||||
('OBJECT', "Object", ""),
|
('OBJECT', "Object", ""),
|
||||||
('COLLECTION', "Collection", ""),
|
('COLLECTION', "Collection", ""),
|
||||||
|
('MESH', "Mesh", ""),
|
||||||
|
('MATERIAL', "Material", ""),
|
||||||
),
|
),
|
||||||
default="OBJECT"
|
default="OBJECT"
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
@ -90,12 +92,14 @@ class BLENVY_OT_component_paste(Operator):
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
source_item_name = context.window_manager.copied_source_item_name
|
source_item_name = context.window_manager.copied_source_item_name
|
||||||
source_item_type = context.window_manager.copied_source_item_type
|
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)
|
source_item = bpy.data.objects.get(source_item_name, None)
|
||||||
elif source_item_type == 'Collection':
|
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")
|
self.report({"ERROR"}, "The source object to copy a component from does not exist")
|
||||||
else:
|
else:
|
||||||
component_name = context.window_manager.copied_source_component_name
|
component_name = context.window_manager.copied_source_component_name
|
||||||
|
@ -105,7 +109,7 @@ class BLENVY_OT_component_paste(Operator):
|
||||||
else:
|
else:
|
||||||
print("pasting component to item:", source_item, "component name:", str(component_name), "component value:" + str(component_value))
|
print("pasting component to item:", source_item, "component name:", str(component_name), "component value:" + str(component_value))
|
||||||
registry = context.window_manager.components_registry
|
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)
|
copy_propertyGroup_values_to_another_item(source_item, target_item, component_name, registry)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
@ -133,6 +137,8 @@ class BLENVY_OT_component_remove(Operator):
|
||||||
items=(
|
items=(
|
||||||
('OBJECT', "Object", ""),
|
('OBJECT', "Object", ""),
|
||||||
('COLLECTION', "Collection", ""),
|
('COLLECTION', "Collection", ""),
|
||||||
|
('MESH', "Mesh", ""),
|
||||||
|
('MATERIAL', "Material", ""),
|
||||||
),
|
),
|
||||||
default="OBJECT"
|
default="OBJECT"
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
@ -142,10 +148,7 @@ class BLENVY_OT_component_remove(Operator):
|
||||||
if self.item_name == "":
|
if self.item_name == "":
|
||||||
self.report({"ERROR"}, "The target to remove ("+ self.component_name +") from does not exist")
|
self.report({"ERROR"}, "The target to remove ("+ self.component_name +") from does not exist")
|
||||||
else:
|
else:
|
||||||
if self.item_type == 'OBJECT':
|
target = get_item_by_type(self.item_type, self.item_name)
|
||||||
target = bpy.data.objects[self.item_name]
|
|
||||||
elif self.item_type == 'COLLECTION':
|
|
||||||
target = bpy.data.collections[self.item_name]
|
|
||||||
|
|
||||||
print("removing component ", self.component_name, "from object '"+target.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:
|
if original_name != '' and target_name != '' and original_name != target_name and len(target_items) > 0:
|
||||||
for index, item_data in enumerate(target_items):
|
for index, item_data in enumerate(target_items):
|
||||||
[item_name, item_type] = item_data
|
[item_name, item_type] = item_data
|
||||||
item = None
|
item = get_item_by_type(item_type, item_name)
|
||||||
if item_type == "OBJECT":
|
|
||||||
item = bpy.data.objects[item_name]
|
|
||||||
elif item_type == "COLLECTION":
|
|
||||||
item = bpy.data.collections[item_name]
|
|
||||||
|
|
||||||
if item and original_name in get_bevy_components(item) or original_name in item:
|
if item and original_name in get_bevy_components(item) or original_name in item:
|
||||||
try:
|
try:
|
||||||
|
@ -367,7 +366,7 @@ class BLENVY_OT_component_toggle_visibility(Operator):
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
target = get_selected_object_or_collection(context)
|
target = get_selected_item(context)
|
||||||
toggle_component(target, self.component_name)
|
toggle_component(target, self.component_name)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import bpy
|
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
|
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
|
layout = self.layout
|
||||||
name = ""
|
name = ""
|
||||||
target_type = ""
|
target_type = ""
|
||||||
object = next(iter(context.selected_objects), None)
|
selected_item = get_selected_item(context)
|
||||||
collection = context.collection
|
target_type = get_selection_type(selected_item)
|
||||||
if object is not None:
|
name = selected_item.name if selected_item is not None else ''
|
||||||
name = object.name
|
|
||||||
target_type = "Object"
|
|
||||||
elif collection is not None:
|
|
||||||
name = collection.name
|
|
||||||
target_type = "Collection"
|
|
||||||
# name = context.object.name if context.object is not None else ''
|
# name = context.object.name if context.object is not None else ''
|
||||||
layout.label(text=f"Components for {name} ({target_type})")
|
layout.label(text=f"Components for {name} ({target_type})")
|
||||||
|
|
||||||
#print("object", context.object, "active", context.active_object, "objects", context.selected_objects)
|
#print("object", context.object, "active", context.active_object, "objects", context.selected_objects)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
object = next(iter(context.selected_objects), None)
|
selected_item = get_selected_item(context)
|
||||||
collection = context.collection
|
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
# we get & load our component registry
|
# 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
|
selected_component = bpy.context.window_manager.blenvy.components.component_selector
|
||||||
registry_has_type_infos = registry.has_type_infos()
|
registry_has_type_infos = registry.has_type_infos()
|
||||||
|
|
||||||
if object is not None:
|
if selected_item is not None:
|
||||||
draw_component_ui(layout, object, registry, selected_component, registry_has_type_infos, context)
|
draw_component_ui(layout, selected_item, 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)
|
|
||||||
else:
|
else:
|
||||||
layout.label(text ="Select an object to edit its components")
|
layout.label(text ="Select an object to edit its components")
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@ import bpy
|
||||||
from .conversions_from_prop_group import property_group_value_to_custom_property_value
|
from .conversions_from_prop_group import property_group_value_to_custom_property_value
|
||||||
from .process_component import process_component
|
from .process_component import process_component
|
||||||
from .utils import update_calback_helper
|
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
|
## main callback function, fired whenever any property changes, no matter the nesting level
|
||||||
def update_component(self, context, definition, component_name):
|
def update_component(self, context, definition, component_name):
|
||||||
registry = bpy.context.window_manager.components_registry
|
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 = 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
|
update_disabled = registry.disable_all_object_updates or update_disabled # global settings
|
||||||
if update_disabled:
|
if update_disabled:
|
||||||
|
|
|
@ -22,6 +22,8 @@ class BLENVY_OT_item_select(Operator):
|
||||||
items=(
|
items=(
|
||||||
('OBJECT', "Object", ""),
|
('OBJECT', "Object", ""),
|
||||||
('COLLECTION', "Collection", ""),
|
('COLLECTION', "Collection", ""),
|
||||||
|
('MESH', "Mesh", ""),
|
||||||
|
('MATERIAL', "Material", ""),
|
||||||
),
|
),
|
||||||
default="OBJECT"
|
default="OBJECT"
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
@ -53,19 +55,38 @@ class BLENVY_OT_item_select(Operator):
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
#FIXME: does not work if object is hidden !!
|
def get_selected_item(context):
|
||||||
def get_selected_object_or_collection(context):
|
selection = None
|
||||||
target = None
|
|
||||||
object = next(iter(context.selected_objects), None)
|
#print("original context", context)
|
||||||
collection = context.collection
|
def get_outliner_area():
|
||||||
if object is not None:
|
if bpy.context.area.type!='OUTLINER':
|
||||||
target = object
|
for area in bpy.context.screen.areas:
|
||||||
elif collection is not None:
|
if area.type == 'OUTLINER':
|
||||||
target = collection
|
return area
|
||||||
return target
|
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):
|
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):
|
if isinstance(selection, bpy.types.Object):
|
||||||
return 'OBJECT'
|
return 'OBJECT'
|
||||||
if isinstance(selection, bpy.types.Collection):
|
if isinstance(selection, bpy.types.Collection):
|
||||||
|
@ -76,18 +97,13 @@ def get_item_by_type(item_type, item_name):
|
||||||
if item_type == 'OBJECT':
|
if item_type == 'OBJECT':
|
||||||
item = bpy.data.objects[item_name]
|
item = bpy.data.objects[item_name]
|
||||||
elif item_type == 'COLLECTION':
|
elif item_type == 'COLLECTION':
|
||||||
print("item NAME", item_name)
|
|
||||||
item = bpy.data.collections[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
|
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, _):
|
def add_component_to_ui_list(self, context, _):
|
||||||
items = []
|
items = []
|
||||||
type_infos = context.window_manager.components_registry.type_infos
|
type_infos = context.window_manager.components_registry.type_infos
|
||||||
|
|
Loading…
Reference in New Issue