Add keymaps, specials menu and auto center view checkbox #3
3
.gitignore
vendored
3
.gitignore
vendored
@ -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 |
@ -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)
|
||||
|
281
__init__.py
281
__init__.py
@ -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()
|
||||
|
@ -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 |
@ -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 |
Loading…
Reference in New Issue
Block a user