feat(Blender):

* added ability to clear/reset settings to default
 * a lot of improvements to QOL ui features
   * fixed issue with editing scenes being tagged as Level scenes
   * fixed mode switching issues
   * added save & reset of camera settings
   * improved selection logic
   * various minor tweaks
   * better naming & cleanups
This commit is contained in:
kaosat.dev 2024-08-14 14:34:12 +02:00
parent 027fec7131
commit 48ce690860
10 changed files with 160 additions and 110 deletions

View File

@ -49,7 +49,7 @@ from .blueprints.operators import BLENVY_OT_blueprint_select
# blenvy core # blenvy core
from .core.blenvy_manager import BlenvyManager from .core.blenvy_manager import BlenvyManager
from .core.operators import BLENVY_OT_configuration_switch, BLENVY_OT_tooling_switch from .core.operators import BLENVY_OT_tooling_switch, BLENVY_OT_configuration_switch, BLENVY_OT_configuration_reset
from .core.ui.ui import (BLENVY_PT_SidePanel) from .core.ui.ui import (BLENVY_PT_SidePanel)
from .core.ui.scenes_list import BLENVY_OT_scenes_list_actions from .core.ui.scenes_list import BLENVY_OT_scenes_list_actions
from .core.ui.menus_and_shortcuts import BLENVY_OT_ui_blueprint_create, BLENVY_OT_ui_blueprint_edit_start, BLENVY_OT_ui_blueprint_edit_end, BLENVY_OT_ui_blueprint_create_or_edit, edit_or_create_blueprint_menu from .core.ui.menus_and_shortcuts import BLENVY_OT_ui_blueprint_create, BLENVY_OT_ui_blueprint_edit_start, BLENVY_OT_ui_blueprint_edit_end, BLENVY_OT_ui_blueprint_create_or_edit, edit_or_create_blueprint_menu
@ -112,6 +112,7 @@ classes = [
BlenvyManager, BlenvyManager,
BLENVY_OT_tooling_switch, BLENVY_OT_tooling_switch,
BLENVY_OT_configuration_switch, BLENVY_OT_configuration_switch,
BLENVY_OT_configuration_reset,
Asset, Asset,
AssetsRegistry, AssetsRegistry,

View File

@ -1,7 +1,7 @@
import bpy import bpy
from bpy_types import (PropertyGroup) from bpy_types import (PropertyGroup)
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, IntProperty) from bpy.props import (EnumProperty, BoolProperty)
from ...settings import load_settings, upsert_settings, generate_complete_settings_dict from ...settings import load_settings, upsert_settings, generate_complete_settings_dict, clear_settings
# list of settings we do NOT want to save # list of settings we do NOT want to save
settings_black_list = ['settings_save_enabled', 'dry_run'] settings_black_list = ['settings_save_enabled', 'dry_run']
@ -128,3 +128,13 @@ class AutoExportSettings(PropertyGroup):
self.settings_save_enabled = True self.settings_save_enabled = True
def reset_settings(self):
for property_name in self.bl_rna.properties.keys():
if property_name not in ["name", "rna_type"]:
self.property_unset(property_name)
# clear the stored settings
clear_settings(".blenvy_export_settings")
clear_settings(".blenvy_export_settings_previous")
clear_settings(".blenvy_gltf_settings_previous")
clear_settings(".blenvy.project_serialized_previous")

View File

@ -1,8 +1,8 @@
import os import os
import bpy import bpy
from bpy_types import (PropertyGroup) from bpy_types import (PropertyGroup)
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, FloatProperty) from bpy.props import (StringProperty, BoolProperty, FloatProperty)
from ...settings import load_settings, upsert_settings, generate_complete_settings_dict from ...settings import load_settings, upsert_settings, generate_complete_settings_dict, clear_settings
from .propGroups.prop_groups import generate_propertyGroups_for_components from .propGroups.prop_groups import generate_propertyGroups_for_components
from .components.metadata import ensure_metadata_for_all_items from .components.metadata import ensure_metadata_for_all_items
@ -154,3 +154,10 @@ class ComponentsSettings(PropertyGroup):
except:pass except:pass
self.settings_save_enabled = True self.settings_save_enabled = True
def reset_settings(self):
for property_name in self.bl_rna.properties.keys():
if property_name not in ["name", "rna_type"]:
self.property_unset(property_name)
# clear the stored settings
clear_settings(".blenvy_components_settings")

