mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-22 11:50:53 +00:00
feat(blenvy):
* improvements to assets ui * assets ui now specific to per level data, not based on selection anymore * blueprints ui now presents assets per blueprint * a lot of tweaks & improvements in the areas above
This commit is contained in:
parent
f3dbf76ce6
commit
b8a7eba71d
@ -53,7 +53,7 @@ from .gltf_auto_export.ui.operators import (OT_OpenFolderbrowser, SCENES_LIST_OT
|
||||
# asset management
|
||||
from .assets.ui import GLTF_PT_auto_export_assets
|
||||
from .assets.assets_registry import AssetsRegistry
|
||||
from .assets.operators import OT_add_bevy_asset, OT_remove_bevy_asset
|
||||
from .assets.operators import OT_Add_asset_filebrowser, OT_add_bevy_asset, OT_remove_bevy_asset
|
||||
|
||||
# blueprints management
|
||||
from .blueprints.ui import GLTF_PT_auto_export_blueprints_list
|
||||
@ -143,6 +143,7 @@ classes = [
|
||||
AssetsRegistry,
|
||||
OT_add_bevy_asset,
|
||||
OT_remove_bevy_asset,
|
||||
OT_Add_asset_filebrowser,
|
||||
GLTF_PT_auto_export_assets,
|
||||
|
||||
BlueprintsRegistry,
|
||||
|
@ -68,6 +68,7 @@ class AssetsRegistry(PropertyGroup):
|
||||
('MODEL', "Model", ""),
|
||||
('AUDIO', "Audio", ""),
|
||||
('IMAGE', "Image", ""),
|
||||
('TEXT', "Text", ""),
|
||||
)
|
||||
) # type: ignore
|
||||
|
||||
|
@ -2,7 +2,9 @@ import os
|
||||
import json
|
||||
import bpy
|
||||
from bpy_types import (Operator)
|
||||
from bpy.props import (StringProperty, EnumProperty)
|
||||
from bpy.props import (BoolProperty, StringProperty, EnumProperty)
|
||||
|
||||
from ..settings import load_settings
|
||||
|
||||
class OT_add_bevy_asset(Operator):
|
||||
"""Add asset"""
|
||||
@ -20,6 +22,7 @@ class OT_add_bevy_asset(Operator):
|
||||
('MODEL', "Model", ""),
|
||||
('AUDIO', "Audio", ""),
|
||||
('IMAGE', "Image", ""),
|
||||
('TEXT', "Text", ""),
|
||||
)
|
||||
) # type: ignore
|
||||
|
||||
@ -29,26 +32,39 @@ class OT_add_bevy_asset(Operator):
|
||||
subtype='FILE_PATH'
|
||||
) # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
assets_list = []
|
||||
blueprint_assets = False
|
||||
if context.collection is not None and context.collection.name == 'Scene Collection':
|
||||
assets_list = json.loads(context.scene.get('assets'))
|
||||
blueprint_assets = False
|
||||
else:
|
||||
if 'assets' in context.collection:
|
||||
assets_list = json.loads(context.collection.get('assets'))
|
||||
blueprint_assets = True
|
||||
# what are we targetting
|
||||
target_type: EnumProperty(
|
||||
name="target type",
|
||||
description="type of the target: scene or blueprint to add an asset to",
|
||||
items=(
|
||||
('SCENE', "Scene", ""),
|
||||
('BLUEPRINT', "Blueprint", ""),
|
||||
),
|
||||
) # type: ignore
|
||||
|
||||
in_list = [asset for asset in assets_list if (asset["path"] == self.asset_path)]
|
||||
target_name: StringProperty(
|
||||
name="target name",
|
||||
description="name of the target blueprint or scene to add asset to"
|
||||
) # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
assets = []
|
||||
blueprint_assets = self.target_type == 'BLUEPRINT'
|
||||
print("FOOO", self.target_name, self.target_type)
|
||||
if blueprint_assets:
|
||||
assets = json.loads(bpy.data.collections[self.target_name].get('assets')) if 'assets' in bpy.data.collections[self.target_name] else []
|
||||
else:
|
||||
assets = json.loads(bpy.data.scenes[self.target_name].get('assets')) if 'assets' in bpy.data.scenes[self.target_name] else []
|
||||
|
||||
in_list = [asset for asset in assets if (asset["path"] == self.asset_path)]
|
||||
in_list = len(in_list) > 0
|
||||
if not in_list:
|
||||
assets_list.append({"name": self.asset_name, "type": self.asset_type, "path": self.asset_path, "internal": False})
|
||||
assets.append({"name": self.asset_name, "type": self.asset_type, "path": self.asset_path, "internal": False})
|
||||
|
||||
if blueprint_assets:
|
||||
context.collection["assets"] = json.dumps(assets_list)
|
||||
bpy.data.collections[self.target_name]["assets"] = json.dumps(assets)
|
||||
else:
|
||||
context.scene["assets"] = json.dumps(assets_list)
|
||||
bpy.data.scenes[self.target_name]["assets"] = json.dumps(assets)
|
||||
#context.window_manager.assets_registry.add_asset(self.asset_name, self.asset_type, self.asset_path, False)
|
||||
return {'FINISHED'}
|
||||
|
||||
@ -65,21 +81,72 @@ class OT_remove_bevy_asset(Operator):
|
||||
subtype='FILE_PATH'
|
||||
) # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
assets_list = []
|
||||
blueprint_assets = False
|
||||
if context.collection is not None and context.collection.name == 'Scene Collection':
|
||||
assets_list = json.loads(context.scene.get('assets'))
|
||||
blueprint_assets = False
|
||||
else:
|
||||
if 'assets' in context.collection:
|
||||
assets_list = json.loads(context.collection.get('assets'))
|
||||
blueprint_assets = True
|
||||
|
||||
assets_list = [asset for asset in assets_list if (asset["path"] != self.asset_path)]
|
||||
clear_all: BoolProperty (
|
||||
name="clear all assets",
|
||||
description="clear all assets",
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
# what are we targetting
|
||||
target_type: EnumProperty(
|
||||
name="target type",
|
||||
description="type of the target: scene or blueprint to add an asset to",
|
||||
items=(
|
||||
('SCENE', "Scene", ""),
|
||||
('BLUEPRINT', "Blueprint", ""),
|
||||
),
|
||||
) # type: ignore
|
||||
|
||||
target_name: StringProperty(
|
||||
name="target name",
|
||||
description="name of the target blueprint or scene to add asset to"
|
||||
) # type: ignore
|
||||
|
||||
|
||||
def execute(self, context):
|
||||
assets = []
|
||||
blueprint_assets = self.target_type == 'BLUEPRINT'
|
||||
if blueprint_assets:
|
||||
context.collection["assets"] = json.dumps(assets_list)
|
||||
assets = json.loads(bpy.data.collections[self.target_name].get('assets')) if 'assets' in bpy.data.collections[self.target_name] else []
|
||||
else:
|
||||
context.scene["assets"] = json.dumps(assets_list)
|
||||
assets = json.loads(bpy.data.scenes[self.target_name].get('assets')) if 'assets' in bpy.data.scenes[self.target_name] else []
|
||||
|
||||
assets = [asset for asset in assets if (asset["path"] != self.asset_path)]
|
||||
if blueprint_assets:
|
||||
bpy.data.collections[self.target_name]["assets"] = json.dumps(assets)
|
||||
else:
|
||||
bpy.data.scenes[self.target_name]["assets"] = json.dumps(assets)
|
||||
#context.window_manager.assets_registry.remove_asset(self.asset_path)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
import os
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
|
||||
class OT_Add_asset_filebrowser(Operator, ImportHelper):
|
||||
"""Browse for asset files"""
|
||||
bl_idname = "asset.open_filebrowser"
|
||||
bl_label = "Select asset file"
|
||||
|
||||
# Define this to tell 'fileselect_add' that we want a directoy
|
||||
filepath: bpy.props.StringProperty(
|
||||
name="asset Path",
|
||||
description="selected file",
|
||||
subtype='FILE_PATH',
|
||||
) # type: ignore
|
||||
|
||||
# Filters files
|
||||
filter_glob: StringProperty(options={'HIDDEN'}, default='*.jpg;*.jpeg;*.png;*.bmp') # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
current_auto_settings = load_settings(".gltf_auto_export_settings")
|
||||
export_root_folder = current_auto_settings.get("export_root_folder")
|
||||
asset_path = os.path.relpath(self.filepath, export_root_folder)
|
||||
|
||||
assets_registry = context.window_manager.assets_registry
|
||||
assets_registry.asset_path_selector = asset_path
|
||||
|
||||
print("SELECTED ASSET PATH", asset_path)
|
||||
|
||||
return {'FINISHED'}
|
@ -1,66 +1,79 @@
|
||||
import bpy
|
||||
import json
|
||||
|
||||
|
||||
def draw_assets(layout, name, title, asset_registry, assets, target_type, target_name):
|
||||
header, panel = layout.box().panel(f"assets{name}", default_closed=False)
|
||||
header.label(text=title)
|
||||
if panel:
|
||||
row = panel.row()
|
||||
row.prop(asset_registry, "asset_name_selector", text="")
|
||||
row.prop(asset_registry, "asset_type_selector", text="")
|
||||
asset_selector = row.operator(operator="asset.open_filebrowser", text="", icon="FILE_FOLDER")
|
||||
|
||||
if asset_registry.asset_type_selector == 'IMAGE':
|
||||
asset_selector.filter_glob = '*.jpg;*.jpeg;*.png;*.bmp'
|
||||
if asset_registry.asset_type_selector == 'MODEL':
|
||||
asset_selector.filter_glob="*.glb;*.gltf"
|
||||
if asset_registry.asset_type_selector == 'TEXT':
|
||||
asset_selector.filter_glob="*.txt;*.md;*.ron;*.json"
|
||||
if asset_registry.asset_type_selector == 'AUDIO':
|
||||
asset_selector.filter_glob="*.mp3;*.wav;*.flac"
|
||||
|
||||
add_asset = row.operator(operator="bevyassets.add", text="", icon="ADD")
|
||||
add_asset.target_type = target_type
|
||||
add_asset.target_name = target_name
|
||||
add_asset.asset_name = asset_registry.asset_name_selector
|
||||
add_asset.asset_type = asset_registry.asset_type_selector
|
||||
add_asset.asset_path = asset_registry.asset_path_selector
|
||||
|
||||
#assets = json.loads(blueprint.collection["assets"]) if "assets" in blueprint.collection else []
|
||||
for asset in assets:
|
||||
row = panel.row()
|
||||
row.label(text=asset["name"])
|
||||
row.label(text=asset["type"])
|
||||
row.label(text=asset["path"])
|
||||
if not asset["internal"]:
|
||||
remove_asset = row.operator(operator="bevyassets.remove", text="", icon="TRASH")
|
||||
remove_asset.target_type = target_type
|
||||
remove_asset.target_name = target_name
|
||||
remove_asset.asset_path = asset["path"]
|
||||
else:
|
||||
row.label(text="")
|
||||
|
||||
class GLTF_PT_auto_export_assets(bpy.types.Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = ""
|
||||
bl_parent_id = "BLENVY_PT_SidePanel"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
bl_options = {'DEFAULT_CLOSED','HIDE_HEADER'}
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.window_manager.blenvy.mode == 'ASSETS'
|
||||
|
||||
def draw_header(self, context):
|
||||
"""def draw_header(self, context):
|
||||
layout = self.layout
|
||||
name = ""
|
||||
if context.collection is not None and context.collection.name == 'Scene Collection':
|
||||
name = f"WORLD/LEVEL: {context.scene.name}"
|
||||
else:
|
||||
name = f"BLUEPRINT: {context.collection.name}"
|
||||
layout.label(text=f"Assets For {name}")
|
||||
layout.label(text=f"Assets For {name}")"""
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
#if "auto_export_tracker" in context.window_manager:
|
||||
asset_registry = context.window_manager.assets_registry
|
||||
|
||||
row = layout.row()
|
||||
row.prop(asset_registry, "asset_name_selector", text="")
|
||||
row.prop(asset_registry, "asset_type_selector", text="")
|
||||
row.prop(asset_registry, "asset_path_selector", text="")
|
||||
add_assets = row.operator(operator="bevyassets.add", text="Add asset")
|
||||
add_assets.asset_name = asset_registry.asset_name_selector
|
||||
add_assets.asset_type = asset_registry.asset_type_selector
|
||||
add_assets.asset_path = asset_registry.asset_path_selector
|
||||
name = "world"
|
||||
header, panel = layout.box().panel(f"assets{name}", default_closed=False)
|
||||
header.label(text="World/Level Assets")
|
||||
|
||||
layout.separator()
|
||||
row = layout.row()
|
||||
row.label(text="Name")
|
||||
row.label(text="Type")
|
||||
row.label(text="Path")
|
||||
row.label(text="Remove")
|
||||
#print("FOO", json.dumps([{"name":"foo", "type":"MODEL", "path":"bla", "internal":True}]))
|
||||
# [{"name": "trigger_sound", "type": "AUDIO", "path": "assets/audio/trigger.mp3", "internal": true}]
|
||||
assets_list = []
|
||||
if context.collection is not None and context.collection.name == 'Scene Collection':
|
||||
assets_list = json.loads(context.scene.get('assets')) #asset_registry.assets_list
|
||||
else:
|
||||
if 'assets' in context.collection:
|
||||
assets_list = json.loads(context.collection.get('assets'))
|
||||
for asset in assets_list:
|
||||
row = layout.row()
|
||||
row.label(text=asset["name"])
|
||||
row.label(text=asset["type"])
|
||||
row.label(text=asset["path"])
|
||||
if not asset["internal"]:
|
||||
remove_asset = row.operator(operator="bevyassets.remove", text="remove")
|
||||
remove_asset.asset_path = asset["path"]
|
||||
else:
|
||||
row.label(text="")
|
||||
|
||||
#
|
||||
if panel:
|
||||
for scene in bpy.data.scenes:
|
||||
if scene.name != "Library": # FIXME: hack for testing
|
||||
assets = json.loads(scene.get('assets')) if 'assets' in scene else []
|
||||
row = panel.row()
|
||||
draw_assets(layout=row, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, assets=assets, target_type="SCENE", target_name=scene.name)
|
||||
|
@ -17,14 +17,3 @@ def make_empty(name, location, rotation, scale, collection):
|
||||
collection.objects.link( empty_obj )
|
||||
#bpy.context.view_layer.update()
|
||||
return empty_obj
|
||||
|
||||
def upsert_settings(name, data):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else bpy.data.texts.new(name)
|
||||
stored_settings.clear()
|
||||
stored_settings.write(json.dumps(data))
|
||||
|
||||
def load_settings(name):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else None
|
||||
if stored_settings != None:
|
||||
return json.loads(stored_settings.as_string())
|
||||
return None
|
||||
|
@ -4,7 +4,8 @@ from bpy_types import (Operator)
|
||||
from bpy.props import (StringProperty)
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
|
||||
from ..helpers 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 ..propGroups.prop_groups import generate_propertyGroups_for_components
|
||||
|
||||
|
@ -6,7 +6,7 @@ from pathlib import Path
|
||||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
||||
|
||||
from ..helpers import load_settings
|
||||
from ...settings import load_settings
|
||||
from ..propGroups.prop_groups import generate_propertyGroups_for_components
|
||||
from ..components.metadata import ComponentMetadata, ensure_metadata_for_all_objects
|
||||
|
||||
|
@ -34,3 +34,4 @@ class OT_select_blueprint(Operator):
|
||||
o.select_set(True)"""
|
||||
|
||||
return {'FINISHED'}
|
||||
|
@ -1,11 +1,14 @@
|
||||
import bpy
|
||||
import json
|
||||
|
||||
from ..assets.ui import draw_assets
|
||||
|
||||
class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Blueprints"
|
||||
bl_parent_id = "BLENVY_PT_SidePanel"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_options = {'DEFAULT_CLOSED','HIDE_HEADER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@ -15,15 +18,22 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
asset_registry = context.window_manager.assets_registry
|
||||
|
||||
for blueprint in context.window_manager.blueprints_registry.blueprints_list:
|
||||
row = layout.row()
|
||||
row.label(icon="RIGHTARROW")
|
||||
row.label(text=blueprint.name)
|
||||
|
||||
if blueprint.local:
|
||||
select_blueprint = row.operator(operator="blueprint.select", text="Select")
|
||||
select_blueprint = row.operator(operator="blueprint.select", text="", icon="RESTRICT_SELECT_OFF")
|
||||
select_blueprint.blueprint_collection_name = blueprint.collection.name
|
||||
select_blueprint.blueprint_scene_name = blueprint.scene.name
|
||||
|
||||
assets = json.loads(blueprint.collection["assets"]) if "assets" in blueprint.collection else []
|
||||
|
||||
draw_assets(layout=layout, name=blueprint.name, title="Assets", asset_registry=asset_registry, assets=assets, target_type="BLUEPRINT", target_name=blueprint.name)
|
||||
|
||||
else:
|
||||
row.label(text="External")
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import bpy
|
||||
import json
|
||||
from ..settings import load_settings
|
||||
|
||||
######################################################
|
||||
## ui logic & co
|
||||
@ -27,11 +27,10 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||
library_scene_active = False
|
||||
active_collection = context.collection
|
||||
|
||||
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_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:
|
||||
current_auto_settings = json.loads(current_auto_settings.as_string())
|
||||
#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"]
|
||||
|
13
tools/blenvy/settings.py
Normal file
13
tools/blenvy/settings.py
Normal file
@ -0,0 +1,13 @@
|
||||
import json
|
||||
import bpy
|
||||
|
||||
def upsert_settings(name, data):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else bpy.data.texts.new(name)
|
||||
stored_settings.clear()
|
||||
stored_settings.write(json.dumps(data))
|
||||
|
||||
def load_settings(name):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else None
|
||||
if stored_settings != None:
|
||||
return json.loads(stored_settings.as_string())
|
||||
return None
|
Loading…
Reference in New Issue
Block a user