feat(bevy_components): continued changes to base logic on long_names

This commit is contained in:
kaosat.dev 2024-05-02 10:24:09 +02:00
parent 185c25f7b2
commit ca02c1df8c
19 changed files with 158 additions and 115 deletions

View File

@ -207,3 +207,10 @@ UI:
- [x] clean up reloading of registry settings
- [x] clean up file watcher
=========================================
Restructuring of storage of components
- [x] marking of invalid root propgroups/components should be based on long name
- [ ] overhaul & check each prop group type's use of short names => long names
- [ ] lists

View File

@ -22,8 +22,7 @@ from .registry.registry import ComponentsRegistry,MissingBevyType
from .registry.operators import (COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL, COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT, COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL, COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT, OT_select_component_name_to_replace, OT_select_object, ReloadRegistryOperator, OT_OpenFilebrowser)
from .registry.ui import (BEVY_COMPONENTS_PT_Configuration, BEVY_COMPONENTS_PT_AdvancedToolsPanel, BEVY_COMPONENTS_PT_MissingTypesPanel, MISSING_TYPES_UL_List)
from .components.metadata import (ComponentMetadata, ComponentsMeta, ensure_metadata_for_all_objects)
from .propGroups.prop_groups import (generate_propertyGroups_for_components)
from .components.metadata import (ComponentMetadata, ComponentsMeta)
from .components.lists import GENERIC_LIST_OT_actions, Generic_LIST_OT_AddItem, Generic_LIST_OT_RemoveItem, Generic_LIST_OT_SelectItem
from .components.definitions_list import (ComponentDefinitionsList, ClearComponentDefinitionsList)
from .components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel)

View File

@ -47,12 +47,12 @@ class ComponentDefinitionsList(bpy.types.PropertyGroup):
description="list",
# items argument required to initialize, just filled with empty values
items = add_component_to_ui_list,
)
) # type: ignore
filter: StringProperty(
name="component filter",
description="filter for the components list",
options={'TEXTEDIT_UPDATE'}
)
) # type: ignore
class ClearComponentDefinitionsList(bpy.types.Operator):

View File

@ -10,19 +10,19 @@ class Generic_LIST_OT_AddItem(Operator):
property_group_path: StringProperty(
name="property group path",
description="",
)
) # type: ignore
component_name: StringProperty(
name="component name",
description="",
)
) # type: ignore
def execute(self, context):
print("")
object = context.object
# information is stored in component meta
components_in_object = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == self.component_name, components_in_object), None)
component_meta = next(filter(lambda component: component["long_name"] == self.component_name, components_in_object), None)
propertyGroup = component_meta
for path_item in json.loads(self.property_group_path):
@ -47,19 +47,19 @@ class Generic_LIST_OT_RemoveItem(Operator):
property_group_path: StringProperty(
name="property group path",
description="",
)
) # type: ignore
component_name: StringProperty(
name="component name",
description="",
)
) # type: ignore
def execute(self, context):
print("remove from list", context.object)
object = context.object
# information is stored in component meta
components_in_object = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == self.component_name, components_in_object), None)
component_meta = next(filter(lambda component: component["long_name"] == self.component_name, components_in_object), None)
propertyGroup = component_meta
for path_item in json.loads(self.property_group_path):
@ -81,14 +81,14 @@ class Generic_LIST_OT_SelectItem(Operator):
property_group_path: StringProperty(
name="property group path",
description="",
)
) # type: ignore
component_name: StringProperty(
name="component name",
description="",
)
) # type: ignore
selection_index: IntProperty()
selection_index: IntProperty() # type: ignore
def execute(self, context):
print("select in list", context.object)
@ -96,7 +96,7 @@ class Generic_LIST_OT_SelectItem(Operator):
object = context.object
# information is stored in component meta
components_in_object = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == self.component_name, components_in_object), None)
component_meta = next(filter(lambda component: component["long_name"] == self.component_name, components_in_object), None)
propertyGroup = component_meta
for path_item in json.loads(self.property_group_path):
@ -121,23 +121,23 @@ class GENERIC_LIST_OT_actions(Operator):
('UP', "Up", ""),
('DOWN', "Down", ""),
('REMOVE', "Remove", ""),
('ADD', "Add", "")))
('ADD', "Add", ""))) # type: ignore
property_group_path: StringProperty(
name="property group path",
description="",
)
) # type: ignore
component_name: StringProperty(
name="component name",
description="",
)
) # type: ignore
def invoke(self, context, event):
object = context.object
# information is stored in component meta
components_in_object = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == self.component_name, components_in_object), None)
component_meta = next(filter(lambda component: component["long_name"] == self.component_name, components_in_object), None)
propertyGroup = component_meta
for path_item in json.loads(self.property_group_path):