View File

@ -101,7 +101,6 @@ class BLENVY_OT_item_select(Operator):
select_area(context=context, area_name="OBJECT") select_area(context=context, area_name="OBJECT")
elif self.item_type == 'COLLECTION': elif self.item_type == 'COLLECTION':
print("selecting collection")
collection = bpy.data.collections[self.target_name] collection = bpy.data.collections[self.target_name]
scene_of_collection = get_collection_scene(collection) if self.override_scene_name == "" else bpy.data.scenes.get(self.override_scene_name, None) scene_of_collection = get_collection_scene(collection) if self.override_scene_name == "" else bpy.data.scenes.get(self.override_scene_name, None)
if scene_of_collection is not None: if scene_of_collection is not None:

View File

@ -1,8 +1,8 @@
import os import os
import bpy import bpy
from bpy_types import (PropertyGroup) from bpy_types import (PropertyGroup)
from bpy.props import (BoolProperty, EnumProperty, PointerProperty, StringProperty, CollectionProperty, IntProperty) from bpy.props import (BoolProperty, EnumProperty, PointerProperty, StringProperty, CollectionProperty, IntProperty, FloatProperty, FloatVectorProperty)
from ..settings import upsert_settings, load_settings, generate_complete_settings_dict from ..settings import upsert_settings, load_settings, generate_complete_settings_dict, clear_settings
from ..add_ons.auto_export.settings import AutoExportSettings from ..add_ons.auto_export.settings import AutoExportSettings
from ..add_ons.bevy_components.settings import ComponentsSettings from ..add_ons.bevy_components.settings import ComponentsSettings
@ -154,11 +154,22 @@ class BlenvyManager(PropertyGroup):
edit_blueprint_previous_mode: StringProperty( edit_blueprint_previous_mode: StringProperty(
name="edit_blueprint_previous_mode", name="edit_blueprint_previous_mode",
description="previous blenvy mode before starting editing the current blueprint", description="previous blenvy mode before starting editing the current Blueprint",
default="", default="",
update=save_settings update=save_settings
)# type: ignore )# type: ignore
edit_blueprint_previous_view_distance: FloatProperty(
name="edit_blueprint_previous_view_distance",
description="previous view distance before focusing in on the specific Blueprint to edit",
default=0.0,
)# type: ignore
edit_blueprint_previous_view_position: FloatVectorProperty(
name="edit_blueprint_previous_view_position",
description="previous view position before focusing in on the specific Blueprint to edit",
)# type: ignore
# sub ones # sub ones
auto_export: PointerProperty(type=AutoExportSettings) # type: ignore auto_export: PointerProperty(type=AutoExportSettings) # type: ignore
components: PointerProperty(type=ComponentsSettings) # type: ignore components: PointerProperty(type=ComponentsSettings) # type: ignore
@ -195,7 +206,7 @@ class BlenvyManager(PropertyGroup):
('Level', 'Level','Level scene'), ('Level', 'Level','Level scene'),
('Library', 'Library', 'Library scene'), ('Library', 'Library', 'Library scene'),
), ),
default='None' default='None'
) )
@classmethod @classmethod
@ -228,3 +239,18 @@ class BlenvyManager(PropertyGroup):
for scene in bpy.data.scenes: for scene in bpy.data.scenes:
self.scenes_to_scene_names[scene] = scene.name self.scenes_to_scene_names[scene] = scene.name
def reset_settings(self):
for property_name in self.bl_rna.properties.keys():
if property_name not in ["name", "rna_type"]:
self.property_unset(property_name)
# now reset auto_export settings
self.auto_export.reset_settings()
# now reset component settings
self.components.reset_settings()
# clear the stored settings
clear_settings(".blenvy_common_settings")
clear_settings(".blenvy_common_settings_previous")

View File

