diff --git a/TODO.md b/TODO.md index f2bec35..7b5ae7c 100644 --- a/TODO.md +++ b/TODO.md @@ -259,6 +259,23 @@ Blender side: - [x] make sure the "add scene" button is not available unless you have actually selected one - [x] make auto export be on by default, however bail out early by detecting if there are any level/blueprint scenes - [x] remove custom components to filter out correctly from exported blueprints list +- [ ] for built in Component types that need to be injected to be used by blueprints, + namely: + - BlueprintInfos (not 100% sure for this one) + - MaterialInfos + - the various scene Components + - BlueprintAssets (although not really needed anymore with the meta files) + + - [ ] Inject real components instead of just custom properties + - [ ] add boilerplate to generate real component values from type definitions instead of hacking pseudo ron strings + - [ ] fall back to bevy_components if that fails (missing registry) or just basic custom properties + - [ ] If that fails as well ? +- [ ] auto reload registry if absent/possible + - cannot be done from UI possibly polling with increasing timeout + - bpy.ops.blenvy.components_registry_reload() + +- [x] filter out MaterialInfos from list of "fixable components" + Bevy Side: - [x] deprecate BlueprintName & BlueprintPath & use BlueprintInfo instead diff --git a/tools/blenvy/add_ons/auto_export/levels/is_object_dynamic.py b/tools/blenvy/add_ons/auto_export/levels/is_object_dynamic.py index f87b2e7..5668600 100644 --- a/tools/blenvy/add_ons/auto_export/levels/is_object_dynamic.py +++ b/tools/blenvy/add_ons/auto_export/levels/is_object_dynamic.py @@ -3,7 +3,6 @@ import bpy from ...bevy_components.components.metadata import get_bevy_component_value_by_long_name # checks if an object is dynamic -# TODO: for efficiency, it might make sense to write this flag semi automatically at the root level of the object so we can skip the inner loop # TODO: we need to recompute these on blueprint changes too # even better, keep a list of dynamic objects per scene , updated only when needed ? def is_object_dynamic(object): @@ -15,17 +14,9 @@ def is_object_dynamic(object): # get the name of the collection this is an instance of collection_name = object.instance_collection.name original_collection = bpy.data.collections[collection_name] - - is_dynamic = get_bevy_component_value_by_long_name(original_collection, 'blenvy::save_load::Dynamic') is not None # scan original collection, look for a 'Dynamic' flag - """for object in original_collection.objects: - #print(" inner", object) - if object.type == 'EMPTY': #and object.name.endswith("components"): - for component_name in object.keys(): - #print(" compo", component_name) - if component_name == 'Dynamic': - is_dynamic = True - break""" + is_dynamic = get_bevy_component_value_by_long_name(original_collection, 'blenvy::save_load::Dynamic') is not None + #print("IS OBJECT DYNAMIC", object, is_dynamic) return is_dynamic diff --git a/tools/blenvy/add_ons/bevy_components/components/ui.py b/tools/blenvy/add_ons/bevy_components/components/ui.py index e839137..c63e34a 100644 --- a/tools/blenvy/add_ons/bevy_components/components/ui.py +++ b/tools/blenvy/add_ons/bevy_components/components/ui.py @@ -5,7 +5,7 @@ from ..utils import get_selected_item, get_selection_type from .metadata import do_item_custom_properties_have_missing_metadata, get_bevy_components -def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_type="OBJECT", item_name=""): +def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_type="OBJECT", item_name="", enabled=True): is_enum = getattr(propertyGroup, "with_enum") is_list = getattr(propertyGroup, "with_list") is_map = getattr(propertyGroup, "with_map") @@ -13,6 +13,7 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_ # if it is an enum, the first field name is always the list of enum variants, the others are the variants field_names = propertyGroup.field_names + layout.enabled = enabled #print("") #print("drawing", propertyGroup, nesting, "component_name", rootName) if is_enum: @@ -31,7 +32,7 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_ nested = getattr(nestedPropertyGroup, "nested", False) #print("nestedPropertyGroup", nestedPropertyGroup, fname, nested) if nested: - draw_propertyGroup(nestedPropertyGroup, subrow.column(), nesting + [fname], rootName, item_type, item_name ) + draw_propertyGroup(nestedPropertyGroup, subrow.column(), nesting + [fname], rootName, item_type, item_name, enabled=enabled ) # if an enum variant is not a propertyGroup break elif is_list: @@ -39,12 +40,13 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_ list_index = getattr(propertyGroup, "list_index") box = layout.box() split = box.split(factor=0.9) + box.enabled = enabled list_column, buttons_column = (split.column(),split.column()) list_column = list_column.box() for index, item in enumerate(item_list): row = list_column.row() - draw_propertyGroup(item, row, nesting, rootName, item_type) + draw_propertyGroup(item, row, nesting, rootName, item_type, enabled=enabled) icon = 'CHECKBOX_HLT' if list_index == index else 'CHECKBOX_DEHLT' op = row.operator('blenvy.component_list_actions', icon=icon, text="") op.action = 'SELECT' @@ -100,10 +102,10 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_ row = box.row() row.label(text="Add entry:") keys_setter = getattr(propertyGroup, "keys_setter") - draw_propertyGroup(keys_setter, row, nesting, rootName, item_type, item_name) + draw_propertyGroup(keys_setter, row, nesting, rootName, item_type, item_name, enabled=enabled) values_setter = getattr(propertyGroup, "values_setter") - draw_propertyGroup(values_setter, row, nesting, rootName, item_type, item_name) + draw_propertyGroup(values_setter, row, nesting, rootName, item_type, item_name, enabled=enabled) op = row.operator('blenvy.component_map_actions', icon='ADD', text="") op.action = 'ADD' @@ -119,10 +121,10 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_ for index, item in enumerate(keys_list): row = list_column.row() - draw_propertyGroup(item, row, nesting, rootName, item_type, item_name) + draw_propertyGroup(item, row, nesting, rootName, item_type, item_name, enabled=enabled) value = values_list[index] - draw_propertyGroup(value, row, nesting, rootName, item_type, item_name) + draw_propertyGroup(value, row, nesting, rootName, item_type, item_name, enabled=enabled) op = row.operator('blenvy.component_map_actions', icon='REMOVE', text="") op.action = 'REMOVE' @@ -151,7 +153,7 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None, item_ layout.label(text=display_name) # this is the name of the field/sub field layout.separator() subrow = layout.row() - draw_propertyGroup(nestedPropertyGroup, subrow, nesting + [fname], rootName, item_type, item_name ) + draw_propertyGroup(nestedPropertyGroup, subrow, nesting + [fname], rootName, item_type, item_name, enabled ) else: subrow = layout.row() subrow.prop(propertyGroup, fname, text=display_name) @@ -233,6 +235,9 @@ def draw_component_ui(layout, object_or_collection, registry, selected_component item_name = object_or_collection.name #print("components_names", dict(components_bla).keys()) + #FIXME: move out, highly inneficient + internal_components = ['BlueprintInfos', 'blenvy::blueprints::materials::MaterialInfos'] + for component_name in sorted(get_bevy_components(object_or_collection)) : # sorted by component name, practical if component_name == "components_meta": continue @@ -244,7 +249,9 @@ def draw_component_ui(layout, object_or_collection, registry, selected_component component_invalid = getattr(component_meta, "invalid") invalid_details = getattr(component_meta, "invalid_details") component_visible = getattr(component_meta, "visible") + component_internal = component_name in internal_components # internal components are not editable ? single_field = False + label = f"{component_name}{' (internal)' if component_internal else ''}" # our whole row box = layout.box() @@ -252,7 +259,8 @@ def draw_component_ui(layout, object_or_collection, registry, selected_component # "header" row.alert = component_invalid row.prop(component_meta, "enabled", text="") - row.label(text=component_name) + row.label(text=label) + #row.enabled = not component_internal # we fetch the matching ui property group root_propertyGroup_name = registry.get_propertyGroupName_from_longName(component_name) @@ -272,7 +280,7 @@ def draw_component_ui(layout, object_or_collection, registry, selected_component error_message = invalid_details if component_invalid else "Missing component UI data, please reload registry !" prop_group_location.label(text=error_message) else: - draw_propertyGroup(propertyGroup, prop_group_location, [root_propertyGroup_name], component_name, item_type, item_name) + draw_propertyGroup(propertyGroup, prop_group_location, [root_propertyGroup_name], component_name, item_type, item_name, enabled=not component_internal) else : row.label(text="details hidden, click on toggle to display") else: @@ -293,17 +301,18 @@ def draw_component_ui(layout, object_or_collection, registry, selected_component op.component_name = component_name row.separator() - op = row.operator("blenvy.component_remove", text="", icon="X") - op.component_name = component_name - op.item_name = object_or_collection.name - op.item_type = get_selection_type(object_or_collection) - row.separator() - - op = row.operator("blenvy.component_copy", text="", icon="COPYDOWN") - op.source_component_name = component_name - op.source_item_name = object_or_collection.name - op.source_item_type = get_selection_type(object_or_collection) - row.separator() + if not component_internal: + op = row.operator("blenvy.component_remove", text="", icon="X") + op.component_name = component_name + op.item_name = object_or_collection.name + op.item_type = get_selection_type(object_or_collection) + row.separator() + + op = row.operator("blenvy.component_copy", text="", icon="COPYDOWN") + op.source_component_name = component_name + op.source_item_name = object_or_collection.name + op.source_item_type = get_selection_type(object_or_collection) + row.separator() #if not single_field: toggle_icon = "TRIA_DOWN" if component_visible else "TRIA_RIGHT" @@ -388,7 +397,7 @@ class BLENVY_PT_component_tools_panel(bpy.types.Panel): self.draw_invalid_or_unregistered(layout, status, custom_property, item, item_type) def gather_invalid_item_data(self, item, invalid_component_names, items_with_invalid_components, items_with_original_components, original_name, item_type): - blenvy_custom_properties = ['components_meta', 'bevy_components', 'user_assets', 'generated_assets', 'BlueprintAssets', 'export_path' ] # some of our own hard coded custom properties that should be ignored + blenvy_custom_properties = ['components_meta', 'bevy_components', 'user_assets', 'generated_assets', 'BlueprintAssets', 'export_path', 'MaterialInfos' ] # some of our own hard coded custom properties that should be ignored upgreadable_entries = [] if "components_meta" in item or hasattr(item, "components_meta"): # FIXME; wrong way of determining diff --git a/tools/blenvy/add_ons/bevy_components/settings.py b/tools/blenvy/add_ons/bevy_components/settings.py index 739cf38..6671faa 100644 --- a/tools/blenvy/add_ons/bevy_components/settings.py +++ b/tools/blenvy/add_ons/bevy_components/settings.py @@ -32,6 +32,7 @@ def watch_schema(): blenvy = bpy.context.window_manager.blenvy component_settings = blenvy.components #print("watching schema file for changes") + reloading_registry = False try: stamp = os.stat(component_settings.schema_path_full).st_mtime stamp = str(stamp) @@ -47,11 +48,19 @@ def watch_schema(): # we need to add an additional delay as the file might not have loaded yet bpy.app.timers.register(lambda: bpy.ops.blenvy.components_registry_reload(), first_interval=1) component_settings.schemaTimeStamp = stamp + reloading_registry = True if component_settings.schemaTimeStamp == "": component_settings.schemaTimeStamp = stamp except Exception as error: pass + + # if there is no registry loaded yet, try to load it + """registry = bpy.context.window_manager.components_registry + if not reloading_registry and len(list(registry.type_infos.keys())) == 0: + print("reload registry here") + bpy.app.timers.register(lambda: bpy.ops.blenvy.components_registry_reload(), first_interval=1)""" + return component_settings.watcher_poll_frequency if component_settings.watcher_enabled else None class ComponentsSettings(PropertyGroup): diff --git a/tools/blenvy/materials/materials_helpers.py b/tools/blenvy/materials/materials_helpers.py index 90a3b4c..8ee2338 100644 --- a/tools/blenvy/materials/materials_helpers.py +++ b/tools/blenvy/materials/materials_helpers.py @@ -1,6 +1,7 @@ import os import posixpath from ..core.helpers_collections import (traverse_tree) +from ..add_ons.bevy_components.components.metadata import apply_propertyGroup_values_to_item_customProperties_for_component, upsert_bevy_component, get_bevy_component_value_by_long_name def find_materials_not_on_disk(materials, materials_path_full, extension): not_found_materials = [] @@ -79,6 +80,7 @@ def get_all_materials(collection_names, library_scenes): used_material_names = list(set(used_material_names)) return (used_material_names, materials_per_object) +import bpy def add_material_info_to_objects(materials_per_object, settings): materials_path = getattr(settings, "materials_path") export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb") @@ -90,8 +92,13 @@ def add_material_info_to_objects(materials_per_object, settings): material_infos.append(material_info) # problem with using actual components: you NEED the type registry/component infos, so if there is none , or it is not loaded yet, it does not work # for a few components we could hardcode this - #bpy.ops.blenvy.component_add(target_item_name=object.name, target_item_type="OBJECT", component_type="blenvy::blueprints::materials::MaterialInfos", component_value=component_value) - object['MaterialInfos'] = f"({material_infos})".replace("'","") + component_value = f"({material_infos})".replace("'","") + try: + bpy.ops.blenvy.component_add(target_item_name=object.name, target_item_type="OBJECT", component_type="blenvy::blueprints::materials::MaterialInfos", component_value=component_value ) + except: + object['MaterialInfos'] = f"({material_infos})".replace("'","") + #upsert_bevy_component(object, "blenvy::blueprints::materials::MaterialInfos", f"({material_infos})".replace("'","") ) + #apply_propertyGroup_values_to_item_customProperties_for_component(object, "MaterialInfos") print("adding materialInfos to object", object, "material infos", material_infos)