View File

@ -10,51 +10,51 @@ class ComponentMetadata(bpy.types.PropertyGroup):
name : bpy.props.StringProperty(
name = "name",
default = ""
)
) # type: ignore
long_name : bpy.props.StringProperty(
name = "long name",
default = ""
)
) # type: ignore
type_name : bpy.props.StringProperty(
name = "Type",
default = ""
)
) # type: ignore
values: bpy.props.StringProperty(
name = "Value",
default = ""
)
) # type: ignore
enabled: BoolProperty(
name="enabled",
description="component enabled",
default=True
)
) # type: ignore
invalid: BoolProperty(
name="invalid",
description="component is invalid, because of missing registration/ other issues",
default=False
)
) # type: ignore
invalid_details: StringProperty(
name="invalid details",
description="detailed information about why the component is invalid",
default=""
)
) # type: ignore
visible: BoolProperty( # REALLY dislike doing this for UI control, but ok hack for now
default=True
)
) # type: ignore
class ComponentsMeta(PropertyGroup):
infos_per_component: StringProperty(
name="infos per component",
description="component"
)
components: bpy.props.CollectionProperty(type = ComponentMetadata)
) # type: ignore
components: bpy.props.CollectionProperty(type = ComponentMetadata) # type: ignore
@classmethod
def register(cls):
@ -72,7 +72,9 @@ def get_component_metadata_by_short_name(object, short_name):
# remove no longer valid metadata from object
def cleanup_invalid_metadata(object):
bevy_components = json.loads(object['bevy_components']) if 'bevy_components' in object else {}
bevy_components = get_bevy_components(object)
if len(bevy_components.keys()) == 0: # no components, bail out
return
components_metadata = object.components_meta.components
to_remove = []
for index, component_meta in enumerate(components_metadata):
@ -93,6 +95,10 @@ def find_component_definition_from_short_name(short_name):
return registry.type_infos.get(long_name, None)
return None
def find_component_definition_from_long_name(long_name):
registry = bpy.context.window_manager.components_registry
return registry.type_infos.get(long_name, None)
# FIXME: feels a bit heavy duty, should only be done
# if the components panel is active ?
def ensure_metadata_for_all_objects():
@ -123,31 +129,45 @@ def do_object_custom_properties_have_missing_metadata(object):
return missing_metadata
# adds metadata to object only if it is missing
def add_metadata_to_components_without_metadata(object):
registry = bpy.context.window_manager.components_registry
for component_name in dict(object) :
if component_name == "components_meta":
continue
upsert_component_in_object(object, component_name, registry)
import json
def inject_component(object, long_name, value):
def upsert_bevy_component(object, long_name, value):
if not 'bevy_components' in object:
object['bevy_components'] = '{}'
previous = json.loads(object['bevy_components'])
previous[long_name] = value
object['bevy_components'] = json.dumps(previous)
bevy_components = json.loads(object['bevy_components'])
bevy_components[long_name] = value
object['bevy_components'] = json.dumps(bevy_components)
#object['bevy_components'][long_name] = value # Sigh, this does not work, hits Blender's 63 char length limit
def bla_component(object, long_name):
def remove_bevy_component(object, long_name):
if 'bevy_components' in object:
current = json.loads(object['bevy_components'])
del current[long_name]
object['bevy_components'] = json.dumps(current)
def get_bevy_components(object):
if 'bevy_components' in object:
bevy_components = json.loads(object['bevy_components'])
return bevy_components
return {}
def get_bevy_component_value_by_long_name(object, long_name):
bevy_components = get_bevy_components(object)
if len(bevy_components.keys()) == 0 :
return None
return bevy_components.get(long_name, None)
def is_bevy_component_in_object(object, long_name):
return get_bevy_component_value_by_long_name(object, long_name) is not None
# adds metadata to object only if it is missing
def add_metadata_to_components_without_metadata(object):
registry = bpy.context.window_manager.components_registry
for component_name in get_bevy_components(object) :
if component_name == "components_meta":
continue
upsert_component_in_object(object, component_name, registry)
# adds a component to an object (including metadata) using the provided component definition & optional value
def add_component_to_object(object, component_definition, value=None):
cleanup_invalid_metadata(object)
@ -158,7 +178,6 @@ def add_component_to_object(object, component_definition, value=None):
if not registry.has_type_infos():
raise Exception('registry type infos have not been loaded yet or are missing !')
definition = registry.type_infos[long_name]
print("HEAAAY", value)
# now we use our pre_generated property groups to set the initial value of our custom property
(_, propertyGroup) = upsert_component_in_object(object, long_name=long_name, registry=registry)
if value == None:
@ -170,7 +189,7 @@ def add_component_to_object(object, component_definition, value=None):
# object[short_name] = value
print("ADDING VAALUEEE", value)
inject_component(object, long_name, value)
upsert_bevy_component(object, long_name, value)
#ping_depsgraph_update(object)
@ -226,14 +245,14 @@ def copy_propertyGroup_values_to_another_object(source_object, target_object, co
if source_object == None or target_object == None or component_name == None:
raise Exception('missing input data, cannot copy component propertryGroup')
component_definition = find_component_definition_from_short_name(component_name)
short_name = component_definition["short_name"]
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
component_definition = find_component_definition_from_long_name(component_name)
long_name = component_name
property_group_name = registry.get_propertyGroupName_from_longName(long_name)
registry = bpy.context.window_manager.components_registry
source_components_metadata = source_object.components_meta.components
source_componentMeta = next(filter(lambda component: component["name"] == short_name, source_components_metadata), None)
source_componentMeta = next(filter(lambda component: component["long_name"] == long_name, source_components_metadata), None)
# matching component means we already have this type of component
source_propertyGroup = getattr(source_componentMeta, property_group_name)
@ -241,28 +260,27 @@ def copy_propertyGroup_values_to_another_object(source_object, target_object, co
(_, target_propertyGroup) = upsert_component_in_object(target_object, component_name, registry)
# add to object
value = property_group_value_to_custom_property_value(target_propertyGroup, component_definition, registry, None)
target_object[short_name] = value
upsert_bevy_component(target_object, long_name, value)
# copy the values over
for field_name in source_propertyGroup.field_names:
if field_name in source_propertyGroup:
target_propertyGroup[field_name] = source_propertyGroup[field_name]
apply_propertyGroup_values_to_object_customProperties(target_object)
ping_depsgraph_update(object)
# TODO: move to propgroups ?
def apply_propertyGroup_values_to_object_customProperties(object):
cleanup_invalid_metadata(object)
registry = bpy.context.window_manager.components_registry
for component_name in dict(object) :
if component_name == "components_meta":
continue
for component_name in get_bevy_components(object) :
"""if component_name == "components_meta":
continue"""
(_, propertyGroup) = upsert_component_in_object(object, component_name, registry)
component_definition = find_component_definition_from_short_name(component_name)
component_definition = find_component_definition_from_long_name(component_name)
if component_definition != None:
value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
object[component_name] = value
upsert_bevy_component(object=object, long_name=component_name, value=value)
# apply component value(s) to custom property of a single component
def apply_propertyGroup_values_to_object_customProperties_for_component(object, component_name):
@ -304,7 +322,7 @@ def apply_customProperty_values_to_object_propertyGroups(object):
# removes the given component from the object: removes both the custom property and the matching metadata from the object
def remove_component_from_object(object, component_name):
bla_component(object, component_name)
remove_bevy_component(object, component_name)
components_metadata = getattr(object, "components_meta", None)
if components_metadata == None:
@ -319,16 +337,14 @@ def remove_component_from_object(object, component_name):
break
for index in to_remove:
components_metadata.remove(index)
ping_depsgraph_update(object)
return True
def add_component_from_custom_property(object):
add_metadata_to_components_without_metadata(object)
apply_customProperty_values_to_object_propertyGroups(object)
ping_depsgraph_update(object)
def toggle_component(object, component_name):
components_in_object = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == component_name, components_in_object), None)
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None)
if component_meta != None:
component_meta.visible = not component_meta.visible