@ -17,10 +17,7 @@ def recurLayerCollection(layerColl, collName):
return found return found
def set_active_collection(scene, collection_name): def set_active_collection(scene, collection_name):
print("set active collection", scene, collection_name)
layer_collection = scene.view_layers['ViewLayer'].layer_collection layer_collection = scene.view_layers['ViewLayer'].layer_collection
layerColl = recurLayerCollection(layer_collection, collection_name) layerColl = recurLayerCollection(layer_collection, collection_name)
print("layerColl", layerColl)
# set active collection to the collection # set active collection to the collection
bpy.context.view_layer.active_layer_collection = layerColl bpy.context.view_layer.active_layer_collection = layerColl

View File

@ -1,6 +1,8 @@
from bpy_types import (Operator) from bpy_types import (Operator)
from bpy.props import (EnumProperty) from bpy.props import (EnumProperty)
from ..settings import clear_settings
class BLENVY_OT_tooling_switch(Operator): class BLENVY_OT_tooling_switch(Operator):
"""Switch blenvy tooling""" """Switch blenvy tooling"""
bl_idname = "bevy.tooling_switch" bl_idname = "bevy.tooling_switch"
@ -26,8 +28,6 @@ class BLENVY_OT_tooling_switch(Operator):
context.window_manager.blenvy.mode = self.tool context.window_manager.blenvy.mode = self.tool
return {'FINISHED'} return {'FINISHED'}
class BLENVY_OT_configuration_switch(Operator): class BLENVY_OT_configuration_switch(Operator):
"""Switch tooling configuration""" """Switch tooling configuration"""
bl_idname = "bevy.config_switch" bl_idname = "bevy.config_switch"
@ -49,4 +49,21 @@ class BLENVY_OT_configuration_switch(Operator):
def execute(self, context): def execute(self, context):
context.window_manager.blenvy.config_mode = self.tool context.window_manager.blenvy.config_mode = self.tool
return {'FINISHED'} return {'FINISHED'}
class BLENVY_OT_configuration_reset(Operator):
"""Reset all blenvy settings to default"""
bl_idname = "bevy.config_reset"
bl_label = "Clear stored setting & reset configuration to default"
#bl_options = {}
def execute(self, context):
print("reset configuration")
blenvy = context.window_manager.blenvy
try:
blenvy.reset_settings()
except Exception as error:
self.report({"ERROR"}, f"Failed to reset settings: {error}")
return {"CANCELLED"}
return {'FINISHED'}

View File

