mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-12-03 16:36:59 +00:00
Compare commits
2 Commits
310ee194a9
...
0432769bda
Author | SHA1 | Date | |
---|---|---|---|
|
0432769bda | ||
|
0172bbe511 |
@ -10,14 +10,15 @@ pub struct CorePlugin;
|
|||||||
impl Plugin for CorePlugin {
|
impl Plugin for CorePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
ExportRegistryPlugin{
|
ExportRegistryPlugin {
|
||||||
|
component_filter: SceneFilter::Denylist(HashSet::from([
|
||||||
component_filter: SceneFilter::Denylist(HashSet::from([ // this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
|
// this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
|
||||||
TypeId::of::<ComponentAToFilterOut>(),
|
TypeId::of::<ComponentAToFilterOut>(),
|
||||||
TypeId::of::<ComponentBToFilterOut>(),
|
TypeId::of::<ComponentBToFilterOut>(),
|
||||||
// and any other commponent you want to include/exclude
|
// and any other commponent you want to include/exclude
|
||||||
])),
|
])),
|
||||||
..Default::default()},
|
..Default::default()
|
||||||
|
},
|
||||||
BlueprintsPlugin {
|
BlueprintsPlugin {
|
||||||
library_folder: "blueprints".into(),
|
library_folder: "blueprints".into(),
|
||||||
format: GltfFormat::GLB,
|
format: GltfFormat::GLB,
|
||||||
|
@ -226,4 +226,4 @@ Restructuring of storage of components
|
|||||||
- [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
|
- [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
|
- [ ] handle missing types in registry for keys & values
|
||||||
|
|
||||||
- Add correct upgrade handling from individual component to bevy_components
|
- [ ] Add correct upgrade handling from individual component to bevy_components
|
@ -150,8 +150,8 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
|
|||||||
|
|
||||||
if not object.name in objects_with_invalid_components:
|
if not object.name in objects_with_invalid_components:
|
||||||
objects_with_invalid_components.append(object.name)
|
objects_with_invalid_components.append(object.name)
|
||||||
if not long_name in invalid_component_names:
|
"""if not long_name in invalid_component_names:
|
||||||
invalid_component_names.append(custom_property)
|
invalid_component_names.append(custom_property)""" # FIXME
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.separator()
|
layout.separator()
|
||||||
original_name = bpy.context.window_manager.bevy_component_rename_helper.original_name
|
original_name = bpy.context.window_manager.bevy_component_rename_helper.original_name
|
||||||
|
@ -56,3 +56,18 @@
|
|||||||
- [ ] remove bulk of tracker related code
|
- [ ] remove bulk of tracker related code
|
||||||
- [ ] clean up
|
- [ ] clean up
|
||||||
- [x] split up change detection in settings to its own panel
|
- [x] split up change detection in settings to its own panel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Change storage of 'blueprint' assets : (from BlueprintsList)
|
||||||
|
- store at the SCENE level: a list/map of assets
|
||||||
|
- asset name + asset path
|
||||||
|
- the asset PATH is determined by the export output folder parameters
|
||||||
|
- make asset storage generic enough to allow adding additional asset types
|
||||||
|
- get inspired by bevy_asset_loader ?
|
||||||
|
|
||||||
|
Assets:
|
||||||
|
- [ ] store assets
|
||||||
|
- [ ] per main scene for level/world assets
|
||||||
|
- [ ] per blueprint for blueprint in lib scene
|
@ -11,12 +11,11 @@ bl_info = {
|
|||||||
"category": "Import-Export"
|
"category": "Import-Export"
|
||||||
}
|
}
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
|
||||||
import json
|
import json
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Context
|
|
||||||
from bpy.props import (StringProperty, BoolProperty, IntProperty, PointerProperty)
|
from bpy.props import (StringProperty, BoolProperty, IntProperty, PointerProperty)
|
||||||
import rna_prop_ui
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# from .extension import ExampleExtensionProperties, GLTF_PT_UserExtensionPanel, unregister_panel
|
# from .extension import ExampleExtensionProperties, GLTF_PT_UserExtensionPanel, unregister_panel
|
||||||
@ -36,12 +35,20 @@ from .ui.main import (GLTF_PT_auto_export_change_detection, GLTF_PT_auto_export_
|
|||||||
GLTF_PT_auto_export_general,
|
GLTF_PT_auto_export_general,
|
||||||
GLTF_PT_auto_export_scenes,
|
GLTF_PT_auto_export_scenes,
|
||||||
GLTF_PT_auto_export_blueprints,
|
GLTF_PT_auto_export_blueprints,
|
||||||
GLTF_PT_auto_export_blueprints_list,
|
|
||||||
SCENE_UL_GLTF_auto_export,
|
SCENE_UL_GLTF_auto_export,
|
||||||
|
|
||||||
GLTF_PT_auto_export_SidePanel
|
GLTF_PT_auto_export_SidePanel
|
||||||
)
|
)
|
||||||
from .ui.operators import (OT_OpenFolderbrowser, SCENES_LIST_OT_actions)
|
from .ui.operators import (OT_OpenFolderbrowser, SCENES_LIST_OT_actions)
|
||||||
|
|
||||||
|
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 .blueprints.ui import GLTF_PT_auto_export_blueprints_list
|
||||||
|
from .blueprints.blueprints_registry import BlueprintsRegistry
|
||||||
|
from .blueprints.operators import OT_select_blueprint
|
||||||
|
|
||||||
from .helpers.generate_complete_preferences_dict import generate_complete_preferences_dict_gltf
|
from .helpers.generate_complete_preferences_dict import generate_complete_preferences_dict_gltf
|
||||||
|
|
||||||
|
|
||||||
@ -104,10 +111,8 @@ classes = [
|
|||||||
SCENE_UL_GLTF_auto_export,
|
SCENE_UL_GLTF_auto_export,
|
||||||
SCENES_LIST_OT_actions,
|
SCENES_LIST_OT_actions,
|
||||||
|
|
||||||
|
|
||||||
OT_OpenFolderbrowser,
|
OT_OpenFolderbrowser,
|
||||||
AutoExportGLTF,
|
AutoExportGLTF,
|
||||||
#AutoExportGltfAddonPreferences,
|
|
||||||
|
|
||||||
CollectionToExport,
|
CollectionToExport,
|
||||||
BlueprintsToExport,
|
BlueprintsToExport,
|
||||||
@ -119,8 +124,17 @@ classes = [
|
|||||||
GLTF_PT_auto_export_scenes,
|
GLTF_PT_auto_export_scenes,
|
||||||
GLTF_PT_auto_export_blueprints,
|
GLTF_PT_auto_export_blueprints,
|
||||||
GLTF_PT_auto_export_SidePanel,
|
GLTF_PT_auto_export_SidePanel,
|
||||||
GLTF_PT_auto_export_blueprints_list,
|
|
||||||
AutoExportTracker,
|
AutoExportTracker,
|
||||||
|
|
||||||
|
AssetsRegistry,
|
||||||
|
OT_add_bevy_asset,
|
||||||
|
OT_remove_bevy_asset,
|
||||||
|
GLTF_PT_auto_export_assets,
|
||||||
|
|
||||||
|
BlueprintsRegistry,
|
||||||
|
OT_select_blueprint,
|
||||||
|
GLTF_PT_auto_export_blueprints_list,
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def glTF2_pre_export_callback(data):
|
def glTF2_pre_export_callback(data):
|
||||||
|
0
tools/gltf_auto_export/assets/__init__.py
Normal file
0
tools/gltf_auto_export/assets/__init__.py
Normal file
96
tools/gltf_auto_export/assets/assets_registry.py
Normal file
96
tools/gltf_auto_export/assets/assets_registry.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import bpy
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
from pathlib import Path
|
||||||
|
from bpy_types import (PropertyGroup)
|
||||||
|
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
||||||
|
|
||||||
|
|
||||||
|
def get_assets(scene, blueprints_data, addon_prefs):
|
||||||
|
export_root_folder = getattr(addon_prefs, "export_root_folder")
|
||||||
|
export_output_folder = getattr(addon_prefs,"export_output_folder")
|
||||||
|
export_levels_path = getattr(addon_prefs,"export_levels_path")
|
||||||
|
export_blueprints_path = getattr(addon_prefs, "export_blueprints_path")
|
||||||
|
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||||
|
|
||||||
|
relative_blueprints_path = os.path.relpath(export_blueprints_path, export_root_folder)
|
||||||
|
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, None)
|
||||||
|
|
||||||
|
blueprint_assets_list = []
|
||||||
|
if blueprint_instance_names_for_scene:
|
||||||
|
for blueprint_name in blueprint_instance_names_for_scene:
|
||||||
|
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
||||||
|
if blueprint is not None:
|
||||||
|
print("BLUEPRINT", blueprint)
|
||||||
|
blueprint_exported_path = None
|
||||||
|
if blueprint.local:
|
||||||
|
blueprint_exported_path = os.path.join(relative_blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
|
else:
|
||||||
|
# get the injected path of the external blueprints
|
||||||
|
blueprint_exported_path = blueprint.collection['Export_path'] if 'Export_path' in blueprint.collection else None
|
||||||
|
print("foo", dict(blueprint.collection))
|
||||||
|
if blueprint_exported_path is not None:
|
||||||
|
blueprint_assets_list.append({"name": blueprint.name, "path": blueprint_exported_path})
|
||||||
|
|
||||||
|
|
||||||
|
# fetch images/textures
|
||||||
|
# see https://blender.stackexchange.com/questions/139859/how-to-get-absolute-file-path-for-linked-texture-image
|
||||||
|
textures = []
|
||||||
|
for ob in bpy.data.objects:
|
||||||
|
if ob.type == "MESH":
|
||||||
|
for mat_slot in ob.material_slots:
|
||||||
|
if mat_slot.material:
|
||||||
|
if mat_slot.material.node_tree:
|
||||||
|
textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE'])
|
||||||
|
print("textures", textures)
|
||||||
|
|
||||||
|
assets_list_name = f"assets_{scene.name}"
|
||||||
|
assets_list_data = {"blueprints": json.dumps(blueprint_assets_list), "sounds":[], "images":[]}
|
||||||
|
|
||||||
|
print("blueprint assets", blueprint_assets_list)
|
||||||
|
|
||||||
|
|
||||||
|
# this is where we store the information for all available assets
|
||||||
|
#
|
||||||
|
class AssetsRegistry(PropertyGroup):
|
||||||
|
assets_list = []
|
||||||
|
|
||||||
|
asset_name_selector: StringProperty(
|
||||||
|
name="asset name",
|
||||||
|
description="name of asset to add",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
asset_type_selector: EnumProperty(
|
||||||
|
name="asset type",
|
||||||
|
description="type of asset to add",
|
||||||
|
items=(
|
||||||
|
('MODEL', "Model", ""),
|
||||||
|
('AUDIO', "Audio", ""),
|
||||||
|
('IMAGE', "Image", ""),
|
||||||
|
)
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
asset_path_selector: StringProperty(
|
||||||
|
name="asset path",
|
||||||
|
description="path of asset to add",
|
||||||
|
subtype='FILE_PATH'
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register(cls):
|
||||||
|
bpy.types.WindowManager.assets_registry = PointerProperty(type=AssetsRegistry)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def unregister(cls):
|
||||||
|
del bpy.types.WindowManager.assets_registry
|
||||||
|
|
||||||
|
|
||||||
|
def add_asset(self, name, type, path, internal): # internal means it cannot be edited by the user, aka auto generated
|
||||||
|
in_list = [asset for asset in self.assets_list if (asset["path"] == path)]
|
||||||
|
in_list = len(in_list) > 0
|
||||||
|
if not in_list:
|
||||||
|
self.assets_list.append({"name": name, "type": type, "path": path, "internal": internal})
|
||||||
|
|
||||||
|
def remove_asset(self, path):
|
||||||
|
self.assets_list[:] = [asset for asset in self.assets_list if (asset["path"] != path)]
|
50
tools/gltf_auto_export/assets/operators.py
Normal file
50
tools/gltf_auto_export/assets/operators.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import os
|
||||||
|
import bpy
|
||||||
|
from bpy_types import (Operator)
|
||||||
|
from bpy.props import (StringProperty, EnumProperty)
|
||||||
|
|
||||||
|
class OT_add_bevy_asset(Operator):
|
||||||
|
"""Add asset"""
|
||||||
|
bl_idname = "bevyassets.add"
|
||||||
|
bl_label = "Add bevy asset"
|
||||||
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
|
asset_name: StringProperty(
|
||||||
|
name="asset name",
|
||||||
|
description="name of asset to add",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
asset_type: bpy.types.WindowManager.asset_type_selector = EnumProperty(
|
||||||
|
items=(
|
||||||
|
('MODEL', "Model", ""),
|
||||||
|
('AUDIO', "Audio", ""),
|
||||||
|
('IMAGE', "Image", ""),
|
||||||
|
)
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
asset_path: StringProperty(
|
||||||
|
name="asset path",
|
||||||
|
description="path of asset to add",
|
||||||
|
subtype='FILE_PATH'
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
context.window_manager.assets_registry.add_asset(self.asset_name, self.asset_type, self.asset_path, False)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class OT_remove_bevy_asset(Operator):
|
||||||
|
"""Remove asset"""
|
||||||
|
bl_idname = "bevyassets.remove"
|
||||||
|
bl_label = "remove bevy asset"
|
||||||
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
|
asset_path: StringProperty(
|
||||||
|
name="asset path",
|
||||||
|
description="path of asset to add",
|
||||||
|
subtype='FILE_PATH'
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
context.window_manager.assets_registry.remove_asset(self.asset_path)
|
||||||
|
return {'FINISHED'}
|
43
tools/gltf_auto_export/assets/ui.py
Normal file
43
tools/gltf_auto_export/assets/ui.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import bpy
|
||||||
|
|
||||||
|
class GLTF_PT_auto_export_assets(bpy.types.Panel):
|
||||||
|
bl_space_type = 'VIEW_3D'
|
||||||
|
bl_region_type = 'UI'
|
||||||
|
bl_label = "Assets"
|
||||||
|
bl_parent_id = "GLTF_PT_auto_export_SidePanel"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
row = layout.row()
|
||||||
|
row.label(text="Name")
|
||||||
|
row.label(text="Type")
|
||||||
|
row.label(text="Path")
|
||||||
|
row.label(text="Remove")
|
||||||
|
|
||||||
|
for asset in asset_registry.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="")
|
@ -74,4 +74,4 @@ def export_gltf (path, export_settings):
|
|||||||
settings = {**export_settings, "filepath": path}
|
settings = {**export_settings, "filepath": path}
|
||||||
# print("export settings",settings)
|
# print("export settings",settings)
|
||||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
bpy.ops.export_scene.gltf(**settings)
|
#bpy.ops.export_scene.gltf(**settings)
|
||||||
|
@ -9,11 +9,6 @@ from ..modules.bevy_dynamic import is_object_dynamic, is_object_static
|
|||||||
from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into
|
from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into
|
||||||
from ..helpers.helpers_blueprints import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene
|
from ..helpers.helpers_blueprints import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene
|
||||||
|
|
||||||
# export all main scenes
|
|
||||||
def export_main_scenes(scenes, blend_file_path, addon_prefs):
|
|
||||||
for scene in scenes:
|
|
||||||
export_main_scene(scene, blend_file_path, addon_prefs)
|
|
||||||
|
|
||||||
def export_main_scene(scene, blend_file_path, addon_prefs, blueprints_data):
|
def export_main_scene(scene, blend_file_path, addon_prefs, blueprints_data):
|
||||||
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
|
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
|
||||||
export_root_folder = getattr(addon_prefs, "export_root_folder")
|
export_root_folder = getattr(addon_prefs, "export_root_folder")
|
||||||
@ -35,8 +30,8 @@ def export_main_scene(scene, blend_file_path, addon_prefs, blueprints_data):
|
|||||||
if export_blueprints :
|
if export_blueprints :
|
||||||
gltf_output_path = os.path.join(export_levels_path, scene.name)
|
gltf_output_path = os.path.join(export_levels_path, scene.name)
|
||||||
|
|
||||||
inject_blueprints_list_into_main_scene(scene, blueprints_data)
|
inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs)
|
||||||
|
return
|
||||||
if export_separate_dynamic_and_static_objects:
|
if export_separate_dynamic_and_static_objects:
|
||||||
#print("SPLIT STATIC AND DYNAMIC")
|
#print("SPLIT STATIC AND DYNAMIC")
|
||||||
# first export static objects
|
# first export static objects
|
||||||
|
0
tools/gltf_auto_export/blueprints/__init__.py
Normal file
0
tools/gltf_auto_export/blueprints/__init__.py
Normal file
49
tools/gltf_auto_export/blueprints/blueprints_registry.py
Normal file
49
tools/gltf_auto_export/blueprints/blueprints_registry.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import bpy
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
from pathlib import Path
|
||||||
|
from bpy_types import (PropertyGroup)
|
||||||
|
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
||||||
|
|
||||||
|
|
||||||
|
# this is where we store the information for all available Blueprints
|
||||||
|
#
|
||||||
|
class BlueprintsRegistry(PropertyGroup):
|
||||||
|
blueprints_data = {}
|
||||||
|
blueprints_list = []
|
||||||
|
|
||||||
|
asset_name_selector: StringProperty(
|
||||||
|
name="asset name",
|
||||||
|
description="name of asset to add",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
asset_type_selector: EnumProperty(
|
||||||
|
name="asset type",
|
||||||
|
description="type of asset to add",
|
||||||
|
items=(
|
||||||
|
('MODEL', "Model", ""),
|
||||||
|
('AUDIO', "Audio", ""),
|
||||||
|
('IMAGE', "Image", ""),
|
||||||
|
)
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
asset_path_selector: StringProperty(
|
||||||
|
name="asset path",
|
||||||
|
description="path of asset to add",
|
||||||
|
subtype='FILE_PATH'
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register(cls):
|
||||||
|
bpy.types.WindowManager.blueprints_registry = PointerProperty(type=BlueprintsRegistry)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def unregister(cls):
|
||||||
|
del bpy.types.WindowManager.blueprints_registry
|
||||||
|
|
||||||
|
|
||||||
|
def add_blueprint(self, blueprint):
|
||||||
|
self.blueprints_list.append(blueprint)
|
||||||
|
|
||||||
|
|
33
tools/gltf_auto_export/blueprints/operators.py
Normal file
33
tools/gltf_auto_export/blueprints/operators.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import os
|
||||||
|
import bpy
|
||||||
|
from bpy_types import (Operator)
|
||||||
|
from bpy.props import (StringProperty)
|
||||||
|
|
||||||
|
class OT_select_blueprint(Operator):
|
||||||
|
"""Select blueprint """
|
||||||
|
bl_idname = "blueprint.select"
|
||||||
|
bl_label = "Select blueprint"
|
||||||
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
|
blueprint_collection_name: StringProperty(
|
||||||
|
name="blueprint collection name",
|
||||||
|
description="blueprints to select's collection name ",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
blueprint_scene_name: StringProperty(
|
||||||
|
name="blueprint scene name",
|
||||||
|
description="blueprints to select's collection name ",
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
if self.blueprint_collection_name:
|
||||||
|
collection = bpy.data.collections[self.blueprint_collection_name]
|
||||||
|
scene = bpy.data.scenes[self.blueprint_scene_name]
|
||||||
|
if scene:
|
||||||
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
|
bpy.context.window.scene = scene
|
||||||
|
bpy.context.view_layer.objects.active = None
|
||||||
|
bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children[self.blueprint_collection_name]
|
||||||
|
# bpy.context.view_layer.active_layer_collection = collection
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
28
tools/gltf_auto_export/blueprints/ui.py
Normal file
28
tools/gltf_auto_export/blueprints/ui.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import bpy
|
||||||
|
|
||||||
|
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 = "GLTF_PT_auto_export_SidePanel"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False # No animation.
|
||||||
|
|
||||||
|
for blueprint in context.window_manager.blueprints_registry.blueprints_list:
|
||||||
|
row = layout.row()
|
||||||
|
row.label(text=blueprint.name)
|
||||||
|
|
||||||
|
if blueprint.local:
|
||||||
|
select_blueprint = row.operator(operator="blueprint.select", text="Select")
|
||||||
|
select_blueprint.blueprint_collection_name = blueprint.collection.name
|
||||||
|
select_blueprint.blueprint_scene_name = blueprint.scene.name
|
||||||
|
else:
|
||||||
|
row.label(text="External")
|
||||||
|
|
||||||
|
for collection in bpy.context.window_manager.exportedCollections:
|
||||||
|
row = layout.row()
|
||||||
|
row.label(text=collection.name)
|
@ -158,6 +158,7 @@ def blueprints_scan(main_scenes, library_scenes, addon_prefs):
|
|||||||
blueprint.collection = collection
|
blueprint.collection = collection
|
||||||
blueprint.instances = external_collection_instances[collection.name] if collection.name in external_collection_instances else []
|
blueprint.instances = external_collection_instances[collection.name] if collection.name in external_collection_instances else []
|
||||||
blueprints[collection.name] = blueprint
|
blueprints[collection.name] = blueprint
|
||||||
|
#print("EXTERNAL COLLECTION", collection, dict(collection))
|
||||||
|
|
||||||
# add nested collections to internal/external_collection instances
|
# add nested collections to internal/external_collection instances
|
||||||
# FIXME: inneficient, third loop over all_objects
|
# FIXME: inneficient, third loop over all_objects
|
||||||
@ -280,11 +281,95 @@ def blueprints_scan(main_scenes, library_scenes, addon_prefs):
|
|||||||
import json
|
import json
|
||||||
from .object_makers import (make_empty)
|
from .object_makers import (make_empty)
|
||||||
|
|
||||||
def inject_blueprints_list_into_main_scene(scene, blueprints_data):
|
|
||||||
# print("injecting assets/blueprints data into scene")
|
def add_scene_property(scene, property_name, property_data):
|
||||||
root_collection = scene.collection
|
root_collection = scene.collection
|
||||||
assets_list = None
|
scene_property = None
|
||||||
|
for object in scene.objects:
|
||||||
|
if object.name == property_name:
|
||||||
|
scene_property = object
|
||||||
|
break
|
||||||
|
|
||||||
|
if scene_property is None:
|
||||||
|
scene_property = make_empty(property_name, [0,0,0], [0,0,0], [0,0,0], root_collection)
|
||||||
|
|
||||||
|
for key in property_data.keys():
|
||||||
|
scene_property[key] = property_data[key]
|
||||||
|
|
||||||
|
|
||||||
|
def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs):
|
||||||
|
export_root_folder = getattr(addon_prefs, "export_root_folder")
|
||||||
|
export_output_folder = getattr(addon_prefs,"export_output_folder")
|
||||||
|
export_levels_path = getattr(addon_prefs,"export_levels_path")
|
||||||
|
export_blueprints_path = getattr(addon_prefs, "export_blueprints_path")
|
||||||
|
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||||
|
|
||||||
|
# print("injecting assets/blueprints data into scene")
|
||||||
assets_list_name = f"assets_list_{scene.name}_components"
|
assets_list_name = f"assets_list_{scene.name}_components"
|
||||||
|
assets_list_data = {}
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: temporary hack
|
||||||
|
for blueprint in blueprints_data.blueprints:
|
||||||
|
bpy.context.window_manager.blueprints_registry.add_blueprint(blueprint)
|
||||||
|
|
||||||
|
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, None)
|
||||||
|
# find all blueprints used in a scene
|
||||||
|
blueprints_in_scene = []
|
||||||
|
if blueprint_instance_names_for_scene: # what are the blueprints used in this scene, inject those into the assets list component
|
||||||
|
children_per_blueprint = {}
|
||||||
|
for blueprint_name in blueprint_instance_names_for_scene:
|
||||||
|
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
||||||
|
if blueprint:
|
||||||
|
children_per_blueprint[blueprint_name] = blueprint.nested_blueprints
|
||||||
|
blueprints_in_scene += blueprint.nested_blueprints
|
||||||
|
assets_list_data["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})"
|
||||||
|
print(blueprint_instance_names_for_scene)
|
||||||
|
add_scene_property(scene, assets_list_name, assets_list_data)
|
||||||
|
|
||||||
|
|
||||||
|
relative_blueprints_path = os.path.relpath(export_blueprints_path, export_root_folder)
|
||||||
|
|
||||||
|
blueprint_assets_list = []
|
||||||
|
if blueprint_instance_names_for_scene:
|
||||||
|
for blueprint_name in blueprint_instance_names_for_scene:
|
||||||
|
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
||||||
|
if blueprint is not None:
|
||||||
|
print("BLUEPRINT", blueprint)
|
||||||
|
blueprint_exported_path = None
|
||||||
|
if blueprint.local:
|
||||||
|
blueprint_exported_path = os.path.join(relative_blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
|
else:
|
||||||
|
# get the injected path of the external blueprints
|
||||||
|
blueprint_exported_path = blueprint.collection['Export_path'] if 'Export_path' in blueprint.collection else None
|
||||||
|
print("foo", dict(blueprint.collection))
|
||||||
|
if blueprint_exported_path is not None:
|
||||||
|
blueprint_assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "internal": True})
|
||||||
|
|
||||||
|
|
||||||
|
# fetch images/textures
|
||||||
|
# see https://blender.stackexchange.com/questions/139859/how-to-get-absolute-file-path-for-linked-texture-image
|
||||||
|
textures = []
|
||||||
|
for ob in bpy.data.objects:
|
||||||
|
if ob.type == "MESH":
|
||||||
|
for mat_slot in ob.material_slots:
|
||||||
|
if mat_slot.material:
|
||||||
|
if mat_slot.material.node_tree:
|
||||||
|
textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE'])
|
||||||
|
print("textures", textures)
|
||||||
|
|
||||||
|
assets_list_name = f"assets_{scene.name}"
|
||||||
|
assets_list_data = {"blueprints": json.dumps(blueprint_assets_list), "sounds":[], "images":[]}
|
||||||
|
|
||||||
|
print("blueprint assets", blueprint_assets_list)
|
||||||
|
add_scene_property(scene, assets_list_name, assets_list_data)
|
||||||
|
for blueprint in blueprint_assets_list:
|
||||||
|
bpy.context.window_manager.assets_registry.add_asset(**blueprint)
|
||||||
|
|
||||||
|
|
||||||
|
'''root_collection = scene.collection
|
||||||
|
|
||||||
|
assets_list = None
|
||||||
for object in scene.objects:
|
for object in scene.objects:
|
||||||
if object.name == assets_list_name:
|
if object.name == assets_list_name:
|
||||||
assets_list = object
|
assets_list = object
|
||||||
@ -301,7 +386,7 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data):
|
|||||||
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
||||||
if blueprint:
|
if blueprint:
|
||||||
children_per_blueprint[blueprint_name] = blueprint.nested_blueprints
|
children_per_blueprint[blueprint_name] = blueprint.nested_blueprints
|
||||||
assets_list["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})"
|
assets_list["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})"'''
|
||||||
|
|
||||||
def remove_blueprints_list_from_main_scene(scene):
|
def remove_blueprints_list_from_main_scene(scene):
|
||||||
assets_list = None
|
assets_list = None
|
||||||
|
@ -9,7 +9,7 @@ custom_properties_to_filter_out = ['_combine', 'template', 'components_meta']
|
|||||||
def is_component_valid(object, component_name):
|
def is_component_valid(object, component_name):
|
||||||
if "components_meta" in object or hasattr(object, "components_meta"):
|
if "components_meta" in object or hasattr(object, "components_meta"):
|
||||||
target_components_metadata = object.components_meta.components
|
target_components_metadata = object.components_meta.components
|
||||||
component_meta = next(filter(lambda component: component["name"] == component_name, target_components_metadata), None)
|
component_meta = next(filter(lambda component: component["long_name"] == component_name, target_components_metadata), None)
|
||||||
if component_meta != None:
|
if component_meta != None:
|
||||||
return component_meta.enabled and not component_meta.invalid
|
return component_meta.enabled and not component_meta.invalid
|
||||||
return True
|
return True
|
||||||
@ -105,6 +105,7 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
|
|||||||
|
|
||||||
"""we inject the collection/blueprint name, as a component called 'BlueprintName', but we only do this in the empty, not the original object"""
|
"""we inject the collection/blueprint name, as a component called 'BlueprintName', but we only do this in the empty, not the original object"""
|
||||||
empty_obj['BlueprintName'] = '("'+collection_name+'")'
|
empty_obj['BlueprintName'] = '("'+collection_name+'")'
|
||||||
|
empty_obj["BlueprintPath"] = ''
|
||||||
empty_obj['SpawnHere'] = '()'
|
empty_obj['SpawnHere'] = '()'
|
||||||
|
|
||||||
# we also inject a list of all sub blueprints, so that the bevy side can preload them
|
# we also inject a list of all sub blueprints, so that the bevy side can preload them
|
||||||
|
@ -55,22 +55,6 @@ class GLTF_PT_auto_export_changes_list(bpy.types.Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.label(text=f' {object_name}')
|
row.label(text=f' {object_name}')
|
||||||
|
|
||||||
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 = "GLTF_PT_auto_export_SidePanel"
|
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
layout.use_property_split = True
|
|
||||||
layout.use_property_decorate = False # No animation.
|
|
||||||
|
|
||||||
for collection in bpy.context.window_manager.exportedCollections:
|
|
||||||
row = layout.row()
|
|
||||||
row.label(text=collection.name)
|
|
||||||
|
|
||||||
# main ui in the file => export
|
# main ui in the file => export
|
||||||
class GLTF_PT_auto_export_main(bpy.types.Panel):
|
class GLTF_PT_auto_export_main(bpy.types.Panel):
|
||||||
bl_space_type = 'FILE_BROWSER'
|
bl_space_type = 'FILE_BROWSER'
|
||||||
|
@ -2,6 +2,15 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
|
|
||||||
|
|
||||||
|
class ASSETS_LIST_OT_actions(Operator):
|
||||||
|
"""Add / remove etc assets"""
|
||||||
|
bl_idname = "asset_list.list_action"
|
||||||
|
bl_label = "Asset Actions"
|
||||||
|
bl_description = "Move items up and down, add and remove"
|
||||||
|
bl_options = {'REGISTER'}
|
||||||
|
|
||||||
|
|
||||||
class SCENES_LIST_OT_actions(Operator):
|
class SCENES_LIST_OT_actions(Operator):
|
||||||
"""Move items up and down, add and remove"""
|
"""Move items up and down, add and remove"""
|
||||||
bl_idname = "scene_list.list_action"
|
bl_idname = "scene_list.list_action"
|
||||||
|
Loading…
Reference in New Issue
Block a user