View File

@ -4,7 +4,7 @@ import bpy
from bpy_types import Operator
from bpy.props import (StringProperty)
from .metadata import add_component_from_custom_property, add_component_to_object, add_metadata_to_components_without_metadata, apply_customProperty_values_to_object_propertyGroups, apply_propertyGroup_values_to_object_customProperties_for_component, copy_propertyGroup_values_to_another_object, find_component_definition_from_short_name, remove_component_from_object, toggle_component
from .metadata import add_component_from_custom_property, add_component_to_object, add_metadata_to_components_without_metadata, apply_customProperty_values_to_object_propertyGroups, apply_propertyGroup_values_to_object_customProperties_for_component, copy_propertyGroup_values_to_another_object, find_component_definition_from_short_name, get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_object, remove_component_from_object, toggle_component
class AddComponentOperator(Operator):
"""Add Bevy component to object"""
@ -36,7 +36,7 @@ class CopyComponentOperator(Operator):
bl_options = {"UNDO"}
source_component_name: StringProperty(
name="source component_name",
name="source component_name (long)",
description="name of the component to copy",
) # type: ignore
@ -80,10 +80,10 @@ class PasteComponentOperator(Operator):
self.report({"ERROR"}, "The source object to copy a component from does not exist")
else:
component_name = context.window_manager.copied_source_component_name
if not component_name in source_object:
component_value = get_bevy_component_value_by_long_name(source_object, component_name)
if component_value is None:
self.report({"ERROR"}, "The source component to copy from does not exist")
else:
component_value = source_object[component_name]
print("pasting component to object: component name:", str(component_name), "component value:" + str(component_value))
print (context.object)
registry = context.window_manager.components_registry
@ -114,10 +114,15 @@ class RemoveComponentOperator(Operator):
else:
object = bpy.data.objects[self.object_name]
print("removing component ", self.component_name, "from object '"+object.name+"'")
if object is not None and 'bevy_components' in object and self.component_name in object['bevy_components']:
remove_component_from_object(object, self.component_name)
if object is not None and 'bevy_components' in object :
component_value = get_bevy_component_value_by_long_name(object, self.component_name)
if component_value is not None:
remove_component_from_object(object, self.component_name)
else :
self.report({"ERROR"}, "The component to remove ("+ self.component_name +") does not exist")
else:
self.report({"ERROR"}, "The object/ component to remove ("+ self.component_name +") does not exist")
self.report({"ERROR"}, "The object to remove ("+ self.component_name +") from does not exist")
return {'FINISHED'}
@ -145,7 +150,7 @@ class RemoveComponentFromAllObjectsOperator(Operator):
total = len(bpy.data.objects)
for index, object in enumerate(bpy.data.objects):
if len(object.keys()) > 0:
if object is not None and self.component_name in object:
if object is not None and is_bevy_component_in_object(object, self.component_name):
remove_component_from_object(object, self.component_name)
progress = index / total
@ -222,7 +227,7 @@ class OT_rename_component(Operator):
components_metadata = getattr(object, "components_meta", None)
if components_metadata:
components_metadata = components_metadata.components
component_meta = next(filter(lambda component: component["name"] == new_name, components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == new_name, components_metadata), None)
if component_meta:
component_meta.invalid = True
component_meta.invalid_details = "unknow issue when renaming/transforming component, please remove it & add it back again"
@ -240,7 +245,7 @@ class OT_rename_component(Operator):
components_metadata = getattr(object, "components_meta", None)
if components_metadata:
components_metadata = components_metadata.components
component_meta = next(filter(lambda component: component["name"] == new_name, components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == new_name, components_metadata), None)
if component_meta:
component_meta.invalid = True
component_meta.invalid_details = "wrong custom property value, overwrite them by changing the values in the ui or change them & regenerate"

