mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-22 20:00:53 +00:00
Compare commits
2 Commits
0b5cdcc4a5
...
f9cb6de4bc
Author | SHA1 | Date | |
---|---|---|---|
|
f9cb6de4bc | ||
|
2b6e17a6b7 |
@ -74,7 +74,7 @@ Components:
|
|||||||
General things to solve:
|
General things to solve:
|
||||||
- [x] save settings
|
- [x] save settings
|
||||||
- [x] load settings
|
- [x] load settings
|
||||||
- [ ] add blueprints data
|
- [x] add blueprints data
|
||||||
|
|
||||||
- [x] rename all path stuff using the old naming convention : "blueprints_path_full"
|
- [x] rename all path stuff using the old naming convention : "blueprints_path_full"
|
||||||
- [x] generate the full paths directly when setting them in the UI
|
- [x] generate the full paths directly when setting them in the UI
|
||||||
@ -100,8 +100,12 @@ General issues:
|
|||||||
|
|
||||||
- [ ] force overwrite of settings files instead of partial updates ?
|
- [ ] force overwrite of settings files instead of partial updates ?
|
||||||
- [ ] add tests for disabled components
|
- [ ] add tests for disabled components
|
||||||
- [x] fix auto export workflow
|
- [x] fix auto export workflow
|
||||||
- [ ] should we write the previous _xxx data only AFTER a sucessfull export only ?
|
- [ ] should we write the previous _xxx data only AFTER a sucessfull export only ?
|
||||||
- [ ] add hashing of modifiers/ geometry nodes in serialize scene
|
- [x] add hashing of modifiers/ geometry nodes in serialize scene
|
||||||
- [ ] add ability to FORCE export specific blueprints & levels
|
- [ ] add ability to FORCE export specific blueprints & levels
|
||||||
- [ ] undo after a save removes any saved "serialized scene" data ? DIG into this
|
- [ ] undo after a save removes any saved "serialized scene" data ? DIG into this
|
||||||
|
- [ ] handle scene renames between saves (breaks diffing)
|
||||||
|
- [ ] change scene selector to work on actual scenes aka to deal with renamed scenes
|
||||||
|
- [x] fix asset file selection
|
||||||
|
- [x] change "assets" tab to "levels"/worlds tab & modify UI accordingly
|
@ -38,6 +38,10 @@ from .assets.ui import Blenvy_assets
|
|||||||
from .assets.assets_registry import Asset, AssetsRegistry
|
from .assets.assets_registry import Asset, AssetsRegistry
|
||||||
from .assets.operators import OT_Add_asset_filebrowser, OT_add_bevy_asset, OT_remove_bevy_asset, OT_test_bevy_assets
|
from .assets.operators import OT_Add_asset_filebrowser, OT_add_bevy_asset, OT_remove_bevy_asset, OT_test_bevy_assets
|
||||||
|
|
||||||
|
# levels management
|
||||||
|
from .levels.ui import Blenvy_levels
|
||||||
|
from .levels.operators import OT_select_level
|
||||||
|
|
||||||
# blueprints management
|
# blueprints management
|
||||||
from .blueprints.ui import GLTF_PT_auto_export_blueprints_list
|
from .blueprints.ui import GLTF_PT_auto_export_blueprints_list
|
||||||
from .blueprints.blueprints_registry import BlueprintsRegistry
|
from .blueprints.blueprints_registry import BlueprintsRegistry
|
||||||
@ -129,6 +133,9 @@ classes = [
|
|||||||
OT_Add_asset_filebrowser,
|
OT_Add_asset_filebrowser,
|
||||||
Blenvy_assets,
|
Blenvy_assets,
|
||||||
|
|
||||||
|
Blenvy_levels,
|
||||||
|
OT_select_level,
|
||||||
|
|
||||||
BlueprintsRegistry,
|
BlueprintsRegistry,
|
||||||
OT_select_blueprint,
|
OT_select_blueprint,
|
||||||
GLTF_PT_auto_export_blueprints_list,
|
GLTF_PT_auto_export_blueprints_list,
|
||||||
|
@ -4,21 +4,27 @@ from .serialize_scene import serialize_scene
|
|||||||
from blenvy.settings import load_settings, upsert_settings
|
from blenvy.settings import load_settings, upsert_settings
|
||||||
|
|
||||||
def bubble_up_changes(object, changes_per_scene):
|
def bubble_up_changes(object, changes_per_scene):
|
||||||
if object.parent:
|
if object is not None and object.parent:
|
||||||
changes_per_scene[object.parent.name] = bpy.data.objects[object.parent.name]
|
changes_per_scene[object.parent.name] = bpy.data.objects[object.parent.name]
|
||||||
bubble_up_changes(object.parent, changes_per_scene)
|
bubble_up_changes(object.parent, changes_per_scene)
|
||||||
|
|
||||||
|
import uuid
|
||||||
def serialize_current(settings):
|
def serialize_current(settings):
|
||||||
# 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:
|
||||||
scene.frame_set(0)
|
scene.frame_set(0)
|
||||||
|
if scene.id_test == '':
|
||||||
|
print("GENERATE ID")
|
||||||
|
scene.id_test = str(uuid.uuid4())
|
||||||
|
print("SCENE ID", scene.id_test)
|
||||||
|
|
||||||
current_scene = bpy.context.window.scene
|
current_scene = bpy.context.window.scene
|
||||||
bpy.context.window.scene = bpy.data.scenes[0]
|
bpy.context.window.scene = bpy.data.scenes[0]
|
||||||
#serialize scene at frame 0
|
#serialize scene at frame 0
|
||||||
"""with bpy.context.temp_override(scene=bpy.data.scenes[1]):
|
"""with bpy.context.temp_override(scene=bpy.data.scenes[1]):
|
||||||
bpy.context.scene.frame_set(0)"""
|
bpy.context.scene.frame_set(0)"""
|
||||||
|
|
||||||
current = serialize_scene(settings)
|
current = serialize_scene(settings)
|
||||||
bpy.context.window.scene = current_scene
|
bpy.context.window.scene = current_scene
|
||||||
|
|
||||||
@ -32,8 +38,13 @@ def get_changes_per_scene(settings):
|
|||||||
previous = load_settings(".blenvy.project_serialized_previous")
|
previous = load_settings(".blenvy.project_serialized_previous")
|
||||||
current = serialize_current(settings)
|
current = serialize_current(settings)
|
||||||
|
|
||||||
|
|
||||||
# determine changes
|
# determine changes
|
||||||
changes_per_scene = project_diff(previous, current)
|
changes_per_scene = {}
|
||||||
|
try:
|
||||||
|
changes_per_scene = project_diff(previous, current, settings)
|
||||||
|
except Exception as error:
|
||||||
|
print("failed to compare current serialized scenes to previous ones", error)
|
||||||
|
|
||||||
# save the current project as previous
|
# save the current project as previous
|
||||||
upsert_settings(".blenvy.project_serialized_previous", current, overwrite=True)
|
upsert_settings(".blenvy.project_serialized_previous", current, overwrite=True)
|
||||||
@ -42,46 +53,56 @@ def get_changes_per_scene(settings):
|
|||||||
return changes_per_scene
|
return changes_per_scene
|
||||||
|
|
||||||
|
|
||||||
def project_diff(previous, current):
|
def project_diff(previous, current, settings):
|
||||||
"""print("previous", previous)
|
"""print("previous", previous)
|
||||||
print("current", current)"""
|
print("current", current)"""
|
||||||
if previous is None or current is None:
|
if previous is None or current is None:
|
||||||
return {}
|
return {}
|
||||||
print("HERE")
|
print("Settings", settings,"current", current, "previous", previous)
|
||||||
|
|
||||||
changes_per_scene = {}
|
changes_per_scene = {}
|
||||||
|
|
||||||
# TODO : how do we deal with changed scene names ???
|
# TODO : how do we deal with changed scene names ???
|
||||||
|
# possible ? on each save, inject an id into each scene, that cannot be copied over
|
||||||
|
|
||||||
|
print('TEST SCENE', bpy.data.scenes.get("ULTRA LEVEL2"), None)
|
||||||
|
|
||||||
for scene in current:
|
for scene in current:
|
||||||
print("SCENE", scene)
|
print("SCENE", scene)
|
||||||
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))
|
|
||||||
removed = list(set(previous_object_names) - set(current_object_names))
|
|
||||||
|
|
||||||
for obj in added:
|
|
||||||
if not scene in changes_per_scene:
|
|
||||||
changes_per_scene[scene] = {}
|
|
||||||
changes_per_scene[scene][obj] = bpy.data.objects[obj]
|
|
||||||
|
|
||||||
# TODO: how do we deal with this, as we obviously do not have data for removed objects ?
|
|
||||||
for obj in removed:
|
|
||||||
if not scene in changes_per_scene:
|
|
||||||
changes_per_scene[scene] = {}
|
|
||||||
changes_per_scene[scene][obj] = None
|
|
||||||
|
|
||||||
for object_name in list(current[scene].keys()): # TODO : exclude directly added/removed objects
|
if scene in previous: # we can only compare scenes that are in both previous and current data
|
||||||
if object_name in previous[scene]:
|
|
||||||
current_obj = current[scene][object_name]
|
|
||||||
prev_obj = previous[scene][object_name]
|
|
||||||
same = str(current_obj) == str(prev_obj)
|
|
||||||
|
|
||||||
if not same:
|
previous_object_names = list(previous[scene].keys())
|
||||||
if not scene in changes_per_scene:
|
added = list(set(current_object_names) - set(previous_object_names))
|
||||||
changes_per_scene[scene] = {}
|
removed = list(set(previous_object_names) - set(current_object_names))
|
||||||
|
|
||||||
|
for obj in added:
|
||||||
|
if not scene in changes_per_scene:
|
||||||
|
changes_per_scene[scene] = {}
|
||||||
|
changes_per_scene[scene][obj] = bpy.data.objects[obj] if obj in bpy.data.objects else None
|
||||||
|
|
||||||
|
# TODO: how do we deal with this, as we obviously do not have data for removed objects ?
|
||||||
|
for obj in removed:
|
||||||
|
if not scene in changes_per_scene:
|
||||||
|
changes_per_scene[scene] = {}
|
||||||
|
changes_per_scene[scene][obj] = None
|
||||||
|
|
||||||
changes_per_scene[scene][object_name] = bpy.data.objects[object_name]
|
for object_name in list(current[scene].keys()): # TODO : exclude directly added/removed objects
|
||||||
bubble_up_changes(bpy.data.objects[object_name], changes_per_scene[scene])
|
if object_name in previous[scene]:
|
||||||
# now bubble up for instances & parents
|
current_obj = current[scene][object_name]
|
||||||
|
prev_obj = previous[scene][object_name]
|
||||||
|
same = str(current_obj) == str(prev_obj)
|
||||||
|
|
||||||
|
if not same:
|
||||||
|
if not scene in changes_per_scene:
|
||||||
|
changes_per_scene[scene] = {}
|
||||||
|
|
||||||
|
target_object = bpy.data.objects[object_name] if object_name in bpy.data.objects else None
|
||||||
|
changes_per_scene[scene][object_name] = target_object
|
||||||
|
bubble_up_changes(target_object, changes_per_scene[scene])
|
||||||
|
# now bubble up for instances & parents
|
||||||
|
else:
|
||||||
|
print(f"scene {scene} not present in previous data")
|
||||||
|
|
||||||
return changes_per_scene
|
return changes_per_scene
|
@ -50,22 +50,75 @@ def _lookup_collection(data):
|
|||||||
def _lookup_materialLineArt(data):
|
def _lookup_materialLineArt(data):
|
||||||
return generic_fields_hasher_evolved(data, fields_to_ignore=fields_to_ignore_generic)
|
return generic_fields_hasher_evolved(data, fields_to_ignore=fields_to_ignore_generic)
|
||||||
|
|
||||||
|
# used for various node trees: shaders, modifiers etc
|
||||||
|
def node_tree(node_tree):
|
||||||
|
print("SCANNING NODE TREE", node_tree)
|
||||||
|
|
||||||
|
# storage for hashing
|
||||||
|
links_hashes = []
|
||||||
|
nodes_hashes = []
|
||||||
|
root_inputs = dict(node_tree) # probably useless for materials, contains settings for certain modifiers
|
||||||
|
|
||||||
|
for node in node_tree.nodes:
|
||||||
|
#print("node", node, node.type, node.name, node.label)
|
||||||
|
|
||||||
|
input_hashes = []
|
||||||
|
for input in node.inputs:
|
||||||
|
#print(" input", input, "label", input.label, "name", input.name, dir(input))
|
||||||
|
default_value = getattr(input, 'default_value', None)
|
||||||
|
input_hash = f"{convert_field(default_value)}"
|
||||||
|
input_hashes.append(input_hash)
|
||||||
|
|
||||||
|
output_hashes = []
|
||||||
|
# IF the node itself is a group input, its outputs are the inputs of the geometry node (yes, not easy)
|
||||||
|
node_in_use = True
|
||||||
|
for (index, output) in enumerate(node.outputs):
|
||||||
|
# print(" output", output, "label", output.label, "name", output.name, "generated name", f"Socket_{index+1}")
|
||||||
|
default_value = getattr(output, 'default_value', None)
|
||||||
|
output_hash = f"{convert_field(default_value)}"
|
||||||
|
output_hashes.append(output_hash)
|
||||||
|
|
||||||
|
node_in_use = node_in_use and default_value is not None
|
||||||
|
#print("NODE IN USE", node_in_use)
|
||||||
|
|
||||||
|
node_fields_to_ignore = fields_to_ignore_generic + ['internal_links', 'inputs', 'outputs']
|
||||||
|
node_hash = f"{generic_fields_hasher_evolved(node, node_fields_to_ignore)}_{str(input_hashes)}_{str(output_hashes)}"
|
||||||
|
#print("node hash", node_hash)
|
||||||
|
#print("node hash", str(input_hashes))
|
||||||
|
nodes_hashes.append(node_hash)
|
||||||
|
|
||||||
|
for link in node_tree.links:
|
||||||
|
"""print("LINK", link, dir(link))
|
||||||
|
print("FROM", link.from_node, link.from_socket)
|
||||||
|
print("TO", link.to_node, link.to_socket)"""
|
||||||
|
|
||||||
|
from_socket_default = link.from_socket.default_value if hasattr(link.from_socket, "default_value") else None
|
||||||
|
to_socket_default = link.to_socket.default_value if hasattr(link.to_socket, "default_value") else None
|
||||||
|
link_hash = f"{link.from_node.name}_{link.from_socket.name}_{from_socket_default}+{link.to_node.name}_{link.to_socket.name}_{to_socket_default}"
|
||||||
|
|
||||||
|
links_hashes.append(link_hash)
|
||||||
|
|
||||||
|
#print("node hashes",nodes_hashes, "links_hashes", links_hashes)
|
||||||
|
print("root_inputs", root_inputs)
|
||||||
|
return f"{str(root_inputs)}_{str(nodes_hashes)}_{str(links_hashes)}"
|
||||||
|
|
||||||
|
|
||||||
type_lookups = {
|
type_lookups = {
|
||||||
Color: _lookup_color,#lambda input: print("dsf")',
|
Color: _lookup_color,#lambda input: print("dsf")',
|
||||||
bpy.types.FloatVectorAttribute: _lookup_array2,
|
bpy.types.FloatVectorAttribute: _lookup_array2,
|
||||||
bpy.types.bpy_prop_array: _lookup_array,
|
bpy.types.bpy_prop_array: _lookup_array,
|
||||||
bpy.types.PropertyGroup: _lookup_prop_group,
|
bpy.types.PropertyGroup: _lookup_prop_group,
|
||||||
bpy.types.bpy_prop_collection: _lookup_collection,
|
bpy.types.bpy_prop_collection: _lookup_collection,
|
||||||
bpy.types.MaterialLineArt: _lookup_materialLineArt
|
bpy.types.MaterialLineArt: _lookup_materialLineArt,
|
||||||
|
bpy.types.NodeTree: node_tree,
|
||||||
}
|
}
|
||||||
|
|
||||||
def convert_field(raw_value, field_name="", scan_node_tree=True):
|
def convert_field(raw_value, field_name="", scan_node_tree=True):
|
||||||
# nodes are a special case: # TODO: find out their types & move these to type lookups
|
"""# nodes are a special case: # TODO: find out their types & move these to type lookups
|
||||||
if field_name in ["node_tree", "node_group"] and scan_node_tree:
|
if field_name in ["node_tree", "node_group"] and scan_node_tree:
|
||||||
print("scan node tree")
|
print("scan node tree", inspect.getmro(type(raw_value)))
|
||||||
return node_tree(raw_value)
|
return node_tree(raw_value)
|
||||||
|
"""
|
||||||
|
|
||||||
conversion_lookup = None # type_lookups.get(type(raw_value), None)
|
conversion_lookup = None # type_lookups.get(type(raw_value), None)
|
||||||
all_types = inspect.getmro(type(raw_value))
|
all_types = inspect.getmro(type(raw_value))
|
||||||
for s_type in all_types:
|
for s_type in all_types:
|
||||||
@ -83,6 +136,7 @@ def convert_field(raw_value, field_name="", scan_node_tree=True):
|
|||||||
|
|
||||||
return field_value
|
return field_value
|
||||||
|
|
||||||
|
# just a helper , for shorthand
|
||||||
def obj_to_dict(object):
|
def obj_to_dict(object):
|
||||||
try:
|
try:
|
||||||
return dict(object)
|
return dict(object)
|
||||||
@ -194,59 +248,6 @@ def armature_hash(obj):
|
|||||||
print("bone", bone, bone_hash(bone))"""
|
print("bone", bone, bone_hash(bone))"""
|
||||||
return str(fields)
|
return str(fields)
|
||||||
|
|
||||||
# used for various node trees: shaders, modifiers etc
|
|
||||||
def node_tree(node_tree):
|
|
||||||
print("SCANNING NODE TREE", node_tree)
|
|
||||||
|
|
||||||
# storage for hashing
|
|
||||||
links_hashes = []
|
|
||||||
nodes_hashes = []
|
|
||||||
root_inputs = dict(node_tree) # probably useless for materials, contains settings for certain modifiers
|
|
||||||
|
|
||||||
for node in node_tree.nodes:
|
|
||||||
#print("node", node, node.type, node.name, node.label)
|
|
||||||
|
|
||||||
input_hashes = []
|
|
||||||
for input in node.inputs:
|
|
||||||
#print(" input", input, "label", input.label, "name", input.name, dir(input))
|
|
||||||
default_value = getattr(input, 'default_value', None)
|
|
||||||
input_hash = f"{convert_field(default_value)}"
|
|
||||||
input_hashes.append(input_hash)
|
|
||||||
|
|
||||||
output_hashes = []
|
|
||||||
# IF the node itself is a group input, its outputs are the inputs of the geometry node (yes, not easy)
|
|
||||||
node_in_use = True
|
|
||||||
for (index, output) in enumerate(node.outputs):
|
|
||||||
# print(" output", output, "label", output.label, "name", output.name, "generated name", f"Socket_{index+1}")
|
|
||||||
default_value = getattr(output, 'default_value', None)
|
|
||||||
output_hash = f"{convert_field(default_value)}"
|
|
||||||
output_hashes.append(output_hash)
|
|
||||||
|
|
||||||
node_in_use = node_in_use and default_value is not None
|
|
||||||
#print("NODE IN USE", node_in_use)
|
|
||||||
|
|
||||||
node_fields_to_ignore = fields_to_ignore_generic + ['internal_links', 'inputs', 'outputs']
|
|
||||||
node_hash = f"{generic_fields_hasher_evolved(node, node_fields_to_ignore)}_{str(input_hashes)}_{str(output_hashes)}"
|
|
||||||
#print("node hash", node_hash)
|
|
||||||
#print("node hash", str(input_hashes))
|
|
||||||
nodes_hashes.append(node_hash)
|
|
||||||
|
|
||||||
for link in node_tree.links:
|
|
||||||
"""print("LINK", link, dir(link))
|
|
||||||
print("FROM", link.from_node, link.from_socket)
|
|
||||||
print("TO", link.to_node, link.to_socket)"""
|
|
||||||
|
|
||||||
from_socket_default = link.from_socket.default_value if hasattr(link.from_socket, "default_value") else None
|
|
||||||
to_socket_default = link.to_socket.default_value if hasattr(link.to_socket, "default_value") else None
|
|
||||||
link_hash = f"{link.from_node.name}_{link.from_socket.name}_{from_socket_default}+{link.to_node.name}_{link.to_socket.name}_{to_socket_default}"
|
|
||||||
|
|
||||||
links_hashes.append(link_hash)
|
|
||||||
|
|
||||||
#print("node hashes",nodes_hashes, "links_hashes", links_hashes)
|
|
||||||
print("root_inputs", root_inputs)
|
|
||||||
return f"{str(root_inputs)}_{str(nodes_hashes)}_{str(links_hashes)}"
|
|
||||||
|
|
||||||
|
|
||||||
def material_hash(material, settings):
|
def material_hash(material, settings):
|
||||||
scan_node_tree = settings.auto_export.materials_in_depth_scan
|
scan_node_tree = settings.auto_export.materials_in_depth_scan
|
||||||
hashed_material_except_node_tree = generic_fields_hasher_evolved(material, fields_to_ignore_generic, scan_node_tree=scan_node_tree)
|
hashed_material_except_node_tree = generic_fields_hasher_evolved(material, fields_to_ignore_generic, scan_node_tree=scan_node_tree)
|
||||||
@ -290,10 +291,29 @@ def serialize_scene(settings):
|
|||||||
cache = {"materials":{}}
|
cache = {"materials":{}}
|
||||||
print("serializing scene")
|
print("serializing scene")
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
|
|
||||||
|
# render settings are injected into each scene
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: only go through scenes actually in our list
|
||||||
for scene in bpy.data.scenes:
|
for scene in bpy.data.scenes:
|
||||||
|
# ignore temporary scenes
|
||||||
if scene.name.startswith(TEMPSCENE_PREFIX):
|
if scene.name.startswith(TEMPSCENE_PREFIX):
|
||||||
continue
|
continue
|
||||||
data[scene.name] = {}
|
data[scene.name] = {}
|
||||||
|
|
||||||
|
custom_properties = custom_properties_hash(scene) if len(scene.keys()) > 0 else None
|
||||||
|
eevee_settings = generic_fields_hasher_evolved(scene.eevee, fields_to_ignore=fields_to_ignore_generic) # TODO: ignore most of the fields
|
||||||
|
scene_field_hashes = {
|
||||||
|
"custom_properties": custom_properties,
|
||||||
|
"eevee": eevee_settings
|
||||||
|
}
|
||||||
|
print("SCENE WORLD", scene.world, dir(scene.eevee))
|
||||||
|
#generic_fields_hasher_evolved(scene.eevee, fields_to_ignore=fields_to_ignore_generic)
|
||||||
|
data[scene.name]["____scene_settings"] = str(hash(str(scene_field_hashes)))
|
||||||
|
|
||||||
|
|
||||||
for object in scene.objects:
|
for object in scene.objects:
|
||||||
object = bpy.data.objects[object.name]
|
object = bpy.data.objects[object.name]
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.WindowManager.auto_export_tracker = PointerProperty(type=AutoExportTracker)
|
bpy.types.WindowManager.auto_export_tracker = PointerProperty(type=AutoExportTracker)
|
||||||
|
|
||||||
|
bpy.types.Scene.id_test = StringProperty(default="")
|
||||||
|
|
||||||
# setup handlers for updates & saving
|
# setup handlers for updates & saving
|
||||||
#bpy.app.handlers.save_post.append(cls.save_handler)
|
#bpy.app.handlers.save_post.append(cls.save_handler)
|
||||||
#bpy.app.handlers.depsgraph_update_post.append(cls.deps_update_handler)
|
#bpy.app.handlers.depsgraph_update_post.append(cls.deps_update_handler)
|
||||||
@ -58,6 +60,8 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
except:pass"""
|
except:pass"""
|
||||||
del bpy.types.WindowManager.auto_export_tracker
|
del bpy.types.WindowManager.auto_export_tracker
|
||||||
|
|
||||||
|
del bpy.types.Scene.id_test
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def save_handler(cls, scene, depsgraph):
|
def save_handler(cls, scene, depsgraph):
|
||||||
print("-------------")
|
print("-------------")
|
||||||
@ -73,6 +77,7 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def deps_post_update_handler(cls, scene, depsgraph):
|
def deps_post_update_handler(cls, scene, depsgraph):
|
||||||
# print("change detection enabled", cls.change_detection_enabled)
|
# print("change detection enabled", cls.change_detection_enabled)
|
||||||
|
print("change detected", list(map(lambda x: x.name, list(bpy.data.scenes))))
|
||||||
|
|
||||||
"""ops = bpy.context.window_manager.operators
|
"""ops = bpy.context.window_manager.operators
|
||||||
print("last operators", ops)
|
print("last operators", ops)
|
||||||
|
@ -144,10 +144,10 @@ class OT_Add_asset_filebrowser(Operator, ImportHelper):
|
|||||||
# Filters files
|
# Filters files
|
||||||
filter_glob: StringProperty(options={'HIDDEN'}, default='*.jpg;*.jpeg;*.png;*.bmp') # type: ignore
|
filter_glob: StringProperty(options={'HIDDEN'}, default='*.jpg;*.jpeg;*.png;*.bmp') # type: ignore
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
current_auto_settings = load_settings(".gltf_auto_export_settings")
|
blenvy = context.window_manager.blenvy
|
||||||
project_root_path = current_auto_settings.get("project_root_path", "../")
|
project_root_path = blenvy.project_root_path
|
||||||
assets_path = current_auto_settings.get("assets_path", "assets")
|
assets_path = blenvy.assets_path
|
||||||
# FIXME: not sure
|
# FIXME: not sure
|
||||||
print("project_root_path", project_root_path, "assets_path", assets_path)
|
print("project_root_path", project_root_path, "assets_path", assets_path)
|
||||||
export_assets_path_absolute = absolute_path_from_blend_file(os.path.join(project_root_path, assets_path))
|
export_assets_path_absolute = absolute_path_from_blend_file(os.path.join(project_root_path, assets_path))
|
||||||
|
@ -5,7 +5,7 @@ from .asset_helpers import get_user_assets
|
|||||||
|
|
||||||
|
|
||||||
def draw_assets(layout, name, title, asset_registry, target_type, target_name, editable=True, user_assets= [], generated_assets = []):
|
def draw_assets(layout, name, title, asset_registry, target_type, target_name, editable=True, user_assets= [], generated_assets = []):
|
||||||
header, panel = layout.box().panel(f"assets{name}", default_closed=False)
|
header, panel = layout.panel(f"assets{name}", default_closed=False)
|
||||||
header.label(text=title)
|
header.label(text=title)
|
||||||
if panel:
|
if panel:
|
||||||
if editable:
|
if editable:
|
||||||
@ -92,6 +92,8 @@ class Blenvy_assets(bpy.types.Panel):
|
|||||||
user_assets = get_user_assets(scene)
|
user_assets = get_user_assets(scene)
|
||||||
#print("user assets", user_assets, scene)
|
#print("user assets", user_assets, scene)
|
||||||
row = panel.row()
|
row = panel.row()
|
||||||
|
row.prop(scene, "always_export")
|
||||||
|
|
||||||
scene_assets_panel = draw_assets(layout=row, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, user_assets=user_assets, target_type="SCENE", target_name=scene.name)
|
scene_assets_panel = draw_assets(layout=row, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, user_assets=user_assets, target_type="SCENE", target_name=scene.name)
|
||||||
"""if scene.name in blueprints_data.blueprint_instances_per_main_scene:
|
"""if scene.name in blueprints_data.blueprint_instances_per_main_scene:
|
||||||
for blueprint_name in blueprints_data.blueprint_instances_per_main_scene[scene.name].keys():
|
for blueprint_name in blueprints_data.blueprint_instances_per_main_scene[scene.name].keys():
|
||||||
|
@ -30,6 +30,8 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
|||||||
row.label(icon="RIGHTARROW")
|
row.label(icon="RIGHTARROW")
|
||||||
row.label(text=blueprint.name)
|
row.label(text=blueprint.name)
|
||||||
|
|
||||||
|
row.prop(blueprint.collection, "always_export")
|
||||||
|
|
||||||
if blueprint.local:
|
if blueprint.local:
|
||||||
|
|
||||||
select_blueprint = row.operator(operator="blueprint.select", text="", icon="RESTRICT_SELECT_OFF")
|
select_blueprint = row.operator(operator="blueprint.select", text="", icon="RESTRICT_SELECT_OFF")
|
||||||
|
@ -48,6 +48,7 @@ class BlenvyManager(PropertyGroup):
|
|||||||
items=(
|
items=(
|
||||||
('COMPONENTS', "Components", ""),
|
('COMPONENTS', "Components", ""),
|
||||||
('BLUEPRINTS', "Blueprints", ""),
|
('BLUEPRINTS', "Blueprints", ""),
|
||||||
|
('LEVELS', "Levels", ""),
|
||||||
('ASSETS', "Assets", ""),
|
('ASSETS', "Assets", ""),
|
||||||
('SETTINGS', "Settings", ""),
|
('SETTINGS', "Settings", ""),
|
||||||
('TOOLS', "Tools", ""),
|
('TOOLS', "Tools", ""),
|
||||||
@ -135,10 +136,19 @@ class BlenvyManager(PropertyGroup):
|
|||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.WindowManager.blenvy = PointerProperty(type=BlenvyManager)
|
bpy.types.WindowManager.blenvy = PointerProperty(type=BlenvyManager)
|
||||||
|
|
||||||
|
# unsure
|
||||||
|
# you can add components to both objects & collections
|
||||||
|
#bpy.types.Object.components_meta = PointerProperty(type=ComponentsMeta)
|
||||||
|
bpy.types.Collection.always_export = BoolProperty(default=False, description="always export this blueprint, regardless of changed status") # FIXME: not sure about this one
|
||||||
|
bpy.types.Scene.always_export = BoolProperty(default=False, description="always export this blueprint, regardless of changed status") # FIXME: not sure about this one
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
del bpy.types.WindowManager.blenvy
|
del bpy.types.WindowManager.blenvy
|
||||||
|
|
||||||
|
del bpy.types.Collection.always_export
|
||||||
|
del bpy.types.Scene.always_export
|
||||||
|
|
||||||
def load_settings(self):
|
def load_settings(self):
|
||||||
print("LOAD SETTINGS")
|
print("LOAD SETTINGS")
|
||||||
settings = load_settings(self.settings_save_path)
|
settings = load_settings(self.settings_save_path)
|
||||||
|
@ -10,11 +10,11 @@ class OT_switch_bevy_tooling(Operator):
|
|||||||
bl_label = "Switch bevy tooling"
|
bl_label = "Switch bevy tooling"
|
||||||
#bl_options = {}
|
#bl_options = {}
|
||||||
|
|
||||||
|
|
||||||
tool: EnumProperty(
|
tool: EnumProperty(
|
||||||
items=(
|
items=(
|
||||||
('COMPONENTS', "Components", "Switch to components"),
|
('COMPONENTS', "Components", "Switch to components"),
|
||||||
('BLUEPRINTS', "Blueprints", ""),
|
('BLUEPRINTS', "Blueprints", ""),
|
||||||
|
('LEVELS', "Levels", ""),
|
||||||
('ASSETS', "Assets", ""),
|
('ASSETS', "Assets", ""),
|
||||||
('SETTINGS', "Settings", ""),
|
('SETTINGS', "Settings", ""),
|
||||||
('TOOLS', "Tools", ""),
|
('TOOLS', "Tools", ""),
|
||||||
|
@ -57,6 +57,10 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||||||
tool_switch_components = target.operator(operator="bevy.tooling_switch", text="", icon="PACKAGE")
|
tool_switch_components = target.operator(operator="bevy.tooling_switch", text="", icon="PACKAGE")
|
||||||
tool_switch_components.tool = "BLUEPRINTS"
|
tool_switch_components.tool = "BLUEPRINTS"
|
||||||
|
|
||||||
|
target = row.box() if active_mode == 'LEVELS' else row
|
||||||
|
tool_switch_components = target.operator(operator="bevy.tooling_switch", text="", icon="PACKAGE")
|
||||||
|
tool_switch_components.tool = "LEVELS"
|
||||||
|
|
||||||
target = row.box() if active_mode == 'ASSETS' else row
|
target = row.box() if active_mode == 'ASSETS' else row
|
||||||
tool_switch_components = target.operator(operator="bevy.tooling_switch", text="", icon="ASSET_MANAGER")
|
tool_switch_components = target.operator(operator="bevy.tooling_switch", text="", icon="ASSET_MANAGER")
|
||||||
tool_switch_components.tool = "ASSETS"
|
tool_switch_components.tool = "ASSETS"
|
||||||
|
0
tools/blenvy/levels/__init__.py
Normal file
0
tools/blenvy/levels/__init__.py
Normal file
26
tools/blenvy/levels/operators.py
Normal file
26
tools/blenvy/levels/operators.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import os
|
||||||
|
import bpy
|
||||||
|
from bpy_types import (Operator)
|
||||||
|
from bpy.props import (StringProperty)
|
||||||
|
|
||||||
|
class OT_select_level(Operator):
|
||||||
|
"""Select level """
|
||||||
|
bl_idname = "level.select"
|
||||||
|
bl_label = "Select level"
|
||||||
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
|
level_name: StringProperty(
|
||||||
|
name="level name",
|
||||||
|
description="level to select",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
if self.level_name:
|
||||||
|
scene = bpy.data.scenes[self.level_name]
|
||||||
|
if scene:
|
||||||
|
# bpy.ops.object.select_all(action='DESELECT')
|
||||||
|
bpy.context.window.scene = scene
|
||||||
|
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
77
tools/blenvy/levels/ui.py
Normal file
77
tools/blenvy/levels/ui.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
from types import SimpleNamespace
|
||||||
|
import bpy
|
||||||
|
from ..assets.assets_scan import get_main_scene_assets_tree
|
||||||
|
from ..assets.asset_helpers import get_user_assets
|
||||||
|
from ..assets.ui import draw_assets
|
||||||
|
|
||||||
|
class Blenvy_levels(bpy.types.Panel):
|
||||||
|
bl_space_type = 'VIEW_3D'
|
||||||
|
bl_region_type = 'UI'
|
||||||
|
bl_label = ""
|
||||||
|
bl_parent_id = "BLENVY_PT_SidePanel"
|
||||||
|
bl_options = {'DEFAULT_CLOSED','HIDE_HEADER'}
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return context.window_manager.blenvy.mode == 'LEVELS'
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False # No animation.
|
||||||
|
blenvy = context.window_manager.blenvy
|
||||||
|
layout.operator(operator="bevyassets.test")
|
||||||
|
|
||||||
|
asset_registry = context.window_manager.assets_registry
|
||||||
|
blueprints_registry = context.window_manager.blueprints_registry
|
||||||
|
#blueprints_registry.refresh_blueprints()
|
||||||
|
blueprints_data = blueprints_registry.blueprints_data
|
||||||
|
|
||||||
|
for scene_selector in blenvy.main_scenes:
|
||||||
|
scene = bpy.data.scenes[scene_selector.name]
|
||||||
|
header, panel = layout.box().panel(f"assets{scene.name}", default_closed=False)
|
||||||
|
if header:
|
||||||
|
header.label(text=scene.name, icon="HIDE_OFF")
|
||||||
|
header.prop(scene, "always_export")
|
||||||
|
select_level = header.operator(operator="level.select", text="", icon="RESTRICT_SELECT_OFF")
|
||||||
|
select_level.level_name = scene.name
|
||||||
|
|
||||||
|
if panel:
|
||||||
|
user_assets = get_user_assets(scene)
|
||||||
|
row = panel.row()
|
||||||
|
#row.label(text="row")
|
||||||
|
"""col = row.column()
|
||||||
|
col.label(text=" ")
|
||||||
|
|
||||||
|
col = row.column()
|
||||||
|
col.label(text="col in row 2")
|
||||||
|
|
||||||
|
column = panel.column()
|
||||||
|
column.label(text="col")"""
|
||||||
|
|
||||||
|
split = panel.split(factor=0.005)
|
||||||
|
col = split.column()
|
||||||
|
col.label(text=" ")
|
||||||
|
|
||||||
|
col = split.column()
|
||||||
|
#col.label(text="col in row 2")
|
||||||
|
|
||||||
|
scene_assets_panel = draw_assets(layout=col, name=f"{scene.name}_assets", title=f"Assets", asset_registry=asset_registry, user_assets=user_assets, target_type="SCENE", target_name=scene.name)
|
||||||
|
|
||||||
|
|
||||||
|
settings = {"blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
||||||
|
settings = SimpleNamespace(**settings)
|
||||||
|
|
||||||
|
"""if panel:
|
||||||
|
for scene_selector in blenvy.main_scenes:
|
||||||
|
scene = bpy.data.scenes[scene_selector.name]
|
||||||
|
#get_main_scene_assets_tree(scene, blueprints_data, settings)
|
||||||
|
user_assets = get_user_assets(scene)
|
||||||
|
#print("user assets", user_assets, scene)
|
||||||
|
row = panel.row()
|
||||||
|
header.prop(scene, "always_export")
|
||||||
|
|
||||||
|
sub_header, sub_panel = row.box().panel(f"assets{name}", default_closed=False)
|
||||||
|
|
||||||
|
|
||||||
|
scene_assets_panel = draw_assets(layout=sub_panel, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, user_assets=user_assets, target_type="SCENE", target_name=scene.name)
|
||||||
|
"""
|
Loading…
Reference in New Issue
Block a user