@ -16,69 +16,92 @@ from ..blenvy_manager import BlenvyManager
- or alternative: sub menu to choose instance creation or not - or alternative: sub menu to choose instance creation or not
- [x] save & restore blenvy mode - [x] save & restore blenvy mode
- [x] add a contextual shortcut to easilly jump in/out of editing mode - [x] add a contextual shortcut to easilly jump in/out of editing mode
- [ ] if editing is already in progress close it first - [x] if editing is already in progress close it first
- [ ] do this for the wrapper - [x] do this for the wrapper
- [x] do this for the shortcut - [x] do this for the shortcut
- [ ] move the "close first" logic to inside create & edit operators - [x] move the "close first" logic to inside create & edit operators
- [ ] also allow triggering editing from library scene with collection selected - [ ] also allow triggering editing from library scene with collection selected
=> requires checking if collection is a blueprint's collection => requires checking if collection is a blueprint's collection
- [x] do not go in create mode if there is an object (not a collection !) selected - [x] do not go in create mode if there is an object (not a collection !) selected
- [ ] save & reset camera - [x] save & reset camera
""" """
def edit_or_create_blueprint_menu(self, context): def edit_or_create_blueprint_menu(self, context):
if bpy.context.active_object and bpy.context.active_object.instance_collection: blenvy = context.window_manager.blenvy # type: BlenvyManager
self.layout.operator(BLENVY_OT_ui_blueprint_edit_start.bl_idname) selected_objects = context.selected_objects
selected_object = selected_objects[0] if len(selected_objects) > 0 else None
text = ""
if selected_object is not None and selected_object.instance_collection:
if blenvy.edit_blueprint_current_scene != "": # if there is already editing in progress, close it first
text = "Exit editing previous Blueprint and start editing Blueprint"
else:
text = "Start editing Blueprint"
else: else:
blenvy = context.window_manager.blenvy # type: BlenvyManager
prev_scene = bpy.data.scenes.get(blenvy.edit_blueprint_previous_scene) prev_scene = bpy.data.scenes.get(blenvy.edit_blueprint_previous_scene)
if prev_scene is not None: if prev_scene is not None:
self.layout.operator(BLENVY_OT_ui_blueprint_edit_end.bl_idname) text = "Exit editing Blueprint"
else: else:
self.layout.operator(BLENVY_OT_ui_blueprint_create.bl_idname) if len(selected_objects) == 0: # do not go into creation mode if any object was selected
if blenvy.edit_blueprint_current_scene != "": # if there is already editing in progress, close it first
text = "Exit editing previous Blueprint and start editing new Blueprint"
else:
text = "Create & start editing Blueprint"
self.layout.operator(BLENVY_OT_ui_blueprint_create_or_edit.bl_idname, text=text)
# for camera save & reset
def find_area():
try:
for a in bpy.data.window_managers[0].windows[0].screen.areas:
if a.type == "VIEW_3D":
return a
return None
except:
return None
def find_viewport_camera(): def find_viewport_camera():
def find_area():
try:
for a in bpy.data.window_managers[0].windows[0].screen.areas:
if a.type == "VIEW_3D":
return a
return None
except:
return None
area = find_area() area = find_area()
if area is None: if area is None:
print("area not find") return None
else: else:
# print(dir(area)) # print(dir(area))
r3d = area.spaces[0].region_3d region_3D = area.spaces[0].region_3d
view_mat = r3d.view_matrix view_mat = region_3D.view_matrix
print("view matrix: ", view_mat)
loc, rot, sca = view_mat.decompose() loc, rot, sca = view_mat.decompose()
print("location xyz: ", loc) """print("location xyz: ", loc)
print("rotation wxyz: ", rot) print("rotation wxyz: ", rot)
print("scale xyz: ", sca) print("scale xyz: ", sca)
print("") print("")
print("view_distance: ", r3d.view_distance) print("view_distance: ", region_3D.view_distance)
print("view_location: ", r3d.view_location) print("view_location: ", region_3D.view_location)
print("view_rotation: ", r3d.view_rotation) print("view_rotation: ", region_3D.view_rotation)
print("view_camera_zoom: ", r3d.view_camera_zoom) print("view_camera_zoom: ", region_3D.view_camera_zoom)
print("view_distance: ", r3d.view_distance) print("view_camera_offset: ", region_3D.view_camera_offset)"""
print("view_camera_offset: ", r3d.view_camera_offset) return (region_3D.view_distance, region_3D.view_location)
def set_viewport_camera(view_distance, view_location):
area = find_area()
if area is None or view_distance == 0.0:
return None
else:
region_3D = area.spaces[0].region_3d
region_3D.view_distance = view_distance
region_3D.view_location = view_location
class BLENVY_OT_ui_blueprint_create_or_edit(bpy.types.Operator): class BLENVY_OT_ui_blueprint_create_or_edit(bpy.types.Operator):
"""Create Blueprint in a new Scene""" """Create/Edit start/stop Blueprint in a new Scene"""
bl_idname = "window_manager.blenvy_blueprint_shortcut" bl_idname = "window_manager.blenvy_blueprint_shortcut"
bl_label = "Edit Blueprint" bl_label = "Edit Blueprint"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def execute(self, context): def execute(self, context):
blenvy = context.window_manager.blenvy # type: BlenvyManager blenvy = context.window_manager.blenvy # type: BlenvyManager
if bpy.context.active_object and bpy.context.active_object.instance_collection: selected_objects = context.selected_objects
selected_object = selected_objects[0] if len(selected_objects) > 0 else None
if selected_object is not None and selected_object.instance_collection:
if blenvy.edit_blueprint_current_scene != "": # if there is already editing in progress, close it first if blenvy.edit_blueprint_current_scene != "": # if there is already editing in progress, close it first
bpy.ops.window_manager.blenvy_exit_edit_blueprint() bpy.ops.window_manager.blenvy_exit_edit_blueprint()
bpy.ops.window_manager.blenvy_blueprint_edit_start() bpy.ops.window_manager.blenvy_blueprint_edit_start()
@ -88,7 +111,7 @@ class BLENVY_OT_ui_blueprint_create_or_edit(bpy.types.Operator):
if prev_scene is not None: if prev_scene is not None:
bpy.ops.window_manager.blenvy_exit_edit_blueprint() bpy.ops.window_manager.blenvy_exit_edit_blueprint()
else: else:
if len(context.selected_objects) == 0: # do not go into creation mode if any object was selected if len(selected_objects) == 0: # do not go into creation mode if any object was selected
if blenvy.edit_blueprint_current_scene != "": # if there is already editing in progress, close it first if blenvy.edit_blueprint_current_scene != "": # if there is already editing in progress, close it first
bpy.ops.window_manager.blenvy_exit_edit_blueprint() bpy.ops.window_manager.blenvy_exit_edit_blueprint()
bpy.ops.window_manager.blenvy_create_blueprint() bpy.ops.window_manager.blenvy_create_blueprint()
@ -118,12 +141,11 @@ class BLENVY_OT_ui_blueprint_create(bpy.types.Operator):
if len(blenvy.library_scenes_names) > 0: if len(blenvy.library_scenes_names) > 0:
library_scene_name = blenvy.library_scenes_names[0] library_scene_name = blenvy.library_scenes_names[0]
else: else:
bpy.data.scenes.new(library_scene_name) scene = bpy.data.scenes.new(library_scene_name)
scene.blenvy_scene_type = "Library"
# automatically add it to the library : find library scene, if any, if not, create it # automatically add it to the library : find library scene, if any, if not, create it
bpy.data.scenes[library_scene_name].collection.children.link(collection) bpy.data.scenes[library_scene_name].collection.children.link(collection)
# create an instance of the blueprint ONLY the current scene we are in is a level scene # create an instance of the blueprint ONLY the current scene we are in is a level scene
if context.scene.blenvy_scene_type == 'Level': if context.scene.blenvy_scene_type == 'Level':
@ -143,6 +165,7 @@ class BLENVY_OT_ui_blueprint_create(bpy.types.Operator):
new_scene = bpy.context.scene new_scene = bpy.context.scene
new_scene.name = scene_name new_scene.name = scene_name
bpy.context.window.scene = new_scene bpy.context.window.scene = new_scene
new_scene.blenvy_scene_type = 'None'
new_scene.collection.children.link(collection) new_scene.collection.children.link(collection)
@ -187,59 +210,21 @@ class BLENVY_OT_ui_blueprint_edit_start(bpy.types.Operator):
new_scene.name = scene_name new_scene.name = scene_name
bpy.context.window.scene = new_scene bpy.context.window.scene = new_scene
new_scene.collection.children.link(collection) new_scene.collection.children.link(collection)
new_scene.blenvy_scene_type = 'None'
# flag the current temporary scene as an active edit # flag the current temporary scene as an active edit
blenvy.edit_blueprint_current_scene = scene_name blenvy.edit_blueprint_current_scene = scene_name
# Assuming you want to focus on the objects from the linked collection
# Switch to the new scene context
"""blenvy.edit_collection_world_texture = "checker"
if blenvy.edit_collection_world_texture != "none":
world = bpy.data.worlds.new(bpy.context.scene.name)
new_scene.world = world
world.use_nodes = True
tree = world.node_tree
if blenvy.edit_collection_world_texture in ["checker", "checker_view"]:
checker_texture = tree.nodes.new("ShaderNodeTexChecker")
checker_texture.inputs["Scale"].default_value = 20
checker_texture.location = Vector((-250, 0))
if blenvy.edit_collection_world_texture == "checker_view":
coord = tree.nodes.new("ShaderNodeTexCoord")
coord.location = Vector((-500, 0))
for op in coord.outputs:
op.hide = True
tree.links.new(coord.outputs["Window"], checker_texture.inputs["Vector"])
tree.links.new(checker_texture.outputs["Color"], tree.nodes["Background"].inputs["Color"])
elif blenvy.edit_collection_world_texture == "gray":
tree.nodes["Background"].inputs["Color"].default_value = (.3, .3, .3, 1)"""
# deselect all objects then select the first object in new scene # deselect all objects then select the first object in new scene
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action='DESELECT')
# find the root object # backup view distance
if len(collection.objects) > 0 : view_distance, view_location = find_viewport_camera()
root_obj = collection.objects[0] if view_distance is not None:
while root_obj.parent: blenvy.edit_blueprint_previous_view_distance = view_distance
root_obj = root_obj.parent blenvy.edit_blueprint_previous_view_position = view_location
# focus on objects in the temp scene
# select object and children bpy.ops.view3d.view_all()
new_scene.objects[root_obj.name].select_set(True)
# def select_children(parent):
# for child in parent.children:
# child.select_set(True)
# select_children(child) # Recursively select further descendants
# select_children(root_obj);
# Select the view layer and view the selected objects
bpy.context.view_layer.objects.active = new_scene.objects[root_obj.name]
bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children[collection.name]
# zoom to selected
bpy.ops.view3d.view_selected()
# now that the 3d view has been adapted, we select what we actually need: the collection/blueprint # now that the 3d view has been adapted, we select what we actually need: the collection/blueprint
bpy.ops.blenvy.select_item(target_name=collection.name, item_type="COLLECTION", override_scene_name=scene_name) bpy.ops.blenvy.select_item(target_name=collection.name, item_type="COLLECTION", override_scene_name=scene_name)
@ -260,10 +245,10 @@ class BLENVY_OT_ui_blueprint_edit_end(bpy.types.Operator):
# we are done editing the blueprint, reset settings to the way they were before # we are done editing the blueprint, reset settings to the way they were before
blenvy.edit_blueprint_previous_scene = "" blenvy.edit_blueprint_previous_scene = ""
blenvy.mode = blenvy.edit_blueprint_previous_mode blenvy.mode = blenvy.edit_blueprint_previous_mode
set_viewport_camera(blenvy.edit_blueprint_previous_view_distance, blenvy.edit_blueprint_previous_view_position)
if prev_scene is None: if prev_scene is None:
print("No scene to return to") self.report({"WARNING"}, "No scene to return to")
return {'CANCELLED'} return {'CANCELLED'}
if blenvy.edit_blueprint_current_scene != "": if blenvy.edit_blueprint_current_scene != "":
active_edit_scene = bpy.data.scenes.get(blenvy.edit_blueprint_current_scene, None) active_edit_scene = bpy.data.scenes.get(blenvy.edit_blueprint_current_scene, None)
@ -278,17 +263,12 @@ class BLENVY_OT_ui_blueprint_edit_end(bpy.types.Operator):
bpy.context.window.scene = prev_scene bpy.context.window.scene = prev_scene
except: except:
bpy.context.window.scene = prev_scene bpy.context.window.scene = prev_scene
"""if current_scene.name.startswith("EDITING:"):
bpy.data.scenes.remove(bpy.context.scene)
bpy.context.window.scene = prev_scene"""
blenvy.edit_blueprint_current_scene = ""
blenvy.edit_blueprint_current_scene = ""
else: else:
blenvy.edit_blueprint_current_scene = "" blenvy.edit_blueprint_current_scene = ""
print("Not in temp scene") self.report({"WARNING"}, "Not currently in Blueprint editing scene")
return {'CANCELLED'} return {'CANCELLED'}
return {'FINISHED'} return {'FINISHED'}

View File

@ -182,4 +182,9 @@ def draw_common_settings_ui(layout, settings):
remove_operator.action = 'REMOVE' remove_operator.action = 'REMOVE'
remove_operator.scene_type = 'LEVEL' remove_operator.scene_type = 'LEVEL'
remove_operator.scene_name = scene.name remove_operator.scene_name = scene.name
col.separator() col.separator()
# reset settings
row = section.row()
row.label(text="Reset settings")
row.operator("bevy.config_reset")

View File

@ -25,6 +25,14 @@ def load_settings(name):
return None return None
return None return None
def clear_settings(name):
texts = bpy.data.texts
stored_settings = texts.get(name, None)
if stored_settings is not None:
stored_settings.clear()
texts.remove(texts[name], do_unlink=True)
# given the input (actual) settings, filters out any invalid/useless params & params that are equal to defaults # given the input (actual) settings, filters out any invalid/useless params & params that are equal to defaults
def generate_complete_settings_dict(settings, presets, ignore_list=[], preset_defaults=True): def generate_complete_settings_dict(settings, presets, ignore_list=[], preset_defaults=True):