Add keymaps, specials menu and auto center view checkbox #3

Merged
dupoxy merged 10 commits from add-keymaps into main 2024-09-21 20:42:48 +02:00
8 changed files with 263 additions and 35 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
C3DB-0.0.4.zip
*.zip
*.*~

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -37,5 +37,11 @@ For 3.3 LTS and 3.6 LTS go to [<blender4.2 branch](https://projects.blender.or
5. **Going to a 3D Cursor:**
- Click on the `Centre View` button. Centers the view on the 3D Cursor.
- Use the checkbox to Automaticely Centre View when Loading a 3D Cursor
6. **3D Cursor Specials menu:**
- Load next 3D Cursor : Go to the next 3D Cursor and Load/Restore it.
- Load previous 3D Cursor : Go to the previous 3D Cursor and Load/Restore it.
- Delete All 3D Cursors : Delete all 3D Cursors from the list.
[LICENSE](LICENSE)

View File

@ -2,19 +2,37 @@
import bpy
class C3DB_PG_properties(bpy.types.PropertyGroup):
location: bpy.props.FloatVectorProperty(name="Location")
rotation: bpy.props.FloatVectorProperty(name="Rotation")
class C3DB_MT_menu_restore(bpy.types.Menu):
bl_label = "3D Cursor Specials"
bl_idname = "C3DB_MT_menu_restore"
def draw(self, context):
layout = self.layout
layout.operator("c3db.restore_next")
layout.operator("c3db.restore_previous")
layout.separator()
layout.operator("c3db.delete_all")
class C3DB_UL_list(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
def draw_item(
self, context, layout, data, item, icon, active_data, active_propname, index
):
layout.prop(item, "name", text="", emboss=False)
class C3DB_OT_save(bpy.types.Operator):
"""Save 3D Cursor location and rotation"""
bl_idname = "c3db.save"
bl_label = "Save"
bl_options = {'REGISTER', 'UNDO'}
bl_label = "Save 3D Cursor"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
item = context.scene.C3DB_3Dcursors_collection.add()
@ -22,35 +40,138 @@ class C3DB_OT_save(bpy.types.Operator):
item.location = context.scene.cursor.location
item.rotation = context.scene.cursor.rotation_euler
# Select the 3D cursor currently saving from the list
context.scene.C3DB_3Dcursors_index = len(context.scene.C3DB_3Dcursors_collection) - 1
return {'FINISHED'}
context.scene.C3DB_3Dcursors_index = (
len(context.scene.C3DB_3Dcursors_collection) - 1
)
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_OT_restore(bpy.types.Operator):
"""Restore selected 3D Cursor"""
bl_idname = "c3db.restore"
bl_label = "Load"
bl_options = {'REGISTER', 'UNDO'}
bl_label = "Load 3D Cursor"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return bool(context.scene.C3DB_3Dcursors_collection) and context.scene.C3DB_3Dcursors_index < len(context.scene.C3DB_3Dcursors_collection)
return bool(
context.scene.C3DB_3Dcursors_collection
) and context.scene.C3DB_3Dcursors_index < len(
context.scene.C3DB_3Dcursors_collection
)
def execute(self, context):
if context.scene.C3DB_3Dcursors_collection:
item = context.scene.C3DB_3Dcursors_collection[context.scene.C3DB_3Dcursors_index]
item = context.scene.C3DB_3Dcursors_collection[
context.scene.C3DB_3Dcursors_index
]
context.scene.cursor.location = item.location
context.scene.cursor.rotation_euler = item.rotation
return {'FINISHED'}
if context.scene.c3db_auto_center_view_checkbox:
bpy.ops.view3d.view_center_cursor()
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_OT_remove_from_list(bpy.types.Operator):
"""Delete selected 3D Cursor from the list"""
bl_idname = "c3db.remove_from_list"
bl_label = "Delete"
bl_options = {'REGISTER', 'UNDO'}
class C3DB_OT_restore_next(bpy.types.Operator):
"""Go to next 3D Cursor and Restore it"""
bl_idname = "c3db.restore_next"
bl_label = "Load next 3D Cursor"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return bool(context.scene.C3DB_3Dcursors_collection) and context.scene.C3DB_3Dcursors_index < len(context.scene.C3DB_3Dcursors_collection)
return (
bool(context.scene.C3DB_3Dcursors_collection)
and len(context.scene.C3DB_3Dcursors_collection) > 1
)
def execute(self, context):
# Select the next valid 3D cursor in the list
C3DB_3Dcursors_collection = context.scene.C3DB_3Dcursors_collection
C3DB_3Dcursors_index = context.scene.C3DB_3Dcursors_index
if C3DB_3Dcursors_index < len(C3DB_3Dcursors_collection) - 1:
context.scene.C3DB_3Dcursors_index = C3DB_3Dcursors_index + 1
elif C3DB_3Dcursors_index == len(C3DB_3Dcursors_collection) - 1:
context.scene.C3DB_3Dcursors_index = 0
# Restore selected 3D cursor in the list
if context.scene.C3DB_3Dcursors_collection:
item = context.scene.C3DB_3Dcursors_collection[
context.scene.C3DB_3Dcursors_index
]
context.scene.cursor.location = item.location
context.scene.cursor.rotation_euler = item.rotation
if context.scene.c3db_auto_center_view_checkbox:
bpy.ops.view3d.view_center_cursor()
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_OT_restore_previous(bpy.types.Operator):
"""Go to previous 3D Cursor and Restore it"""
bl_idname = "c3db.restore_previous"
bl_label = "Load previous 3D Cursor"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return (
bool(context.scene.C3DB_3Dcursors_collection)
and len(context.scene.C3DB_3Dcursors_collection) > 1
)
def execute(self, context):
# Select the previous valid 3D cursor in the list
C3DB_3Dcursors_collection = context.scene.C3DB_3Dcursors_collection
C3DB_3Dcursors_index = context.scene.C3DB_3Dcursors_index
if C3DB_3Dcursors_index > 0:
context.scene.C3DB_3Dcursors_index = C3DB_3Dcursors_index - 1
elif C3DB_3Dcursors_index == 0:
context.scene.C3DB_3Dcursors_index = len(C3DB_3Dcursors_collection) - 1
# Restore selected 3D cursor in the list
if context.scene.C3DB_3Dcursors_collection:
item = context.scene.C3DB_3Dcursors_collection[
context.scene.C3DB_3Dcursors_index
]
context.scene.cursor.location = item.location
context.scene.cursor.rotation_euler = item.rotation
if context.scene.c3db_auto_center_view_checkbox:
bpy.ops.view3d.view_center_cursor()
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_OT_delete_all(bpy.types.Operator):
"""Delete all 3D Cursors"""
bl_idname = "c3db.delete_all"
bl_label = "Delete All 3D Cursors"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
context.scene.C3DB_3Dcursors_collection.clear()
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_OT_remove_from_list(bpy.types.Operator):
"""Delete selected 3D Cursor"""
bl_idname = "c3db.remove_from_list"
bl_label = "Delete 3D Cursor"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return bool(
context.scene.C3DB_3Dcursors_collection
) and context.scene.C3DB_3Dcursors_index < len(
context.scene.C3DB_3Dcursors_collection
)
def execute(self, context):
C3DB_3Dcursors_collection = context.scene.C3DB_3Dcursors_collection
@ -63,10 +184,13 @@ class C3DB_OT_remove_from_list(bpy.types.Operator):
context.scene.C3DB_3Dcursors_index = C3DB_3Dcursors_index
elif C3DB_3Dcursors_collection:
context.scene.C3DB_3Dcursors_index = len(C3DB_3Dcursors_collection) - 1
return {'FINISHED'}
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_OT_move_up_list(bpy.types.Operator):
"""Move the selected 3D Cursor up in the list"""
bl_idname = "c3db.move_up_list"
bl_label = "Move 3D Cursor Up the list"
@ -79,29 +203,37 @@ class C3DB_OT_move_up_list(bpy.types.Operator):
collection = context.scene.C3DB_3Dcursors_collection
collection.move(index, index - 1)
context.scene.C3DB_3Dcursors_index -= 1
return {'FINISHED'}
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_OT_move_down_list(bpy.types.Operator):
"""Move the selected 3D Cursor down in the list"""
bl_idname = "c3db.move_down_list"
bl_label = "Move 3D Cursor Down the list"
@classmethod
def poll(cls, context):
return context.scene.C3DB_3Dcursors_index < len(context.scene.C3DB_3Dcursors_collection) - 1
return (
context.scene.C3DB_3Dcursors_index
< len(context.scene.C3DB_3Dcursors_collection) - 1
)
def execute(self, context):
index = context.scene.C3DB_3Dcursors_index
collection = context.scene.C3DB_3Dcursors_collection
collection.move(index, index + 1)
context.scene.C3DB_3Dcursors_index += 1
return {'FINISHED'}
context.area.tag_redraw() # Refresh the UI
return {"FINISHED"}
class C3DB_PT_panel(bpy.types.Panel):
bl_label = "3D Cursors 💼"
bl_idname = "C3DB_PT_panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "View"
bl_parent_id = "VIEW3D_PT_view3d_cursor"
@ -109,31 +241,118 @@ class C3DB_PT_panel(bpy.types.Panel):
layout = self.layout
row = layout.row()
col = row.column()
col.template_list("C3DB_UL_list", "", context.scene, "C3DB_3Dcursors_collection", context.scene, "C3DB_3Dcursors_index", rows=3)
col.template_list(
"C3DB_UL_list",
"",
context.scene,
"C3DB_3Dcursors_collection",
context.scene,
"C3DB_3Dcursors_index",
rows=3,
)
col = row.column(align=True)
col.operator("c3db.save", icon='ADD', text="")
col.operator("c3db.remove_from_list", icon='REMOVE', text="")
col.operator("c3db.save", icon="ADD", text="")
col.operator("c3db.remove_from_list", icon="REMOVE", text="")
col.separator()
if context.scene.C3DB_3Dcursors_collection and context.scene.C3DB_3Dcursors_index < len(context.scene.C3DB_3Dcursors_collection):
col.operator("c3db.move_up_list", icon='TRIA_UP', text="")
col.operator("c3db.move_down_list", icon='TRIA_DOWN', text="")
col.menu("C3DB_MT_menu_restore", icon="DOWNARROW_HLT", text="")
col.separator()
if (
context.scene.C3DB_3Dcursors_collection
and context.scene.C3DB_3Dcursors_index
< len(context.scene.C3DB_3Dcursors_collection)
):
col.operator("c3db.move_up_list", icon="TRIA_UP", text="")
col.operator("c3db.move_down_list", icon="TRIA_DOWN", text="")
row = layout.row()
row.operator("c3db.restore")
row.operator("c3db.restore", text="Load")
row.operator("view3d.view_center_cursor", text="Center View")
row.prop(context.scene, "c3db_auto_center_view_checkbox")
classes = (
C3DB_PG_properties,
C3DB_UL_list,
C3DB_MT_menu_restore,
C3DB_OT_save,
C3DB_OT_restore,
C3DB_OT_restore_next,
C3DB_OT_restore_previous,
C3DB_OT_delete_all,
C3DB_OT_remove_from_list,
C3DB_OT_move_up_list,
C3DB_OT_move_down_list,
C3DB_PT_panel,
)
c3db_keymaps = []
classes = (C3DB_PG_properties, C3DB_UL_list, C3DB_OT_save, C3DB_OT_restore, C3DB_OT_remove_from_list, C3DB_OT_move_up_list, C3DB_OT_move_down_list, C3DB_PT_panel)
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.Scene.C3DB_3Dcursors_collection = bpy.props.CollectionProperty(type=C3DB_PG_properties)
bpy.types.Scene.C3DB_3Dcursors_collection = bpy.props.CollectionProperty(
type=C3DB_PG_properties
)
bpy.types.Scene.C3DB_3Dcursors_index = bpy.props.IntProperty()
bpy.types.Scene.c3db_auto_center_view_checkbox = bpy.props.BoolProperty(
name="", description="Auto center view on 3D Cursor", default=False
)
wm = bpy.context.window_manager
km = wm.keyconfigs.addon.keymaps.new(name="3D View", space_type="VIEW_3D")
kmi = km.keymap_items.new(
C3DB_OT_save.bl_idname, "S", "PRESS", ctrl=True, shift=True
)
c3db_keymaps.append((km, kmi))
kmi = km.keymap_items.new(
C3DB_OT_remove_from_list.bl_idname, "D", "PRESS", ctrl=True, shift=True
)
c3db_keymaps.append((km, kmi))
kmi = km.keymap_items.new(C3DB_OT_restore.bl_idname, "R", "PRESS", ctrl=True)
c3db_keymaps.append((km, kmi))
kmi = km.keymap_items.new(
C3DB_OT_restore_next.bl_idname, "R", "PRESS", ctrl=True, shift=True
)
c3db_keymaps.append((km, kmi))
kmi = km.keymap_items.new(
C3DB_OT_restore_previous.bl_idname,
"R",
"PRESS",
ctrl=True,
shift=True,
alt=True,
)
c3db_keymaps.append((km, kmi))
kmi = km.keymap_items.new(
C3DB_OT_delete_all.bl_idname,
"X",
"PRESS",
ctrl=True,
shift=True,
)
c3db_keymaps.append((km, kmi))
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
del bpy.types.Scene.C3DB_3Dcursors_collection
del bpy.types.Scene.C3DB_3Dcursors_index
del bpy.types.Scene.c3db_auto_center_view_checkbox
wm = bpy.context.window_manager
for km, kmi in c3db_keymaps:
km.keymap_items.remove(kmi)
c3db_keymaps.clear()
if __name__ == "__main__":
register()

View File

@ -1,7 +1,7 @@
schema_version = "1.0.0"
id = "C3DB"
name = "3D Cursors Briefcase"
version = "0.0.4"
version = "0.0.5"
tagline = "Store and manage multiple 3D Cursors"
maintainer = "dupoxy"
type = "add-on"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -1,5 +1,7 @@
for video I used a screen size off 1920x1080 in OBS, machine screen is at 1920x1200
blender Interface display resolution scale to 1.35
blender Interface display resolution scale to 1.36
for image
blender Interface display resolution scale to 4.00
blender Interface display resolution scale to 4.00 : icon.png, Featured image.png
blender Interface display resolution scale to 2.00 : 3d-cursors-case-guide.png
blender Interface display resolution scale to 1.36 : Show-off.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 KiB

After

Width:  |  Height:  |  Size: 344 KiB