mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-22 20:00:53 +00:00
feat(bevy_components): added basic of hashmap/map support
* added handling of additional map flags * added map handling in conversion from prop group * added basic (& clunky) UI * related boilerplate * added various testing components to try this out & experiment with
This commit is contained in:
parent
ca02c1df8c
commit
98a654095b
@ -145,11 +145,11 @@ impl Plugin for GamePlugin {
|
|||||||
.add_systems(Update, play_animations)
|
.add_systems(Update, play_animations)
|
||||||
.add_systems(Update, react_to_animation_markers)
|
.add_systems(Update, react_to_animation_markers)
|
||||||
|
|
||||||
.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once
|
/*.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
exit_game.run_if(on_timer(Duration::from_secs_f32(0.5))),
|
exit_game.run_if(on_timer(Duration::from_secs_f32(0.5))),
|
||||||
) // shut down the app after this time
|
) // shut down the app after this time*/
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,43 @@ impl MaterialExtension for MyExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
use bevy::utils::HashMap;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct HashmapTestSimple {
|
||||||
|
pub named_animations: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct HashmapTestStringFloat {
|
||||||
|
pub named_animations: HashMap<String, f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct HashmapTestIntString {
|
||||||
|
pub named_animations: HashMap<u32, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct HashmapTestIntColor {
|
||||||
|
pub inner: HashMap<u32, Color>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct HashmapTestStringColor {
|
||||||
|
pub inner: HashMap<String, Color>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct HashmapTestStringColorFlat(HashMap<String, Color>);
|
||||||
|
|
||||||
pub struct ComponentsTestPlugin;
|
pub struct ComponentsTestPlugin;
|
||||||
impl Plugin for ComponentsTestPlugin {
|
impl Plugin for ComponentsTestPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
@ -185,6 +222,20 @@ impl Plugin for ComponentsTestPlugin {
|
|||||||
.register_type::<Vec<f32>>()
|
.register_type::<Vec<f32>>()
|
||||||
// .register_type::<AAAAddedCOMPONENT>()
|
// .register_type::<AAAAddedCOMPONENT>()
|
||||||
.register_type::<AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut>()
|
.register_type::<AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut>()
|
||||||
|
.register_type::<HashMap<String, String>>()
|
||||||
|
.register_type::<HashmapTestSimple>()
|
||||||
|
.register_type::<HashMap<String, f32>>()
|
||||||
|
.register_type::<HashmapTestStringFloat>()
|
||||||
|
.register_type::<HashMap<u32, String>>()
|
||||||
|
.register_type::<HashmapTestIntString>()
|
||||||
|
|
||||||
|
.register_type::<HashMap<u32, Color>>()
|
||||||
|
.register_type::<HashmapTestIntColor>()
|
||||||
|
|
||||||
|
.register_type::<HashMap<String, Color>>()
|
||||||
|
.register_type::<HashmapTestStringColor>()
|
||||||
|
.register_type::<HashmapTestStringColorFlat>()
|
||||||
|
|
||||||
.add_plugins(MaterialPlugin::<
|
.add_plugins(MaterialPlugin::<
|
||||||
ExtendedMaterial<StandardMaterial, MyExtension>,
|
ExtendedMaterial<StandardMaterial, MyExtension>,
|
||||||
>::default());
|
>::default());
|
||||||
|
@ -213,4 +213,7 @@ UI:
|
|||||||
Restructuring of storage of components
|
Restructuring of storage of components
|
||||||
- [x] marking of invalid root propgroups/components should be based on long name
|
- [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
|
- [ ] overhaul & check each prop group type's use of short names => long names
|
||||||
- [ ] lists
|
- [ ] lists
|
||||||
|
|
||||||
|
- [ ] in conversions from propgroups
|
||||||
|
component_name = definition["short_name"]
|
||||||
|
@ -24,6 +24,7 @@ from .registry.ui import (BEVY_COMPONENTS_PT_Configuration, BEVY_COMPONENTS_PT_A
|
|||||||
|
|
||||||
from .components.metadata import (ComponentMetadata, ComponentsMeta)
|
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.lists import GENERIC_LIST_OT_actions, Generic_LIST_OT_AddItem, Generic_LIST_OT_RemoveItem, Generic_LIST_OT_SelectItem
|
||||||
|
from .components.maps import GENERIC_MAP_OT_actions
|
||||||
from .components.definitions_list import (ComponentDefinitionsList, ClearComponentDefinitionsList)
|
from .components.definitions_list import (ComponentDefinitionsList, ClearComponentDefinitionsList)
|
||||||
from .components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel)
|
from .components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel)
|
||||||
|
|
||||||
@ -122,7 +123,9 @@ classes = [
|
|||||||
Generic_LIST_OT_SelectItem,
|
Generic_LIST_OT_SelectItem,
|
||||||
Generic_LIST_OT_AddItem,
|
Generic_LIST_OT_AddItem,
|
||||||
Generic_LIST_OT_RemoveItem,
|
Generic_LIST_OT_RemoveItem,
|
||||||
GENERIC_LIST_OT_actions
|
GENERIC_LIST_OT_actions,
|
||||||
|
|
||||||
|
GENERIC_MAP_OT_actions
|
||||||
]
|
]
|
||||||
|
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
|
71
tools/bevy_components/components/maps.py
Normal file
71
tools/bevy_components/components/maps.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import json
|
||||||
|
from bpy_types import Operator, UIList
|
||||||
|
from bpy.props import (StringProperty, EnumProperty, PointerProperty, FloatVectorProperty, IntProperty)
|
||||||
|
|
||||||
|
class GENERIC_MAP_OT_actions(Operator):
|
||||||
|
"""Move items up and down, add and remove"""
|
||||||
|
bl_idname = "generic_map.map_action"
|
||||||
|
bl_label = "List Actions"
|
||||||
|
bl_description = "Move items up and down, add and remove"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
action: EnumProperty(
|
||||||
|
items=(
|
||||||
|
('UP', "Up", ""),
|
||||||
|
('DOWN', "Down", ""),
|
||||||
|
('REMOVE', "Remove", ""),
|
||||||
|
('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["long_name"] == self.component_name, components_in_object), None)
|
||||||
|
|
||||||
|
propertyGroup = component_meta
|
||||||
|
for path_item in json.loads(self.property_group_path):
|
||||||
|
propertyGroup = getattr(propertyGroup, path_item)
|
||||||
|
|
||||||
|
target_list = getattr(propertyGroup, "list")
|
||||||
|
index = getattr(propertyGroup, "list_index")
|
||||||
|
|
||||||
|
values_list = getattr(propertyGroup, "values_list")
|
||||||
|
values_index = getattr(propertyGroup, "values_list_index")
|
||||||
|
|
||||||
|
|
||||||
|
if self.action == 'DOWN' and index < len(target_list) - 1:
|
||||||
|
#item_next = scn.rule_list[index + 1].name
|
||||||
|
target_list.move(index, index + 1)
|
||||||
|
propertyGroup.list_index += 1
|
||||||
|
|
||||||
|
elif self.action == 'UP' and index >= 1:
|
||||||
|
#item_prev = scn.rule_list[index - 1].name
|
||||||
|
target_list.move(index, index - 1)
|
||||||
|
propertyGroup.list_index -= 1
|
||||||
|
|
||||||
|
elif self.action == 'REMOVE':
|
||||||
|
target_list.remove(index)
|
||||||
|
propertyGroup.list_index = min(max(0, index - 1), len(target_list) - 1)
|
||||||
|
|
||||||
|
if self.action == 'ADD':
|
||||||
|
key = target_list.add()
|
||||||
|
value = values_list.add()
|
||||||
|
|
||||||
|
propertyGroup.list_index = index + 1 # we use this to force the change detection
|
||||||
|
propertyGroup.values_index = index + 1 # we use this to force the change detection
|
||||||
|
|
||||||
|
|
||||||
|
#info = '"%s" added to list' % (item.name)
|
||||||
|
#self.report({'INFO'}, info)
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
@ -8,6 +8,7 @@ from .operators import AddComponentOperator, CopyComponentOperator, Fix_Componen
|
|||||||
def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None):
|
def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None):
|
||||||
is_enum = getattr(propertyGroup, "with_enum")
|
is_enum = getattr(propertyGroup, "with_enum")
|
||||||
is_list = getattr(propertyGroup, "with_list")
|
is_list = getattr(propertyGroup, "with_list")
|
||||||
|
is_map = getattr(propertyGroup, "with_map")
|
||||||
#nesting = nesting + [current_short_name] # we need this convoluted "nested path strings " workaround so that operators working on a given
|
#nesting = nesting + [current_short_name] # we need this convoluted "nested path strings " workaround so that operators working on a given
|
||||||
# item in our components hierarchy can get the correct propertyGroup by STRINGS because of course, we cannot pass objects to operators...sigh
|
# item in our components hierarchy can get the correct propertyGroup by STRINGS because of course, we cannot pass objects to operators...sigh
|
||||||
|
|
||||||
@ -83,6 +84,43 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None):
|
|||||||
op.component_name = rootName
|
op.component_name = rootName
|
||||||
op.property_group_path = json.dumps(nesting)
|
op.property_group_path = json.dumps(nesting)
|
||||||
|
|
||||||
|
elif is_map:
|
||||||
|
keys_list = getattr(propertyGroup, "list")
|
||||||
|
values_list = getattr(propertyGroup, "values_list")
|
||||||
|
box = layout.box()
|
||||||
|
row = box.row()
|
||||||
|
row.label(text="key")
|
||||||
|
row.label(text="value")
|
||||||
|
#values_setter = getattr(propertyGroup, "values_setter")
|
||||||
|
# draw_propertyGroup(values_setter, row, nesting, rootName)
|
||||||
|
|
||||||
|
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()
|
||||||
|
#row.label(text=str(index))
|
||||||
|
draw_propertyGroup(item, row, nesting, rootName)
|
||||||
|
|
||||||
|
value = values_list[index]
|
||||||
|
draw_propertyGroup(value, row, nesting, rootName)
|
||||||
|
|
||||||
|
|
||||||
|
#various control buttons
|
||||||
|
buttons_column.separator()
|
||||||
|
row = buttons_column.row()
|
||||||
|
op = row.operator('generic_map.map_action', icon='ADD', text="")
|
||||||
|
op.action = 'ADD'
|
||||||
|
op.component_name = rootName
|
||||||
|
op.property_group_path = json.dumps(nesting)
|
||||||
|
|
||||||
|
row = buttons_column.row()
|
||||||
|
op = row.operator('generic_map.map_action', icon='REMOVE', text="")
|
||||||
|
op.action = 'REMOVE'
|
||||||
|
op.component_name = rootName
|
||||||
|
op.property_group_path = json.dumps(nesting)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for fname in field_names:
|
for fname in field_names:
|
||||||
subrow = layout.row()
|
subrow = layout.row()
|
||||||
|
@ -5,8 +5,8 @@ conversion_tables = {
|
|||||||
|
|
||||||
"char": lambda value: '"'+value+'"',
|
"char": lambda value: '"'+value+'"',
|
||||||
"str": lambda value: '"'+value+'"',
|
"str": lambda value: '"'+value+'"',
|
||||||
"alloc::string::String": lambda value: '"'+value+'"',
|
"alloc::string::String": lambda value: '"'+str(value)+'"',
|
||||||
"alloc::borrow::Cow<str>": lambda value: '"'+value+'"',
|
"alloc::borrow::Cow<str>": lambda value: '"'+str(value)+'"',
|
||||||
|
|
||||||
"glam::Vec2": lambda value: "Vec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
"glam::Vec2": lambda value: "Vec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
||||||
"glam::DVec2": lambda value: "DVec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
"glam::DVec2": lambda value: "DVec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
||||||
@ -28,20 +28,22 @@ conversion_tables = {
|
|||||||
#converts the value of a property group(no matter its complexity) into a single custom property value
|
#converts the value of a property group(no matter its complexity) into a single custom property value
|
||||||
# this is more or less a glorified "to_ron()" method (not quite but close to)
|
# this is more or less a glorified "to_ron()" method (not quite but close to)
|
||||||
def property_group_value_to_custom_property_value(property_group, definition, registry, parent=None, value=None):
|
def property_group_value_to_custom_property_value(property_group, definition, registry, parent=None, value=None):
|
||||||
component_name = definition["short_name"]
|
component_name = definition["short_name"] # FIXME: we should operate based on long names
|
||||||
type_info = definition["typeInfo"] if "typeInfo" in definition else None
|
type_info = definition["typeInfo"] if "typeInfo" in definition else None
|
||||||
type_def = definition["type"] if "type" in definition else None
|
type_def = definition["type"] if "type" in definition else None
|
||||||
type_name = definition["title"]
|
type_name = definition["title"]
|
||||||
is_value_type = type_name in conversion_tables
|
is_value_type = type_name in conversion_tables
|
||||||
#print("computing custom property", component_name, type_info, type_def, 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:
|
if is_value_type:
|
||||||
value = conversion_tables[type_name](value)
|
value = conversion_tables[type_name](value)
|
||||||
elif type_info == "Struct":
|
elif type_info == "Struct":
|
||||||
|
print("generating string for struct")
|
||||||
values = {}
|
values = {}
|
||||||
if len(property_group.field_names) ==0:
|
if len(property_group.field_names) ==0:
|
||||||
value = '()'
|
value = '()'
|
||||||
else:
|
else:
|
||||||
|
print("toto", type_def, definition, property_group)
|
||||||
for index, field_name in enumerate(property_group.field_names):
|
for index, field_name in enumerate(property_group.field_names):
|
||||||
item_type_name = definition["properties"][field_name]["type"]["$ref"].replace("#/$defs/", "")
|
item_type_name = definition["properties"][field_name]["type"]["$ref"].replace("#/$defs/", "")
|
||||||
item_definition = registry.type_infos[item_type_name] if item_type_name in registry.type_infos else None
|
item_definition = registry.type_infos[item_type_name] if item_type_name in registry.type_infos else None
|
||||||
@ -74,8 +76,10 @@ def property_group_value_to_custom_property_value(property_group, definition, re
|
|||||||
elif type_info == "TupleStruct":
|
elif type_info == "TupleStruct":
|
||||||
values = {}
|
values = {}
|
||||||
for index, field_name in enumerate(property_group.field_names):
|
for index, field_name in enumerate(property_group.field_names):
|
||||||
|
#print("toto", index, definition["prefixItems"][index]["type"]["$ref"])
|
||||||
item_type_name = definition["prefixItems"][index]["type"]["$ref"].replace("#/$defs/", "")
|
item_type_name = definition["prefixItems"][index]["type"]["$ref"].replace("#/$defs/", "")
|
||||||
item_definition = registry.type_infos[item_type_name] if item_type_name in registry.type_infos else None
|
item_definition = registry.type_infos[item_type_name] if item_type_name in registry.type_infos else None
|
||||||
|
# print("here", item_type_name, item_definition)
|
||||||
|
|
||||||
value = getattr(property_group, field_name)
|
value = getattr(property_group, field_name)
|
||||||
is_property_group = isinstance(value, PropertyGroup)
|
is_property_group = isinstance(value, PropertyGroup)
|
||||||
@ -88,6 +92,7 @@ def property_group_value_to_custom_property_value(property_group, definition, re
|
|||||||
|
|
||||||
value = tuple(e for e in list(values.values()))
|
value = tuple(e for e in list(values.values()))
|
||||||
elif type_info == "Enum":
|
elif type_info == "Enum":
|
||||||
|
# TODO: perhaps use a mapping of (long) component name to a short ID , like we do in get_propertyGroupName_from_longName
|
||||||
selected = getattr(property_group, component_name)
|
selected = getattr(property_group, component_name)
|
||||||
|
|
||||||
if type_def == "object":
|
if type_def == "object":
|
||||||
@ -134,6 +139,38 @@ def property_group_value_to_custom_property_value(property_group, definition, re
|
|||||||
else:
|
else:
|
||||||
item_value = '""'
|
item_value = '""'
|
||||||
value.append(item_value)
|
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 = {}
|
||||||
|
for index, key in enumerate(keys_list):
|
||||||
|
# first get the keys
|
||||||
|
key_type_name = getattr(key, "type_name")
|
||||||
|
definition = registry.type_infos[key_type_name] if key_type_name in registry.type_infos else None
|
||||||
|
if definition != None:
|
||||||
|
key_value = property_group_value_to_custom_property_value(key, definition, registry, component_name, None)
|
||||||
|
if key_type_name.startswith("wrapper_"): #if we have a "fake" tupple for aka for value types, we need to remove one nested level
|
||||||
|
key_value = key_value[0]
|
||||||
|
else:
|
||||||
|
key_value = '""'
|
||||||
|
# and then the values
|
||||||
|
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
|
||||||
|
val_value = val_value[0]
|
||||||
|
else:
|
||||||
|
val_value = '""'
|
||||||
|
|
||||||
|
|
||||||
|
value[key_value] = val_value
|
||||||
|
print("MAP VALUES", value)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
value = conversion_tables[type_name](value) if is_value_type else value
|
value = conversion_tables[type_name](value) if is_value_type else value
|
||||||
value = '""' if isinstance(value, PropertyGroup) else value
|
value = '""' if isinstance(value, PropertyGroup) else value
|
||||||
@ -145,7 +182,7 @@ def property_group_value_to_custom_property_value(property_group, definition, re
|
|||||||
if parent == None:
|
if parent == None:
|
||||||
value = str(value).replace("'", "")
|
value = str(value).replace("'", "")
|
||||||
value = value.replace(",)",")")
|
value = value.replace(",)",")")
|
||||||
value = value.replace("{", "(").replace("}", ")")
|
value = value.replace("{", "(").replace("}", ")") # FIXME: deal with hashmaps
|
||||||
value = value.replace("True", "true").replace("False", "false")
|
value = value.replace("True", "true").replace("False", "false")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ from . import process_structs
|
|||||||
from . import process_tupples
|
from . import process_tupples
|
||||||
from . import process_enum
|
from . import process_enum
|
||||||
from . import process_list
|
from . import process_list
|
||||||
|
from . import process_map
|
||||||
|
|
||||||
def process_component(registry, definition, update, extras=None, nesting = [], nesting_long_names = []):
|
def process_component(registry, definition, update, extras=None, nesting = [], nesting_long_names = []):
|
||||||
component_name = definition['title']
|
component_name = definition['title']
|
||||||
@ -18,6 +19,7 @@ def process_component(registry, definition, update, extras=None, nesting = [], n
|
|||||||
has_prefixItems = len(prefixItems) > 0
|
has_prefixItems = len(prefixItems) > 0
|
||||||
is_enum = type_info == "Enum"
|
is_enum = type_info == "Enum"
|
||||||
is_list = type_info == "List"
|
is_list = type_info == "List"
|
||||||
|
is_map = type_info == "Map"
|
||||||
|
|
||||||
# print("processing", short_name, component_name, type_def, type_info)
|
# print("processing", short_name, component_name, type_def, type_info)
|
||||||
|
|
||||||
@ -28,6 +30,7 @@ def process_component(registry, definition, update, extras=None, nesting = [], n
|
|||||||
with_items = False
|
with_items = False
|
||||||
with_enum = False
|
with_enum = False
|
||||||
with_list = False
|
with_list = False
|
||||||
|
with_map = False
|
||||||
|
|
||||||
|
|
||||||
if has_properties:
|
if has_properties:
|
||||||
@ -47,6 +50,10 @@ def process_component(registry, definition, update, extras=None, nesting = [], n
|
|||||||
if is_list:
|
if is_list:
|
||||||
__annotations__ = __annotations__ | process_list.process_list(registry, definition, update, nesting, nesting_long_names)
|
__annotations__ = __annotations__ | process_list.process_list(registry, definition, update, nesting, nesting_long_names)
|
||||||
with_list= True
|
with_list= True
|
||||||
|
|
||||||
|
if is_map:
|
||||||
|
__annotations__ = __annotations__ | process_map.process_map(registry, definition, update, nesting, nesting_long_names)
|
||||||
|
with_map = True
|
||||||
|
|
||||||
field_names = []
|
field_names = []
|
||||||
for a in __annotations__:
|
for a in __annotations__:
|
||||||
@ -64,7 +71,7 @@ def process_component(registry, definition, update, extras=None, nesting = [], n
|
|||||||
'__annotations__': __annotations__,
|
'__annotations__': __annotations__,
|
||||||
'tupple_or_struct': tupple_or_struct,
|
'tupple_or_struct': tupple_or_struct,
|
||||||
'field_names': field_names,
|
'field_names': field_names,
|
||||||
**dict(with_properties = with_properties, with_items= with_items, with_enum= with_enum, with_list= with_list, short_name= short_name),
|
**dict(with_properties = with_properties, with_items= with_items, with_enum= with_enum, with_list= with_list, with_map = with_map, short_name= short_name),
|
||||||
'root_component': root_component
|
'root_component': root_component
|
||||||
}
|
}
|
||||||
#FIXME: YIKES, but have not found another way:
|
#FIXME: YIKES, but have not found another way:
|
||||||
@ -74,7 +81,7 @@ def process_component(registry, definition, update, extras=None, nesting = [], n
|
|||||||
-BasicTest => the registration & update callback of this one overwrites the first "basicTest"
|
-BasicTest => the registration & update callback of this one overwrites the first "basicTest"
|
||||||
have not found a cleaner workaround so far
|
have not found a cleaner workaround so far
|
||||||
"""
|
"""
|
||||||
property_group_name = registry.generate_propGroup_name(nesting, short_name, component_name)
|
property_group_name = registry.generate_propGroup_name(nesting, component_name)
|
||||||
(property_group_pointer, property_group_class) = property_group_from_infos(property_group_name, property_group_params)
|
(property_group_pointer, property_group_class) = property_group_from_infos(property_group_name, property_group_params)
|
||||||
# add our component propertyGroup to the registry
|
# add our component propertyGroup to the registry
|
||||||
registry.register_component_propertyGroup(property_group_name, property_group_pointer)
|
registry.register_component_propertyGroup(property_group_name, property_group_pointer)
|
||||||
|
@ -9,6 +9,9 @@ def process_list(registry, definition, update, nesting=[], nesting_long_names=[]
|
|||||||
short_name = definition["short_name"]
|
short_name = definition["short_name"]
|
||||||
long_name = definition["title"]
|
long_name = definition["title"]
|
||||||
ref_name = definition["items"]["type"]["$ref"].replace("#/$defs/", "")
|
ref_name = definition["items"]["type"]["$ref"].replace("#/$defs/", "")
|
||||||
|
|
||||||
|
nesting = nesting+[short_name]
|
||||||
|
nesting_long_names = nesting_long_names + [long_name]
|
||||||
|
|
||||||
item_definition = type_infos[ref_name]
|
item_definition = type_infos[ref_name]
|
||||||
item_long_name = item_definition["title"]
|
item_long_name = item_definition["title"]
|
||||||
@ -18,14 +21,11 @@ def process_list(registry, definition, update, nesting=[], nesting_long_names=[]
|
|||||||
property_group_class = None
|
property_group_class = None
|
||||||
#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 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_item_value_type:
|
if is_item_value_type:
|
||||||
property_group_class = generate_wrapper_propertyGroup(short_name, item_long_name, definition["items"]["type"]["$ref"],registry, update)
|
property_group_class = generate_wrapper_propertyGroup(long_name, item_long_name, definition["items"]["type"]["$ref"], registry, update)
|
||||||
else:
|
else:
|
||||||
(_, list_content_group_class) = process_component.process_component(registry, item_definition, update, {"nested": True, "type_name": item_long_name}, nesting)
|
(_, list_content_group_class) = process_component.process_component(registry, item_definition, update, {"nested": True, "type_name": item_long_name}, nesting)
|
||||||
property_group_class = list_content_group_class
|
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_collection = CollectionProperty(type=property_group_class)
|
||||||
|
|
||||||
item_short_name = item_short_name if not is_item_value_type else "wrapper_" + item_short_name
|
item_short_name = item_short_name if not is_item_value_type else "wrapper_" + item_short_name
|
||||||
|
71
tools/bevy_components/propGroups/process_map.py
Normal file
71
tools/bevy_components/propGroups/process_map.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
from bpy.props import (StringProperty, IntProperty, CollectionProperty)
|
||||||
|
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
|
||||||
|
|
||||||
|
short_name = definition["short_name"]
|
||||||
|
long_name = definition["title"]
|
||||||
|
|
||||||
|
nesting = nesting + [short_name]
|
||||||
|
nesting_long_names = nesting_long_names + [long_name]
|
||||||
|
|
||||||
|
#ref_name = definition["items"]["type"]["$ref"].replace("#/$defs/", "")
|
||||||
|
value_ref_name = definition["additionalProperties"]["type"]["$ref"].replace("#/$defs/", "")
|
||||||
|
key_ref_name = long_name.split(',')[0].split('<')[1]# FIXME: hack !!!
|
||||||
|
key_type = ''
|
||||||
|
value_type = ''
|
||||||
|
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(long_name, 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)
|
||||||
|
values_property_group_class = list_content_group_class
|
||||||
|
|
||||||
|
values_collection = CollectionProperty(type=values_property_group_class)
|
||||||
|
|
||||||
|
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}"
|
||||||
|
|
||||||
|
#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_key_value_type:
|
||||||
|
keys_property_group_class = generate_wrapper_propertyGroup(long_name+'_values', original_type_name, definition_link, registry, update)
|
||||||
|
else:
|
||||||
|
(_, list_content_group_class) = process_component.process_component(registry, key_definition, update, {"nested": True, "type_name": original_type_name}, nesting)
|
||||||
|
keys_property_group_class = list_content_group_class
|
||||||
|
|
||||||
|
keys_collection = CollectionProperty(type=keys_property_group_class)
|
||||||
|
|
||||||
|
__annotations__ = {
|
||||||
|
"list": keys_collection,
|
||||||
|
"list_index": IntProperty(name = "Index for keys", default = 0, update=update),
|
||||||
|
"values_list": values_collection,
|
||||||
|
"values_list_index": IntProperty(name = "Index for values", default = 0, update=update),
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
"values_setter": values_setter,
|
||||||
|
"values_list": values_collection,
|
||||||
|
"values_list_index": IntProperty(name = "Index for values", default = 0, update=update),
|
||||||
|
'''
|
||||||
|
|
||||||
|
return __annotations__
|
@ -13,9 +13,12 @@ def process_structs(registry, definition, properties, update, nesting, nesting_l
|
|||||||
nesting = nesting + [short_name]
|
nesting = nesting + [short_name]
|
||||||
nesting_long_names = nesting_long_names + [long_name]
|
nesting_long_names = nesting_long_names + [long_name]
|
||||||
|
|
||||||
|
if short_name == "HashmapTestSimple":
|
||||||
|
print("Struct", short_name)
|
||||||
for property_name in properties.keys():
|
for property_name in properties.keys():
|
||||||
ref_name = properties[property_name]["type"]["$ref"].replace("#/$defs/", "")
|
ref_name = properties[property_name]["type"]["$ref"].replace("#/$defs/", "")
|
||||||
|
if short_name == "HashmapTestSimple":
|
||||||
|
print("ref name", ref_name)
|
||||||
if ref_name in type_infos:
|
if ref_name in type_infos:
|
||||||
original = type_infos[ref_name]
|
original = type_infos[ref_name]
|
||||||
original_type_name = original["title"]
|
original_type_name = original["title"]
|
||||||
@ -23,6 +26,9 @@ def process_structs(registry, definition, properties, update, nesting, nesting_l
|
|||||||
value = value_types_defaults[original_type_name] if is_value_type else None
|
value = value_types_defaults[original_type_name] if is_value_type else None
|
||||||
default_values[property_name] = value
|
default_values[property_name] = value
|
||||||
|
|
||||||
|
if short_name == "HashmapTestSimple":
|
||||||
|
print("original",original, original_type_name, is_value_type, value)
|
||||||
|
|
||||||
if is_value_type:
|
if is_value_type:
|
||||||
if original_type_name in blender_property_mapping:
|
if original_type_name in blender_property_mapping:
|
||||||
blender_property_def = blender_property_mapping[original_type_name]
|
blender_property_def = blender_property_mapping[original_type_name]
|
||||||
|
@ -8,13 +8,16 @@ from bpy_types import PropertyGroup
|
|||||||
|
|
||||||
# this helper creates a "fake"/wrapper property group that is NOT a real type in the registry
|
# this helper creates a "fake"/wrapper property group that is NOT a real type in the registry
|
||||||
# usefull for things like value types in list items etc
|
# usefull for things like value types in list items etc
|
||||||
def generate_wrapper_propertyGroup(short_name, item_long_name, definition, registry, update):
|
def generate_wrapper_propertyGroup(wrapped_type_long_name_name, item_long_name, definition_link, registry, update):
|
||||||
value_types_defaults = registry.value_types_defaults
|
value_types_defaults = registry.value_types_defaults
|
||||||
blender_property_mapping = registry.blender_property_mapping
|
blender_property_mapping = registry.blender_property_mapping
|
||||||
is_item_value_type = item_long_name in value_types_defaults
|
is_item_value_type = item_long_name in value_types_defaults
|
||||||
|
|
||||||
wrapper_name = "wrapper_" + short_name
|
wrapper_name = "wrapper_" + wrapped_type_long_name_name
|
||||||
|
print("WRAPPER NAME", wrapper_name)
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: this is not a correct generic value for hashmaps !!?
|
||||||
wrapper_definition = {
|
wrapper_definition = {
|
||||||
"isComponent": False,
|
"isComponent": False,
|
||||||
"isResource": False,
|
"isResource": False,
|
||||||
@ -22,17 +25,21 @@ def generate_wrapper_propertyGroup(short_name, item_long_name, definition, regis
|
|||||||
"prefixItems": [
|
"prefixItems": [
|
||||||
{
|
{
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": definition
|
"$ref": definition_link
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"short_name": wrapper_name,
|
"short_name": wrapper_name, # FIXME !!!
|
||||||
"title": wrapper_name,
|
"title": wrapper_name,
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"typeInfo": "TupleStruct"
|
"typeInfo": "TupleStruct"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# we generate a very small 'hash' for the component name
|
||||||
|
property_group_name = registry.generate_propGroup_name(nesting=[], longName=wrapper_name)
|
||||||
registry.add_custom_type(wrapper_name, wrapper_definition)
|
registry.add_custom_type(wrapper_name, wrapper_definition)
|
||||||
|
|
||||||
|
|
||||||
blender_property = StringProperty(default="", update=update)
|
blender_property = StringProperty(default="", update=update)
|
||||||
if item_long_name in blender_property_mapping:
|
if item_long_name in blender_property_mapping:
|
||||||
value = value_types_defaults[item_long_name] if is_item_value_type else None
|
value = value_types_defaults[item_long_name] if is_item_value_type else None
|
||||||
@ -51,9 +58,9 @@ def generate_wrapper_propertyGroup(short_name, item_long_name, definition, regis
|
|||||||
'__annotations__': wrapper_annotations,
|
'__annotations__': wrapper_annotations,
|
||||||
'tupple_or_struct': "tupple",
|
'tupple_or_struct': "tupple",
|
||||||
'field_names': ['0'],
|
'field_names': ['0'],
|
||||||
**dict(with_properties = False, with_items= True, with_enum= False, with_list= False, short_name= wrapper_name, type_name=wrapper_name),
|
**dict(with_properties = False, with_items= True, with_enum= False, with_list= False, with_map =False, short_name=wrapper_name, type_name=wrapper_name),
|
||||||
}
|
}
|
||||||
property_group_class = type(wrapper_name, (PropertyGroup,), property_group_params)
|
property_group_class = type(property_group_name, (PropertyGroup,), property_group_params)
|
||||||
bpy.utils.register_class(property_group_class)
|
bpy.utils.register_class(property_group_class)
|
||||||
|
|
||||||
return property_group_class
|
return property_group_class
|
@ -336,7 +336,7 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
long_names_to_propgroup_names = {}
|
long_names_to_propgroup_names = {}
|
||||||
|
|
||||||
# generate propGroup name from nesting level & shortName: each shortName + nesting is unique
|
# generate propGroup name from nesting level & shortName: each shortName + nesting is unique
|
||||||
def generate_propGroup_name(self, nesting, shortName, longName):
|
def generate_propGroup_name(self, nesting, longName):
|
||||||
#print("gen propGroup name for", shortName, nesting)
|
#print("gen propGroup name for", shortName, nesting)
|
||||||
#if shortName in self.short_names_to_propgroup_names and len(nesting) == 0:
|
#if shortName in self.short_names_to_propgroup_names and len(nesting) == 0:
|
||||||
# return self.get_propertyGroupName_from_shortName(shortName)
|
# return self.get_propertyGroupName_from_shortName(shortName)
|
||||||
@ -359,7 +359,9 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
|
|
||||||
def get_propertyGroupName_from_longName(self, longName):
|
def get_propertyGroupName_from_longName(self, longName):
|
||||||
return self.long_names_to_propgroup_names.get(longName, None)
|
return self.long_names_to_propgroup_names.get(longName, None)
|
||||||
|
|
||||||
|
def long_name_to_key():
|
||||||
|
pass
|
||||||
|
|
||||||
###########
|
###########
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user