View File

@ -178,12 +178,12 @@ class BEVY_COMPONENTS_PT_ComponentsPanel(bpy.types.Panel):
# we fetch the matching ui property group
root_propertyGroup_name = registry.get_propertyGroupName_from_longName(component_name)
print("root_propertyGroup_name", root_propertyGroup_name)
print("component_meta", component_meta, component_invalid)
"""print("root_propertyGroup_name", root_propertyGroup_name)
print("component_meta", component_meta, component_invalid)"""
if root_propertyGroup_name:
propertyGroup = getattr(component_meta, root_propertyGroup_name, None)
print("propertyGroup", propertyGroup)
"""print("propertyGroup", propertyGroup)"""
if propertyGroup:
# if the component has only 0 or 1 field names, display inline, otherwise change layout
single_field = len(propertyGroup.field_names) < 2

View File

@ -6,7 +6,7 @@ from . import process_tupples
from . import process_enum
from . import process_list
def process_component(registry, definition, update, extras=None, nesting = []):
def process_component(registry, definition, update, extras=None, nesting = [], nesting_long_names = []):
component_name = definition['title']
short_name = definition["short_name"]
type_info = definition["typeInfo"] if "typeInfo" in definition else None
@ -31,21 +31,21 @@ def process_component(registry, definition, update, extras=None, nesting = []):
if has_properties:
__annotations__ = __annotations__ | process_structs.process_structs(registry, definition, properties, update, nesting)
__annotations__ = __annotations__ | process_structs.process_structs(registry, definition, properties, update, nesting, nesting_long_names)
with_properties = True
tupple_or_struct = "struct"
if has_prefixItems:
__annotations__ = __annotations__ | process_tupples.process_tupples(registry, definition, prefixItems, update, nesting)
__annotations__ = __annotations__ | process_tupples.process_tupples(registry, definition, prefixItems, update, nesting, nesting_long_names)
with_items = True
tupple_or_struct = "tupple"
if is_enum:
__annotations__ = __annotations__ | process_enum.process_enum(registry, definition, update, nesting)
__annotations__ = __annotations__ | process_enum.process_enum(registry, definition, update, nesting, nesting_long_names)
with_enum = True
if is_list:
__annotations__ = __annotations__ | process_list.process_list(registry, definition, update, nesting)
__annotations__ = __annotations__ | process_list.process_list(registry, definition, update, nesting, nesting_long_names)
with_list= True
field_names = []
@ -56,7 +56,7 @@ def process_component(registry, definition, update, extras=None, nesting = []):
extras = extras if extras is not None else {
"type_name": component_name
}
root_component = nesting[0] if len(nesting) > 0 else component_name
root_component = nesting_long_names[0] if len(nesting_long_names) > 0 else component_name
# print("DONE:",short_name,"__annotations__", __annotations__)
# print("")
property_group_params = {

View File

@ -1,13 +1,17 @@
from bpy.props import (StringProperty)
from . import process_component
def process_enum(registry, definition, update, nesting):
def process_enum(registry, definition, update, nesting, nesting_long_names):
blender_property_mapping = registry.blender_property_mapping
short_name = definition["short_name"]
long_name = definition["title"]
type_def = definition["type"] if "type" in definition else None
values = definition["oneOf"]
nesting = nesting + [short_name]
nesting_long_names = nesting_long_names = [long_name]
__annotations__ = {}
original_type_name = "enum"
@ -25,12 +29,12 @@ def process_enum(registry, definition, update, nesting):
if "prefixItems" in item:
#print("tupple variant in enum", short_name, item)
registry.add_custom_type(item_short_name, item)
(sub_component_group, _) = process_component.process_component(registry, item, update, {"nested": True}, nesting)
(sub_component_group, _) = process_component.process_component(registry, item, update, {"nested": True}, nesting, nesting_long_names)
additional_annotations[variant_name] = sub_component_group
elif "properties" in item:
#print("struct variant in enum", short_name, item)
registry.add_custom_type(item_short_name, item)
(sub_component_group, _) = process_component.process_component(registry, item, update, {"nested": True}, nesting)
(sub_component_group, _) = process_component.process_component(registry, item, update, {"nested": True}, nesting, nesting_long_names)
additional_annotations[variant_name] = sub_component_group
else: # for the cases where it's neither a tupple nor a structs: FIXME: not 100% sure of this
#print("other variant in enum", short_name)

View File

@ -2,11 +2,12 @@ from bpy.props import (StringProperty, IntProperty, CollectionProperty)
from .utils import generate_wrapper_propertyGroup
from . import process_component
def process_list(registry, definition, update, nesting=[]):
def process_list(registry, definition, update, nesting=[], nesting_long_names=[]):
value_types_defaults = registry.value_types_defaults
type_infos = registry.type_infos
short_name = definition["short_name"]
long_name = definition["title"]
ref_name = definition["items"]["type"]["$ref"].replace("#/$defs/", "")
item_definition = type_infos[ref_name]
@ -23,6 +24,8 @@ def process_list(registry, definition, update, nesting=[]):
property_group_class = list_content_group_class
nesting = nesting+[short_name]
nesting_long_names = nesting_long_names + [long_name]
item_collection = CollectionProperty(type=property_group_class)
item_short_name = item_short_name if not is_item_value_type else "wrapper_" + item_short_name

View File

@ -1,15 +1,17 @@
from bpy.props import (StringProperty)
from . import process_component
def process_structs(registry, definition, properties, update, nesting):
def process_structs(registry, definition, properties, update, nesting, nesting_long_names):
value_types_defaults = registry.value_types_defaults
blender_property_mapping = registry.blender_property_mapping
type_infos = registry.type_infos
long_name = definition["title"]
short_name = definition["short_name"]
__annotations__ = {}
default_values = {}
nesting = nesting + [short_name]
nesting_long_names = nesting_long_names + [long_name]
for property_name in properties.keys():
ref_name = properties[property_name]["type"]["$ref"].replace("#/$defs/", "")
@ -33,7 +35,7 @@ def process_structs(registry, definition, properties, update, nesting):
__annotations__[property_name] = blender_property
else:
original_long_name = original["title"]
(sub_component_group, _) = process_component.process_component(registry, original, update, {"nested": True, "type_name": original_long_name}, nesting)
(sub_component_group, _) = process_component.process_component(registry, original, update, {"nested": True, "type_name": original_long_name}, nesting, nesting_long_names)
__annotations__[property_name] = sub_component_group
# if there are sub fields, add an attribute "sub_fields" possibly a pointer property ? or add a standard field to the type , that is stored under "attributes" and not __annotations (better)
else:
@ -41,6 +43,6 @@ def process_structs(registry, definition, properties, update, nesting):
__annotations__[property_name] = StringProperty(default="N/A")
registry.add_missing_typeInfo(ref_name)
# the root component also becomes invalid (in practice it is not always a component, but good enough)
registry.add_invalid_component(nesting[0])
registry.add_invalid_component(nesting_long_names[0])
return __annotations__

View File

@ -1,13 +1,15 @@
from bpy.props import (StringProperty)
from . import process_component
def process_tupples(registry, definition, prefixItems, update, nesting=[]):
def process_tupples(registry, definition, prefixItems, update, nesting=[], nesting_long_names=[]):
value_types_defaults = registry.value_types_defaults
blender_property_mapping = registry.blender_property_mapping
type_infos = registry.type_infos
long_name = definition["title"]
short_name = definition["short_name"]
nesting = nesting+[short_name]
nesting_long_names = nesting_long_names + [long_name]
__annotations__ = {}
default_values = []
@ -46,7 +48,7 @@ def process_tupples(registry, definition, prefixItems, update, nesting=[]):
__annotations__[property_name] = StringProperty(default="N/A")
registry.add_missing_typeInfo(ref_name)
# the root component also becomes invalid (in practice it is not always a component, but good enough)
registry.add_invalid_component(nesting[0])
registry.add_invalid_component(nesting_long_names[0])
return __annotations__

View File

@ -3,6 +3,7 @@ from .conversions_from_prop_group import property_group_value_to_custom_property
from .process_component import process_component
from .utils import update_calback_helper
import json
## 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
@ -14,12 +15,17 @@ def update_component(self, context, definition, component_name):
print("")
print("update in component", component_name, self, "current_object", current_object.name)
components_in_object = current_object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == component_name, components_in_object), None)
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None)
print("component_meta", component_meta)
if component_meta != None:
property_group_name = registry.get_propertyGroupName_from_shortName(component_name)
self = getattr(component_meta, property_group_name)
property_group_name = registry.get_propertyGroupName_from_longName(component_name)
property_group = getattr(component_meta, property_group_name)
# we use our helper to set the values
context.object[component_name] = property_group_value_to_custom_property_value(self, definition, registry, None)
object = context.object
previous = json.loads(object['bevy_components'])
previous[component_name] = property_group_value_to_custom_property_value(property_group, definition, registry, None)
object['bevy_components'] = json.dumps(previous)
def generate_propertyGroups_for_components():
@ -31,9 +37,8 @@ def generate_propertyGroups_for_components():
for component_name in type_infos:
definition = type_infos[component_name]
short_name = definition["short_name"]
is_component = definition['isComponent'] if "isComponent" in definition else False
root_property_name = short_name if is_component else None
root_property_name = component_name if is_component else None
process_component(registry, definition, update_calback_helper(definition, update_component, root_property_name), None, [])
# if we had to add any wrapper types on the fly, process them now

