From ac02e8b3644706d570894c20a1236e6d07a3789b Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Sat, 4 May 2024 01:42:45 +0200 Subject: [PATCH] feat(bevy_components): more tweaks, error handling , improvements etc --- tools/bevy_components/TODO.md | 4 + .../components/definitions_list.py | 11 --- tools/bevy_components/components/metadata.py | 2 +- tools/bevy_components/components/ui.py | 76 ++++++++-------- .../propGroups/conversions_from_prop_group.py | 10 +-- .../bevy_components/propGroups/process_map.py | 90 ++++++++++--------- tools/bevy_components/registry/ui.py | 11 +-- 7 files changed, 98 insertions(+), 106 deletions(-) diff --git a/tools/bevy_components/TODO.md b/tools/bevy_components/TODO.md index d746e06..1032903 100644 --- a/tools/bevy_components/TODO.md +++ b/tools/bevy_components/TODO.md @@ -217,3 +217,7 @@ Restructuring of storage of components - [ ] in conversions from propgroups component_name = definition["short_name"] + +- Hashmap Support + - [ ] fix parsing of keys's type either on Bevy side (prefered, unlikely to be possible) or on the Blender side + - [ ] handle missing types in registry for keys & values \ No newline at end of file diff --git a/tools/bevy_components/components/definitions_list.py b/tools/bevy_components/components/definitions_list.py index ca953e6..56cfc83 100644 --- a/tools/bevy_components/components/definitions_list.py +++ b/tools/bevy_components/components/definitions_list.py @@ -11,17 +11,6 @@ class ComponentDefinitionsList(bpy.types.PropertyGroup): #print("add components to ui_list") items = [] type_infos = context.window_manager.components_registry.type_infos - short_names = context.window_manager.components_registry.short_names_to_long_names - """for short_name in sorted(short_names.keys()): - long_name = short_names[short_name] - definition = type_infos[long_name] - is_component = definition['isComponent'] if "isComponent" in definition else False - - if self.filter in short_name and is_component: - if not 'Handle' in short_name and not "Cow" in short_name and not "AssetId" in short_name and short_name not in self.exclude: # FIXME: hard coded, seems wrong - items.append((long_name, short_name, long_name))""" - - for long_name in type_infos.keys(): definition = type_infos[long_name] short_name = definition["short_name"] diff --git a/tools/bevy_components/components/metadata.py b/tools/bevy_components/components/metadata.py index bbb2ae0..14d8ba4 100644 --- a/tools/bevy_components/components/metadata.py +++ b/tools/bevy_components/components/metadata.py @@ -225,7 +225,7 @@ def upsert_component_in_object(object, long_name, registry): # now deal with property groups details if propertyGroup != None: - if short_name in registry.invalid_components: + if long_name in registry.invalid_components: component_meta.enabled = False component_meta.invalid = True component_meta.invalid_details = "component contains fields that are not in the schema, disabling" diff --git a/tools/bevy_components/components/ui.py b/tools/bevy_components/components/ui.py index 8e943d6..1b2d6b7 100644 --- a/tools/bevy_components/components/ui.py +++ b/tools/bevy_components/components/ui.py @@ -86,51 +86,45 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None): elif is_map: root = layout.row().column() - """box = root.box() - box.label(text="test") - root.separator() + if hasattr(propertyGroup, "list"): # TODO: improve handling of non drawable UI + keys_list = getattr(propertyGroup, "list") + values_list = getattr(propertyGroup, "values_list") + box = root.box() + row = box.row() + row.label(text="Add entry:") + keys_setter = getattr(propertyGroup, "keys_setter") + draw_propertyGroup(keys_setter, row, nesting, rootName) - box = root.box() - box.label(text="test2")""" + values_setter = getattr(propertyGroup, "values_setter") + draw_propertyGroup(values_setter, row, nesting, rootName) - keys_list = getattr(propertyGroup, "list") - values_list = getattr(propertyGroup, "values_list") - box = root.box() - row = box.row() - row.label(text="Add entry:") - keys_setter = getattr(propertyGroup, "keys_setter") - draw_propertyGroup(keys_setter, row, nesting, rootName) - - values_setter = getattr(propertyGroup, "values_setter") - draw_propertyGroup(values_setter, row, nesting, rootName) - - op = row.operator('generic_map.map_action', icon='ADD', text="") - op.action = 'ADD' - op.component_name = rootName - op.property_group_path = json.dumps(nesting) - - box = root.box() - split = box.split(factor=0.9) - list_column, buttons_column = (split.column(),split.column()) - list_column = list_column.box() - - for index, item in enumerate(keys_list): - row = list_column.row() - draw_propertyGroup(item, row, nesting, rootName) - - value = values_list[index] - draw_propertyGroup(value, row, nesting, rootName) - - op = row.operator('generic_map.map_action', icon='REMOVE', text="") - op.action = 'REMOVE' + op = row.operator('generic_map.map_action', icon='ADD', text="") + op.action = 'ADD' op.component_name = rootName op.property_group_path = json.dumps(nesting) - op.target_index = index + + box = root.box() + split = box.split(factor=0.9) + list_column, buttons_column = (split.column(),split.column()) + list_column = list_column.box() + + for index, item in enumerate(keys_list): + row = list_column.row() + draw_propertyGroup(item, row, nesting, rootName) + + value = values_list[index] + draw_propertyGroup(value, row, nesting, rootName) + + op = row.operator('generic_map.map_action', icon='REMOVE', text="") + op.action = 'REMOVE' + op.component_name = rootName + op.property_group_path = json.dumps(nesting) + op.target_index = index - #various control buttons - buttons_column.separator() - row = buttons_column.row() + #various control buttons + buttons_column.separator() + row = buttons_column.row() else: @@ -232,8 +226,8 @@ 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) diff --git a/tools/bevy_components/propGroups/conversions_from_prop_group.py b/tools/bevy_components/propGroups/conversions_from_prop_group.py index 74e0553..cc960be 100644 --- a/tools/bevy_components/propGroups/conversions_from_prop_group.py +++ b/tools/bevy_components/propGroups/conversions_from_prop_group.py @@ -33,7 +33,7 @@ def property_group_value_to_custom_property_value(property_group, definition, re type_def = definition["type"] if "type" in definition else None type_name = definition["title"] is_value_type = type_name in conversion_tables - print("computing custom property: component name:", component_name, "type_info", type_info, "type_def", type_def, "type_name", type_name) + # print("computing custom property: component name:", component_name, "type_info", type_info, "type_def", type_def, "type_name", type_name) if is_value_type: value = conversion_tables[type_name](value) @@ -139,7 +139,6 @@ def property_group_value_to_custom_property_value(property_group, definition, re value.append(item_value) elif type_info == "Map": - print("MAAAAAP", property_group) keys_list = getattr(property_group, "list", {}) values_list = getattr(property_group, "values_list") value = {} @@ -157,7 +156,6 @@ def property_group_value_to_custom_property_value(property_group, definition, re val = values_list[index] value_type_name = getattr(val, "type_name") definition = registry.type_infos[value_type_name] if value_type_name in registry.type_infos else None - print("value definition", definition) if definition != None: val_value = property_group_value_to_custom_property_value(val, definition, registry, component_name, None) if value_type_name.startswith("wrapper_"): #if we have a "fake" tupple for aka for value types, we need to remove one nested level @@ -165,10 +163,8 @@ def property_group_value_to_custom_property_value(property_group, definition, re else: val_value = '""' - value[key_value] = val_value - print("MAP VALUES", value) - + value = str(value).replace('{','@').replace('}','²') # FIXME: eeek !! else: value = conversion_tables[type_name](value) if is_value_type else value value = '""' if isinstance(value, PropertyGroup) else value @@ -178,9 +174,11 @@ def property_group_value_to_custom_property_value(property_group, definition, re value = value.replace("'", "") if parent == None: + print("transforming value", value, definition) value = str(value).replace("'", "") value = value.replace(",)",")") value = value.replace("{", "(").replace("}", ")") # FIXME: deal with hashmaps value = value.replace("True", "true").replace("False", "false") + value = value.replace('@', '{').replace('²', '}') return value diff --git a/tools/bevy_components/propGroups/process_map.py b/tools/bevy_components/propGroups/process_map.py index 16c2471..fb8574b 100644 --- a/tools/bevy_components/propGroups/process_map.py +++ b/tools/bevy_components/propGroups/process_map.py @@ -1,10 +1,8 @@ -from bpy.props import (StringProperty, IntProperty, CollectionProperty) -from bpy.props import (PointerProperty) +from bpy.props import (StringProperty, IntProperty, CollectionProperty, PointerProperty) from .utils import generate_wrapper_propertyGroup from . import process_component def process_map(registry, definition, update, nesting=[], nesting_long_names=[]): - print("IS HASHMAP") value_types_defaults = registry.value_types_defaults type_infos = registry.type_infos @@ -17,34 +15,11 @@ def process_map(registry, definition, update, nesting=[], nesting_long_names=[]) value_ref_name = definition["additionalProperties"]["type"]["$ref"].replace("#/$defs/", "") key_ref_name = long_name.split(',')[0].split('<')[1]# FIXME: hack !!! - print("infos", short_name, "long name", long_name) - print("value ref", value_ref_name, "key ref", key_ref_name) #print("definition", definition) - - if value_ref_name in type_infos: - value_definition = type_infos[value_ref_name] - original_type_name = value_definition["title"] - original_short_name = value_definition["short_name"] - is_value_value_type = original_type_name in value_types_defaults - definition_link = definition["additionalProperties"]["type"]["$ref"]#f"#/$defs/{value_ref_name}" - - print("hashmap VALUE type", original_type_name) - - #if the content of the list is a unit type, we need to generate a fake wrapper, otherwise we cannot use layout.prop(group, "propertyName") as there is no propertyName ! - if is_value_value_type: - values_property_group_class = generate_wrapper_propertyGroup(f"{long_name}_keys", original_type_name, definition_link, registry, update) - else: - (_, list_content_group_class) = process_component.process_component(registry, value_definition, update, {"nested": True, "type_name": original_type_name}, nesting, nesting_long_names) - values_property_group_class = list_content_group_class - - values_collection = CollectionProperty(type=values_property_group_class) - values_property_group_pointer = PointerProperty(type=values_property_group_class) - - + __annotations__ = {} if key_ref_name in type_infos: key_definition = type_infos[key_ref_name] original_type_name = key_definition["title"] - original_short_name = key_definition["short_name"] is_key_value_type = original_type_name in value_types_defaults definition_link = f"#/$defs/{key_ref_name}" @@ -57,23 +32,54 @@ def process_map(registry, definition, update, nesting=[], nesting_long_names=[]) keys_collection = CollectionProperty(type=keys_property_group_class) keys_property_group_pointer = PointerProperty(type=keys_property_group_class) + else: + __annotations__["list"] = StringProperty(default="N/A") + registry.add_missing_typeInfo(key_ref_name) + # the root component also becomes invalid (in practice it is not always a component, but good enough) + registry.add_invalid_component(nesting_long_names[0]) + + if value_ref_name in type_infos: + value_definition = type_infos[value_ref_name] + original_type_name = value_definition["title"] + is_value_value_type = original_type_name in value_types_defaults + definition_link = definition["additionalProperties"]["type"]["$ref"]#f"#/$defs/{value_ref_name}" + + #if the content of the list is a unit type, we need to generate a fake wrapper, otherwise we cannot use layout.prop(group, "propertyName") as there is no propertyName ! + if is_value_value_type: + values_property_group_class = generate_wrapper_propertyGroup(f"{long_name}_keys", original_type_name, definition_link, registry, update) + else: + (_, list_content_group_class) = process_component.process_component(registry, value_definition, update, {"nested": True, "type_name": original_type_name}, nesting, nesting_long_names) + values_property_group_class = list_content_group_class + + values_collection = CollectionProperty(type=values_property_group_class) + values_property_group_pointer = PointerProperty(type=values_property_group_class) + + else: + #__annotations__["list"] = StringProperty(default="N/A") + registry.add_missing_typeInfo(value_ref_name) + # the root component also becomes invalid (in practice it is not always a component, but good enough) + registry.add_invalid_component(nesting_long_names[0]) - __annotations__ = { - "list": keys_collection, - "list_index": IntProperty(name = "Index for keys", default = 0, update=update), - "keys_setter":keys_property_group_pointer, + if key_ref_name in type_infos and value_ref_name in type_infos: + __annotations__ = { + "list": keys_collection, + "list_index": IntProperty(name = "Index for keys", default = 0, update=update), + "keys_setter":keys_property_group_pointer, - "values_list": values_collection, - "values_list_index": IntProperty(name = "Index for values", default = 0, update=update), - "values_setter":values_property_group_pointer, - "toto": {} - - } - ''' - "values_setter": values_setter, - "values_list": values_collection, - "values_list_index": IntProperty(name = "Index for values", default = 0, update=update), - ''' + "values_list": values_collection, + "values_list_index": IntProperty(name = "Index for values", default = 0, update=update), + "values_setter":values_property_group_pointer, + } + + """__annotations__["list"] = StringProperty(default="N/A") + __annotations__["values_list"] = StringProperty(default="N/A") + __annotations__["keys_setter"] = StringProperty(default="N/A")""" + + """registry.add_missing_typeInfo(key_ref_name) + registry.add_missing_typeInfo(value_ref_name) + # the root component also becomes invalid (in practice it is not always a component, but good enough) + registry.add_invalid_component(nesting_long_names[0]) + print("setting invalid flag for", nesting_long_names[0])""" return __annotations__ diff --git a/tools/bevy_components/registry/ui.py b/tools/bevy_components/registry/ui.py index 9df1ab0..2a42504 100644 --- a/tools/bevy_components/registry/ui.py +++ b/tools/bevy_components/registry/ui.py @@ -132,17 +132,18 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel): comp_names = [] for index, component_meta in enumerate(components_metadata): short_name = component_meta.name + long_name = component_meta.long_name if component_meta.invalid: - self.draw_invalid_or_unregistered(layout, "Invalid", short_name, object) + self.draw_invalid_or_unregistered(layout, "Invalid", long_name, object) if not object.name in objects_with_invalid_components: objects_with_invalid_components.append(object.name) - if not short_name in invalid_component_names: - invalid_component_names.append(short_name) + if not long_name in invalid_component_names: + invalid_component_names.append(long_name) - comp_names.append(short_name) + comp_names.append(long_name) for custom_property in object.keys(): if custom_property != 'components_meta' and custom_property not in comp_names: @@ -150,7 +151,7 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel): if not object.name in objects_with_invalid_components: objects_with_invalid_components.append(object.name) - if not short_name in invalid_component_names: + if not long_name in invalid_component_names: invalid_component_names.append(custom_property) layout.separator() layout.separator()