mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-26 21:37:01 +00:00
Compare commits
3 Commits
70bdd489a1
...
382f37be74
Author | SHA1 | Date | |
---|---|---|---|
|
382f37be74 | ||
|
dc7422fe7a | ||
|
7ac0c5bca9 |
@ -9,6 +9,7 @@ Auto export
|
|||||||
- root path => relative to blend file path
|
- root path => relative to blend file path
|
||||||
- asset path => relative to root path
|
- asset path => relative to root path
|
||||||
- blueprints/levels/blueprints path => relative to assets path
|
- blueprints/levels/blueprints path => relative to assets path
|
||||||
|
- [ ] add error handling for de/serialization of project, so that in case of error, the previous saved serialized project is thrown away
|
||||||
|
|
||||||
|
|
||||||
- move out some parameters from auto export to a higher level (as they are now used in multiple places)
|
- move out some parameters from auto export to a higher level (as they are now used in multiple places)
|
||||||
@ -50,7 +51,22 @@ Blueprints:
|
|||||||
- [ ] decide where & when to do & store blueprints data
|
- [ ] decide where & when to do & store blueprints data
|
||||||
|
|
||||||
Components:
|
Components:
|
||||||
- [ ] add support for adding components to collections
|
- [x] add support for adding components to collections
|
||||||
|
- [ ] upgrade all operators:
|
||||||
|
- [x] add
|
||||||
|
- [x] remove
|
||||||
|
- [x] copy & paste
|
||||||
|
- [ ] OT_rename_component
|
||||||
|
- [ ] Fix_Component_Operator
|
||||||
|
- [ ] add handling for core::ops::Range<f32> & other ranges
|
||||||
|
- [ ] fix is_component_valid that is used in gltf_auto_export
|
||||||
|
- Hashmap Support
|
||||||
|
- [x] fix parsing of keys's type either on Bevy side (prefered) or on the Blender side
|
||||||
|
- [x] fix weird issue with missing "0" property when adding new entry in empty hashmap => happens only if the values for the "setter" have never been set
|
||||||
|
- [ ] handle missing types in registry for keys & values
|
||||||
|
|
||||||
|
- [ ] Add correct upgrade handling from individual component to bevy_components
|
||||||
|
|
||||||
|
|
||||||
General things to solve:
|
General things to solve:
|
||||||
- [x] save settings
|
- [x] save settings
|
||||||
@ -67,3 +83,4 @@ General issues:
|
|||||||
- "parents" can only be blueprints
|
- "parents" can only be blueprints
|
||||||
- they normally need/have unique export paths (otherwise, user error, perhaps show it ?)
|
- they normally need/have unique export paths (otherwise, user error, perhaps show it ?)
|
||||||
- perhaps a simple hashing of the parent's path would be enought
|
- perhaps a simple hashing of the parent's path would be enought
|
||||||
|
- addon-prefs => settings
|
@ -17,7 +17,7 @@ from bpy.props import (StringProperty)
|
|||||||
|
|
||||||
|
|
||||||
# components management
|
# components management
|
||||||
from .bevy_components.components.operators import CopyComponentOperator, Fix_Component_Operator, OT_rename_component, RemoveComponentFromAllObjectsOperator, RemoveComponentOperator, GenerateComponent_From_custom_property_Operator, PasteComponentOperator, AddComponentOperator, RenameHelper, Toggle_ComponentVisibility
|
from .bevy_components.components.operators import CopyComponentOperator, Fix_Component_Operator, OT_rename_component, RemoveComponentFromAllItemsOperator, RemoveComponentOperator, GenerateComponent_From_custom_property_Operator, PasteComponentOperator, AddComponentOperator, RenameHelper, Toggle_ComponentVisibility
|
||||||
|
|
||||||
from .bevy_components.registry.registry import ComponentsRegistry,MissingBevyType
|
from .bevy_components.registry.registry import ComponentsRegistry,MissingBevyType
|
||||||
from .bevy_components.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_OpenSchemaFileBrowser)
|
from .bevy_components.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_OpenSchemaFileBrowser)
|
||||||
@ -74,7 +74,7 @@ classes = [
|
|||||||
CopyComponentOperator,
|
CopyComponentOperator,
|
||||||
PasteComponentOperator,
|
PasteComponentOperator,
|
||||||
RemoveComponentOperator,
|
RemoveComponentOperator,
|
||||||
RemoveComponentFromAllObjectsOperator,
|
RemoveComponentFromAllItemsOperator,
|
||||||
Fix_Component_Operator,
|
Fix_Component_Operator,
|
||||||
OT_rename_component,
|
OT_rename_component,
|
||||||
RenameHelper,
|
RenameHelper,
|
||||||
|
@ -166,7 +166,7 @@ class OT_Add_asset_filebrowser(Operator, ImportHelper):
|
|||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
|
||||||
def write_ron_assets_file(level_name, assets_hierarchy, internal_only=False):
|
def write_ron_assets_file(level_name, assets_hierarchy, internal_only=False, levels_path_full="."):
|
||||||
# just for testing, this uses the format of bevy_asset_loader's asset files
|
# just for testing, this uses the format of bevy_asset_loader's asset files
|
||||||
'''
|
'''
|
||||||
({
|
({
|
||||||
@ -187,7 +187,7 @@ def write_ron_assets_file(level_name, assets_hierarchy, internal_only=False):
|
|||||||
if asset["internal"] or not internal_only:
|
if asset["internal"] or not internal_only:
|
||||||
bla = f'\n "{asset["name"]}": File ( path: "{asset["path"]}" ),'
|
bla = f'\n "{asset["name"]}": File ( path: "{asset["path"]}" ),'
|
||||||
formated_assets.append(bla)
|
formated_assets.append(bla)
|
||||||
with open(f"testing/bevy_example/assets/assets_{level_name}.assets.ron", "w") as assets_file:
|
with open(f"{levels_path_full}/{level_name}.assets.ron", "w") as assets_file:
|
||||||
assets_file.write("({")
|
assets_file.write("({")
|
||||||
assets_file.writelines(formated_assets)
|
assets_file.writelines(formated_assets)
|
||||||
assets_file.write("\n})")
|
assets_file.write("\n})")
|
||||||
@ -200,15 +200,14 @@ class OT_test_bevy_assets(Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
blenvy = context.window_manager.blenvy
|
blenvy = context.window_manager.blenvy
|
||||||
|
settings = blenvy
|
||||||
blueprints_registry = context.window_manager.blueprints_registry
|
blueprints_registry = context.window_manager.blueprints_registry
|
||||||
blueprints_registry.add_blueprints_data()
|
blueprints_registry.add_blueprints_data()
|
||||||
blueprints_data = blueprints_registry.blueprints_data
|
blueprints_data = blueprints_registry.blueprints_data
|
||||||
|
|
||||||
settings = {"blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
|
||||||
settings = SimpleNamespace(**settings)
|
|
||||||
for scene in blenvy.main_scenes:
|
for scene in blenvy.main_scenes:
|
||||||
assets_hierarchy = get_main_scene_assets_tree(scene, blueprints_data, settings)
|
assets_hierarchy = get_main_scene_assets_tree(scene, blueprints_data, settings)
|
||||||
scene["assets"] = json.dumps(assets_hierarchy)
|
scene["assets"] = json.dumps(assets_hierarchy)
|
||||||
write_ron_assets_file(scene.name, assets_hierarchy, internal_only=False)
|
write_ron_assets_file(scene.name, assets_hierarchy, internal_only = False, levels_path_full = blenvy.levels_path_full)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
@ -52,23 +52,26 @@ class ComponentsMeta(PropertyGroup):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
|
# you can add components to both objects & collections
|
||||||
bpy.types.Object.components_meta = PointerProperty(type=ComponentsMeta)
|
bpy.types.Object.components_meta = PointerProperty(type=ComponentsMeta)
|
||||||
|
bpy.types.Collection.components_meta = PointerProperty(type=ComponentsMeta)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
del bpy.types.Object.components_meta
|
del bpy.types.Object.components_meta
|
||||||
|
del bpy.types.Collection.components_meta
|
||||||
|
|
||||||
# remove no longer valid metadata from object
|
# remove no longer valid metadata from item
|
||||||
def cleanup_invalid_metadata(object):
|
def cleanup_invalid_metadata(item):
|
||||||
bevy_components = get_bevy_components(object)
|
bevy_components = get_bevy_components(item)
|
||||||
if len(bevy_components.keys()) == 0: # no components, bail out
|
if len(bevy_components.keys()) == 0: # no components, bail out
|
||||||
return
|
return
|
||||||
components_metadata = object.components_meta.components
|
components_metadata = item.components_meta.components
|
||||||
to_remove = []
|
to_remove = []
|
||||||
for index, component_meta in enumerate(components_metadata):
|
for index, component_meta in enumerate(components_metadata):
|
||||||
long_name = component_meta.long_name
|
long_name = component_meta.long_name
|
||||||
if long_name not in bevy_components.keys():
|
if long_name not in bevy_components.keys():
|
||||||
print("component:", long_name, "present in metadata, but not in object")
|
print("component:", long_name, "present in metadata, but not in item")
|
||||||
to_remove.append(index)
|
to_remove.append(index)
|
||||||
for index in to_remove:
|
for index in to_remove:
|
||||||
components_metadata.remove(index)
|
components_metadata.remove(index)
|
||||||
@ -81,20 +84,22 @@ def find_component_definition_from_long_name(long_name):
|
|||||||
|
|
||||||
# FIXME: feels a bit heavy duty, should only be done
|
# FIXME: feels a bit heavy duty, should only be done
|
||||||
# if the components panel is active ?
|
# if the components panel is active ?
|
||||||
def ensure_metadata_for_all_objects():
|
def ensure_metadata_for_all_items():
|
||||||
for object in bpy.data.objects:
|
for object in bpy.data.objects:
|
||||||
add_metadata_to_components_without_metadata(object)
|
add_metadata_to_components_without_metadata(object)
|
||||||
|
for collection in bpy.data.collections:
|
||||||
|
add_metadata_to_components_without_metadata(collection)
|
||||||
|
|
||||||
# returns whether an object has custom properties without matching metadata
|
# returns whether an item has custom properties without matching metadata
|
||||||
def do_object_custom_properties_have_missing_metadata(object):
|
def do_item_custom_properties_have_missing_metadata(item):
|
||||||
components_metadata = getattr(object, "components_meta", None)
|
components_metadata = getattr(item, "components_meta", None)
|
||||||
if components_metadata == None:
|
if components_metadata == None:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
components_metadata = components_metadata.components
|
components_metadata = components_metadata.components
|
||||||
|
|
||||||
missing_metadata = False
|
missing_metadata = False
|
||||||
for component_name in get_bevy_components(object) :
|
for component_name in get_bevy_components(item) :
|
||||||
if component_name == "components_meta":
|
if component_name == "components_meta":
|
||||||
continue
|
continue
|
||||||
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None)
|
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None)
|
||||||
@ -111,72 +116,72 @@ def do_object_custom_properties_have_missing_metadata(object):
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
def upsert_bevy_component(object, long_name, value):
|
def upsert_bevy_component(item, long_name, value):
|
||||||
if not 'bevy_components' in object:
|
if not 'bevy_components' in item:
|
||||||
object['bevy_components'] = '{}'
|
item['bevy_components'] = '{}'
|
||||||
bevy_components = json.loads(object['bevy_components'])
|
bevy_components = json.loads(item['bevy_components'])
|
||||||
bevy_components[long_name] = value
|
bevy_components[long_name] = value
|
||||||
object['bevy_components'] = json.dumps(bevy_components)
|
item['bevy_components'] = json.dumps(bevy_components)
|
||||||
#object['bevy_components'][long_name] = value # Sigh, this does not work, hits Blender's 63 char length limit
|
#item['bevy_components'][long_name] = value # Sigh, this does not work, hits Blender's 63 char length limit
|
||||||
|
|
||||||
def remove_bevy_component(object, long_name):
|
def remove_bevy_component(item, long_name):
|
||||||
if 'bevy_components' in object:
|
if 'bevy_components' in item:
|
||||||
bevy_components = json.loads(object['bevy_components'])
|
bevy_components = json.loads(item['bevy_components'])
|
||||||
if long_name in bevy_components:
|
if long_name in bevy_components:
|
||||||
del bevy_components[long_name]
|
del bevy_components[long_name]
|
||||||
object['bevy_components'] = json.dumps(bevy_components)
|
item['bevy_components'] = json.dumps(bevy_components)
|
||||||
if long_name in object:
|
if long_name in item:
|
||||||
del object[long_name]
|
del item[long_name]
|
||||||
|
|
||||||
def get_bevy_components(object):
|
def get_bevy_components(item):
|
||||||
if 'bevy_components' in object:
|
if 'bevy_components' in item:
|
||||||
bevy_components = json.loads(object['bevy_components'])
|
bevy_components = json.loads(item['bevy_components'])
|
||||||
return bevy_components
|
return bevy_components
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def get_bevy_component_value_by_long_name(object, long_name):
|
def get_bevy_component_value_by_long_name(item, long_name):
|
||||||
bevy_components = get_bevy_components(object)
|
bevy_components = get_bevy_components(item)
|
||||||
if len(bevy_components.keys()) == 0 :
|
if len(bevy_components.keys()) == 0 :
|
||||||
return None
|
return None
|
||||||
return bevy_components.get(long_name, None)
|
return bevy_components.get(long_name, None)
|
||||||
|
|
||||||
def is_bevy_component_in_object(object, long_name):
|
def is_bevy_component_in_item(item, long_name):
|
||||||
return get_bevy_component_value_by_long_name(object, long_name) is not None
|
return get_bevy_component_value_by_long_name(item, long_name) is not None
|
||||||
|
|
||||||
# adds metadata to object only if it is missing
|
# adds metadata to item only if it is missing
|
||||||
def add_metadata_to_components_without_metadata(object):
|
def add_metadata_to_components_without_metadata(item):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
|
|
||||||
for component_name in get_bevy_components(object) :
|
for component_name in get_bevy_components(item) :
|
||||||
if component_name == "components_meta":
|
if component_name == "components_meta":
|
||||||
continue
|
continue
|
||||||
upsert_component_in_object(object, component_name, registry)
|
upsert_component_in_item(item, component_name, registry)
|
||||||
|
|
||||||
# adds a component to an object (including metadata) using the provided component definition & optional value
|
# adds a component to an item (including metadata) using the provided component definition & optional value
|
||||||
def add_component_to_object(object, component_definition, value=None):
|
def add_component_to_item(item, component_definition, value=None):
|
||||||
cleanup_invalid_metadata(object)
|
cleanup_invalid_metadata(item)
|
||||||
if object is not None:
|
if item is not None:
|
||||||
# print("add_component_to_object", component_definition)
|
# print("add_component_to_item", component_definition)
|
||||||
long_name = component_definition["long_name"]
|
long_name = component_definition["long_name"]
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
if not registry.has_type_infos():
|
if not registry.has_type_infos():
|
||||||
raise Exception('registry type infos have not been loaded yet or are missing !')
|
raise Exception('registry type infos have not been loaded yet or are missing !')
|
||||||
definition = registry.type_infos[long_name]
|
definition = registry.type_infos[long_name]
|
||||||
# now we use our pre_generated property groups to set the initial value of our custom property
|
# 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)
|
(_, propertyGroup) = upsert_component_in_item(item, long_name=long_name, registry=registry)
|
||||||
if value == None:
|
if value == None:
|
||||||
value = property_group_value_to_custom_property_value(propertyGroup, definition, registry, None)
|
value = property_group_value_to_custom_property_value(propertyGroup, definition, registry, None)
|
||||||
else: # we have provided a value, that is a raw , custom property value, to set the value of the propertyGroup
|
else: # we have provided a value, that is a raw , custom property value, to set the value of the propertyGroup
|
||||||
object["__disable__update"] = True # disable update callback while we set the values of the propertyGroup "tree" (as a propertyGroup can contain other propertyGroups)
|
item["__disable__update"] = True # disable update callback while we set the values of the propertyGroup "tree" (as a propertyGroup can contain other propertyGroups)
|
||||||
property_group_value_from_custom_property_value(propertyGroup, definition, registry, value)
|
property_group_value_from_custom_property_value(propertyGroup, definition, registry, value)
|
||||||
del object["__disable__update"]
|
del item["__disable__update"]
|
||||||
|
|
||||||
upsert_bevy_component(object, long_name, value)
|
upsert_bevy_component(item, long_name, value)
|
||||||
|
|
||||||
def upsert_component_in_object(object, long_name, registry):
|
def upsert_component_in_item(item, long_name, registry):
|
||||||
# print("upsert_component_in_object", object, "component name", component_name)
|
# print("upsert_component_in_item", item, "component name", component_name)
|
||||||
# TODO: upsert this part too ?
|
# TODO: upsert this part too ?
|
||||||
target_components_metadata = object.components_meta.components
|
target_components_metadata = item.components_meta.components
|
||||||
component_definition = registry.type_infos.get(long_name, None)
|
component_definition = registry.type_infos.get(long_name, None)
|
||||||
if component_definition != None:
|
if component_definition != None:
|
||||||
short_name = component_definition["short_name"]
|
short_name = component_definition["short_name"]
|
||||||
@ -213,15 +218,15 @@ def upsert_component_in_object(object, long_name, registry):
|
|||||||
component_meta.enabled = False
|
component_meta.enabled = False
|
||||||
component_meta.invalid = True
|
component_meta.invalid = True
|
||||||
component_meta.invalid_details = "component not present in the schema, possibly renamed? Disabling for now"
|
component_meta.invalid_details = "component not present in the schema, possibly renamed? Disabling for now"
|
||||||
# property_group_value_from_custom_property_value(propertyGroup, component_definition, registry, object[component_name])
|
# property_group_value_from_custom_property_value(propertyGroup, component_definition, registry, item[component_name])
|
||||||
|
|
||||||
return (component_meta, propertyGroup)
|
return (component_meta, propertyGroup)
|
||||||
else:
|
else:
|
||||||
return(None, None)
|
return(None, None)
|
||||||
|
|
||||||
|
|
||||||
def copy_propertyGroup_values_to_another_object(source_object, target_object, component_name, registry):
|
def copy_propertyGroup_values_to_another_item(source_item, target_item, component_name, registry):
|
||||||
if source_object == None or target_object == None or component_name == None:
|
if source_item == None or target_item == None or component_name == None:
|
||||||
raise Exception('missing input data, cannot copy component propertryGroup')
|
raise Exception('missing input data, cannot copy component propertryGroup')
|
||||||
|
|
||||||
component_definition = find_component_definition_from_long_name(component_name)
|
component_definition = find_component_definition_from_long_name(component_name)
|
||||||
@ -230,82 +235,82 @@ def copy_propertyGroup_values_to_another_object(source_object, target_object, co
|
|||||||
|
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
|
|
||||||
source_components_metadata = source_object.components_meta.components
|
source_components_metadata = source_item.components_meta.components
|
||||||
source_componentMeta = next(filter(lambda component: component["long_name"] == long_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
|
# matching component means we already have this type of component
|
||||||
source_propertyGroup = getattr(source_componentMeta, property_group_name)
|
source_propertyGroup = getattr(source_componentMeta, property_group_name)
|
||||||
|
|
||||||
# now deal with the target object
|
# now deal with the target item
|
||||||
(_, target_propertyGroup) = upsert_component_in_object(target_object, component_name, registry)
|
(_, target_propertyGroup) = upsert_component_in_item(target_item, component_name, registry)
|
||||||
# add to object
|
# add to item
|
||||||
value = property_group_value_to_custom_property_value(target_propertyGroup, component_definition, registry, None)
|
value = property_group_value_to_custom_property_value(target_propertyGroup, component_definition, registry, None)
|
||||||
upsert_bevy_component(target_object, long_name, value)
|
upsert_bevy_component(target_item, long_name, value)
|
||||||
|
|
||||||
# copy the values over
|
# copy the values over
|
||||||
for field_name in source_propertyGroup.field_names:
|
for field_name in source_propertyGroup.field_names:
|
||||||
if field_name in source_propertyGroup:
|
if field_name in source_propertyGroup:
|
||||||
target_propertyGroup[field_name] = source_propertyGroup[field_name]
|
target_propertyGroup[field_name] = source_propertyGroup[field_name]
|
||||||
apply_propertyGroup_values_to_object_customProperties(target_object)
|
apply_propertyGroup_values_to_item_customProperties(target_item)
|
||||||
|
|
||||||
|
|
||||||
# TODO: move to propgroups ?
|
# TODO: move to propgroups ?
|
||||||
def apply_propertyGroup_values_to_object_customProperties(object):
|
def apply_propertyGroup_values_to_item_customProperties(item):
|
||||||
cleanup_invalid_metadata(object)
|
cleanup_invalid_metadata(item)
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
for component_name in get_bevy_components(object) :
|
for component_name in get_bevy_components(item) :
|
||||||
"""if component_name == "components_meta":
|
"""if component_name == "components_meta":
|
||||||
continue"""
|
continue"""
|
||||||
(_, propertyGroup) = upsert_component_in_object(object, component_name, registry)
|
(_, propertyGroup) = upsert_component_in_item(item, component_name, registry)
|
||||||
component_definition = find_component_definition_from_long_name(component_name)
|
component_definition = find_component_definition_from_long_name(component_name)
|
||||||
if component_definition != None:
|
if component_definition != None:
|
||||||
value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
|
value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
|
||||||
upsert_bevy_component(object=object, long_name=component_name, value=value)
|
upsert_bevy_component(item=item, long_name=component_name, value=value)
|
||||||
|
|
||||||
# apply component value(s) to custom property of a single component
|
# apply component value(s) to custom property of a single component
|
||||||
def apply_propertyGroup_values_to_object_customProperties_for_component(object, component_name):
|
def apply_propertyGroup_values_to_item_customProperties_for_component(item, component_name):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
(_, propertyGroup) = upsert_component_in_object(object, component_name, registry)
|
(_, propertyGroup) = upsert_component_in_item(item, component_name, registry)
|
||||||
component_definition = find_component_definition_from_long_name(component_name)
|
component_definition = find_component_definition_from_long_name(component_name)
|
||||||
if component_definition != None:
|
if component_definition != None:
|
||||||
value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
|
value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
|
||||||
object[component_name] = value
|
item[component_name] = value
|
||||||
|
|
||||||
components_metadata = object.components_meta.components
|
components_metadata = item.components_meta.components
|
||||||
componentMeta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None)
|
componentMeta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None)
|
||||||
if componentMeta:
|
if componentMeta:
|
||||||
componentMeta.invalid = False
|
componentMeta.invalid = False
|
||||||
componentMeta.invalid_details = ""
|
componentMeta.invalid_details = ""
|
||||||
|
|
||||||
|
|
||||||
def apply_customProperty_values_to_object_propertyGroups(object):
|
def apply_customProperty_values_to_item_propertyGroups(item):
|
||||||
print("apply custom properties to ", object.name)
|
print("apply custom properties to ", item.name)
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
for component_name in get_bevy_components(object) :
|
for component_name in get_bevy_components(item) :
|
||||||
if component_name == "components_meta":
|
if component_name == "components_meta":
|
||||||
continue
|
continue
|
||||||
component_definition = find_component_definition_from_long_name(component_name)
|
component_definition = find_component_definition_from_long_name(component_name)
|
||||||
if component_definition != None:
|
if component_definition != None:
|
||||||
property_group_name = registry.get_propertyGroupName_from_longName(component_name)
|
property_group_name = registry.get_propertyGroupName_from_longName(component_name)
|
||||||
components_metadata = object.components_meta.components
|
components_metadata = item.components_meta.components
|
||||||
source_componentMeta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None)
|
source_componentMeta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None)
|
||||||
# matching component means we already have this type of component
|
# matching component means we already have this type of component
|
||||||
propertyGroup = getattr(source_componentMeta, property_group_name, None)
|
propertyGroup = getattr(source_componentMeta, property_group_name, None)
|
||||||
customProperty_value = get_bevy_component_value_by_long_name(object, component_name)
|
customProperty_value = get_bevy_component_value_by_long_name(item, component_name)
|
||||||
#value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
|
#value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
|
||||||
|
|
||||||
object["__disable__update"] = True # disable update callback while we set the values of the propertyGroup "tree" (as a propertyGroup can contain other propertyGroups)
|
item["__disable__update"] = True # disable update callback while we set the values of the propertyGroup "tree" (as a propertyGroup can contain other propertyGroups)
|
||||||
property_group_value_from_custom_property_value(propertyGroup, component_definition, registry, customProperty_value)
|
property_group_value_from_custom_property_value(propertyGroup, component_definition, registry, customProperty_value)
|
||||||
del object["__disable__update"]
|
del item["__disable__update"]
|
||||||
source_componentMeta.invalid = False
|
source_componentMeta.invalid = False
|
||||||
source_componentMeta.invalid_details = ""
|
source_componentMeta.invalid_details = ""
|
||||||
|
|
||||||
# removes the given component from the object: removes both the custom property and the matching metadata from the object
|
# removes the given component from the item: removes both the custom property and the matching metadata from the item
|
||||||
def remove_component_from_object(object, component_name):
|
def remove_component_from_item(item, component_name):
|
||||||
# remove the component value
|
# remove the component value
|
||||||
remove_bevy_component(object, component_name)
|
remove_bevy_component(item, component_name)
|
||||||
|
|
||||||
# now remove the component's metadata
|
# now remove the component's metadata
|
||||||
components_metadata = getattr(object, "components_meta", None)
|
components_metadata = getattr(item, "components_meta", None)
|
||||||
if components_metadata == None:
|
if components_metadata == None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -320,25 +325,25 @@ def remove_component_from_object(object, component_name):
|
|||||||
components_metadata.remove(index)
|
components_metadata.remove(index)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_component_from_custom_property(object):
|
def add_component_from_custom_property(item):
|
||||||
add_metadata_to_components_without_metadata(object)
|
add_metadata_to_components_without_metadata(item)
|
||||||
apply_customProperty_values_to_object_propertyGroups(object)
|
apply_customProperty_values_to_item_propertyGroups(item)
|
||||||
|
|
||||||
def rename_component(object, original_long_name, new_long_name):
|
def rename_component(item, original_long_name, new_long_name):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
type_infos = registry.type_infos
|
type_infos = registry.type_infos
|
||||||
component_definition = type_infos[new_long_name]
|
component_definition = type_infos[new_long_name]
|
||||||
|
|
||||||
component_ron_value = get_bevy_component_value_by_long_name(object=object, long_name=original_long_name)
|
component_ron_value = get_bevy_component_value_by_long_name(item=item, long_name=original_long_name)
|
||||||
if component_ron_value is None and original_long_name in object:
|
if component_ron_value is None and original_long_name in item:
|
||||||
component_ron_value = object[original_long_name]
|
component_ron_value = item[original_long_name]
|
||||||
|
|
||||||
remove_component_from_object(object, original_long_name)
|
remove_component_from_item(item, original_long_name)
|
||||||
add_component_to_object(object, component_definition, component_ron_value)
|
add_component_to_item(item, component_definition, component_ron_value)
|
||||||
|
|
||||||
|
|
||||||
def toggle_component(object, component_name):
|
def toggle_component(item, component_name):
|
||||||
components_in_object = object.components_meta.components
|
components_in_item = item.components_meta.components
|
||||||
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None)
|
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_item), None)
|
||||||
if component_meta != None:
|
if component_meta != None:
|
||||||
component_meta.visible = not component_meta.visible
|
component_meta.visible = not component_meta.visible
|
||||||
|
@ -4,12 +4,13 @@ import bpy
|
|||||||
from bpy_types import Operator
|
from bpy_types import Operator
|
||||||
from bpy.props import (StringProperty)
|
from bpy.props import (StringProperty)
|
||||||
|
|
||||||
from .metadata import add_component_from_custom_property, add_component_to_object, apply_propertyGroup_values_to_object_customProperties_for_component, copy_propertyGroup_values_to_another_object, get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_object, remove_component_from_object, rename_component, toggle_component
|
from .metadata import add_component_from_custom_property, add_component_to_item, apply_propertyGroup_values_to_item_customProperties_for_component, copy_propertyGroup_values_to_another_item, get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_item, remove_component_from_item, rename_component, toggle_component
|
||||||
|
from ..utils import get_selected_object_or_collection
|
||||||
|
|
||||||
class AddComponentOperator(Operator):
|
class AddComponentOperator(Operator):
|
||||||
"""Add Bevy component to object"""
|
"""Add Bevy component to object/collection"""
|
||||||
bl_idname = "object.add_bevy_component"
|
bl_idname = "object.add_bevy_component"
|
||||||
bl_label = "Add component to object Operator"
|
bl_label = "Add component to object/collection Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
component_type: StringProperty(
|
component_type: StringProperty(
|
||||||
@ -18,14 +19,14 @@ class AddComponentOperator(Operator):
|
|||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
object = context.object
|
target = get_selected_object_or_collection(context)
|
||||||
print("adding component ", self.component_type, "to object '"+object.name+"'")
|
print("adding component ", self.component_type, "to target '"+target.name+"'")
|
||||||
|
|
||||||
has_component_type = self.component_type != ""
|
has_component_type = self.component_type != ""
|
||||||
if has_component_type and object != None:
|
if has_component_type and target != None:
|
||||||
type_infos = context.window_manager.components_registry.type_infos
|
type_infos = context.window_manager.components_registry.type_infos
|
||||||
component_definition = type_infos[self.component_type]
|
component_definition = type_infos[self.component_type]
|
||||||
add_component_to_object(object, component_definition)
|
add_component_to_item(target, component_definition)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -40,28 +41,36 @@ class CopyComponentOperator(Operator):
|
|||||||
description="name of the component to copy",
|
description="name of the component to copy",
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
source_object_name: StringProperty(
|
source_item_name: StringProperty(
|
||||||
name="source object name",
|
name="source item name",
|
||||||
description="name of the object to copy the component from",
|
description="name of the object/collection to copy the component from",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
source_item_type: StringProperty(
|
||||||
|
name="source item type",
|
||||||
|
description="type of the object/collection to copy the component from",
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.WindowManager.copied_source_component_name = StringProperty()
|
bpy.types.WindowManager.copied_source_component_name = StringProperty()
|
||||||
bpy.types.WindowManager.copied_source_object = StringProperty()
|
bpy.types.WindowManager.copied_source_item_name = StringProperty()
|
||||||
|
bpy.types.WindowManager.copied_source_item_type = StringProperty()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
del bpy.types.WindowManager.copied_source_component_name
|
del bpy.types.WindowManager.copied_source_component_name
|
||||||
del bpy.types.WindowManager.copied_source_object
|
del bpy.types.WindowManager.copied_source_item_name
|
||||||
|
del bpy.types.WindowManager.copied_source_item_type
|
||||||
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
if self.source_component_name != '' and self.source_object_name != "":
|
if self.source_component_name != '' and self.source_item_name != "" and self.source_item_type != "":
|
||||||
context.window_manager.copied_source_component_name = self.source_component_name
|
context.window_manager.copied_source_component_name = self.source_component_name
|
||||||
context.window_manager.copied_source_object = self.source_object_name
|
context.window_manager.copied_source_item_name = self.source_item_name
|
||||||
|
context.window_manager.copied_source_item_type = self.source_item_type
|
||||||
else:
|
else:
|
||||||
self.report({"ERROR"}, "The source object name / component name to copy a component from have not been specified")
|
self.report({"ERROR"}, "The source object/collection name or component name to copy a component from have not been specified")
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -73,28 +82,32 @@ class PasteComponentOperator(Operator):
|
|||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
source_object_name = context.window_manager.copied_source_object
|
source_item_name = context.window_manager.copied_source_item_name
|
||||||
source_object = bpy.data.objects.get(source_object_name, None)
|
source_item_type = context.window_manager.copied_source_item_type
|
||||||
print("source object", source_object)
|
if source_item_type == 'Object':
|
||||||
if source_object == None:
|
source_item = bpy.data.objects.get(source_item_name, None)
|
||||||
|
elif source_item_type == 'Collection':
|
||||||
|
source_item = bpy.data.collections.get(source_item_name, None)
|
||||||
|
|
||||||
|
if source_item == None:
|
||||||
self.report({"ERROR"}, "The source object to copy a component from does not exist")
|
self.report({"ERROR"}, "The source object to copy a component from does not exist")
|
||||||
else:
|
else:
|
||||||
component_name = context.window_manager.copied_source_component_name
|
component_name = context.window_manager.copied_source_component_name
|
||||||
component_value = get_bevy_component_value_by_long_name(source_object, component_name)
|
component_value = get_bevy_component_value_by_long_name(source_item, component_name)
|
||||||
if component_value is None:
|
if component_value is None:
|
||||||
self.report({"ERROR"}, "The source component to copy from does not exist")
|
self.report({"ERROR"}, "The source component to copy from does not exist")
|
||||||
else:
|
else:
|
||||||
print("pasting component to object: component name:", str(component_name), "component value:" + str(component_value))
|
print("pasting component to item:", source_item, "component name:", str(component_name), "component value:" + str(component_value))
|
||||||
print (context.object)
|
|
||||||
registry = context.window_manager.components_registry
|
registry = context.window_manager.components_registry
|
||||||
copy_propertyGroup_values_to_another_object(source_object, context.object, component_name, registry)
|
target_item = get_selected_object_or_collection(context)
|
||||||
|
copy_propertyGroup_values_to_another_item(source_item, target_item, component_name, registry)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class RemoveComponentOperator(Operator):
|
class RemoveComponentOperator(Operator):
|
||||||
"""Remove Bevy component from object"""
|
"""Remove Bevy component from object/collection"""
|
||||||
bl_idname = "object.remove_bevy_component"
|
bl_idname = "object.remove_bevy_component"
|
||||||
bl_label = "Remove component from object Operator"
|
bl_label = "Remove component from object/collection Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
component_name: StringProperty(
|
component_name: StringProperty(
|
||||||
@ -102,34 +115,44 @@ class RemoveComponentOperator(Operator):
|
|||||||
description="component to delete",
|
description="component to delete",
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
object_name: StringProperty(
|
item_name: StringProperty(
|
||||||
name="object name",
|
name="object name",
|
||||||
description="object whose component to delete",
|
description="object whose component to delete",
|
||||||
default=""
|
default=""
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
def execute(self, context):
|
item_type: StringProperty(
|
||||||
if self.object_name == "":
|
name="item type",
|
||||||
object = context.object
|
description="type of the object/collection to delete",
|
||||||
else:
|
) # type: ignore
|
||||||
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 :
|
def execute(self, context):
|
||||||
component_value = get_bevy_component_value_by_long_name(object, self.component_name)
|
target = None
|
||||||
|
if self.item_name == "":
|
||||||
|
self.report({"ERROR"}, "The target to remove ("+ self.component_name +") from does not exist")
|
||||||
|
else:
|
||||||
|
if self.item_type == 'Object':
|
||||||
|
target = bpy.data.objects[self.item_name]
|
||||||
|
elif self.item_type == 'Collection':
|
||||||
|
target = bpy.data.collections[self.item_name]
|
||||||
|
|
||||||
|
print("removing component ", self.component_name, "from object '"+target.name+"'")
|
||||||
|
|
||||||
|
if target is not None and 'bevy_components' in target :
|
||||||
|
component_value = get_bevy_component_value_by_long_name(target, self.component_name)
|
||||||
if component_value is not None:
|
if component_value is not None:
|
||||||
remove_component_from_object(object, self.component_name)
|
remove_component_from_item(target, self.component_name)
|
||||||
else :
|
else :
|
||||||
self.report({"ERROR"}, "The component to remove ("+ self.component_name +") does not exist")
|
self.report({"ERROR"}, "The component to remove ("+ self.component_name +") does not exist")
|
||||||
else:
|
else:
|
||||||
self.report({"ERROR"}, "The object to remove ("+ self.component_name +") from does not exist")
|
self.report({"ERROR"}, "The target to remove ("+ self.component_name +") from does not exist")
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class RemoveComponentFromAllObjectsOperator(Operator):
|
class RemoveComponentFromAllItemsOperator(Operator):
|
||||||
"""Remove Bevy component from all object"""
|
"""Remove Bevy component from all items"""
|
||||||
bl_idname = "object.remove_bevy_component_all"
|
bl_idname = "object.remove_bevy_component_all"
|
||||||
bl_label = "Remove component from all objects Operator"
|
bl_label = "Remove component from all items Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
component_name: StringProperty(
|
component_name: StringProperty(
|
||||||
@ -146,17 +169,28 @@ class RemoveComponentFromAllObjectsOperator(Operator):
|
|||||||
del bpy.types.WindowManager.components_remove_progress
|
del bpy.types.WindowManager.components_remove_progress
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
print("removing component ", self.component_name, "from all objects")
|
print("removing component ", self.component_name, "from all objects/collections")
|
||||||
total = len(bpy.data.objects)
|
total = len(bpy.data.objects) + len(bpy.data.collections)
|
||||||
for index, object in enumerate(bpy.data.objects):
|
for index, object in enumerate(bpy.data.objects):
|
||||||
if len(object.keys()) > 0:
|
if len(object.keys()) > 0:
|
||||||
if object is not None and is_bevy_component_in_object(object, self.component_name):
|
if object is not None and is_bevy_component_in_item(object, self.component_name):
|
||||||
remove_component_from_object(object, self.component_name)
|
remove_component_from_item(object, self.component_name)
|
||||||
|
|
||||||
progress = index / total
|
progress = index / total
|
||||||
context.window_manager.components_remove_progress = progress
|
context.window_manager.components_remove_progress = progress
|
||||||
# now force refresh the ui
|
# now force refresh the ui
|
||||||
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
||||||
|
|
||||||
|
for index, collection in enumerate(bpy.data.collections):
|
||||||
|
if len(collection.keys()) > 0:
|
||||||
|
if collection is not None and is_bevy_component_in_item(collection, self.component_name):
|
||||||
|
remove_component_from_item(collection, self.component_name)
|
||||||
|
|
||||||
|
progress = index / total
|
||||||
|
context.window_manager.components_remove_progress = progress
|
||||||
|
# now force refresh the ui
|
||||||
|
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
||||||
|
|
||||||
context.window_manager.components_remove_progress = -1.0
|
context.window_manager.components_remove_progress = -1.0
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
@ -212,8 +246,8 @@ class OT_rename_component(Operator):
|
|||||||
total = len(target_objects)
|
total = len(target_objects)
|
||||||
|
|
||||||
if original_name != '' and new_name != '' and original_name != new_name and len(target_objects) > 0:
|
if original_name != '' and new_name != '' and original_name != new_name and len(target_objects) > 0:
|
||||||
for index, object_name in enumerate(target_objects):
|
for index, item_name in enumerate(target_objects):
|
||||||
object = bpy.data.objects[object_name]
|
object = bpy.data.objects[item_name]
|
||||||
if object and original_name in get_bevy_components(object) or original_name in object:
|
if object and original_name in get_bevy_components(object) or original_name in object:
|
||||||
try:
|
try:
|
||||||
# attempt conversion
|
# attempt conversion
|
||||||
@ -293,7 +327,7 @@ class Fix_Component_Operator(Operator):
|
|||||||
object = context.object
|
object = context.object
|
||||||
error = False
|
error = False
|
||||||
try:
|
try:
|
||||||
apply_propertyGroup_values_to_object_customProperties_for_component(object, self.component_name)
|
apply_propertyGroup_values_to_item_customProperties_for_component(object, self.component_name)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
if "__disable__update" in object:
|
if "__disable__update" in object:
|
||||||
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
|
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
|
||||||
@ -315,7 +349,7 @@ class Toggle_ComponentVisibility(Operator):
|
|||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
object = context.object
|
target = get_selected_object_or_collection(context)
|
||||||
toggle_component(object, self.component_name)
|
toggle_component(target, self.component_name)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import json
|
import json
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
|
from ..utils import get_selection_type
|
||||||
from ..registry.operators import COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT
|
from ..registry.operators import COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT
|
||||||
from .metadata import do_object_custom_properties_have_missing_metadata, get_bevy_components
|
from .metadata import do_item_custom_properties_have_missing_metadata, get_bevy_components
|
||||||
from .operators import AddComponentOperator, CopyComponentOperator, Fix_Component_Operator, RemoveComponentOperator, GenerateComponent_From_custom_property_Operator, PasteComponentOperator, Toggle_ComponentVisibility
|
from .operators import AddComponentOperator, CopyComponentOperator, Fix_Component_Operator, RemoveComponentOperator, GenerateComponent_From_custom_property_Operator, PasteComponentOperator, Toggle_ComponentVisibility
|
||||||
|
|
||||||
def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None):
|
def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None):
|
||||||
@ -158,11 +159,24 @@ class BEVY_COMPONENTS_PT_ComponentsPanel(bpy.types.Panel):
|
|||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
name = context.object.name if context.object != None else ''
|
name = ""
|
||||||
layout.label(text="Components For "+ name)
|
target_type = ""
|
||||||
|
object = next(iter(context.selected_objects), None)
|
||||||
|
collection = context.collection
|
||||||
|
if object is not None:
|
||||||
|
name = object.name
|
||||||
|
target_type = "Object"
|
||||||
|
elif collection is not None:
|
||||||
|
name = collection.name
|
||||||
|
target_type = "Collection"
|
||||||
|
# name = context.object.name if context.object != None else ''
|
||||||
|
layout.label(text=f"Components for {name} ({target_type})")
|
||||||
|
|
||||||
|
print("object", context.object, "active", context.active_object, "objects", context.selected_objects)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
object = context.object
|
object = next(iter(context.selected_objects), None)
|
||||||
|
collection = context.collection
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
# we get & load our component registry
|
# we get & load our component registry
|
||||||
@ -171,109 +185,118 @@ class BEVY_COMPONENTS_PT_ComponentsPanel(bpy.types.Panel):
|
|||||||
registry_has_type_infos = registry.has_type_infos()
|
registry_has_type_infos = registry.has_type_infos()
|
||||||
|
|
||||||
if object is not None:
|
if object is not None:
|
||||||
row = layout.row(align=True)
|
draw_component_ui(layout, object, registry, available_components, registry_has_type_infos, context)
|
||||||
row.prop(available_components, "list", text="Component")
|
elif collection is not None:
|
||||||
row.prop(available_components, "filter",text="Filter")
|
draw_component_ui(layout, collection, registry, available_components, registry_has_type_infos, context)
|
||||||
|
|
||||||
# add components
|
|
||||||
row = layout.row(align=True)
|
|
||||||
op = row.operator(AddComponentOperator.bl_idname, text="Add", icon="ADD")
|
|
||||||
op.component_type = available_components.list
|
|
||||||
row.enabled = available_components.list != ''
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
|
|
||||||
# paste components
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.operator(PasteComponentOperator.bl_idname, text="Paste component ("+bpy.context.window_manager.copied_source_component_name+")", icon="PASTEDOWN")
|
|
||||||
row.enabled = registry_has_type_infos and context.window_manager.copied_source_object != ''
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
|
|
||||||
# upgrate custom props to components
|
|
||||||
upgradeable_customProperties = registry.has_type_infos() and do_object_custom_properties_have_missing_metadata(context.object)
|
|
||||||
if upgradeable_customProperties:
|
|
||||||
row = layout.row(align=True)
|
|
||||||
op = row.operator(GenerateComponent_From_custom_property_Operator.bl_idname, text="generate components from custom properties" , icon="LOOP_FORWARDS")
|
|
||||||
layout.separator()
|
|
||||||
|
|
||||||
|
|
||||||
components_in_object = object.components_meta.components
|
|
||||||
#print("components_names", dict(components_bla).keys())
|
|
||||||
|
|
||||||
for component_name in sorted(get_bevy_components(object)) : # sorted by component name, practical
|
|
||||||
#print("component_name", component_name)
|
|
||||||
if component_name == "components_meta":
|
|
||||||
continue
|
|
||||||
# anything withouth metadata gets skipped, we only want to see real components, not all custom props
|
|
||||||
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None)
|
|
||||||
if component_meta == None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
component_invalid = getattr(component_meta, "invalid")
|
|
||||||
invalid_details = getattr(component_meta, "invalid_details")
|
|
||||||
component_visible = getattr(component_meta, "visible")
|
|
||||||
single_field = False
|
|
||||||
|
|
||||||
# our whole row
|
|
||||||
box = layout.box()
|
|
||||||
row = box.row(align=True)
|
|
||||||
# "header"
|
|
||||||
row.alert = component_invalid
|
|
||||||
row.prop(component_meta, "enabled", text="")
|
|
||||||
row.label(text=component_name)
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
if root_propertyGroup_name:
|
|
||||||
propertyGroup = getattr(component_meta, root_propertyGroup_name, None)
|
|
||||||
"""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
|
|
||||||
prop_group_location = box.row(align=True).column()
|
|
||||||
"""if single_field:
|
|
||||||
prop_group_location = row.column(align=True)#.split(factor=0.9)#layout.row(align=False)"""
|
|
||||||
|
|
||||||
if component_visible:
|
|
||||||
if component_invalid:
|
|
||||||
error_message = invalid_details if component_invalid else "Missing component UI data, please reload registry !"
|
|
||||||
prop_group_location.label(text=error_message)
|
|
||||||
draw_propertyGroup(propertyGroup, prop_group_location, [root_propertyGroup_name], component_name)
|
|
||||||
else :
|
|
||||||
row.label(text="details hidden, click on toggle to display")
|
|
||||||
else:
|
|
||||||
error_message = invalid_details if component_invalid else "Missing component UI data, please reload registry !"
|
|
||||||
row.label(text=error_message)
|
|
||||||
|
|
||||||
# "footer" with additional controls
|
|
||||||
if component_invalid:
|
|
||||||
if root_propertyGroup_name:
|
|
||||||
propertyGroup = getattr(component_meta, root_propertyGroup_name, None)
|
|
||||||
if propertyGroup:
|
|
||||||
unit_struct = len(propertyGroup.field_names) == 0
|
|
||||||
if unit_struct:
|
|
||||||
op = row.operator(Fix_Component_Operator.bl_idname, text="", icon="SHADERFX")
|
|
||||||
op.component_name = component_name
|
|
||||||
row.separator()
|
|
||||||
|
|
||||||
op = row.operator(RemoveComponentOperator.bl_idname, text="", icon="X")
|
|
||||||
op.component_name = component_name
|
|
||||||
row.separator()
|
|
||||||
|
|
||||||
op = row.operator(CopyComponentOperator.bl_idname, text="", icon="COPYDOWN")
|
|
||||||
op.source_component_name = component_name
|
|
||||||
op.source_object_name = object.name
|
|
||||||
row.separator()
|
|
||||||
|
|
||||||
#if not single_field:
|
|
||||||
toggle_icon = "TRIA_DOWN" if component_visible else "TRIA_RIGHT"
|
|
||||||
op = row.operator(Toggle_ComponentVisibility.bl_idname, text="", icon=toggle_icon)
|
|
||||||
op.component_name = component_name
|
|
||||||
#row.separator()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
layout.label(text ="Select an object to edit its components")
|
layout.label(text ="Select an object to edit its components")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def draw_component_ui(layout, object_or_collection, registry, available_components, registry_has_type_infos, context):
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(available_components, "list", text="Component")
|
||||||
|
row.prop(available_components, "filter",text="Filter")
|
||||||
|
|
||||||
|
# add components
|
||||||
|
row = layout.row(align=True)
|
||||||
|
op = row.operator(AddComponentOperator.bl_idname, text="Add", icon="ADD")
|
||||||
|
op.component_type = available_components.list
|
||||||
|
row.enabled = available_components.list != ''
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
# paste components
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.operator(PasteComponentOperator.bl_idname, text="Paste component ("+bpy.context.window_manager.copied_source_component_name+")", icon="PASTEDOWN")
|
||||||
|
row.enabled = registry_has_type_infos and context.window_manager.copied_source_item_name != ''
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
# upgrate custom props to components
|
||||||
|
upgradeable_customProperties = registry.has_type_infos() and do_item_custom_properties_have_missing_metadata(object_or_collection)
|
||||||
|
if upgradeable_customProperties:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
op = row.operator(GenerateComponent_From_custom_property_Operator.bl_idname, text="generate components from custom properties" , icon="LOOP_FORWARDS")
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
|
||||||
|
components_in_object = object_or_collection.components_meta.components
|
||||||
|
#print("components_names", dict(components_bla).keys())
|
||||||
|
|
||||||
|
for component_name in sorted(get_bevy_components(object_or_collection)) : # sorted by component name, practical
|
||||||
|
#print("component_name", component_name)
|
||||||
|
if component_name == "components_meta":
|
||||||
|
continue
|
||||||
|
# anything withouth metadata gets skipped, we only want to see real components, not all custom props
|
||||||
|
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None)
|
||||||
|
if component_meta == None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
component_invalid = getattr(component_meta, "invalid")
|
||||||
|
invalid_details = getattr(component_meta, "invalid_details")
|
||||||
|
component_visible = getattr(component_meta, "visible")
|
||||||
|
single_field = False
|
||||||
|
|
||||||
|
# our whole row
|
||||||
|
box = layout.box()
|
||||||
|
row = box.row(align=True)
|
||||||
|
# "header"
|
||||||
|
row.alert = component_invalid
|
||||||
|
row.prop(component_meta, "enabled", text="")
|
||||||
|
row.label(text=component_name)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
if root_propertyGroup_name:
|
||||||
|
propertyGroup = getattr(component_meta, root_propertyGroup_name, None)
|
||||||
|
"""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
|
||||||
|
prop_group_location = box.row(align=True).column()
|
||||||
|
"""if single_field:
|
||||||
|
prop_group_location = row.column(align=True)#.split(factor=0.9)#layout.row(align=False)"""
|
||||||
|
|
||||||
|
if component_visible:
|
||||||
|
if component_invalid:
|
||||||
|
error_message = invalid_details if component_invalid else "Missing component UI data, please reload registry !"
|
||||||
|
prop_group_location.label(text=error_message)
|
||||||
|
draw_propertyGroup(propertyGroup, prop_group_location, [root_propertyGroup_name], component_name)
|
||||||
|
else :
|
||||||
|
row.label(text="details hidden, click on toggle to display")
|
||||||
|
else:
|
||||||
|
error_message = invalid_details if component_invalid else "Missing component UI data, please reload registry !"
|
||||||
|
row.label(text=error_message)
|
||||||
|
|
||||||
|
# "footer" with additional controls
|
||||||
|
if component_invalid:
|
||||||
|
if root_propertyGroup_name:
|
||||||
|
propertyGroup = getattr(component_meta, root_propertyGroup_name, None)
|
||||||
|
if propertyGroup:
|
||||||
|
unit_struct = len(propertyGroup.field_names) == 0
|
||||||
|
if unit_struct:
|
||||||
|
op = row.operator(Fix_Component_Operator.bl_idname, text="", icon="SHADERFX")
|
||||||
|
op.component_name = component_name
|
||||||
|
row.separator()
|
||||||
|
|
||||||
|
op = row.operator(RemoveComponentOperator.bl_idname, 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(CopyComponentOperator.bl_idname, 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"
|
||||||
|
op = row.operator(Toggle_ComponentVisibility.bl_idname, text="", icon=toggle_icon)
|
||||||
|
op.component_name = component_name
|
||||||
|
#row.separator()
|
@ -1,30 +1,30 @@
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from .conversions_from_prop_group import property_group_value_to_custom_property_value
|
from .conversions_from_prop_group import property_group_value_to_custom_property_value
|
||||||
from .process_component import process_component
|
from .process_component import process_component
|
||||||
from .utils import update_calback_helper
|
from .utils import update_calback_helper
|
||||||
|
from ..utils import get_selected_object_or_collection
|
||||||
|
|
||||||
import json
|
import json
|
||||||
## main callback function, fired whenever any property changes, no matter the nesting level
|
## main callback function, fired whenever any property changes, no matter the nesting level
|
||||||
def update_component(self, context, definition, component_name):
|
def update_component(self, context, definition, component_name):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
current_object = bpy.context.object
|
|
||||||
update_disabled = current_object["__disable__update"] if "__disable__update" in current_object else False
|
current_object_or_collection = get_selected_object_or_collection(context)
|
||||||
|
update_disabled = current_object_or_collection["__disable__update"] if "__disable__update" in current_object_or_collection else False
|
||||||
update_disabled = registry.disable_all_object_updates or update_disabled # global settings
|
update_disabled = registry.disable_all_object_updates or update_disabled # global settings
|
||||||
if update_disabled:
|
if update_disabled:
|
||||||
return
|
return
|
||||||
print("")
|
components_in_object = current_object_or_collection.components_meta.components
|
||||||
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["long_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:
|
if component_meta != None:
|
||||||
property_group_name = registry.get_propertyGroupName_from_longName(component_name)
|
property_group_name = registry.get_propertyGroupName_from_longName(component_name)
|
||||||
property_group = getattr(component_meta, property_group_name)
|
property_group = getattr(component_meta, property_group_name)
|
||||||
# we use our helper to set the values
|
# we use our helper to set the values
|
||||||
object = context.object
|
previous = json.loads(current_object_or_collection['bevy_components'])
|
||||||
previous = json.loads(object['bevy_components'])
|
|
||||||
previous[component_name] = property_group_value_to_custom_property_value(property_group, definition, registry, None)
|
previous[component_name] = property_group_value_to_custom_property_value(property_group, definition, registry, None)
|
||||||
object['bevy_components'] = json.dumps(previous)
|
current_object_or_collection['bevy_components'] = json.dumps(previous)
|
||||||
|
|
||||||
|
|
||||||
def generate_propertyGroups_for_components():
|
def generate_propertyGroups_for_components():
|
||||||
|
@ -6,7 +6,7 @@ from bpy_extras.io_utils import ImportHelper
|
|||||||
|
|
||||||
from ...settings import upsert_settings
|
from ...settings import upsert_settings
|
||||||
|
|
||||||
from ..components.metadata import apply_customProperty_values_to_object_propertyGroups, apply_propertyGroup_values_to_object_customProperties, ensure_metadata_for_all_objects
|
from ..components.metadata import apply_customProperty_values_to_item_propertyGroups, apply_propertyGroup_values_to_item_customProperties, ensure_metadata_for_all_items
|
||||||
from ..propGroups.prop_groups import generate_propertyGroups_for_components
|
from ..propGroups.prop_groups import generate_propertyGroups_for_components
|
||||||
|
|
||||||
class ReloadRegistryOperator(Operator):
|
class ReloadRegistryOperator(Operator):
|
||||||
@ -27,7 +27,7 @@ class ReloadRegistryOperator(Operator):
|
|||||||
print("")
|
print("")
|
||||||
print("")
|
print("")
|
||||||
print("")
|
print("")
|
||||||
ensure_metadata_for_all_objects()
|
ensure_metadata_for_all_items()
|
||||||
|
|
||||||
# now force refresh the ui
|
# now force refresh the ui
|
||||||
for area in context.screen.areas:
|
for area in context.screen.areas:
|
||||||
@ -57,7 +57,7 @@ class COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL(Operator):
|
|||||||
total = len(bpy.data.objects)
|
total = len(bpy.data.objects)
|
||||||
|
|
||||||
for index, object in enumerate(bpy.data.objects):
|
for index, object in enumerate(bpy.data.objects):
|
||||||
apply_propertyGroup_values_to_object_customProperties(object)
|
apply_propertyGroup_values_to_item_customProperties(object)
|
||||||
progress = index / total
|
progress = index / total
|
||||||
context.window_manager.custom_properties_from_components_progress_all = progress
|
context.window_manager.custom_properties_from_components_progress_all = progress
|
||||||
# now force refresh the ui
|
# now force refresh the ui
|
||||||
@ -86,7 +86,7 @@ class COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT(Operator):
|
|||||||
context.window_manager.custom_properties_from_components_progress = 0.5
|
context.window_manager.custom_properties_from_components_progress = 0.5
|
||||||
# now force refresh the ui
|
# now force refresh the ui
|
||||||
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
||||||
apply_propertyGroup_values_to_object_customProperties(object)
|
apply_propertyGroup_values_to_item_customProperties(object)
|
||||||
|
|
||||||
context.window_manager.custom_properties_from_components_progress = -1.0
|
context.window_manager.custom_properties_from_components_progress = -1.0
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
@ -111,7 +111,7 @@ class COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT(Operator):
|
|||||||
object = context.object
|
object = context.object
|
||||||
error = False
|
error = False
|
||||||
try:
|
try:
|
||||||
apply_customProperty_values_to_object_propertyGroups(object)
|
apply_customProperty_values_to_item_propertyGroups(object)
|
||||||
progress = 0.5
|
progress = 0.5
|
||||||
context.window_manager.components_from_custom_properties_progress = progress
|
context.window_manager.components_from_custom_properties_progress = progress
|
||||||
try:
|
try:
|
||||||
@ -153,7 +153,7 @@ class COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL(Operator):
|
|||||||
for index, object in enumerate(bpy.data.objects):
|
for index, object in enumerate(bpy.data.objects):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
apply_customProperty_values_to_object_propertyGroups(object)
|
apply_customProperty_values_to_item_propertyGroups(object)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
|
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
|
||||||
errors.append( "object: '" + object.name + "', error: " + str(error))
|
errors.append( "object: '" + object.name + "', error: " + str(error))
|
||||||
|
@ -8,7 +8,7 @@ from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorP
|
|||||||
|
|
||||||
from ...settings import load_settings
|
from ...settings import load_settings
|
||||||
from ..propGroups.prop_groups import generate_propertyGroups_for_components
|
from ..propGroups.prop_groups import generate_propertyGroups_for_components
|
||||||
from ..components.metadata import ComponentMetadata, ensure_metadata_for_all_objects
|
from ..components.metadata import ComponentMetadata, ensure_metadata_for_all_items
|
||||||
|
|
||||||
# helper class to store missing bevy types information
|
# helper class to store missing bevy types information
|
||||||
class MissingBevyType(bpy.types.PropertyGroup):
|
class MissingBevyType(bpy.types.PropertyGroup):
|
||||||
@ -286,7 +286,7 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
self.schemaPath = settings["components_schemaPath"]
|
self.schemaPath = settings["components_schemaPath"]
|
||||||
self.load_schema()
|
self.load_schema()
|
||||||
generate_propertyGroups_for_components()
|
generate_propertyGroups_for_components()
|
||||||
ensure_metadata_for_all_objects()
|
ensure_metadata_for_all_items()
|
||||||
|
|
||||||
|
|
||||||
# we keep a list of component propertyGroup around
|
# we keep a list of component propertyGroup around
|
||||||
|
@ -3,7 +3,7 @@ import bpy
|
|||||||
from bpy_types import (UIList)
|
from bpy_types import (UIList)
|
||||||
from bpy.props import (StringProperty)
|
from bpy.props import (StringProperty)
|
||||||
|
|
||||||
from ..components.operators import OT_rename_component, RemoveComponentFromAllObjectsOperator, RemoveComponentOperator
|
from ..components.operators import OT_rename_component, RemoveComponentFromAllItemsOperator, RemoveComponentOperator
|
||||||
from .operators import(
|
from .operators import(
|
||||||
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL,
|
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL,
|
||||||
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT,
|
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT,
|
||||||
@ -197,7 +197,7 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
|
|||||||
col = row.column()
|
col = row.column()
|
||||||
remove_components_progress = context.window_manager.components_remove_progress
|
remove_components_progress = context.window_manager.components_remove_progress
|
||||||
if remove_components_progress == -1.0:
|
if remove_components_progress == -1.0:
|
||||||
operator = row.operator(RemoveComponentFromAllObjectsOperator.bl_idname, text="", icon="X")
|
operator = row.operator(RemoveComponentFromAllItemsOperator.bl_idname, text="", icon="X")
|
||||||
operator.component_name = context.window_manager.bevy_component_rename_helper.original_name
|
operator.component_name = context.window_manager.bevy_component_rename_helper.original_name
|
||||||
col.enabled = registry_has_type_infos and original_name != ""
|
col.enabled = registry_has_type_infos and original_name != ""
|
||||||
else:
|
else:
|
||||||
|
18
tools/blenvy/bevy_components/utils.py
Normal file
18
tools/blenvy/bevy_components/utils.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import bpy
|
||||||
|
|
||||||
|
#FIXME: does not work if object is hidden !!
|
||||||
|
def get_selected_object_or_collection(context):
|
||||||
|
target = None
|
||||||
|
object = next(iter(context.selected_objects), None)
|
||||||
|
collection = context.collection
|
||||||
|
if object is not None:
|
||||||
|
target = object
|
||||||
|
elif collection is not None:
|
||||||
|
target = collection
|
||||||
|
return target
|
||||||
|
|
||||||
|
def get_selection_type(selection):
|
||||||
|
if isinstance(selection, bpy.types.Object):
|
||||||
|
return 'Object'
|
||||||
|
if isinstance(selection, bpy.types.Collection):
|
||||||
|
return 'Collection'
|
@ -44,21 +44,10 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||||||
library_scene_active = False
|
library_scene_active = False
|
||||||
active_collection = context.collection
|
active_collection = context.collection
|
||||||
|
|
||||||
print("BLA", blenvy.assets_path_full)
|
"""print("BLA", blenvy.assets_path_full)
|
||||||
print("BLA", blenvy.blueprints_path_full)
|
print("BLA", blenvy.blueprints_path_full)
|
||||||
print("BLA", blenvy.levels_path_full)
|
print("BLA", blenvy.levels_path_full)
|
||||||
print("BLA", blenvy.materials_path_full)
|
print("BLA", blenvy.materials_path_full)"""
|
||||||
|
|
||||||
"""current_auto_settings = load_settings(".gltf_auto_export_settings")
|
|
||||||
current_gltf_settings = load_settings(".gltf_auto_export_gltf_settings")
|
|
||||||
|
|
||||||
if current_auto_settings is not None:
|
|
||||||
#print("current_auto_settings", current_auto_settings)
|
|
||||||
main_scene_names = current_auto_settings["main_scene_names"]
|
|
||||||
library_scene_names = current_auto_settings["library_scene_names"]
|
|
||||||
|
|
||||||
world_scene_active = context.scene.name in main_scene_names
|
|
||||||
library_scene_active = context.scene.name in library_scene_names"""
|
|
||||||
|
|
||||||
# Now to actual drawing of the UI
|
# Now to actual drawing of the UI
|
||||||
target = row.box() if active_mode == 'COMPONENTS' else row
|
target = row.box() if active_mode == 'COMPONENTS' else row
|
||||||
@ -103,8 +92,6 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||||||
draw_folder_browser(layout=row, label="Materials Folder", prop_origin=blenvy, target_property="materials_path")
|
draw_folder_browser(layout=row, label="Materials Folder", prop_origin=blenvy, target_property="materials_path")
|
||||||
|
|
||||||
panel.separator()
|
panel.separator()
|
||||||
|
|
||||||
|
|
||||||
# scenes selection
|
# scenes selection
|
||||||
if len(blenvy.main_scenes) == 0 and len(blenvy.library_scenes) == 0:
|
if len(blenvy.main_scenes) == 0 and len(blenvy.library_scenes) == 0:
|
||||||
row = panel.row()
|
row = panel.row()
|
||||||
@ -114,7 +101,6 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||||||
row = panel.row()
|
row = panel.row()
|
||||||
row.label(text="Please select and add one using the UI below")
|
row.label(text="Please select and add one using the UI below")
|
||||||
|
|
||||||
|
|
||||||
section = panel
|
section = panel
|
||||||
rows = 2
|
rows = 2
|
||||||
row = section.row()
|
row = section.row()
|
||||||
|
@ -13,9 +13,10 @@ def cleanup_file():
|
|||||||
|
|
||||||
def gltf_post_export_callback(data):
|
def gltf_post_export_callback(data):
|
||||||
#print("post_export", data)
|
#print("post_export", data)
|
||||||
|
blenvy = bpy.context.window_manager.blenvy
|
||||||
bpy.context.window_manager.auto_export_tracker.export_finished()
|
bpy.context.window_manager.auto_export_tracker.export_finished()
|
||||||
|
|
||||||
gltf_settings_backup = bpy.context.window_manager.gltf_settings_backup
|
gltf_settings_backup = blenvy.auto_export.gltf_settings_backup
|
||||||
gltf_filepath = data["gltf_filepath"]
|
gltf_filepath = data["gltf_filepath"]
|
||||||
gltf_export_id = data['gltf_export_id']
|
gltf_export_id = data['gltf_export_id']
|
||||||
if gltf_export_id == "gltf_auto_export":
|
if gltf_export_id == "gltf_auto_export":
|
||||||
@ -30,7 +31,7 @@ def gltf_post_export_callback(data):
|
|||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
if "glTF2ExportSettings" in scene:
|
if "glTF2ExportSettings" in scene:
|
||||||
settings = scene["glTF2ExportSettings"]
|
settings = scene["glTF2ExportSettings"]
|
||||||
export_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
# now write new settings
|
# now write new settings
|
||||||
export_settings.clear()
|
export_settings.clear()
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ def gltf_post_export_callback(data):
|
|||||||
else:
|
else:
|
||||||
if "glTF2ExportSettings" in scene:
|
if "glTF2ExportSettings" in scene:
|
||||||
del scene["glTF2ExportSettings"]
|
del scene["glTF2ExportSettings"]
|
||||||
bpy.context.window_manager.gltf_settings_backup = ""
|
blenvy.auto_export.gltf_settings_backup = ""
|
||||||
|
|
||||||
# the absurd length one has to go through to RESET THE OPERATOR because it has global state !!!!! AAAAAHHH
|
# the absurd length one has to go through to RESET THE OPERATOR because it has global state !!!!! AAAAAHHH
|
||||||
last_operator = bpy.context.window_manager.auto_export_tracker.last_operator
|
last_operator = bpy.context.window_manager.auto_export_tracker.last_operator
|
||||||
|
@ -2,7 +2,7 @@ import bpy
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
def get_standard_exporter_settings():
|
def get_standard_exporter_settings():
|
||||||
standard_gltf_exporter_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else None
|
standard_gltf_exporter_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else None
|
||||||
if standard_gltf_exporter_settings != None:
|
if standard_gltf_exporter_settings != None:
|
||||||
try:
|
try:
|
||||||
standard_gltf_exporter_settings = json.loads(standard_gltf_exporter_settings.as_string())
|
standard_gltf_exporter_settings = json.loads(standard_gltf_exporter_settings.as_string())
|
||||||
|
@ -135,10 +135,10 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||||||
return True
|
return True
|
||||||
# compare both the auto export settings & the gltf settings
|
# compare both the auto export settings & the gltf settings
|
||||||
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else None
|
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else None
|
||||||
previous_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings_previous"] if ".gltf_auto_export_gltf_settings_previous" in bpy.data.texts else None
|
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else None
|
||||||
|
|
||||||
current_auto_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else None
|
current_auto_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else None
|
||||||
current_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else None
|
current_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else None
|
||||||
|
|
||||||
#check if params have changed
|
#check if params have changed
|
||||||
|
|
||||||
@ -149,10 +149,10 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||||||
changed = True
|
changed = True
|
||||||
elif previous_gltf_settings == None:
|
elif previous_gltf_settings == None:
|
||||||
#print("previous gltf settings missing, exporting")
|
#print("previous gltf settings missing, exporting")
|
||||||
previous_gltf_settings = bpy.data.texts.new(".gltf_auto_export_gltf_settings_previous")
|
previous_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings_previous")
|
||||||
previous_gltf_settings.write(json.dumps({}))
|
previous_gltf_settings.write(json.dumps({}))
|
||||||
if current_gltf_settings == None:
|
if current_gltf_settings == None:
|
||||||
current_gltf_settings = bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
current_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
current_gltf_settings.write(json.dumps({}))
|
current_gltf_settings.write(json.dumps({}))
|
||||||
|
|
||||||
changed = True
|
changed = True
|
||||||
@ -177,7 +177,7 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||||||
previous_auto_settings.write(current_auto_settings.as_string()) # TODO : check if this is always valid
|
previous_auto_settings.write(current_auto_settings.as_string()) # TODO : check if this is always valid
|
||||||
|
|
||||||
if current_gltf_settings != None:
|
if current_gltf_settings != None:
|
||||||
previous_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings_previous"] if ".gltf_auto_export_gltf_settings_previous" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings_previous")
|
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings_previous")
|
||||||
previous_gltf_settings.clear()
|
previous_gltf_settings.clear()
|
||||||
previous_gltf_settings.write(current_gltf_settings.as_string())
|
previous_gltf_settings.write(current_gltf_settings.as_string())
|
||||||
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
import bpy
|
||||||
|
|
||||||
|
from .project_diff import get_changes_per_scene, project_diff, serialize_current
|
||||||
|
from ...settings import are_settings_identical
|
||||||
|
from .auto_export import auto_export
|
||||||
|
from .settings_diff import get_setting_changes
|
||||||
|
|
||||||
|
# prepare export by gather the changes to the scenes & settings
|
||||||
|
def prepare_and_export():
|
||||||
|
blenvy = bpy.context.window_manager.blenvy
|
||||||
|
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||||
|
auto_export_settings = blenvy.auto_export
|
||||||
|
if auto_export_settings.auto_export: # only do the actual exporting if auto export is actually enabled
|
||||||
|
|
||||||
|
# determine changed objects
|
||||||
|
per_scene_changes = get_changes_per_scene()
|
||||||
|
# determine changed parameters
|
||||||
|
setting_changes = get_setting_changes()
|
||||||
|
# do the actual export
|
||||||
|
auto_export(per_scene_changes, setting_changes, blenvy)
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
# TODO: these are likely obsolete
|
||||||
|
# reset the list of changes in the tracker
|
||||||
|
bpy.context.window_manager.auto_export_tracker.clear_changes()
|
||||||
|
print("AUTO EXPORT DONE")
|
||||||
|
bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=0.1)
|
@ -22,7 +22,8 @@ def foo():
|
|||||||
previous_stored.clear()
|
previous_stored.clear()
|
||||||
previous_stored.write(json.dumps(current))
|
previous_stored.write(json.dumps(current))
|
||||||
|
|
||||||
def project_diff(previous, current):
|
|
||||||
|
def serialize_current():
|
||||||
# sigh... you need to save & reset the frame otherwise it saves the values AT THE CURRENT FRAME WHICH CAN DIFFER ACROSS SCENES
|
# sigh... you need to save & reset the frame otherwise it saves the values AT THE CURRENT FRAME WHICH CAN DIFFER ACROSS SCENES
|
||||||
current_frames = [scene.frame_current for scene in bpy.data.scenes]
|
current_frames = [scene.frame_current for scene in bpy.data.scenes]
|
||||||
for scene in bpy.data.scenes:
|
for scene in bpy.data.scenes:
|
||||||
@ -40,10 +41,35 @@ def project_diff(previous, current):
|
|||||||
for (index, scene) in enumerate(bpy.data.scenes):
|
for (index, scene) in enumerate(bpy.data.scenes):
|
||||||
scene.frame_set(int(current_frames[index]))
|
scene.frame_set(int(current_frames[index]))
|
||||||
|
|
||||||
|
return current
|
||||||
|
|
||||||
|
def get_changes_per_scene():
|
||||||
|
current = serialize_current()
|
||||||
|
|
||||||
|
previous_stored = bpy.data.texts[".blenvy.project.serialized"] if ".blenvy.project.serialized" in bpy.data.texts else None
|
||||||
|
if previous_stored == None:
|
||||||
|
previous_stored = bpy.data.texts.new(".blenvy.project.serialized")
|
||||||
|
previous_stored.write(json.dumps(current))
|
||||||
|
return {}
|
||||||
|
|
||||||
|
previous = json.loads(previous_stored.as_string())
|
||||||
|
|
||||||
|
# determin changes
|
||||||
|
changes_per_scene = project_diff(previous, current)
|
||||||
|
|
||||||
|
# save the current project as previous
|
||||||
|
previous_stored.clear()
|
||||||
|
previous_stored.write(json.dumps(current))
|
||||||
|
return changes_per_scene
|
||||||
|
|
||||||
|
|
||||||
|
def project_diff(previous, current):
|
||||||
|
|
||||||
changes_per_scene = {}
|
changes_per_scene = {}
|
||||||
|
|
||||||
# TODO : how do we deal with changed scene names ???
|
# TODO : how do we deal with changed scene names ???
|
||||||
for scene in current:
|
for scene in current:
|
||||||
|
print("SCENE", scene)
|
||||||
previous_object_names = list(previous[scene].keys())
|
previous_object_names = list(previous[scene].keys())
|
||||||
current_object_names =list(current[scene].keys())
|
current_object_names =list(current[scene].keys())
|
||||||
added = list(set(current_object_names) - set(previous_object_names))
|
added = list(set(current_object_names) - set(previous_object_names))
|
85
tools/blenvy/gltf_auto_export/auto_export/settings_diff.py
Normal file
85
tools/blenvy/gltf_auto_export/auto_export/settings_diff.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import bpy
|
||||||
|
|
||||||
|
from ...settings import are_settings_identical, load_settings
|
||||||
|
|
||||||
|
# which settings are specific to auto_export # TODO: can we infer this ?
|
||||||
|
auto_export_parameter_names = [
|
||||||
|
'project_root_path',
|
||||||
|
'assets_path',
|
||||||
|
'blueprints_path',
|
||||||
|
'levels_path',
|
||||||
|
'materials_path',
|
||||||
|
#'main_scene_names',
|
||||||
|
#'library_scene_names',
|
||||||
|
|
||||||
|
'export_scene_settings',
|
||||||
|
'export_blueprints',
|
||||||
|
'export_separate_dynamic_and_static_objects',
|
||||||
|
'export_materials_library',
|
||||||
|
'collection_instances_combine_mode',
|
||||||
|
'export_marked_assets'
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_setting_changes():
|
||||||
|
previous_gltf_settings = load_settings(".blenvy_gltf_settings_previous")
|
||||||
|
current_gltf_settings = load_settings(".blenvy_gltf_settings")
|
||||||
|
gltf_settings_changed = not are_settings_identical(previous_gltf_settings, current_gltf_settings)
|
||||||
|
|
||||||
|
previous_export_settings = load_settings(".blenvy_export_settings_previous")
|
||||||
|
current_export_settings = load_settings(".blenvy_export_settings")
|
||||||
|
auto_export_settings_changed = not are_settings_identical(previous_export_settings, current_export_settings)
|
||||||
|
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def did_export_settings_change(self):
|
||||||
|
return True
|
||||||
|
# compare both the auto export settings & the gltf settings
|
||||||
|
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else None
|
||||||
|
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else None
|
||||||
|
|
||||||
|
current_auto_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else None
|
||||||
|
current_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else None
|
||||||
|
|
||||||
|
#check if params have changed
|
||||||
|
|
||||||
|
# if there were no setting before, it is new, we need export
|
||||||
|
changed = False
|
||||||
|
if previous_auto_settings == None:
|
||||||
|
#print("previous settings missing, exporting")
|
||||||
|
changed = True
|
||||||
|
elif previous_gltf_settings == None:
|
||||||
|
#print("previous gltf settings missing, exporting")
|
||||||
|
previous_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings_previous")
|
||||||
|
previous_gltf_settings.write(json.dumps({}))
|
||||||
|
if current_gltf_settings == None:
|
||||||
|
current_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
|
current_gltf_settings.write(json.dumps({}))
|
||||||
|
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
auto_settings_changed = sorted(json.loads(previous_auto_settings.as_string()).items()) != sorted(json.loads(current_auto_settings.as_string()).items()) if current_auto_settings != None else False
|
||||||
|
gltf_settings_changed = sorted(json.loads(previous_gltf_settings.as_string()).items()) != sorted(json.loads(current_gltf_settings.as_string()).items()) if current_gltf_settings != None else False
|
||||||
|
|
||||||
|
"""print("auto settings previous", sorted(json.loads(previous_auto_settings.as_string()).items()))
|
||||||
|
print("auto settings current", sorted(json.loads(current_auto_settings.as_string()).items()))
|
||||||
|
print("auto_settings_changed", auto_settings_changed)
|
||||||
|
|
||||||
|
print("gltf settings previous", sorted(json.loads(previous_gltf_settings.as_string()).items()))
|
||||||
|
print("gltf settings current", sorted(json.loads(current_gltf_settings.as_string()).items()))
|
||||||
|
print("gltf_settings_changed", gltf_settings_changed)"""
|
||||||
|
|
||||||
|
changed = auto_settings_changed or gltf_settings_changed
|
||||||
|
# now write the current settings to the "previous settings"
|
||||||
|
if current_auto_settings != None:
|
||||||
|
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings_previous")
|
||||||
|
previous_auto_settings.clear()
|
||||||
|
previous_auto_settings.write(current_auto_settings.as_string()) # TODO : check if this is always valid
|
||||||
|
|
||||||
|
if current_gltf_settings != None:
|
||||||
|
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings_previous")
|
||||||
|
previous_gltf_settings.clear()
|
||||||
|
previous_gltf_settings.write(current_gltf_settings.as_string())
|
||||||
|
|
||||||
|
return changed
|
@ -4,6 +4,8 @@ import bpy
|
|||||||
from bpy.types import (PropertyGroup)
|
from bpy.types import (PropertyGroup)
|
||||||
from bpy.props import (PointerProperty, IntProperty, StringProperty)
|
from bpy.props import (PointerProperty, IntProperty, StringProperty)
|
||||||
|
|
||||||
|
from .prepare_and_export import prepare_and_export
|
||||||
|
|
||||||
from ..constants import TEMPSCENE_PREFIX
|
from ..constants import TEMPSCENE_PREFIX
|
||||||
|
|
||||||
class AutoExportTracker(PropertyGroup):
|
class AutoExportTracker(PropertyGroup):
|
||||||
@ -51,9 +53,7 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
def save_handler(cls, scene, depsgraph):
|
def save_handler(cls, scene, depsgraph):
|
||||||
print("-------------")
|
print("-------------")
|
||||||
print("saved", bpy.data.filepath)
|
print("saved", bpy.data.filepath)
|
||||||
# auto_export(changes_per_scene, export_parameters_changed)
|
prepare_and_export()
|
||||||
bpy.ops.export_scenes.auto_gltf(direct_mode= True)
|
|
||||||
|
|
||||||
# (re)set a few things after exporting
|
# (re)set a few things after exporting
|
||||||
# reset wether the gltf export paramters were changed since the last save
|
# reset wether the gltf export paramters were changed since the last save
|
||||||
cls.export_params_changed = False
|
cls.export_params_changed = False
|
||||||
|
@ -228,6 +228,6 @@ def serialize_scene():
|
|||||||
print("")
|
print("")
|
||||||
print("data json", json.dumps(data))"""
|
print("data json", json.dumps(data))"""
|
||||||
|
|
||||||
return json.dumps(data)
|
return data # json.dumps(data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ def duplicate_object2(object, original_name):
|
|||||||
settings = scene["glTF2ExportSettings"]
|
settings = scene["glTF2ExportSettings"]
|
||||||
formatted_settings = dict(settings)
|
formatted_settings = dict(settings)
|
||||||
|
|
||||||
export_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
|
|
||||||
#check if params have changed
|
#check if params have changed
|
||||||
bpy.context.window_manager.gltf_settings_changed = sorted(json.loads(export_settings.as_string()).items()) != sorted(formatted_settings.items())
|
bpy.context.window_manager.gltf_settings_changed = sorted(json.loads(export_settings.as_string()).items()) != sorted(formatted_settings.items())
|
||||||
|
@ -71,3 +71,10 @@ class AutoExportSettings(PropertyGroup):
|
|||||||
description='Collections that have been marked as assets will be systematically exported, even if not in use in another scene',
|
description='Collections that have been marked as assets will be systematically exported, even if not in use in another scene',
|
||||||
default=True
|
default=True
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
# special property for gltf settings
|
||||||
|
gltf_settings_backup: StringProperty(
|
||||||
|
name="gltf settings backup",
|
||||||
|
description="backup for existing gltf settings so that we can restore them"
|
||||||
|
) # type: ignore
|
||||||
|
@ -91,7 +91,7 @@ def test_export_complex(setup_data):
|
|||||||
stored_auto_settings.write(json.dumps(export_props))
|
stored_auto_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
# and store settings for the gltf part
|
# and store settings for the gltf part
|
||||||
stored_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
stored_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
stored_gltf_settings.clear()
|
stored_gltf_settings.clear()
|
||||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
stored_gltf_settings.write(json.dumps(gltf_settings))
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ def test_export_external_blueprints(setup_data):
|
|||||||
stored_auto_settings.write(json.dumps(export_props))
|
stored_auto_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
# and store settings for the gltf part
|
# and store settings for the gltf part
|
||||||
stored_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
stored_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
stored_gltf_settings.clear()
|
stored_gltf_settings.clear()
|
||||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
stored_gltf_settings.write(json.dumps(gltf_settings))
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ def test_export_changed_parameters(setup_data):
|
|||||||
"export_optimize_animation_size": False
|
"export_optimize_animation_size": False
|
||||||
}
|
}
|
||||||
# and store settings for the gltf part
|
# and store settings for the gltf part
|
||||||
stored_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
stored_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
stored_gltf_settings.clear()
|
stored_gltf_settings.clear()
|
||||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
stored_gltf_settings.write(json.dumps(gltf_settings))
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ def test_export_changed_parameters(setup_data):
|
|||||||
"export_optimize_animation_size": True
|
"export_optimize_animation_size": True
|
||||||
}
|
}
|
||||||
|
|
||||||
stored_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
stored_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
stored_gltf_settings.clear()
|
stored_gltf_settings.clear()
|
||||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
stored_gltf_settings.write(json.dumps(gltf_settings))
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ def test_copy_paste_components(setup_data):
|
|||||||
setattr(propertyGroup, propertyGroup.field_names[0], 25.0)
|
setattr(propertyGroup, propertyGroup.field_names[0], 25.0)
|
||||||
|
|
||||||
copy_component_operator = bpy.ops.object.copy_bevy_component
|
copy_component_operator = bpy.ops.object.copy_bevy_component
|
||||||
copy_component_operator(source_component_name=long_name, source_object_name=object.name)
|
copy_component_operator(source_component_name=long_name, source_item_name=object.name)
|
||||||
|
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
# TARGET object
|
# TARGET object
|
||||||
|
@ -20,7 +20,7 @@ def prepare_auto_export(auto_export_overrides={}, gltf_export_settings = {"expor
|
|||||||
|
|
||||||
gltf_settings = gltf_export_settings
|
gltf_settings = gltf_export_settings
|
||||||
# and store settings for the gltf part
|
# and store settings for the gltf part
|
||||||
stored_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
stored_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||||
stored_gltf_settings.clear()
|
stored_gltf_settings.clear()
|
||||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
stored_gltf_settings.write(json.dumps(gltf_settings))
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import bpy
|
|||||||
import pprint
|
import pprint
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ..bevy_components.components.metadata import get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_object, upsert_bevy_component
|
from ..bevy_components.components.metadata import get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_item, upsert_bevy_component
|
||||||
|
|
||||||
from .setup_data import setup_data
|
from .setup_data import setup_data
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ def test_rename_component_single_unit_struct(setup_data):
|
|||||||
|
|
||||||
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name]))
|
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name]))
|
||||||
|
|
||||||
is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
|
is_old_component_in_object = is_bevy_component_in_item(object, source_component_name)
|
||||||
is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
|
is_new_component_in_object = is_bevy_component_in_item(object, target_component_name)
|
||||||
assert is_old_component_in_object == False
|
assert is_old_component_in_object == False
|
||||||
assert is_new_component_in_object == True
|
assert is_new_component_in_object == True
|
||||||
assert get_bevy_component_value_by_long_name(object, target_component_name) == '()'
|
assert get_bevy_component_value_by_long_name(object, target_component_name) == '()'
|
||||||
@ -60,8 +60,8 @@ def test_rename_component_single_complex_struct(setup_data):
|
|||||||
|
|
||||||
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name]))
|
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name]))
|
||||||
|
|
||||||
is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
|
is_old_component_in_object = is_bevy_component_in_item(object, source_component_name)
|
||||||
is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
|
is_new_component_in_object = is_bevy_component_in_item(object, target_component_name)
|
||||||
assert is_old_component_in_object == False
|
assert is_old_component_in_object == False
|
||||||
assert is_new_component_in_object == True
|
assert is_new_component_in_object == True
|
||||||
assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
|
assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
|
||||||
@ -86,8 +86,8 @@ def test_rename_component_bulk(setup_data):
|
|||||||
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps(objects_names))
|
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps(objects_names))
|
||||||
|
|
||||||
for object in bpy.data.objects:
|
for object in bpy.data.objects:
|
||||||
is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
|
is_old_component_in_object = is_bevy_component_in_item(object, source_component_name)
|
||||||
is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
|
is_new_component_in_object = is_bevy_component_in_item(object, target_component_name)
|
||||||
assert is_old_component_in_object == False
|
assert is_old_component_in_object == False
|
||||||
assert is_new_component_in_object == True
|
assert is_new_component_in_object == True
|
||||||
assert get_bevy_component_value_by_long_name(object, target_component_name) == '()'
|
assert get_bevy_component_value_by_long_name(object, target_component_name) == '()'
|
||||||
@ -113,8 +113,8 @@ def test_rename_component_single_error_handling(setup_data):
|
|||||||
|
|
||||||
target_component_metadata = get_component_metadata(object, target_component_name)
|
target_component_metadata = get_component_metadata(object, target_component_name)
|
||||||
|
|
||||||
is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
|
is_old_component_in_object = is_bevy_component_in_item(object, source_component_name)
|
||||||
is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
|
is_new_component_in_object = is_bevy_component_in_item(object, target_component_name)
|
||||||
assert is_old_component_in_object == False
|
assert is_old_component_in_object == False
|
||||||
assert is_new_component_in_object == True
|
assert is_new_component_in_object == True
|
||||||
assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
|
assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
|
||||||
@ -143,8 +143,8 @@ def test_rename_component_single_error_handling_clean_errors(setup_data):
|
|||||||
|
|
||||||
target_component_metadata = get_component_metadata(object, target_component_name)
|
target_component_metadata = get_component_metadata(object, target_component_name)
|
||||||
|
|
||||||
is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
|
is_old_component_in_object = is_bevy_component_in_item(object, source_component_name)
|
||||||
is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
|
is_new_component_in_object = is_bevy_component_in_item(object, target_component_name)
|
||||||
assert is_old_component_in_object == False
|
assert is_old_component_in_object == False
|
||||||
assert is_new_component_in_object == True
|
assert is_new_component_in_object == True
|
||||||
assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
|
assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
|
||||||
|
Loading…
Reference in New Issue
Block a user