View File

@ -52,7 +52,6 @@ def generate_wrapper_propertyGroup(short_name, item_long_name, definition, regis
'tupple_or_struct': "tupple",
'field_names': ['0'],
**dict(with_properties = False, with_items= True, with_enum= False, with_list= False, short_name= wrapper_name, type_name=wrapper_name),
#'root_component': root_component
}
property_group_class = type(wrapper_name, (PropertyGroup,), property_group_params)
bpy.utils.register_class(property_group_class)

View File

@ -317,6 +317,7 @@ class ComponentsRegistry(PropertyGroup):
self.type_infos[type_name] = self.custom_types_to_add[type_name]
self.custom_types_to_add.clear()
# add an invalid component to the list (long name)
def add_invalid_component(self, component_name):
self.invalid_components.append(component_name)
@ -350,7 +351,7 @@ class ComponentsRegistry(PropertyGroup):
self.short_names_to_propgroup_names[key] = propGroupName"""
# FIXME:
key = str(nesting) + longName if len(nesting) > 0 else longName
self.long_names_to_propgroup_names[longName] = propGroupName
self.long_names_to_propgroup_names[key] = propGroupName
return propGroupName
def get_propertyGroupName_from_shortName(self, shortName):

View File

@ -39,7 +39,7 @@ def test_components_should_generate_correct_custom_properties(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
added_components.append(component_type)
custom_property_values[short_name] = object[short_name]
@ -87,7 +87,7 @@ def test_components_should_generate_correct_custom_properties_with_randomized_va
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
component_values_shuffler(seed= 10, property_group=propertyGroup, definition=definition, registry=registry)
@ -136,7 +136,7 @@ def test_components_should_generate_correct_propertyGroup_values_from_custom_pro
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
added_components.append(component_type)
# randomise values
@ -195,7 +195,7 @@ def test_remove_components(setup_data):
object = bpy.context.object
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
# print("propertyGroup", propertyGroup, propertyGroup.field_names)
added_components.append(component_type)
@ -231,7 +231,7 @@ def test_copy_paste_components(setup_data):
object = context.object
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
setattr(propertyGroup, propertyGroup.field_names[0], 25.0)
@ -246,7 +246,7 @@ def test_copy_paste_components(setup_data):
# change name
new_cube.name = "TargetCube"
target_components_metadata = new_cube.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
# first check that there is no component currently
assert component_meta == None
@ -255,7 +255,7 @@ def test_copy_paste_components(setup_data):
paste_component_operator()
target_components_metadata = new_cube.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
# now after pasting to the new object, it should have component meta
assert component_meta != None

View File

@ -16,7 +16,7 @@ def test_blend(setup_data):
object = bpy.context.object
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)

View File

@ -9,7 +9,7 @@ from .setup_data import setup_data
# small helpers
def get_component_metadata(object, component_name):
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == component_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == component_name, target_components_metadata), None)
return component_meta
def get_component_propGroup(registry, component_name, component_meta):

View File

@ -19,7 +19,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]
@ -38,7 +38,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]
@ -57,7 +57,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]
@ -75,7 +75,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]
@ -95,7 +95,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]
@ -113,7 +113,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]
@ -130,7 +130,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]
@ -148,7 +148,7 @@ def test_shuffler(setup_data):
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type]