├── .gitignore
├── icons
├── align_n.png
├── align_x.png
├── align_y.png
├── align_z.png
├── event_x.png
├── event_y.png
├── event_z.png
├── rota_x.png
├── rota_y.png
├── rota_z.png
├── scale_x.png
├── scale_y.png
├── scale_z.png
├── world_x.png
├── world_y.png
├── world_z.png
├── align_xy.png
├── align_xyz.png
├── align_zx.png
├── align_zy.png
├── annotate.png
├── event_xy.png
├── event_zx.png
├── event_zy.png
├── rota_xyz.png
├── scale_xyz.png
├── snap_grid.png
├── snap_move.png
├── snap_set.png
├── world_xyz.png
├── align_both.png
├── align_circle.png
├── align_curve.png
├── align_smooth.png
├── align_space.png
├── snap_active.png
├── snap_center.png
├── snap_closest.png
├── snap_cursor.png
├── snap_custom.png
├── snap_measure.png
├── snap_pcursor.png
├── snap_place.png
├── snap_retopo.png
├── snap_rotate.png
├── snap_scale.png
├── align_flatten.png
├── align_radians.png
├── align_unbevel.png
├── align_vertices.png
├── annotate_line.png
├── cursor_loca_x.png
├── cursor_loca_y.png
├── cursor_loca_z.png
├── cursor_rota_x.png
├── cursor_rota_y.png
├── cursor_rota_z.png
├── snap_perpendic.png
├── align_distribute.png
├── align_laplacian.png
├── align_looptools.png
├── align_straigten.png
├── annotate_eraser.png
├── annotate_polygon.png
├── cursor_loca_xyz.png
├── cursor_rota_xyz.png
└── icons.py
├── images
├── menu_context.png
├── panel_layout.png
├── panel_layout2.png
├── pie_menu_layouts.png
├── panel_menu_header.png
├── menu_context_special.png
├── pie_menu_auxiliary_addons.png
├── append_functions_preferences.png
└── append_functions_to_snap_settings.png
├── view3d_snapset_updater
└── view3d_snapset_updater_status.json
├── ot_keymap.py
├── developer_utils.py
├── ui_utils.py
├── README.md
├── ui_keymap.py
├── ot_axis.py
├── ot_modal.py
├── ui_panel.py
├── ot_targets.py
├── ui_snapping.py
├── ot_custom.py
├── ui_editor.py
├── ot_cursor.py
├── ui_menu.py
└── LICENSE.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
--------------------------------------------------------------------------------
/icons/align_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_n.png
--------------------------------------------------------------------------------
/icons/align_x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_x.png
--------------------------------------------------------------------------------
/icons/align_y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_y.png
--------------------------------------------------------------------------------
/icons/align_z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_z.png
--------------------------------------------------------------------------------
/icons/event_x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/event_x.png
--------------------------------------------------------------------------------
/icons/event_y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/event_y.png
--------------------------------------------------------------------------------
/icons/event_z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/event_z.png
--------------------------------------------------------------------------------
/icons/rota_x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/rota_x.png
--------------------------------------------------------------------------------
/icons/rota_y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/rota_y.png
--------------------------------------------------------------------------------
/icons/rota_z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/rota_z.png
--------------------------------------------------------------------------------
/icons/scale_x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/scale_x.png
--------------------------------------------------------------------------------
/icons/scale_y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/scale_y.png
--------------------------------------------------------------------------------
/icons/scale_z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/scale_z.png
--------------------------------------------------------------------------------
/icons/world_x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/world_x.png
--------------------------------------------------------------------------------
/icons/world_y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/world_y.png
--------------------------------------------------------------------------------
/icons/world_z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/world_z.png
--------------------------------------------------------------------------------
/icons/align_xy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_xy.png
--------------------------------------------------------------------------------
/icons/align_xyz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_xyz.png
--------------------------------------------------------------------------------
/icons/align_zx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_zx.png
--------------------------------------------------------------------------------
/icons/align_zy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_zy.png
--------------------------------------------------------------------------------
/icons/annotate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/annotate.png
--------------------------------------------------------------------------------
/icons/event_xy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/event_xy.png
--------------------------------------------------------------------------------
/icons/event_zx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/event_zx.png
--------------------------------------------------------------------------------
/icons/event_zy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/event_zy.png
--------------------------------------------------------------------------------
/icons/rota_xyz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/rota_xyz.png
--------------------------------------------------------------------------------
/icons/scale_xyz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/scale_xyz.png
--------------------------------------------------------------------------------
/icons/snap_grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_grid.png
--------------------------------------------------------------------------------
/icons/snap_move.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_move.png
--------------------------------------------------------------------------------
/icons/snap_set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_set.png
--------------------------------------------------------------------------------
/icons/world_xyz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/world_xyz.png
--------------------------------------------------------------------------------
/icons/align_both.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_both.png
--------------------------------------------------------------------------------
/icons/align_circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_circle.png
--------------------------------------------------------------------------------
/icons/align_curve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_curve.png
--------------------------------------------------------------------------------
/icons/align_smooth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_smooth.png
--------------------------------------------------------------------------------
/icons/align_space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_space.png
--------------------------------------------------------------------------------
/icons/snap_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_active.png
--------------------------------------------------------------------------------
/icons/snap_center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_center.png
--------------------------------------------------------------------------------
/icons/snap_closest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_closest.png
--------------------------------------------------------------------------------
/icons/snap_cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_cursor.png
--------------------------------------------------------------------------------
/icons/snap_custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_custom.png
--------------------------------------------------------------------------------
/icons/snap_measure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_measure.png
--------------------------------------------------------------------------------
/icons/snap_pcursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_pcursor.png
--------------------------------------------------------------------------------
/icons/snap_place.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_place.png
--------------------------------------------------------------------------------
/icons/snap_retopo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_retopo.png
--------------------------------------------------------------------------------
/icons/snap_rotate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_rotate.png
--------------------------------------------------------------------------------
/icons/snap_scale.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_scale.png
--------------------------------------------------------------------------------
/icons/align_flatten.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_flatten.png
--------------------------------------------------------------------------------
/icons/align_radians.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_radians.png
--------------------------------------------------------------------------------
/icons/align_unbevel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_unbevel.png
--------------------------------------------------------------------------------
/icons/align_vertices.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_vertices.png
--------------------------------------------------------------------------------
/icons/annotate_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/annotate_line.png
--------------------------------------------------------------------------------
/icons/cursor_loca_x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_loca_x.png
--------------------------------------------------------------------------------
/icons/cursor_loca_y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_loca_y.png
--------------------------------------------------------------------------------
/icons/cursor_loca_z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_loca_z.png
--------------------------------------------------------------------------------
/icons/cursor_rota_x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_rota_x.png
--------------------------------------------------------------------------------
/icons/cursor_rota_y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_rota_y.png
--------------------------------------------------------------------------------
/icons/cursor_rota_z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_rota_z.png
--------------------------------------------------------------------------------
/icons/snap_perpendic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/snap_perpendic.png
--------------------------------------------------------------------------------
/images/menu_context.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/menu_context.png
--------------------------------------------------------------------------------
/images/panel_layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/panel_layout.png
--------------------------------------------------------------------------------
/images/panel_layout2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/panel_layout2.png
--------------------------------------------------------------------------------
/icons/align_distribute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_distribute.png
--------------------------------------------------------------------------------
/icons/align_laplacian.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_laplacian.png
--------------------------------------------------------------------------------
/icons/align_looptools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_looptools.png
--------------------------------------------------------------------------------
/icons/align_straigten.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/align_straigten.png
--------------------------------------------------------------------------------
/icons/annotate_eraser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/annotate_eraser.png
--------------------------------------------------------------------------------
/icons/annotate_polygon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/annotate_polygon.png
--------------------------------------------------------------------------------
/icons/cursor_loca_xyz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_loca_xyz.png
--------------------------------------------------------------------------------
/icons/cursor_rota_xyz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/icons/cursor_rota_xyz.png
--------------------------------------------------------------------------------
/images/pie_menu_layouts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/pie_menu_layouts.png
--------------------------------------------------------------------------------
/images/panel_menu_header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/panel_menu_header.png
--------------------------------------------------------------------------------
/images/menu_context_special.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/menu_context_special.png
--------------------------------------------------------------------------------
/images/pie_menu_auxiliary_addons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/pie_menu_auxiliary_addons.png
--------------------------------------------------------------------------------
/images/append_functions_preferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/append_functions_preferences.png
--------------------------------------------------------------------------------
/images/append_functions_to_snap_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkbreuer/view3d_snapset/HEAD/images/append_functions_to_snap_settings.png
--------------------------------------------------------------------------------
/view3d_snapset_updater/view3d_snapset_updater_status.json:
--------------------------------------------------------------------------------
1 | {
2 | "last_check": "2020-01-12 10:40:34.230532",
3 | "backup_date": "",
4 | "update_ready": false,
5 | "ignore": false,
6 | "just_restored": false,
7 | "just_updated": false,
8 | "version_text": {}
9 | }
--------------------------------------------------------------------------------
/ot_keymap.py:
--------------------------------------------------------------------------------
1 | # LOAD MODULE #
2 | import bpy
3 | from bpy import*
4 | from bpy.props import*
5 |
6 | from os.path import dirname
7 | from . import ui_keymap
8 |
9 | class VIEW3D_OT_keymap_snapset(bpy.types.Operator):
10 | bl_idname = "tpc_ot.keymap_snapset"
11 | bl_label = "Keys in Text Editor"
12 | bl_description = "open keymap file in the text editor"
13 |
14 | def execute(self, context):
15 | path = ui_keymap.__file__
16 | bpy.data.texts.load(path)
17 |
18 | bpy.ops.screen.userpref_show('INVOKE_DEFAULT')
19 |
20 | for window in context.window_manager.windows:
21 | if len(window.screen.areas) == 1 and window.screen.areas[0].type == 'PREFERENCES':
22 | window.screen.areas[0].type = 'TEXT_EDITOR'
23 |
24 | bpy.context.space_data.show_line_numbers = True
25 | bpy.context.space_data.show_syntax_highlight = True
26 |
27 | return {"FINISHED"}
28 |
29 |
--------------------------------------------------------------------------------
/developer_utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import pkgutil
4 | import importlib
5 |
6 | def setup_addon_modules(path, package_name, reload):
7 | """
8 | Imports and reloads all modules in this addon.
9 |
10 | path -- __path__ from __init__.py
11 | package_name -- __name__ from __init__.py
12 |
13 | Individual modules can define a __reload_order_index__ property which
14 | will be used to reload the modules in a specific order. The default is 0.
15 | """
16 | def get_submodule_names(path = path[0], root = ""):
17 | module_names = []
18 | for importer, module_name, is_package in pkgutil.iter_modules([path]):
19 | if is_package:
20 | sub_path = os.path.join(path, module_name)
21 | sub_root = root + module_name + "."
22 | module_names.extend(get_submodule_names(sub_path, sub_root))
23 | else:
24 | module_names.append(root + module_name)
25 | return module_names
26 |
27 | def import_submodules(names):
28 | modules = []
29 | for name in names:
30 | modules.append(importlib.import_module("." + name, package_name))
31 | return modules
32 |
33 | def reload_modules(modules):
34 | modules.sort(key = lambda module: getattr(module, "__reload_order_index__", 0))
35 | for module in modules:
36 | importlib.reload(module)
37 |
38 | names = get_submodule_names()
39 | modules = import_submodules(names)
40 | if reload:
41 | reload_modules(modules)
42 | return modules
43 |
--------------------------------------------------------------------------------
/ui_utils.py:
--------------------------------------------------------------------------------
1 | # LOAD MODUL #
2 | import bpy
3 | import os
4 |
5 | # ADDON CHECK #
6 | import addon_utils
7 |
8 | def get_addon_prefs():
9 | addon_name = os.path.splitext(__package__)[0]
10 | preferences = bpy.context.preferences
11 | addon_prefs = preferences.addons[addon_name].preferences
12 | return (addon_prefs)
13 |
14 | def get_addon_name():
15 | return os.path.basename(os.path.dirname(os.path.realpath(__file__)))
16 |
17 | def addon_exists(name):
18 | for addon_name in bpy.context.preferences.addons.keys():
19 | if name in addon_name: return True
20 | return False
21 |
22 |
23 | class VIEW3D_OT_align_tools(bpy.types.Operator):
24 | """enable align tools (save user settings be required for a permant activation)"""
25 | bl_label = "AlignTool"
26 | bl_idname = "tpc_ot.activate_align_tools"
27 | bl_options = {'REGISTER', 'UNDO'}
28 |
29 | def execute(self, context):
30 | # check for needed addons
31 | align_tools_addon = "space_view3d_align_tools"
32 | state = addon_utils.check(align_tools_addon)
33 | if not state[0]:
34 | bpy.ops.preferences.addon_enable(module=align_tools_addon)
35 | print(self)
36 | self.report({'INFO'}, "Align Tools activated!")
37 |
38 | return {'FINISHED'}
39 |
40 |
41 | class VIEW3D_OT_align_mesh(bpy.types.Operator):
42 | """enable align mesh (save user settings be required for a permant activation)"""
43 | bl_label = "Align Mesh"
44 | bl_idname = "tpc_ot.activate_align_mesh"
45 | bl_options = {'REGISTER', 'UNDO'}
46 |
47 | def execute(self, context):
48 | # check for needed addons
49 | alignmesh_addon = "view3d_alignmesh"
50 | state = addon_utils.check(alignmesh_addon)
51 | if not state[0]:
52 | bpy.ops.preferences.addon_enable(module=alignmesh_addon)
53 | print(self)
54 | self.report({'INFO'}, "Align Mesh activated!")
55 |
56 | return {'FINISHED'}
57 |
58 |
59 | class VIEW3D_OT_looptools(bpy.types.Operator):
60 | """enable looptools (save user settings be required for a permant activation)"""
61 | bl_label = "Looptools"
62 | bl_idname = "tpc_ot.activate_looptools"
63 | bl_options = {'REGISTER', 'UNDO'}
64 |
65 | def execute(self, context):
66 | # check for needed addons
67 | loop_tools_addon = "mesh_looptools"
68 | state = addon_utils.check(loop_tools_addon)
69 | if not state[0]:
70 | bpy.ops.preferences.addon_enable(module=loop_tools_addon)
71 | print(self)
72 | self.report({'INFO'}, "LoopTools activated!")
73 |
74 | return {'FINISHED'}
75 |
76 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SnapSet - Blender Addon
2 |
3 | > Batch presets for snapping task
4 |
5 | - as durable buttons or as one time modal buttons
6 | - all buttons are full customizable
7 | - different layouts for context menus and pie menu with custom shortcut key creation
8 | - appending to different locations: editor header, special menu, snapping setting panel, etc.
9 | - with auxiliary addons for the pie menu: align objects (objectmode), looptools and align mesh (editmode)
10 |
11 | Release Download https://github.com/mkbreuer/view3d_snapset/releases
12 |
13 | ##
14 |
15 | ### Durable Tools
16 | > After execute the snap settings toggle to the needed durable preferences.
17 |
18 | - Grid > snap pivot with absolute grid alignment
19 | - Place > objectmode: snap object to surface of other objects
20 | - Retopo > editmode: snap selected onto target surface
21 | - Cursor > set 3d cursor to active or selected
22 | - Closest > snap closest point onto target
23 | - Active > snap active pivot onto target
24 | - MidPoint > snap selected onto target
25 | - Perpendic > snap selected onto target
26 | - PlaceCursor > place 3D cursor onto a target surface
27 |
28 | ### (*) Modal Tools
29 | > After execute the snap settings toggle to the needed modal preferences.
30 | > It finish the modal directly after an click and the settings switch back to the previous durable one.
31 |
32 | - Grid* > snap pivot with absolute grid alignment till release
33 | - Place* > object mode: snap object to surface of other objects till release
34 | - Retopo* > edit mode: snap selected onto target surface till release
35 | - MidPoint* > snap selected onto target till release
36 | - Perpendic* > snap selected onto target till release
37 | - PlaceCursor* > snap 3d cursor onto target surface till release
38 | - Custom* > customizable extra button
39 |
40 | ##
41 |
42 | ### Panel layout
43 | 
44 | 
45 |
46 | ### Append to header snap settings
47 | 
48 | 
49 |
50 | ### Append to context menu, key [W]
51 | 
52 |
53 | ### Custom context menu, key [customizable]
54 | 
55 |
56 | ### Custom pie menu, key [customizable]
57 | 
58 |
59 | ### Auxiliary addons for the pie menu
60 | 
61 |
62 | ### Align Mesh Addon
63 | - comes not with blender by default and must be installed separatly!
64 | - release download: https://github.com/mkbreuer/view3d_alignmesh/releases
65 |
66 | ---
67 |
68 | ### Support core Blender development - https://fund.blender.org
--------------------------------------------------------------------------------
/ui_keymap.py:
--------------------------------------------------------------------------------
1 | # LOAD MODUL #
2 | import bpy
3 | from bpy import *
4 | from .ui_utils import get_addon_prefs
5 |
6 | # ADD 3D VIEW MENU #
7 | from view3d_snapset.ui_menu import (VIEW3D_MT_snapset_menu)
8 | from view3d_snapset.ui_menu_pie_1 import (VIEW3D_MT_snapset_menu_pie_1)
9 | from view3d_snapset.ui_menu_pie_2 import (VIEW3D_MT_snapset_menu_pie_2)
10 |
11 | # KEY REGISTRY #
12 | addon_keymaps = []
13 | def update_snapset_menu(self, context):
14 |
15 | # commented: registered as sub-classes
16 | # try:
17 | # bpy.utils.unregister_class(VIEW3D_MT_snapset_menu)
18 | # bpy.utils.unregister_class(VIEW3D_MT_snapset_menu_pie_1)
19 | # bpy.utils.unregister_class(VIEW3D_MT_snapset_menu_pie_2)
20 |
21 | # # Keymapping
22 | # # remove keymaps when add-on is deactivated
23 | # for km, kmi in addon_keymaps:
24 | # km.keymap_items.remove(kmi)
25 | # # clear the list
26 | # addon_keymaps.clear()
27 |
28 | # except:
29 | # pass
30 |
31 | wm = bpy.context.window_manager
32 | kc = wm.keyconfigs.addon
33 | if kc:
34 |
35 | addon_prefs = get_addon_prefs()
36 | if addon_prefs.toggle_keymap_menus == True:
37 |
38 |
39 | if addon_prefs.toggle_keymap_type == 'menu':
40 |
41 | #bpy.utils.register_class(VIEW3D_MT_snapset_menu)
42 |
43 | km = kc.keymaps.new(name='3D View', space_type='VIEW_3D')
44 | #kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', shift=True) #, ctrl=True, alt=True)
45 |
46 | kmi = km.keymap_items.new('wm.call_menu', addon_prefs.hotkey_menu, 'PRESS', ctrl=addon_prefs.hotkey_menu_ctrl, alt=addon_prefs.hotkey_menu_alt, shift=addon_prefs.hotkey_menu_shift)
47 |
48 | kmi.properties.name = "VIEW3D_MT_snapset_menu"
49 | addon_keymaps.append((km,kmi))
50 |
51 |
52 | if addon_prefs.toggle_keymap_type == 'pie':
53 |
54 | #if addon_prefs.toggle_pie_layout == False:
55 | #bpy.utils.register_class(VIEW3D_MT_snapset_menu_pie_1)
56 | # else:
57 | #bpy.utils.register_class(VIEW3D_MT_snapset_menu_pie_2)
58 |
59 | km = kc.keymaps.new(name='3D View', space_type='VIEW_3D')
60 | #kmi = km.keymap_items.new('wm.call_menu_pie', 'W', 'PRESS', shift=True) #, ctrl=True, alt=True)
61 |
62 | kmi = km.keymap_items.new('wm.call_menu_pie', addon_prefs.hotkey_menu, 'PRESS', ctrl=addon_prefs.hotkey_menu_ctrl, alt=addon_prefs.hotkey_menu_alt, shift=addon_prefs.hotkey_menu_shift)
63 |
64 | if addon_prefs.toggle_pie_layout == False:
65 | kmi.properties.name = "VIEW3D_MT_snapset_menu_pie_1"
66 | else:
67 | kmi.properties.name = "VIEW3D_MT_snapset_menu_pie_2"
68 | addon_keymaps.append((km,kmi))
69 |
70 |
71 | if addon_prefs.toggle_keymap_menus == False:
72 |
73 | # Keymapping
74 | # remove keymaps when add-on is deactivated
75 | for km, kmi in addon_keymaps:
76 | km.keymap_items.remove(kmi)
77 | # clear the list
78 | addon_keymaps.clear()
79 |
80 |
--------------------------------------------------------------------------------
/ot_axis.py:
--------------------------------------------------------------------------------
1 | # LOAD MODUL #
2 | import bpy
3 | from bpy import *
4 | from bpy.props import *
5 |
6 | class VIEW3D_OT_align_object_to_axis(bpy.types.Operator):
7 | """align object to an axis"""
8 | bl_idname = "tpc_ot.align_object_to_axis"
9 | bl_label = "Align to Axis"
10 | bl_options = {"REGISTER", "UNDO"}
11 |
12 | @classmethod
13 | def poll(cls, context):
14 | return True
15 |
16 | use_align_axis_x : BoolProperty(name="X", description=" ", default=True, options={'SKIP_SAVE'})
17 | use_align_axis_y : BoolProperty(name="Y", description=" ", default=False, options={'SKIP_SAVE'})
18 | use_align_axis_z : BoolProperty(name="Z", description=" ", default=False, options={'SKIP_SAVE'})
19 |
20 | def draw(self, context):
21 | layout = self.layout
22 |
23 | box = layout.box().column(align=True)
24 | box.separator()
25 |
26 | row = box.row(align=True)
27 | row.label(text='Axis:')
28 | row.prop(self, 'use_align_axis_x')
29 | row.prop(self, 'use_align_axis_y')
30 | row.prop(self, 'use_align_axis_z')
31 |
32 | box.separator()
33 |
34 |
35 | def execute(self, context):
36 |
37 | view_layer = bpy.context.view_layer
38 | selected = bpy.context.selected_objects
39 | obj_list = [obj for obj in selected]
40 |
41 | if obj_list:
42 | current_mode = bpy.context.object.mode
43 | bpy.ops.object.mode_set(mode = 'OBJECT')
44 | else:
45 | self.report({'INFO'}, 'No active selection!')
46 | return {'CANCELLED'}
47 |
48 |
49 | for obj in selected:
50 | view_layer.objects.active = obj
51 |
52 | axis_x = ''
53 | axis_y = ''
54 | axis_z = ''
55 |
56 | if self.use_align_axis_x == True and self.use_align_axis_y == False and self.use_align_axis_z == False:
57 | obj.location[1] = 0
58 | axis_x = 'X Align'
59 |
60 | if self.use_align_axis_x == False and self.use_align_axis_y == True and self.use_align_axis_z == False:
61 | obj.location[0] = 0
62 | axis_y = 'Y Align'
63 |
64 | if self.use_align_axis_x == False and self.use_align_axis_y == False and self.use_align_axis_z == True:
65 | obj.location[2] = 0
66 | axis_z = 'Z Align'
67 |
68 | if self.use_align_axis_x == True and self.use_align_axis_y == True and self.use_align_axis_z == False:
69 | obj.location[1] = 0
70 | obj.location[0] = 0
71 | axis_x = 'X'
72 | axis_y = 'Y Align'
73 |
74 | if self.use_align_axis_x == True and self.use_align_axis_y == False and self.use_align_axis_z == True:
75 | obj.location[1] = 0
76 | obj.location[2] = 0
77 | axis_x = 'X'
78 | axis_z = 'Z Align'
79 |
80 | if self.use_align_axis_x == False and self.use_align_axis_y == True and self.use_align_axis_z == True:
81 | obj.location[0] = 0
82 | obj.location[2] = 0
83 | axis_y = 'Y'
84 | axis_z = 'Z Align'
85 |
86 | if self.use_align_axis_x == True and self.use_align_axis_y == True and self.use_align_axis_z == True:
87 | obj.location[0] = 0
88 | obj.location[1] = 0
89 | obj.location[2] = 0
90 | axis_x = 'X'
91 | axis_y = 'Y'
92 | axis_z = 'Z Align'
93 |
94 | bpy.ops.object.mode_set(mode=current_mode)
95 |
96 | message = ("World Axis: " + axis_x + axis_y + axis_z)
97 | self.report({'INFO'}, message)
98 | return {'FINISHED'}
99 |
100 |
101 |
--------------------------------------------------------------------------------
/icons/icons.py:
--------------------------------------------------------------------------------
1 | import os
2 | import bpy
3 | import bpy.utils.previews
4 |
5 | mkb_icon_collections = {}
6 | mkb_icons_loaded = False
7 |
8 | def load_icons():
9 | global mkb_icon_collections
10 | global mkb_icons_loaded
11 |
12 | if mkb_icons_loaded: return mkb_icon_collections["main"]
13 |
14 | mkb_icons = bpy.utils.previews.new()
15 |
16 | icons_dir = os.path.join(os.path.dirname(__file__))
17 |
18 | #--------------------------------------------
19 |
20 | mkb_icons.load("icon_snap_active", os.path.join(icons_dir, "snap_active.png"), 'IMAGE')
21 | mkb_icons.load("icon_snap_closest", os.path.join(icons_dir, "snap_closest.png"), 'IMAGE')
22 | mkb_icons.load("icon_snap_cursor", os.path.join(icons_dir, "snap_cursor.png"), 'IMAGE')
23 | mkb_icons.load("icon_snap_grid", os.path.join(icons_dir, "snap_grid.png"), 'IMAGE')
24 | mkb_icons.load("icon_snap_retopo", os.path.join(icons_dir, "snap_retopo.png"), 'IMAGE')
25 | mkb_icons.load("icon_snap_place", os.path.join(icons_dir, "snap_place.png"), 'IMAGE')
26 | mkb_icons.load("icon_snap_set", os.path.join(icons_dir, "snap_set.png"), 'IMAGE')
27 | mkb_icons.load("icon_snap_move", os.path.join(icons_dir, "snap_move.png"), 'IMAGE')
28 | mkb_icons.load("icon_snap_rotate", os.path.join(icons_dir, "snap_rotate.png"), 'IMAGE')
29 | mkb_icons.load("icon_snap_scale", os.path.join(icons_dir, "snap_scale.png"), 'IMAGE')
30 | mkb_icons.load("icon_snap_measure", os.path.join(icons_dir, "snap_measure.png"), 'IMAGE')
31 |
32 | mkb_icons.load("icon_snap_annotate", os.path.join(icons_dir, "annotate.png"), 'IMAGE')
33 | mkb_icons.load("icon_snap_annotate_line", os.path.join(icons_dir, "annotate_line.png"), 'IMAGE')
34 | mkb_icons.load("icon_snap_annotate_polygon", os.path.join(icons_dir, "annotate_polygon.png"), 'IMAGE')
35 | mkb_icons.load("icon_snap_annotate_eraser", os.path.join(icons_dir, "annotate_eraser.png"), 'IMAGE')
36 |
37 | mkb_icons.load("icon_snap_center", os.path.join(icons_dir, "snap_center.png"), 'IMAGE')
38 | mkb_icons.load("icon_snap_perpendic", os.path.join(icons_dir, "snap_perpendic.png"), 'IMAGE')
39 | mkb_icons.load("icon_snap_pcursor", os.path.join(icons_dir, "snap_pcursor.png"), 'IMAGE')
40 |
41 | mkb_icons.load("icon_snap_custom", os.path.join(icons_dir, "snap_custom.png"), 'IMAGE')
42 |
43 | mkb_icons.load("icon_align_x", os.path.join(icons_dir, "align_x.png"), 'IMAGE')
44 | mkb_icons.load("icon_align_y", os.path.join(icons_dir, "align_y.png"), 'IMAGE')
45 | mkb_icons.load("icon_align_z", os.path.join(icons_dir, "align_z.png"), 'IMAGE')
46 | mkb_icons.load("icon_align_xyz", os.path.join(icons_dir, "align_xyz.png"), 'IMAGE')
47 |
48 | mkb_icons.load("icon_align_xy", os.path.join(icons_dir, "align_xy.png"), 'IMAGE')
49 | mkb_icons.load("icon_align_zx", os.path.join(icons_dir, "align_zx.png"), 'IMAGE')
50 | mkb_icons.load("icon_align_zy", os.path.join(icons_dir, "align_zy.png"), 'IMAGE')
51 |
52 | mkb_icons.load("icon_rota_x", os.path.join(icons_dir, "rota_x.png"), 'IMAGE')
53 | mkb_icons.load("icon_rota_y", os.path.join(icons_dir, "rota_y.png"), 'IMAGE')
54 | mkb_icons.load("icon_rota_z", os.path.join(icons_dir, "rota_z.png"), 'IMAGE')
55 | mkb_icons.load("icon_rota_xyz", os.path.join(icons_dir, "rota_xyz.png"), 'IMAGE')
56 |
57 | mkb_icons.load("icon_scale_x", os.path.join(icons_dir, "scale_x.png"), 'IMAGE')
58 | mkb_icons.load("icon_scale_y", os.path.join(icons_dir, "scale_y.png"), 'IMAGE')
59 | mkb_icons.load("icon_scale_z", os.path.join(icons_dir, "scale_z.png"), 'IMAGE')
60 | mkb_icons.load("icon_scale_xyz", os.path.join(icons_dir, "scale_xyz.png"), 'IMAGE')
61 |
62 | mkb_icons.load("icon_world_x", os.path.join(icons_dir, "world_x.png"), 'IMAGE')
63 | mkb_icons.load("icon_world_y", os.path.join(icons_dir, "world_y.png"), 'IMAGE')
64 | mkb_icons.load("icon_world_z", os.path.join(icons_dir, "world_z.png"), 'IMAGE')
65 | mkb_icons.load("icon_world_xyz", os.path.join(icons_dir, "world_xyz.png"), 'IMAGE')
66 |
67 | mkb_icons.load("icon_cursor_loca_x", os.path.join(icons_dir, "cursor_loca_x.png"), 'IMAGE')
68 | mkb_icons.load("icon_cursor_loca_y", os.path.join(icons_dir, "cursor_loca_y.png"), 'IMAGE')
69 | mkb_icons.load("icon_cursor_loca_z", os.path.join(icons_dir, "cursor_loca_z.png"), 'IMAGE')
70 | mkb_icons.load("icon_cursor_loca_xyz", os.path.join(icons_dir, "cursor_loca_xyz.png"), 'IMAGE')
71 |
72 | mkb_icons.load("icon_cursor_rota_x", os.path.join(icons_dir, "cursor_rota_x.png"), 'IMAGE')
73 | mkb_icons.load("icon_cursor_rota_y", os.path.join(icons_dir, "cursor_rota_y.png"), 'IMAGE')
74 | mkb_icons.load("icon_cursor_rota_z", os.path.join(icons_dir, "cursor_rota_z.png"), 'IMAGE')
75 | mkb_icons.load("icon_cursor_rota_xyz", os.path.join(icons_dir, "cursor_rota_xyz.png"), 'IMAGE')
76 |
77 | mkb_icons.load("icon_event_x", os.path.join(icons_dir, "event_x.png"), 'IMAGE')
78 | mkb_icons.load("icon_event_y", os.path.join(icons_dir, "event_y.png"), 'IMAGE')
79 | mkb_icons.load("icon_event_z", os.path.join(icons_dir, "event_z.png"), 'IMAGE')
80 | mkb_icons.load("icon_event_xy", os.path.join(icons_dir, "event_xy.png"), 'IMAGE')
81 | mkb_icons.load("icon_event_zx", os.path.join(icons_dir, "event_zx.png"), 'IMAGE')
82 | mkb_icons.load("icon_event_zy", os.path.join(icons_dir, "event_zy.png"), 'IMAGE')
83 |
84 | mkb_icons.load("icon_align_n", os.path.join(icons_dir, "align_n.png"), 'IMAGE')
85 |
86 | mkb_icons.load("icon_align_distribute", os.path.join(icons_dir, "align_distribute.png"), 'IMAGE')
87 | mkb_icons.load("icon_align_straigten", os.path.join(icons_dir, "align_straigten.png"), 'IMAGE')
88 | mkb_icons.load("icon_align_both", os.path.join(icons_dir, "align_both.png"), 'IMAGE')
89 |
90 | mkb_icons.load("icon_align_laplacian", os.path.join(icons_dir, "align_laplacian.png"), 'IMAGE')
91 | mkb_icons.load("icon_align_looptools", os.path.join(icons_dir, "align_looptools.png"), 'IMAGE')
92 | mkb_icons.load("icon_align_vertices", os.path.join(icons_dir, "align_vertices.png"), 'IMAGE')
93 |
94 | mkb_icons.load("icon_align_space", os.path.join(icons_dir, "align_space.png"), 'IMAGE')
95 | mkb_icons.load("icon_align_circle", os.path.join(icons_dir, "align_circle.png"), 'IMAGE')
96 | mkb_icons.load("icon_align_curve", os.path.join(icons_dir, "align_curve.png"), 'IMAGE')
97 | mkb_icons.load("icon_align_flatten", os.path.join(icons_dir, "align_flatten.png"), 'IMAGE')
98 | mkb_icons.load("icon_align_smooth", os.path.join(icons_dir, "align_smooth.png"), 'IMAGE')
99 |
100 | #--------------------------------------------
101 |
102 | mkb_icon_collections["main"] = mkb_icons
103 | mkb_icons_loaded = True
104 |
105 | return mkb_icon_collections["main"]
106 |
107 | def clear_icons():
108 | global mkb_icons_loaded
109 | for icon in mkb_icon_collections.values():
110 | bpy.utils.previews.remove(icon)
111 | mkb_icon_collections.clear()
112 | mkb_icons_loaded = False
--------------------------------------------------------------------------------
/ot_modal.py:
--------------------------------------------------------------------------------
1 | # ##### BEGIN GPL LICENSE BLOCK #####
2 | #
3 | # (C) 2019 MKB
4 | #
5 | # This program is free software; you can redistribute it and / or
6 | # modify it under the terms of the GNU General Public License
7 | # as published by the Free Software Foundation; either version 3
8 | # of the License, or (at your option) any later version.
9 | #
10 | # This program is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program; if not, write to the Free Software Foundation,
17 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA.
18 | #
19 | # ##### END GPL LICENSE BLOCK #####
20 | #
21 |
22 |
23 | # LOAD MODUL #
24 | import bpy
25 | from bpy import *
26 | from bpy.props import *
27 |
28 | class VIEW3D_OT_snapset_modal(bpy.types.Operator):
29 | """use of a function and reload previous toolsettings when finished"""
30 | bl_idname = "tpc_ot.snapset_modal"
31 | bl_label = "Snapset Modal"
32 | #bl_options = {'REGISTER', 'UNDO'}
33 |
34 | # print info in system console
35 | def __init__(self):
36 | print("Start")
37 |
38 | def __del__(self):
39 | print("End")
40 |
41 | def store(self):
42 | # get snap settings
43 | store_pivot : bpy.context.scene.tool_settings.transform_pivot_point
44 | store_elements : bpy.context.scene.tool_settings.snap_elements
45 | store_target : bpy.context.scene.tool_settings.snap_target
46 | store_rotation : bpy.context.scene.tool_settings.use_snap_align_rotation
47 | store_project : bpy.context.scene.tool_settings.use_snap_project
48 | store_snap : bpy.context.scene.tool_settings.use_snap
49 |
50 |
51 | # property to define operator type in event
52 | mode : bpy.props.StringProperty(default="")
53 |
54 | count = 0
55 |
56 | # get the context arguments
57 | def modal(self, context, event):
58 |
59 | # header info
60 | #context.area.header_text_set("SnapSet: %s - %s - %s" % (self.mode, event.type, event.value))
61 |
62 | # do til event
63 | self.count += 1
64 | if self.count == 1:
65 | bpy.ops.transform.translate('INVOKE_DEFAULT')
66 |
67 | # do event
68 | elif event.type == 'LEFTMOUSE':
69 |
70 | # reload settings after event
71 | bpy.context.scene.tool_settings.transform_pivot_point = self.store_pivot
72 | bpy.context.scene.tool_settings.snap_elements = self.store_elements
73 | bpy.context.scene.tool_settings.snap_target = self.store_target
74 | bpy.context.scene.tool_settings.use_snap_align_rotation = self.store_rotation
75 | bpy.context.scene.tool_settings.use_snap_project = self.store_project
76 | bpy.context.scene.tool_settings.use_snap = self.store_snap
77 | return {'FINISHED'}
78 |
79 |
80 | # do event
81 | elif event.type in {'RIGHTMOUSE', 'ESC'}:
82 |
83 | # reload settings after event
84 | bpy.context.scene.tool_settings.transform_pivot_point = self.store_pivot
85 | bpy.context.scene.tool_settings.snap_elements = self.store_elements
86 | bpy.context.scene.tool_settings.snap_target = self.store_target
87 | bpy.context.scene.tool_settings.use_snap_align_rotation = self.store_rotation
88 | bpy.context.scene.tool_settings.use_snap_project = self.store_project
89 | bpy.context.scene.tool_settings.use_snap = self.store_snap
90 | return {'CANCELLED'}
91 |
92 | return {'RUNNING_MODAL'}
93 |
94 |
95 | # do by execute
96 | def invoke(self, context, event):
97 |
98 | # check if something selected
99 | if bpy.context.active_object is not None:
100 |
101 | # store exist settings
102 | self.store_pivot = bpy.context.scene.tool_settings.transform_pivot_point
103 | self.store_elements = bpy.context.scene.tool_settings.snap_elements
104 | self.store_target = bpy.context.scene.tool_settings.snap_target
105 | self.store_rotation = bpy.context.scene.tool_settings.use_snap_align_rotation
106 | self.store_project = bpy.context.scene.tool_settings.use_snap_project
107 | self.store_snap = bpy.context.scene.tool_settings.use_snap
108 |
109 |
110 | # change settings: snap active to surfaces
111 | if "GRID" in self.mode:
112 | bpy.context.scene.tool_settings.transform_pivot_point = 'BOUNDING_BOX_CENTER'
113 | bpy.context.scene.tool_settings.snap_elements = {'INCREMENT'}
114 | bpy.context.scene.tool_settings.use_snap_rotate = True
115 | bpy.context.scene.tool_settings.use_snap_rotate = False
116 | bpy.context.scene.tool_settings.use_snap = True
117 |
118 |
119 | # change settings: snap active to surfaces
120 | if "PLACE" in self.mode:
121 | bpy.context.scene.tool_settings.transform_pivot_point = 'ACTIVE_ELEMENT'
122 | bpy.context.scene.tool_settings.snap_elements = {'FACE'}
123 | bpy.context.scene.tool_settings.snap_target = 'CLOSEST'
124 | bpy.context.scene.tool_settings.use_snap_align_rotation = True
125 | bpy.context.scene.tool_settings.use_snap_project = True
126 | bpy.context.scene.tool_settings.use_snap = True
127 |
128 |
129 | # change settings: snap active to surfaces
130 | if "RETOPO" in self.mode:
131 | bpy.context.scene.tool_settings.transform_pivot_point = 'BOUNDING_BOX_CENTER'
132 | bpy.context.scene.tool_settings.snap_elements = {'FACE'}
133 | bpy.context.scene.tool_settings.snap_target = 'CLOSEST'
134 | bpy.context.scene.tool_settings.use_snap_align_rotation = False
135 | bpy.context.scene.tool_settings.use_snap_project = True
136 | bpy.context.scene.tool_settings.use_snap = True
137 |
138 |
139 | # change settings: snap active to perpendicular edges
140 | if "CENTER" in self.mode:
141 | bpy.context.scene.tool_settings.transform_pivot_point = 'ACTIVE_ELEMENT'
142 | bpy.context.scene.tool_settings.snap_elements = {'EDGE_MIDPOINT'}
143 | bpy.context.scene.tool_settings.snap_target = 'ACTIVE'
144 | bpy.context.scene.tool_settings.use_snap_align_rotation = False
145 | bpy.context.scene.tool_settings.use_snap_project = True
146 | bpy.context.scene.tool_settings.use_snap = True
147 |
148 |
149 | # change settings: snap active to center edges
150 | if "PERPENDICULAR" in self.mode:
151 | bpy.context.scene.tool_settings.transform_pivot_point = 'ACTIVE_ELEMENT'
152 | bpy.context.scene.tool_settings.snap_elements = {'EDGE_PERPENDICULAR'}
153 | bpy.context.scene.tool_settings.snap_target = 'ACTIVE'
154 | bpy.context.scene.tool_settings.use_snap_align_rotation = False
155 | bpy.context.scene.tool_settings.use_snap_project = True
156 | bpy.context.scene.tool_settings.use_snap = True
157 |
158 |
159 | # change settings: snap active to surfaces = place
160 | if "CUSTOM" in self.mode:
161 |
162 | addon_prefs = context.preferences.addons[__package__].preferences
163 |
164 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_btM_pivot
165 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_btM_use_pivot
166 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_btM_elements}
167 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_btM_target
168 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_btM_absolute_grid
169 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_btM_snap_self
170 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_btM_align_rotation
171 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_btM_project
172 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_btM_peel_object
173 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_btM_translate
174 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_btM_rotation
175 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_btM_scale
176 |
177 | #bpy.context.scene.tool_settings.use_snap = prefs.tpc_use_snap
178 | bpy.context.scene.tool_settings.use_snap = True
179 |
180 | context.window_manager.modal_handler_add(self)
181 | return {'RUNNING_MODAL'}
182 |
183 | else:
184 | self.report({'WARNING'}, "Need Active in 3D View")
185 | return {'CANCELLED'}
186 |
187 |
--------------------------------------------------------------------------------
/ui_panel.py:
--------------------------------------------------------------------------------
1 | # LOAD UI #
2 | from view3d_snapset.ui_menu import VIEW3D_MT_snapset_menu_panel
3 |
4 | # LOAD MODUL #
5 | import bpy
6 | from bpy import *
7 | from bpy.props import *
8 | from . icons.icons import load_icons
9 | from .ui_utils import get_addon_prefs
10 |
11 | # ADDON CHECK #
12 | import addon_utils
13 |
14 | def draw_snapset_ui(context, layout):
15 | icons = load_icons()
16 |
17 | addon_prefs = get_addon_prefs()
18 | snap_global = context.window_manager.snap_global_props
19 |
20 | layout.scale_y = addon_prefs.ui_scale_y_panel
21 |
22 | layout.operator_context = 'INVOKE_REGION_WIN'
23 |
24 | col = layout.column(align=True)
25 |
26 | box = col.box().column(align=True)
27 |
28 | # USE BUTTONS #
29 | if addon_prefs.toggle_display_buttons_pl == 'on':
30 |
31 | # NAMES / ICONS #
32 | if addon_prefs.toggle_display_name_pl == 'both_id':
33 |
34 | tx_snapset_grid = addon_prefs.name_bta
35 | tx_snapset_place = addon_prefs.name_btb
36 | tx_snapset_cursor = addon_prefs.name_btc
37 | tx_snapset_active = addon_prefs.name_btd
38 | tx_snapset_closet = addon_prefs.name_bte
39 | tx_snapset_retopo = addon_prefs.name_btf
40 | tx_snapset_center = addon_prefs.name_btg
41 | tx_snapset_perpendic = addon_prefs.name_bth
42 | tx_snapset_pcursor = addon_prefs.name_bti
43 |
44 | if addon_prefs.toggle_display_name_pl == 'icon_id':
45 |
46 | tx_snapset_grid = " "
47 | tx_snapset_place = " "
48 | tx_snapset_cursor = " "
49 | tx_snapset_active = " "
50 | tx_snapset_closet = " "
51 | tx_snapset_retopo = " "
52 | tx_snapset_center = " "
53 | tx_snapset_perpendic = " "
54 | tx_snapset_pcursor = " "
55 |
56 |
57 | if snap_global.toggle_dropdown == False:
58 |
59 | row = box.row(align=True)
60 | row.label(text="Durables")
61 |
62 | # DURABLE #
63 | if addon_prefs.toggle_display_name_pl == 'both_id':
64 | row = box.column(align=True)
65 | else:
66 | row = box.row(align=True)
67 |
68 | if addon_prefs.tpc_use_grid == True:
69 | if addon_prefs.use_internal_icon_bta == True:
70 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon=addon_prefs.icon_bta)
71 | else:
72 | button_snap_grid = icons.get("icon_snap_grid")
73 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon_value=button_snap_grid.icon_id)
74 |
75 | if context.mode == 'OBJECT':
76 | if addon_prefs.tpc_use_place == True:
77 | if addon_prefs.use_internal_icon_btb == True:
78 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon=addon_prefs.icon_btb)
79 | else:
80 | button_snap_place = icons.get("icon_snap_place")
81 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon_value=button_snap_place.icon_id)
82 | else:
83 | if addon_prefs.tpc_use_retopo == True:
84 | if addon_prefs.use_internal_icon_btf == True:
85 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon=addon_prefs.icon_btf)
86 | else:
87 | button_snap_retopo = icons.get("icon_snap_retopo")
88 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon_value=button_snap_retopo.icon_id)
89 |
90 | if addon_prefs.tpc_use_active == True:
91 | if addon_prefs.use_internal_icon_btd == True:
92 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon=addon_prefs.icon_btd)
93 | else:
94 | button_snap_active = icons.get("icon_snap_active")
95 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon_value=button_snap_active.icon_id)
96 |
97 | if addon_prefs.tpc_use_closest == True:
98 | if addon_prefs.use_internal_icon_bte == True:
99 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon=addon_prefs.icon_bte)
100 | else:
101 | button_snap_closest = icons.get("icon_snap_closest")
102 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon_value=button_snap_closest.icon_id)
103 |
104 | if addon_prefs.tpc_use_center == True:
105 | if addon_prefs.use_internal_icon_btg == True:
106 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon=addon_prefs.icon_btg)
107 | else:
108 | icon_snap_center = icons.get("icon_snap_center")
109 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon_value=icon_snap_center.icon_id)
110 |
111 | if addon_prefs.tpc_use_perpendic == True:
112 | if addon_prefs.use_internal_icon_bth == True:
113 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon=addon_prefs.icon_bth)
114 | else:
115 | icon_snap_perpendic = icons.get("icon_snap_perpendic")
116 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon_value=icon_snap_perpendic.icon_id)
117 |
118 | if addon_prefs.tpc_use_cursor == True:
119 | if addon_prefs.use_internal_icon_btc == True:
120 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon=addon_prefs.icon_btc)
121 | else:
122 | button_snap_cursor = icons.get("icon_snap_cursor")
123 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon_value=button_snap_cursor.icon_id)
124 |
125 | if addon_prefs.tpc_use_pcursor == True:
126 | if addon_prefs.use_internal_icon_bti == True:
127 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon=addon_prefs.icon_bti)
128 | else:
129 | icon_snap_pcursor = icons.get("icon_snap_pcursor")
130 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon_value=icon_snap_pcursor.icon_id)
131 |
132 | else:
133 | row = box.row(align=True)
134 | row.label(text="Modals*")
135 |
136 | row = box.column(align=True)
137 |
138 | button_snap_grid = icons.get("icon_snap_grid")
139 | row.operator("tpc_ot.snapset_modal", text="Grid*", icon_value=button_snap_grid.icon_id).mode = "GRID"
140 |
141 | if context.mode == 'OBJECT':
142 | button_snap_place = icons.get("icon_snap_place")
143 | row.operator("tpc_ot.snapset_modal", text="Place*", icon_value=button_snap_place.icon_id).mode = "PLACE"
144 |
145 | if context.mode == 'EDIT_MESH':
146 | button_snap_retopo = icons.get("icon_snap_retopo")
147 | row.operator("tpc_ot.snapset_modal", text="Retopo*", icon_value=button_snap_retopo.icon_id).mode = "RETOPO"
148 |
149 | icon_snap_center = icons.get("icon_snap_center")
150 | row.operator("tpc_ot.snapset_modal", text="MidPoint*", icon_value=icon_snap_center.icon_id).mode = "CENTER"
151 |
152 | icon_snap_perpendic = icons.get("icon_snap_perpendic")
153 | row.operator("tpc_ot.snapset_modal", text="Perpendic*", icon_value=icon_snap_perpendic.icon_id).mode = "PERPENDICULAR"
154 |
155 | icon_snap_pcursor = icons.get("icon_snap_pcursor")
156 | row.operator("tpc_ot.place_cursor_modal", text="PlaceCursor*", icon_value=icon_snap_pcursor.icon_id)
157 |
158 | icon_snap_custom = icons.get("icon_snap_custom")
159 | row.operator("tpc_ot.snapset_modal", text="Modal Custom*", icon_value=icon_snap_custom.icon_id).mode = "CUSTOM"
160 |
161 |
162 |
163 | # USE MENUS #
164 | else:
165 |
166 | # NAMES / ICONS #
167 | if addon_prefs.toggle_display_name_pl == 'both_id':
168 |
169 | tx_snapset = " SnapSet"
170 |
171 | if addon_prefs.toggle_display_name_pl == 'icon_id':
172 |
173 | tx_snapset = " "
174 |
175 | # OPTIONS #
176 | row = box.row(align=True)
177 |
178 | if addon_prefs.toggle_display_buttons_pl == 'off':
179 | if addon_prefs.toggle_display_name_pl == 'icon_id':
180 | row.operator("tpc_ot.set_pivot", text=" ", icon="PIVOT_BOUNDBOX").tpc_pivot="BOUNDING_BOX_CENTER"
181 | row.operator("tpc_ot.set_pivot", text=" ", icon="PIVOT_CURSOR").tpc_pivot="CURSOR"
182 | row.operator("tpc_ot.set_pivot", text=" ", icon="PIVOT_ACTIVE").tpc_pivot="ACTIVE_ELEMENT"
183 | row.operator("tpc_ot.set_pivot", text=" ", icon="PIVOT_INDIVIDUAL").tpc_pivot="INDIVIDUAL_ORIGINS"
184 | row.operator("tpc_ot.set_pivot", text=" ", icon="PIVOT_MEDIAN").tpc_pivot="MEDIAN_POINT"
185 | else:
186 | pass
187 |
188 | row.menu("VIEW3D_MT_snapset_menu_panel", text= tx_snapset, icon='SNAP_OFF')
189 |
190 |
191 | col = layout.row(align=True)
192 | col.scale_y = 0.8
193 | col.operator("preferences.addon_show", text=" ", icon="LAYER_USED").module="view3d_snapset"
194 |
195 | if addon_prefs.toggle_display_buttons_pl == 'on':
196 |
197 | if snap_global.toggle_dropdown == True:
198 | col.prop(snap_global, "toggle_dropdown", text=" ", icon="PINNED")
199 | else:
200 | col.prop(snap_global, "toggle_dropdown", text=" ", icon="UNPINNED")
201 |
202 |
203 |
--------------------------------------------------------------------------------
/ot_targets.py:
--------------------------------------------------------------------------------
1 | # LOAD MODULE #
2 | import bpy
3 | from bpy import *
4 | from bpy.props import *
5 |
6 |
7 | class VIEW3D_OT_pivot_target(bpy.types.Operator):
8 | """set pivot point"""
9 | bl_idname = "tpc_ot.set_pivot"
10 | bl_label = "Set Pivot"
11 | bl_options = {'REGISTER', 'UNDO'}
12 |
13 | tpc_pivot : bpy.props.EnumProperty(
14 | items=[("BOUNDING_BOX_CENTER" ," " ,"" ,"ROTATE" , 1),
15 | ("CURSOR" ," " ,"" ,"CURSOR" , 2),
16 | ("INDIVIDUAL_ORIGINS" ," " ,"" ,"ROTATECOLLECTION" , 3),
17 | ("MEDIAN_POINT" ," " ,"" ,"ROTATECENTER" , 4),
18 | ("ACTIVE_ELEMENT" ," " ,"" ,"ROTACTIVE" , 5)],
19 | name = "Pivot",
20 | default = "BOUNDING_BOX_CENTER")
21 |
22 |
23 | tpc_align : BoolProperty(name="Only Origins",description="manipulate center points", default=False)
24 |
25 | def draw(self, context):
26 | layout = self.layout.column(align = True)
27 |
28 | box = layout.box().column(align = True)
29 |
30 | row = box.column(align = True)
31 | row.alignment = 'CENTER'
32 | row.prop(self, 'tpc_pivot',text=" ", expand =True)
33 |
34 | box.separator()
35 |
36 | row = box.column(align = True)
37 | row.alignment = 'CENTER'
38 | row.prop(self, 'tpc_align',text=" ", expand =True)
39 |
40 | box.separator()
41 |
42 | def execute(self, context):
43 |
44 | if self.tpc_pivot == "BOUNDING_BOX_CENTER":
45 | bpy.context.scene.tool_settings.transform_pivot_point = 'BOUNDING_BOX_CENTER'
46 |
47 | elif self.tpc_pivot == "CURSOR":
48 | bpy.context.scene.tool_settings.transform_pivot_point = 'CURSOR'
49 |
50 | elif self.tpc_pivot == "INDIVIDUAL_ORIGINS":
51 | bpy.context.scene.tool_settings.transform_pivot_point = 'INDIVIDUAL_ORIGINS'
52 |
53 | elif self.tpc_pivot == "MEDIAN_POINT":
54 | bpy.context.scene.tool_settings.transform_pivot_point = 'MEDIAN_POINT'
55 |
56 | elif self.tpc_pivot == "ACTIVE_ELEMENT":
57 | bpy.context.scene.tool_settings.transform_pivot_point = 'ACTIVE_ELEMENT'
58 |
59 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = self.tpc_align
60 |
61 | # header info
62 | #context.area.header_text_set("SnapSet: %s" % (self.tpc_pivot))
63 | return {'FINISHED'}
64 |
65 |
66 |
67 | class VIEW3D_OT_orient_axis(bpy.types.Operator):
68 | """set transform axis orientation"""
69 | bl_idname = "tpc_ot.orient_axis"
70 | bl_label = "Transform Axis Orientation"
71 | bl_options = {'REGISTER', 'UNDO'}
72 |
73 | tpc_axis : bpy.props.EnumProperty(
74 | items=[("GLOBAL" ,"Global" ,"Global"),
75 | ("LOCAL" ,"Local" ,"Local"),
76 | ("NORMAL" ,"Normal" ,"Normal"),
77 | ("GIMBAL" ,"Gimbal" ,"Gimbal"),
78 | ("VIEW" ,"View" ,"View"),
79 | ("CURSOR" ,"Cursor" ,"Cursor")],
80 | name = "Orientation",
81 | default = "GLOBAL",
82 | description = "change manipulator axis")
83 |
84 | def draw(self, context):
85 | layout = self.layout.column(align = True)
86 |
87 | box = layout.box().column(align = True)
88 |
89 | row = box.column(align = True)
90 | row.alignment = 'CENTER'
91 | row.prop(self, 'tpc_axis',text=" ", expand =True)
92 |
93 | box.separator()
94 |
95 | def execute(self, context):
96 |
97 | if self.tpc_axis == "GLOBAL":
98 | bpy.context.scene.transform_orientation_slots[0].type = 'GLOBAL'
99 |
100 | elif self.tpc_axis == "LOCAL":
101 | bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL'
102 |
103 | elif self.tpc_axis == "NORMAL":
104 | bpy.context.scene.transform_orientation_slots[0].type = 'NORMAL'
105 |
106 | elif self.tpc_axis == "GIMBAL":
107 | bpy.context.scene.transform_orientation_slots[0].type = 'GIMBAL'
108 |
109 | elif self.tpc_axis == "VIEW":
110 | bpy.context.scene.transform_orientation_slots[0].type = 'VIEW'
111 |
112 | elif self.tpc_axis == "CURSOR":
113 | bpy.context.scene.transform_orientation_slots[0].type = 'CURSOR'
114 |
115 | # header info
116 | #context.area.header_text_set("SnapSet: %s" % (self.tpc_axis))
117 | return {'FINISHED'}
118 |
119 |
120 |
121 | class VIEW3D_OT_set_orientation(bpy.types.Operator):
122 | """creates custom transform orientation and overwrite"""
123 | bl_idname = "tpc_ot.set_orientation"
124 | bl_label = "Custom Orientation"
125 | bl_options = {'REGISTER', 'UNDO'}
126 |
127 | set_orientation_name : StringProperty(name="User Input", default="Custom", description="")
128 | use_view : BoolProperty(name="Use View",description="", default=False)
129 | use : BoolProperty(name="Use after creation",description="", default=True)
130 | overwrite : BoolProperty(name="Overwrite Previous",description="", default=True)
131 |
132 | def execute(self, context):
133 | snap_global = context.window_manager.snap_global_props
134 | bpy.ops.transform.create_orientation(name=snap_global.set_orientation_name, use_view=self.use_view, use=self.use, overwrite=self.overwrite)
135 | return {"FINISHED"}
136 |
137 |
138 |
139 | class VIEW3D_OT_snap_target(bpy.types.Operator):
140 | """set snap target"""
141 | bl_idname = "tpc_ot.snap_target"
142 | bl_label = "Snap Target"
143 | bl_options = {'REGISTER', 'UNDO'}
144 |
145 | tpc_snapt : bpy.props.EnumProperty(
146 | items=[("CLOSEST" ,"Closest" ,"Closest" ,"" , 1),
147 | ("CENTER" ,"Center" ,"Center" ,"" , 2),
148 | ("MEDIAN" ,"Median" ,"Median" ,"" , 3),
149 | ("ACTIVE" ,"Active" ,"Active" ,"" , 4)],
150 | name = "Snap Target",
151 | default = "CLOSEST")
152 |
153 | def draw(self, context):
154 | layout = self.layout.column(align = True)
155 |
156 | box = layout.box().column(align = True)
157 |
158 | row = box.column(align = True)
159 | row.alignment = 'CENTER'
160 | row.prop(self, 'tpc_snapt',text=" ", expand =True)
161 |
162 | box.separator()
163 |
164 | def execute(self, context):
165 |
166 | if self.tpc_snapt == "CLOSEST":
167 | bpy.context.scene.tool_settings.snap_target = 'CLOSEST'
168 |
169 | elif self.tpc_snapt == "CENTER":
170 | bpy.context.scene.tool_settings.snap_target = 'CENTER'
171 |
172 | elif self.tpc_snapt == "MEDIAN":
173 | bpy.context.scene.tool_settings.snap_target = 'MEDIAN'
174 |
175 | elif self.tpc_snapt == "ACTIVE":
176 | bpy.context.scene.tool_settings.snap_target = 'ACTIVE'
177 |
178 | # header info
179 | #context.area.header_text_set("SnapSet: %s" % (self.tpc_snapt))
180 | return {'FINISHED'}
181 |
182 |
183 |
184 |
185 | class VIEW3D_OT_snap_element(bpy.types.Operator):
186 | """set snap elements"""
187 | bl_idname = "tpc_ot.snap_element"
188 | bl_label = "Snap Element"
189 | bl_options = {'REGISTER', 'UNDO'}
190 |
191 | tpc_snape : EnumProperty(
192 | items=[("INCREMENT" ,"Increment" ,"" ,"SNAP_INCREMENT" , 1),
193 | ("VERTEX" ,"Vertex" ,"" ,"SNAP_VERTEX" , 2),
194 | ("EDGE" ,"Edge" ,"" ,"SNAP_EDGE" , 3),
195 | ("FACE" ,"Face" ,"" ,"SNAP_FACE" , 4),
196 | ("VOLUME" ,"Volume" ,"" ,"SNAP_VOLUME" , 5),
197 | ("EDGE_MIDPOINT" ,"MidPoint" ,"" ,"SNAP_MIDPOINT" , 6),
198 | ("EDGE_PERPENDICULAR" ,"Perpendic" ,"" ,"SNAP_PERPENDICULAR" , 7)],
199 | name = "Snap Element",
200 | default = "INCREMENT")
201 |
202 | def draw(self, context):
203 | layout = self.layout.column(align = True)
204 |
205 | box = layout.box().column(align = True)
206 |
207 | row = box.column(align = True)
208 | row.alignment = 'CENTER'
209 | row.prop(self, 'tpc_snape',text=" ", expand=True)
210 |
211 | box.separator()
212 |
213 |
214 | def execute(self, context):
215 |
216 | # seven_elements = [self.tpc_increment, self.tpc_vertex, self.tpc_edge, self.tpc_face, self.tpc_volume, self.tpc_midpoint, self.tpc_perpendic]
217 | # if seven_elements == True:
218 | # bpy.context.scene.tool_settings.snap_elements = {'INCREMENT', 'VERTEX', 'EDGE', 'FACE', 'VOLUME', 'EDGE_MIDPOINT', 'EDGE_PERPENDICULAR'}
219 |
220 | if self.tpc_snape == "INCREMENT":
221 | bpy.context.scene.tool_settings.snap_elements = {'INCREMENT'}
222 |
223 | if self.tpc_snape == "VERTEX":
224 | bpy.context.scene.tool_settings.snap_elements = {'VERTEX'}
225 |
226 | if self.tpc_snape == "EDGE":
227 | bpy.context.scene.tool_settings.snap_elements = {'EDGE'}
228 |
229 | if self.tpc_snape == "FACE":
230 | bpy.context.scene.tool_settings.snap_elements = {'FACE'}
231 |
232 | if self.tpc_snape == "VOLUME":
233 | bpy.context.scene.tool_settings.snap_elements = {'VOLUME'}
234 |
235 | if self.tpc_snape == "EDGE_MIDPOINT":
236 | bpy.context.scene.tool_settings.snap_elements = {'EDGE_MIDPOINT'}
237 |
238 | if self.tpc_snape == "EDGE_PERPENDICULAR":
239 | bpy.context.scene.tool_settings.snap_elements = {'EDGE_PERPENDICULAR'}
240 |
241 | # header info
242 | # context.area.header_text_set("SnapSet: %s" % (self.tpc_snape))
243 |
244 | return {'FINISHED'}
245 |
246 |
247 |
248 |
249 | class VIEW3D_OT_snap_use(bpy.types.Operator):
250 | """toggle use snap on/off"""
251 | bl_idname = "tpc_ot.snap_use"
252 | bl_label = "Use Snap"
253 | bl_options = {'REGISTER', 'UNDO'}
254 |
255 | mode : bpy.props.StringProperty(default="")
256 |
257 | def execute(self, context):
258 |
259 | if self.mode == "use_snap":
260 | bpy.context.scene.tool_settings.use_snap = True
261 |
262 | if self.mode == "unuse_snap":
263 | bpy.context.scene.tool_settings.use_snap = False
264 |
265 | # header info
266 | #context.area.header_text_set("SnapSet: %s" % (self.mode))
267 | return {'FINISHED'}
268 |
269 |
270 |
--------------------------------------------------------------------------------
/ui_snapping.py:
--------------------------------------------------------------------------------
1 | # LOAD MODUL #
2 | import bpy
3 | from bpy import *
4 | from bpy.props import *
5 | from . icons.icons import load_icons
6 | from .ui_utils import get_addon_prefs
7 |
8 |
9 | def draw_snapset_snapping_layout(self, context):
10 |
11 | icons = load_icons()
12 | icon_snap_set = icons.get("icon_snap_set")
13 | icon_snap_grid = icons.get("icon_snap_grid")
14 | icon_snap_place = icons.get("icon_snap_place")
15 | icon_snap_retopo = icons.get("icon_snap_retopo")
16 | icon_snap_cursor = icons.get("icon_snap_cursor")
17 | icon_snap_closest = icons.get("icon_snap_closest")
18 | icon_snap_active = icons.get("icon_snap_active")
19 | icon_snap_center = icons.get("icon_snap_center")
20 | icon_snap_perpendic = icons.get("icon_snap_perpendic")
21 | icon_snap_pcursor = icons.get("icon_snap_pcursor")
22 | icon_snap_custom = icons.get("icon_snap_custom")
23 |
24 | addon_prefs = get_addon_prefs()
25 |
26 | layout = self.layout
27 |
28 | layout.operator_context = 'INVOKE_REGION_WIN'
29 |
30 | if addon_prefs.toggle_snapping_type in ['menu', 'buttons']:
31 |
32 | tx_snapset_grid = addon_prefs.name_bta
33 | tx_snapset_place = addon_prefs.name_btb
34 | tx_snapset_cursor = addon_prefs.name_btc
35 | tx_snapset_closet = addon_prefs.name_btd
36 | tx_snapset_active = addon_prefs.name_bte
37 | tx_snapset_retopo = addon_prefs.name_btf
38 | tx_snapset_center = addon_prefs.name_btg
39 | tx_snapset_perpendic = addon_prefs.name_bth
40 | tx_snapset_pcursor = addon_prefs.name_bti
41 | tx_snapset_custom = addon_prefs.name_btM
42 |
43 | tx_snapset_gridm = "Grid*"
44 | tx_snapset_placem = "Place*"
45 | tx_snapset_retopom = "Retopo*"
46 | tx_snapset_centerm = "MidPoint*"
47 | tx_snapset_perpendicm = "Perpendic*"
48 | tx_snapset_pcursorm = "PlaceCursor*"
49 | tx_snapset_customM = "Custom*"
50 |
51 | else:
52 |
53 | tx_snapset_grid = " "
54 | tx_snapset_place = " "
55 | tx_snapset_cursor = " "
56 | tx_snapset_closet = " "
57 | tx_snapset_active = " "
58 | tx_snapset_retopo = " "
59 | tx_snapset_center = " "
60 | tx_snapset_perpendic = " "
61 | tx_snapset_pcursor = " "
62 | tx_snapset_custom = " "
63 |
64 | tx_snapset_gridm = " "
65 | tx_snapset_placem = " "
66 | tx_snapset_retopom = " "
67 | tx_snapset_centerm = " "
68 | tx_snapset_perpendicm = " "
69 | tx_snapset_pcursorm = " "
70 | tx_snapset_custoM = " "
71 |
72 |
73 | if addon_prefs.toggle_snapping_type in ['buttons', 'icons']:
74 |
75 | if addon_prefs.toggle_snapping_type_layout == 'column':
76 | row = layout.column(align=addon_prefs.row_align_snapping_hor)
77 |
78 | if addon_prefs.toggle_snapping_type_layout == 'flow':
79 | row = layout.column_flow(columns=2, align=addon_prefs.row_align_snapping_hor)
80 |
81 | if addon_prefs.toggle_snapping_type_layout == 'row':
82 | row = layout.row(align=addon_prefs.row_align_snapping_hor)
83 |
84 | if addon_prefs.toggle_snapping_type_layout == 'rows':
85 | row = layout.row(align=addon_prefs.row_align_snapping_hor)
86 |
87 | else:
88 | if addon_prefs.toggle_snapping_type_layout == 'column':
89 | row = layout.column(align=addon_prefs.row_align_snapping_hor)
90 |
91 | if addon_prefs.toggle_snapping_type_layout == 'flow':
92 | row = layout.column_flow(columns=2, align=addon_prefs.row_align_snapping_hor)
93 |
94 | if addon_prefs.toggle_snapping_type_layout == 'row':
95 | row = layout.row(align=addon_prefs.row_align_snapping_hor)
96 |
97 | if addon_prefs.toggle_snapping_type_layout == 'rows':
98 | row = layout.row(align=addon_prefs.row_align_snapping_hor)
99 |
100 | row.scale_y = addon_prefs.ui_scale_y_snapping
101 |
102 | if addon_prefs.tpc_use_grid_snapping == True:
103 | if addon_prefs.use_internal_icon_bta == True:
104 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon=addon_prefs.icon_bta)
105 | else:
106 | button_snap_grid = icons.get("icon_snap_grid")
107 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon_value=button_snap_grid.icon_id)
108 |
109 |
110 | if context.mode == 'OBJECT':
111 |
112 | if addon_prefs.tpc_use_place_snapping == True:
113 | if addon_prefs.use_internal_icon_btb == True:
114 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon=addon_prefs.icon_btb)
115 | else:
116 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon_value=icon_snap_place.icon_id)
117 |
118 | else:
119 | if addon_prefs.tpc_use_retopo_snapping == True:
120 | if addon_prefs.use_internal_icon_btf == True:
121 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon=addon_prefs.icon_btf)
122 | else:
123 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon_value=icon_snap_retopo.icon_id)
124 |
125 |
126 | if addon_prefs.tpc_use_cursor_snapping == True:
127 | if addon_prefs.use_internal_icon_btc == True:
128 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon=addon_prefs.icon_btc)
129 | else:
130 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon_value=icon_snap_cursor.icon_id)
131 |
132 |
133 | if addon_prefs.tpc_use_closest_snapping == True:
134 | if addon_prefs.use_internal_icon_bte == True:
135 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon=addon_prefs.icon_bte)
136 | else:
137 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon_value=icon_snap_closest.icon_id)
138 |
139 |
140 | if addon_prefs.toggle_snapping_type_layout == 'rows':
141 | layout = self.layout.column(align=True)
142 | row = layout.row(align=True)
143 |
144 |
145 | if addon_prefs.tpc_use_active_snapping == True:
146 | if addon_prefs.use_internal_icon_btd == True:
147 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon=addon_prefs.icon_btd)
148 | else:
149 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon_value=icon_snap_active.icon_id)
150 |
151 | if addon_prefs.tpc_use_center_snapping == True:
152 | if addon_prefs.use_internal_icon_btg == True:
153 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon=addon_prefs.icon_btg)
154 | else:
155 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon_value=icon_snap_center.icon_id)
156 |
157 | if addon_prefs.tpc_use_perpendic_snapping == True:
158 | if addon_prefs.use_internal_icon_bth == True:
159 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon=addon_prefs.icon_bth)
160 | else:
161 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon_value=icon_snap_perpendic.icon_id)
162 |
163 | if addon_prefs.tpc_use_pcursor_snapping == True:
164 | if addon_prefs.use_internal_icon_bti == True:
165 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon=addon_prefs.icon_bti)
166 | else:
167 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon_value=icon_snap_pcursor.icon_id)
168 |
169 |
170 |
171 | # HIDDEN MODAL BUTTONS #
172 | """
173 | if addon_prefs.tpc_use_grid_modal_snapping == True:
174 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm).mode = "GRID"
175 | else:
176 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm, icon_value=icon_snap_grid.icon_id).mode = "GRID"
177 |
178 | if context.mode == 'OBJECT':
179 | if addon_prefs.tpc_use_place_modal_snapping == True:
180 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_placem).mode = "PLACE"
181 | else:
182 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_placem, icon_value=icon_snap_place.icon_id).mode = "PLACE"
183 | else:
184 | if addon_prefs.tpc_use_retopo_modal_snapping == True:
185 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom).mode = "RETOPO"
186 | else:
187 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom, icon_value=icon_snap_retopo.icon_id).mode = "RETOPO"
188 |
189 | if addon_prefs.tpc_use_center_modal_snapping == True:
190 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm).mode = "CENTER"
191 | else:
192 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm, icon_value=icon_snap_center.icon_id).mode = "CENTER"
193 |
194 | if addon_prefs.tpc_use_perpendic_modal_snapping == True:
195 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm).mode = "PERPENDICULAR"
196 | else:
197 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm, icon_value=icon_snap_perpendic.icon_id).mode = "PERPENDICULAR"
198 |
199 | if addon_prefs.tpc_use_custom_modal_snapping == True:
200 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_customM).mode = "CUSTOM"
201 | else:
202 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_customM, icon_value=icon_snap_custom.icon_id).mode = "CUSTOM"
203 |
204 | if addon_prefs.tpc_use_settings_snapping == True:
205 | row.operator("preferences.addon_show", text="Settings").module="view3d_snapset"
206 | else:
207 | row.operator("preferences.addon_show", text="Settings", icon="LAYER_USED").module="view3d_snapset"
208 | """
209 |
210 |
211 |
212 |
213 |
214 | # UI: SNAPPING MENU # icon_snap_perpendic
215 | class VIEW3D_MT_snapset_menu_snapping(bpy.types.Menu):
216 | bl_label = "SnapSet"
217 | bl_idname = "VIEW3D_MT_snapset_menu_snapping"
218 |
219 | def draw(self, context):
220 | layout = self.layout
221 | layout.operator_context = 'INVOKE_REGION_WIN'
222 |
223 | draw_snapset_snapping_layout(self, context)
224 |
225 |
226 |
227 | def draw_snapset_snapping(self, context):
228 | layout = self.layout
229 |
230 | icons = load_icons()
231 |
232 | addon_prefs = context.preferences.addons[__package__].preferences
233 |
234 | layout.scale_y = addon_prefs.ui_scale_y_snapping
235 |
236 | layout.operator_context = 'INVOKE_REGION_WIN'
237 |
238 | if addon_prefs.toggle_snapping_type in ['buttons', 'icons']:
239 |
240 | row = layout.row(align=True)
241 | row.label(text="SnapSet")
242 | row.operator("preferences.addon_show", text='', icon="LAYER_USED").module="view3d_snapset"
243 | draw_snapset_snapping_layout(self, context)
244 |
245 | else:
246 |
247 | row = layout.row(align=True)
248 |
249 | button_snap_set = icons.get("icon_snap_set")
250 | row.menu("VIEW3D_MT_snapset_menu_snapping", text= " SnapSet")#, icon_value=button_snap_set.icon_id)
251 | row.operator("preferences.addon_show", text="", icon="LAYER_USED").module="view3d_snapset"
252 |
253 |
254 |
255 |
256 |
--------------------------------------------------------------------------------
/ot_custom.py:
--------------------------------------------------------------------------------
1 | # LOAD MODULE #
2 | import bpy
3 | from bpy import*
4 | from bpy.props import*
5 |
6 |
7 | class VIEW3D_OT_snapset_button_A(bpy.types.Operator):
8 | """Default Snap Grid > Button A Settings"""
9 | bl_idname = "tpc_ot.snapset_button_a"
10 | bl_label = "Snap Button A..."
11 | bl_options = {'REGISTER', 'UNDO'}
12 |
13 | def execute(self, context):
14 |
15 | addon_prefs = context.preferences.addons[__package__].preferences
16 |
17 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
18 |
19 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_bta_pivot
20 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_bta_use_pivot
21 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_bta_elements}
22 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_bta_target
23 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_bta_absolute_grid
24 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_bta_snap_self
25 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_bta_align_rotation
26 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_bta_project
27 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_bta_peel_object
28 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_bta_translate
29 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_bta_rotation
30 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_bta_scale
31 |
32 | # header info
33 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_bta))
34 | return {'FINISHED'}
35 |
36 |
37 | class VIEW3D_OT_snapset_button_B(bpy.types.Operator):
38 | """Default Snap Place > Button B Settings"""
39 | bl_idname = "tpc_ot.snapset_button_b"
40 | bl_label = "Snap Button B..."
41 | bl_options = {'REGISTER', 'UNDO'}
42 |
43 | def execute(self, context):
44 |
45 | addon_prefs = context.preferences.addons[__package__].preferences
46 |
47 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
48 |
49 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_btb_pivot
50 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_btb_use_pivot
51 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_btb_elements}
52 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_btb_target
53 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_btb_absolute_grid
54 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_btb_snap_self
55 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_btb_align_rotation
56 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_btb_project
57 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_btb_peel_object
58 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_btb_translate
59 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_btb_rotation
60 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_btb_scale
61 |
62 | # header info
63 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_btb))
64 | return {'FINISHED'}
65 |
66 |
67 | class VIEW3D_OT_snapset_button_C(bpy.types.Operator):
68 | """Default Snap Cursor > Button C Settings"""
69 | bl_idname = "tpc_ot.snapset_button_c"
70 | bl_label = "Snap Button C..."
71 | bl_options = {'REGISTER', 'UNDO'}
72 |
73 | def execute(self, context):
74 |
75 | addon_prefs = context.preferences.addons[__package__].preferences
76 |
77 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
78 |
79 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_btc_pivot
80 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_btc_use_pivot
81 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_btc_elements}
82 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_btc_target
83 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_btc_absolute_grid
84 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_btc_snap_self
85 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_btc_align_rotation
86 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_btc_project
87 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_btc_peel_object
88 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_btc_translate
89 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_btc_rotation
90 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_btc_scale
91 |
92 | # header info
93 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_btc))
94 | return {'FINISHED'}
95 |
96 |
97 | class VIEW3D_OT_snapset_button_D(bpy.types.Operator):
98 | """Default Snap Active > Button D Settings"""
99 | bl_idname = "tpc_ot.snapset_button_d"
100 | bl_label = "Snap Button D..."
101 | bl_options = {'REGISTER', 'UNDO'}
102 |
103 | def execute(self, context):
104 |
105 | addon_prefs = context.preferences.addons[__package__].preferences
106 |
107 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
108 |
109 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_btd_pivot
110 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_btd_use_pivot
111 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_btd_elements}
112 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_btd_target
113 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_btd_absolute_grid
114 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_btd_snap_self
115 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_btd_align_rotation
116 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_btd_project
117 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_btd_peel_object
118 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_btd_translate
119 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_btd_rotation
120 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_btd_scale
121 |
122 | # header info
123 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_btd))
124 | return {'FINISHED'}
125 |
126 |
127 | class VIEW3D_OT_snapset_button_E(bpy.types.Operator):
128 | """Default Snap Closest > Button E Settings"""
129 | bl_idname = "tpc_ot.snapset_button_e"
130 | bl_label = "Snap Button E..."
131 | bl_options = {'REGISTER', 'UNDO'}
132 |
133 | def execute(self, context):
134 |
135 | addon_prefs = context.preferences.addons[__package__].preferences
136 |
137 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
138 |
139 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_bte_pivot
140 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_bte_use_pivot
141 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_bte_elements}
142 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_bte_target
143 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_bte_absolute_grid
144 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_bte_snap_self
145 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_bte_align_rotation
146 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_bte_project
147 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_bte_peel_object
148 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_bte_translate
149 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_bte_rotation
150 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_bte_scale
151 |
152 | # header info
153 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_bte))
154 | return {'FINISHED'}
155 |
156 |
157 |
158 | class VIEW3D_OT_snapset_button_F(bpy.types.Operator):
159 | """Default Snap Retopo > Button F Settings"""
160 | bl_idname = "tpc_ot.snapset_button_f"
161 | bl_label = "Snap Button F..."
162 | bl_options = {'REGISTER', 'UNDO'}
163 |
164 | def execute(self, context):
165 |
166 | addon_prefs = context.preferences.addons[__package__].preferences
167 |
168 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
169 |
170 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_btf_pivot
171 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_btf_use_pivot
172 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_btf_elements}
173 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_btf_target
174 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_btf_absolute_grid
175 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_btf_snap_self
176 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_btf_align_rotation
177 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_btf_project
178 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_btf_peel_object
179 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_btf_translate
180 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_btf_rotation
181 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_btf_scale
182 |
183 | # header info
184 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_btf))
185 | return {'FINISHED'}
186 |
187 |
188 |
189 | class VIEW3D_OT_snapset_button_G(bpy.types.Operator):
190 | """Default Snap MidPoint > Button G Settings"""
191 | bl_idname = "tpc_ot.snapset_button_g"
192 | bl_label = "Snap Button G..."
193 | bl_options = {'REGISTER', 'UNDO'}
194 |
195 | def execute(self, context):
196 |
197 | addon_prefs = context.preferences.addons[__package__].preferences
198 |
199 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
200 |
201 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_btg_pivot
202 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_btg_use_pivot
203 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_btg_elements}
204 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_btg_target
205 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_btg_absolute_grid
206 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_btg_snap_self
207 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_btg_align_rotation
208 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_btg_project
209 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_btg_peel_object
210 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_btg_translate
211 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_btg_rotation
212 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_btg_scale
213 |
214 | # header info
215 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_btf))
216 | return {'FINISHED'}
217 |
218 |
219 | class VIEW3D_OT_snapset_button_H(bpy.types.Operator):
220 | """Default Snap Perpendic > Button H Settings"""
221 | bl_idname = "tpc_ot.snapset_button_h"
222 | bl_label = "Snap Button H..."
223 | bl_options = {'REGISTER', 'UNDO'}
224 |
225 | def execute(self, context):
226 |
227 | addon_prefs = context.preferences.addons[__package__].preferences
228 |
229 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
230 |
231 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_bth_pivot
232 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_bth_use_pivot
233 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_bth_elements}
234 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_bth_target
235 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_bth_absolute_grid
236 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_bth_snap_self
237 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_bth_align_rotation
238 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_bth_project
239 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_bth_peel_object
240 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_bth_translate
241 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_bth_rotation
242 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_bth_scale
243 |
244 | # header info
245 | #context.area.header_text_set("SnapSet: %s" % (addon_prefs.name_btf))
246 | return {'FINISHED'}
247 |
248 |
249 |
--------------------------------------------------------------------------------
/ui_editor.py:
--------------------------------------------------------------------------------
1 | # LOAD UI #
2 | from view3d_snapset.ui_menu import draw_snapset_menu_ui
3 |
4 | # LOAD MODUL #
5 | import bpy
6 | from bpy import *
7 | from bpy.props import *
8 | from . icons.icons import load_icons
9 | from .ui_utils import get_addon_prefs
10 |
11 | def draw_snapset_item_editor(self, context):
12 | layout = self.layout
13 |
14 | addon_prefs = get_addon_prefs()
15 |
16 | row = layout.row(align=addon_prefs.row_align)
17 |
18 | if addon_prefs.toggle_editor_layout_scale_x == True:
19 | row.scale_x = addon_prefs.ui_scale_x_editor
20 |
21 | if addon_prefs.toggle_editor_layout_scale_y == True:
22 | row.scale_y = addon_prefs.ui_scale_y_editor
23 |
24 | icons = load_icons()
25 | icon_snap_set = icons.get("icon_snap_set")
26 |
27 | icon_snap_grid = icons.get("icon_snap_grid")
28 | icon_snap_place = icons.get("icon_snap_place")
29 | icon_snap_retopo = icons.get("icon_snap_retopo")
30 | icon_snap_cursor = icons.get("icon_snap_cursor")
31 | icon_snap_closest = icons.get("icon_snap_closest")
32 | icon_snap_active = icons.get("icon_snap_active")
33 | icon_snap_center = icons.get("icon_snap_center")
34 | icon_snap_perpendic = icons.get("icon_snap_perpendic")
35 | icon_snap_pcursor = icons.get("icon_snap_pcursor")
36 |
37 | # layout spacer
38 | if addon_prefs.toggle_editor_separator_prepend == True:
39 | row.separator(factor=addon_prefs.factor_separator_prepend)
40 |
41 |
42 | # USE BUTTONS #
43 | if addon_prefs.toggle_editor_layout == 'buttons':
44 |
45 | # NAMES / ICONS #
46 | if addon_prefs.toggle_editor_menu_name == 'icon':
47 |
48 | if addon_prefs.toggle_editor_layout_scale_x == False:
49 |
50 | tx_snapset_grid = ""
51 | tx_snapset_place = ""
52 | tx_snapset_cursor = ""
53 | tx_snapset_closet = ""
54 | tx_snapset_active = ""
55 | tx_snapset_retopo = ""
56 | tx_snapset_center = ""
57 | tx_snapset_perpendic = ""
58 | tx_snapset_pcursor = ""
59 |
60 | tx_snapset_gridm = ""
61 | tx_snapset_placem = ""
62 | tx_snapset_retopom = ""
63 | tx_snapset_centerm = ""
64 | tx_snapset_perpendicm = ""
65 | tx_snapset_pcursorm = ""
66 |
67 | else:
68 |
69 | # for x scale
70 | tx_snapset_grid = " "
71 | tx_snapset_place = " "
72 | tx_snapset_cursor = " "
73 | tx_snapset_closet = " "
74 | tx_snapset_active = " "
75 | tx_snapset_retopo = " "
76 | tx_snapset_center = " "
77 | tx_snapset_perpendic = " "
78 | tx_snapset_pcursor = ""
79 |
80 | tx_snapset_gridm = " "
81 | tx_snapset_placem = " "
82 | tx_snapset_retopom = " "
83 | tx_snapset_centerm = " "
84 | tx_snapset_perpendicm = " "
85 | tx_snapset_pcursorm = ""
86 |
87 | if addon_prefs.toggle_editor_menu_name in ['namend', 'both']:
88 |
89 | tx_snapset_grid = addon_prefs.name_bta
90 | tx_snapset_place = addon_prefs.name_btb
91 | tx_snapset_cursor = addon_prefs.name_btc
92 | tx_snapset_closet = addon_prefs.name_btd
93 | tx_snapset_active = addon_prefs.name_bte
94 | tx_snapset_retopo = addon_prefs.name_btf
95 | tx_snapset_center = addon_prefs.name_btg
96 | tx_snapset_perpendic = addon_prefs.name_bth
97 | tx_snapset_pcursor = addon_prefs.name_bti
98 |
99 | tx_snapset_gridm = "Grid*"
100 | tx_snapset_placem = "Place*"
101 | tx_snapset_retopom = "Retopo*"
102 | tx_snapset_centerm = "MidPoint*"
103 | tx_snapset_perpendicm = "Perpendic*"
104 | tx_snapset_pcursorm = "PlaceCursor*"
105 |
106 |
107 | if addon_prefs.tpc_use_grid_editor == True:
108 | if addon_prefs.toggle_editor_menu_name == 'namend':
109 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid)
110 | else:
111 | if addon_prefs.use_internal_icon_bta == True:
112 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid , icon=addon_prefs.icon_bta)
113 | else:
114 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon_value=icon_snap_grid.icon_id)
115 |
116 |
117 | # mode switch
118 | if context.mode == 'OBJECT':
119 | if addon_prefs.tpc_use_place_editor == True:
120 | if addon_prefs.toggle_editor_menu_name == 'namend':
121 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place)
122 | else:
123 | if addon_prefs.use_internal_icon_btb == True:
124 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon=addon_prefs.icon_btb)
125 | else:
126 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon_value=icon_snap_place.icon_id)
127 | else:
128 | if addon_prefs.tpc_use_retopo_editor == True:
129 | if addon_prefs.toggle_editor_menu_name == 'namend':
130 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo)
131 | else:
132 | if addon_prefs.use_internal_icon_btf == True:
133 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon=addon_prefs.icon_btf)
134 | else:
135 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon_value=icon_snap_retopo.icon_id)
136 |
137 |
138 |
139 | if addon_prefs.tpc_use_cursor_editor == True:
140 | if addon_prefs.toggle_editor_menu_name == 'namend':
141 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor)
142 | else:
143 | if addon_prefs.use_internal_icon_btc == True:
144 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon=addon_prefs.icon_btc)
145 | else:
146 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon_value=icon_snap_cursor.icon_id)
147 |
148 | if addon_prefs.tpc_use_closest_editor == True:
149 | if addon_prefs.toggle_editor_menu_name == 'namend':
150 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet)
151 | else:
152 | if addon_prefs.use_internal_icon_bte == True:
153 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon=addon_prefs.icon_bte)
154 | else:
155 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon_value=icon_snap_closest.icon_id)
156 |
157 |
158 | if addon_prefs.tpc_use_active_editor == True:
159 | if addon_prefs.toggle_editor_menu_name == 'namend':
160 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active)
161 | else:
162 | if addon_prefs.use_internal_icon_btd == True:
163 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon=addon_prefs.icon_btd)
164 | else:
165 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon_value=icon_snap_active.icon_id)
166 |
167 | if addon_prefs.tpc_use_center_editor == True:
168 | if addon_prefs.toggle_editor_menu_name == 'namend':
169 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center)
170 | else:
171 | if addon_prefs.use_internal_icon_btg == True:
172 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon=addon_prefs.icon_btg)
173 | else:
174 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon_value=icon_snap_center.icon_id)
175 |
176 | if addon_prefs.tpc_use_perpendic_editor == True:
177 | if addon_prefs.toggle_editor_menu_name == 'namend':
178 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic)
179 | else:
180 | if addon_prefs.use_internal_icon_bth == True:
181 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon=addon_prefs.icon_bth)
182 | else:
183 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon_value=icon_snap_perpendic.icon_id)
184 |
185 |
186 | if addon_prefs.tpc_use_pcursor_editor == True:
187 | if addon_prefs.toggle_editor_menu_name == 'namend':
188 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor)
189 | else:
190 | if addon_prefs.use_internal_icon_bti == True:
191 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon=addon_prefs.icon_bti)
192 | else:
193 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon_value=icon_snap_pcursor.icon_id)
194 |
195 |
196 |
197 | # MODAL BUTTONS #
198 | if addon_prefs.tpc_use_grid_modal_editor == True:
199 | if addon_prefs.toggle_editor_menu_name == 'namend':
200 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm).mode = "GRID"
201 | else:
202 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm, icon_value=icon_snap_grid.icon_id).mode = "GRID"
203 |
204 | if context.mode == 'OBJECT':
205 | if addon_prefs.tpc_use_place_modal_editor == True:
206 | if addon_prefs.toggle_editor_menu_name == 'namend':
207 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_placem).mode = "PLACE"
208 | else:
209 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_placem, icon_value=icon_snap_place.icon_id).mode = "PLACE"
210 | else:
211 | if addon_prefs.tpc_use_retopo_modal_editor == True:
212 | if addon_prefs.toggle_editor_menu_name == 'namend':
213 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom).mode = "RETOPO"
214 | else:
215 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom, icon_value=icon_snap_retopo.icon_id).mode = "RETOPO"
216 |
217 | if addon_prefs.tpc_use_center_modal_editor == True:
218 | if addon_prefs.toggle_editor_menu_name == 'namend':
219 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm).mode = "CENTER"
220 | else:
221 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm, icon_value=icon_snap_center.icon_id).mode = "CENTER"
222 |
223 | if addon_prefs.tpc_use_perpendic_modal_editor == True:
224 | if addon_prefs.toggle_editor_menu_name == 'namend':
225 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm).mode = "PERPENDICULAR"
226 | else:
227 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm, icon_value=icon_snap_perpendic.icon_id).mode = "PERPENDICULAR"
228 |
229 | if addon_prefs.tpc_use_pcursor_modal_editor == True:
230 | if addon_prefs.toggle_editor_menu_name == 'namend':
231 | row.operator("tpc_ot.place_cursor_modal", text=tx_snapset_pcursorm)
232 | else:
233 | row.operator("tpc_ot.place_cursor_modal", text=tx_snapset_pcursorm, icon_value=icon_snap_pcursor.icon_id)
234 |
235 |
236 |
237 |
238 | # USE PANEL #
239 | if addon_prefs.toggle_editor_layout == 'panel':
240 |
241 | if addon_prefs.toggle_editor_menu_name == 'icon':
242 | row.popover(panel="VIEW3D_PT_snapset_panel_ui", text="", icon_value=icon_snap_set.icon_id)
243 |
244 | if addon_prefs.toggle_editor_menu_name == 'namend':
245 | row.popover(panel="VIEW3D_PT_snapset_panel_ui", text="SnapSet")
246 |
247 | if addon_prefs.toggle_editor_menu_name == 'both':
248 | row.popover(panel="VIEW3D_PT_snapset_panel_ui", text=" SnapSet", icon_value=icon_snap_set.icon_id)
249 |
250 |
251 | # USE MENUS #
252 | if addon_prefs.toggle_editor_layout == 'menu':
253 |
254 | if addon_prefs.toggle_editor_menu_name == 'icon':
255 | row.menu("VIEW3D_MT_snapset_menu_editor", text="", icon_value=icon_snap_set.icon_id)
256 |
257 | if addon_prefs.toggle_editor_menu_name == 'namend':
258 | row.menu("VIEW3D_MT_snapset_menu_editor", text="SnapSet")
259 |
260 | if addon_prefs.toggle_editor_menu_name == 'both':
261 | row.menu("VIEW3D_MT_snapset_menu_editor", text=" SnapSet", icon_value=icon_snap_set.icon_id)
262 |
263 |
264 |
265 | # layout spacer
266 | if addon_prefs.toggle_editor_separator_append == True:
267 | row.separator(factor=addon_prefs.factor_separator_append)
268 |
269 |
270 |
271 | class VIEW3D_PT_snapset_panel_editor(bpy.types.Panel):
272 | bl_space_type = 'VIEW_3D'
273 | bl_region_type = 'HEADER'
274 | bl_label = "Snapset"
275 | #bl_ui_units_x = 8
276 |
277 | def draw(self, context):
278 | layout = self.layout
279 | layout.operator_context = 'INVOKE_REGION_WIN'
280 |
281 | draw_snapset_menu_ui(context, layout)
282 |
283 |
284 | # UI: HEADER MENU #
285 | class VIEW3D_HT_snapset_header(bpy.types.Header):
286 | bl_space_type = 'VIEW_3D'
287 | bl_region_type = 'HEADER'
288 |
289 | @classmethod
290 | def poll(self, context):
291 | return
292 |
293 | def draw(self, context):
294 | layout = self.layout.row(align=True)
295 | layout.operator_context = 'INVOKE_REGION_WIN'
296 |
297 | draw_snapset_item_editor(self, context)
298 |
299 |
300 |
301 | # UI: EDITOR MENU #
302 | class VIEW3D_MT_snapset_menu_editor(bpy.types.Menu):
303 | bl_label = "SnapSet"
304 | bl_idname = "VIEW3D_MT_snapset_menu_editor"
305 |
306 | def draw(self, context):
307 | layout = self.layout
308 | layout.operator_context = 'INVOKE_REGION_WIN'
309 |
310 | draw_snapset_menu_ui(context, layout)
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
--------------------------------------------------------------------------------
/ot_cursor.py:
--------------------------------------------------------------------------------
1 | # LOAD MODUL #
2 | import bpy
3 | from bpy import *
4 | from bpy.props import *
5 | from bpy.app.handlers import persistent
6 |
7 | import math
8 | import mathutils
9 | from mathutils import *
10 |
11 |
12 |
13 | class VIEW3D_OT_place_cursor(bpy.types.Operator):
14 | """Default Snap PlaceCursor > Button I Settings"""
15 | bl_idname = "tpc_ot.place_cursor"
16 | bl_label = "PlaceCursor"
17 | bl_options = {"REGISTER", 'UNDO'}
18 |
19 | depth : BoolProperty(name="Surface Project", description="project onto the surface", default=True)
20 |
21 | orient : bpy.props.EnumProperty(
22 | items = [("NONE", "None", "leave orientation unchanged" ,1),
23 | ("VIEW", "View", "orient to the viewport" ,2),
24 | ("XFORM", "Transform", "orient to the current transform setting" ,3),
25 | ("GEOM", "Geometry", "match the surface normal" ,4)],
26 | name = "Orientation",
27 | default = "GEOM",
28 | description="Preset viewpoint to use")
29 |
30 | object_align : bpy.props.EnumProperty(
31 | items = [("WORLD", "World", "align new objects to world cooridnate system" ,1),
32 | ("VIEW", "View", "align new objects to active 3D view" ,2),
33 | ("CURSOR", "3D Cursor", "align new objects to 3D cursors rotation" ,3)],
34 | name = "Align to",
35 | default = "CURSOR",
36 | description="")
37 |
38 | rotation : FloatProperty(name="Rotate Cursor", description="", default=0, min= -360, max = 360, subtype='PERCENTAGE')
39 |
40 | def draw(self, context):
41 | layout = self.layout
42 | layout.operator_context = 'INVOKE_AREA'
43 | layout.operator_context = "INVOKE_DEFAULT"
44 |
45 | box = layout.box().column(align=True)
46 |
47 | row = box.row(align=True)
48 | row.label(text="Surface Project")
49 | row.prop(self, "depth", text='')
50 |
51 | box.separator()
52 |
53 | row = box.row(align=True)
54 | row.label(text="Orientation")
55 | row.prop(self, "orient", text='')
56 |
57 | box.separator()
58 |
59 | row = box.row(align=True)
60 | row.label(text="Align to")
61 | row.prop(self, "object_align", text='')
62 |
63 | box.separator()
64 |
65 | row = box.row(align=True)
66 | row.label(text="Rotation")
67 | row.prop(self, "rotation", text='')
68 |
69 | box.separator()
70 |
71 |
72 | def execute(self, context):
73 |
74 | addon_prefs = context.preferences.addons[__package__].preferences
75 |
76 | bpy.context.scene.tool_settings.use_snap = addon_prefs.tpc_use_snap
77 |
78 | bpy.context.space_data.overlay.show_cursor = True
79 |
80 | bpy.ops.wm.tool_set_by_id(name="builtin.cursor")
81 |
82 | #https://docs.blender.org/api/current/bpy.ops.view3d.html
83 | bpy.ops.view3d.cursor3d(use_depth=self.depth, orientation=self.orient)
84 | bpy.context.preferences.edit.object_align=self.object_align
85 |
86 | bpy.context.scene.tool_settings.transform_pivot_point = addon_prefs.prop_bti_pivot
87 |
88 | #bpy.context.scene.tool_settings.snap_elements = {'VERTEX', 'EDGE', 'FACE'}
89 | bpy.context.scene.tool_settings.snap_elements = {addon_prefs.prop_bti_elements}
90 |
91 | bpy.context.scene.tool_settings.snap_target = addon_prefs.prop_bti_target
92 | bpy.context.scene.tool_settings.use_snap_align_rotation = addon_prefs.prop_bti_align_rotation
93 |
94 | bpy.context.scene.tool_settings.use_transform_pivot_point_align = addon_prefs.prop_bti_use_pivot
95 | bpy.context.scene.tool_settings.use_snap_grid_absolute = addon_prefs.prop_bti_absolute_grid
96 | bpy.context.scene.tool_settings.use_snap_self = addon_prefs.prop_bti_snap_self
97 | bpy.context.scene.tool_settings.use_snap_project = addon_prefs.prop_bti_project
98 | bpy.context.scene.tool_settings.use_snap_peel_object = addon_prefs.prop_bti_peel_object
99 | bpy.context.scene.tool_settings.use_snap_translate = addon_prefs.prop_bti_translate
100 | bpy.context.scene.tool_settings.use_snap_rotate = addon_prefs.prop_bti_rotation
101 | bpy.context.scene.tool_settings.use_snap_scale = addon_prefs.prop_bti_scale
102 |
103 | bpy.context.scene.cursor.rotation_euler[2] = self.rotation
104 | return {'FINISHED'}
105 |
106 |
107 |
108 |
109 |
110 | def func_cursor_copy(self, context):
111 |
112 | view_layer = bpy.context.view_layer
113 | selected = bpy.context.selected_objects
114 | obj_list = [obj for obj in selected]
115 | if obj_list:
116 |
117 | for obj in obj_list:
118 | view_layer.objects.active = obj
119 | obj.select_set(state=True)
120 |
121 | scene = bpy.context.scene
122 |
123 | # LOCATION
124 | if self.copy_loc == True:
125 | obj.location[0] = scene.cursor.location[0]
126 | obj.location[1] = scene.cursor.location[1]
127 | obj.location[2] = scene.cursor.location[2]
128 | loc_x = 'X'
129 | loc_y = 'Y'
130 | loc_z = 'Z Location'
131 |
132 | else:
133 | if self.copy_loc_x == True:
134 | obj.location[0] = scene.cursor.location[0]
135 | loc_x = 'X Location'
136 | else:
137 | loc_x = ''
138 |
139 | if self.copy_loc_y == True:
140 | obj.location[1] = scene.cursor.location[1]
141 | loc_y = 'Y Location'
142 | else:
143 | loc_y = ''
144 |
145 | if self.copy_loc_z == True:
146 | obj.location[2] = scene.cursor.location[2]
147 | loc_z = 'Z Location'
148 | else:
149 | loc_z = ''
150 |
151 |
152 | # ROTATION
153 | if self.copy_rot == True:
154 |
155 | obj.rotation_euler[0] = scene.cursor.rotation_euler[0]
156 | obj.rotation_euler[1] = scene.cursor.rotation_euler[1]
157 | obj.rotation_euler[2] = scene.cursor.rotation_euler[2]
158 | rot_x = 'X'
159 | rot_y = 'Y'
160 | rot_z = 'Z Rotation'
161 |
162 | else:
163 | if self.copy_rot_x == True:
164 | obj.rotation_euler[0] = scene.cursor.rotation_euler[0]
165 | rot_x = 'X Rotation'
166 | else:
167 | rot_x = ''
168 |
169 | if self.copy_rot_y == True:
170 | obj.rotation_euler[1] = scene.cursor.rotation_euler[1]
171 | rot_y = 'Y Rotation'
172 | else:
173 | rot_y = ''
174 |
175 | if self.copy_rot_z == True:
176 | obj.rotation_euler[2] = scene.cursor.rotation_euler[2]
177 | rot_z = 'Z Rotation'
178 | else:
179 | rot_z = ''
180 |
181 | message = ("Copy Cursor: " + rot_x + rot_y + rot_z + loc_x + loc_y + loc_z)
182 | self.report({'INFO'}, message)
183 | else:
184 | self.report({'INFO'}, 'No active selection!')
185 |
186 |
187 |
188 | class VIEW3D_OT_3d_cursor_copy(bpy.types.Operator):
189 | """copy 3d cursor rotation to selected"""
190 | bl_idname = "tpc_ot.cursor_copy"
191 | bl_label = "Cursor Copy"
192 | bl_options = {"REGISTER", 'UNDO'}
193 |
194 | copy_loc : BoolProperty(name="XYZ", description="toggle axis", default=False, options={'SKIP_SAVE'})
195 | copy_loc_x : BoolProperty(name="X", description="toggle axis", default=False, options={'SKIP_SAVE'})
196 | copy_loc_y : BoolProperty(name="Y", description="toggle axis", default=False, options={'SKIP_SAVE'})
197 | copy_loc_z : BoolProperty(name="Z", description="toggle axis", default=False, options={'SKIP_SAVE'})
198 |
199 | copy_rot : BoolProperty(name="XYZ", description="toggle axis", default=True, options={'SKIP_SAVE'})
200 | copy_rot_x : BoolProperty(name="X", description="toggle axis", default=False, options={'SKIP_SAVE'})
201 | copy_rot_y : BoolProperty(name="Y", description="toggle axis", default=False, options={'SKIP_SAVE'})
202 | copy_rot_z : BoolProperty(name="Z", description="toggle axis", default=False, options={'SKIP_SAVE'})
203 |
204 | def draw(self, context):
205 | layout = self.layout
206 |
207 | box = layout.box().column(align=True)
208 |
209 | row = box.row(align=True)
210 | row.label(text="Rotation:")
211 |
212 | sub1 = row.column(align=True)
213 | display_rota = not self.copy_rot
214 | sub1.prop(self, "copy_rot")
215 | row.label(text=" ")
216 | row.label(text=" ")
217 |
218 | row = box.row(align=True)
219 | row.label(text="Axis")
220 |
221 | sub1 = row.row(align=True)
222 | sub1.active = display_rota
223 | #sub1.scale_x = 0.5
224 | sub1.prop(self, "copy_rot_x")
225 | sub1.prop(self, "copy_rot_y")
226 | sub1.prop(self, "copy_rot_z")
227 |
228 | box.separator()
229 |
230 | row = box.row(align=True)
231 | row.label(text="Location:")
232 |
233 | sub1 = row.column(align=True)
234 | display_loc = not self.copy_loc
235 | sub1.prop(self, "copy_loc")
236 | row.label(text=" ")
237 | row.label(text=" ")
238 |
239 | row = box.row(align=True)
240 | row.label(text="Axis")
241 |
242 | sub1 = row.row(align=True)
243 | sub1.active = display_loc
244 | #sub1.scale_x = 0.5
245 | sub1.prop(self, "copy_loc_x")
246 | sub1.prop(self, "copy_loc_y")
247 | sub1.prop(self, "copy_loc_z")
248 |
249 | box.separator()
250 |
251 |
252 | def execute(self, context):
253 | func_cursor_copy(self, context)
254 | return {'FINISHED'}
255 |
256 |
257 | #def invoke(self, context, event):
258 | #return context.window_manager.invoke_props_popup(self, event)
259 |
260 |
261 | class VIEW3D_OT_place_cursor_modal(bpy.types.Operator):
262 | """use of a function and reload previous toolsettings when finished"""
263 | bl_idname = "tpc_ot.place_cursor_modal"
264 | bl_label = "PlaceCursor"
265 | bl_options = {'REGISTER', 'UNDO'}
266 |
267 | depth : BoolProperty(name="Surface Project", description="project onto the surface", default=True)
268 |
269 | orient : bpy.props.EnumProperty(
270 | items = [("NONE", "None", "leave orientation unchanged" ,1),
271 | ("VIEW", "View", "orient to the viewport" ,2),
272 | ("XFORM", "Transform", "orient to the current transform setting" ,3),
273 | ("GEOM", "Geometry", "match the surface normal" ,4)],
274 | name = "Orientation",
275 | default = "GEOM",
276 | description="Preset viewpoint to use")
277 |
278 | object_align : bpy.props.EnumProperty(
279 | items = [("WORLD", "World", "align new objects to world cooridnate system" ,1),
280 | ("VIEW", "View", "align new objects to active 3D view" ,2),
281 | ("CURSOR", "3D Cursor", "align new objects to 3D cursors rotation" ,3)],
282 | name = "Align to",
283 | default = "CURSOR",
284 | description="")
285 |
286 | rotation : FloatProperty(name="Rotate Cursor", description="", default=0, min= -360, max = 360, subtype='PERCENTAGE')
287 |
288 | def modal(self, context, event):
289 | context.area.tag_redraw()
290 | context.area.header_text_set("Leftclick+Press: Snap Cursor, + Mousewheel: Rotate Cursor, Rightclick/ESC: Cancel")
291 |
292 | # print info in system console
293 | def __init__(self):
294 | print("Start")
295 |
296 | def __del__(self):
297 | print("End")
298 |
299 | def store(self):
300 | # get snap settings
301 | store_pivot : bpy.context.scene.tool_settings.transform_pivot_point
302 | store_elements : bpy.context.scene.tool_settings.snap_elements
303 | store_target : bpy.context.scene.tool_settings.snap_target
304 | store_rotation : bpy.context.scene.tool_settings.use_snap_align_rotation
305 | store_project : bpy.context.scene.tool_settings.use_snap_project
306 | store_snap : bpy.context.scene.tool_settings.use_snap
307 |
308 | running = False
309 |
310 | # get the context arguments
311 | def modal(self, context, event):
312 |
313 | if event.value == "RELEASE" and self.running:
314 | # reload settings after event
315 | bpy.context.scene.tool_settings.transform_pivot_point = self.store_pivot
316 | bpy.context.scene.tool_settings.snap_elements = self.store_elements
317 | bpy.context.scene.tool_settings.snap_target = self.store_target
318 | bpy.context.scene.tool_settings.use_snap_align_rotation = self.store_rotation
319 | bpy.context.scene.tool_settings.use_snap_project = self.store_project
320 | bpy.context.scene.tool_settings.use_snap = self.store_snap
321 |
322 | bpy.ops.wm.tool_set_by_id(name="builtin.move")
323 | self.running = False
324 | return {'FINISHED'}
325 |
326 | elif event.type == 'LEFTMOUSE' and event.value =="PRESS" and not self.running:
327 | self.running = True
328 | bpy.ops.wm.tool_set_by_id(name="builtin.cursor")
329 |
330 | if event.type == 'WHEELUPMOUSE':
331 | bpy.context.scene.cursor.rotation_euler[2] = -self.rotation
332 |
333 | if event.type == 'WHEELDOWNMOUSE':
334 | bpy.context.scene.cursor.rotation_euler[2] = self.rotation
335 |
336 | # do event
337 | elif event.type in {'RIGHTMOUSE', 'ESC'}:
338 | # reload settings after event
339 | bpy.context.scene.tool_settings.transform_pivot_point = self.store_pivot
340 | bpy.context.scene.tool_settings.snap_elements = self.store_elements
341 | bpy.context.scene.tool_settings.snap_target = self.store_target
342 | bpy.context.scene.tool_settings.use_snap_align_rotation = self.store_rotation
343 | bpy.context.scene.tool_settings.use_snap_project = self.store_project
344 | bpy.context.scene.tool_settings.use_snap = self.store_snap
345 |
346 | bpy.ops.wm.tool_set_by_id(name="builtin.move")
347 | return {'CANCELLED'}
348 |
349 | return {'PASS_THROUGH'}
350 |
351 | #return {'RUNNING_MODAL'}
352 |
353 |
354 | # do by execute
355 | def invoke(self, context, event):
356 |
357 | if context.mode in "OBJECT":
358 | bpy.ops.object.select_all(action='DESELECT')
359 |
360 | # check if something selected
361 | if bpy.context.area.ui_type == 'VIEW_3D':
362 |
363 | # store exist settings
364 | self.store_pivot = bpy.context.scene.tool_settings.transform_pivot_point
365 | self.store_elements = bpy.context.scene.tool_settings.snap_elements
366 | self.store_target = bpy.context.scene.tool_settings.snap_target
367 | self.store_rotation = bpy.context.scene.tool_settings.use_snap_align_rotation
368 | self.store_project = bpy.context.scene.tool_settings.use_snap_project
369 | self.store_snap = bpy.context.scene.tool_settings.use_snap
370 |
371 | bpy.context.scene.tool_settings.transform_pivot_point = 'MEDIAN_POINT'
372 | bpy.context.scene.tool_settings.use_snap = True
373 | bpy.context.scene.tool_settings.snap_elements = {'VERTEX', 'EDGE', 'FACE'}
374 | bpy.context.scene.tool_settings.snap_target = 'MEDIAN'
375 | bpy.context.scene.tool_settings.use_snap_align_rotation = True
376 |
377 | bpy.context.space_data.overlay.show_cursor = True
378 | #https://docs.blender.org/api/current/bpy.ops.view3d.html
379 | bpy.ops.view3d.cursor3d(use_depth=self.depth, orientation=self.orient)
380 | bpy.context.preferences.edit.object_align=self.object_align
381 | bpy.context.scene.cursor.rotation_euler[2] = self.rotation
382 | #bpy.ops.wm.tool_set_by_id(name="builtin.cursor")
383 |
384 | context.window_manager.modal_handler_add(self)
385 | return {'RUNNING_MODAL'}
386 |
387 | else:
388 | self.report({'WARNING'}, "Must be in 3D View")
389 | return {'CANCELLED'}
390 |
391 |
392 |
393 |
394 |
--------------------------------------------------------------------------------
/ui_menu.py:
--------------------------------------------------------------------------------
1 | # LOAD MODUL #
2 | import bpy
3 | from bpy import *
4 | from bpy.props import *
5 | from . icons.icons import load_icons
6 | from .ui_utils import get_addon_prefs
7 |
8 | def draw_snapset_menu_ui(context, layout):
9 |
10 | icons = load_icons()
11 | icon_snap_set = icons.get("icon_snap_set")
12 | icon_snap_grid = icons.get("icon_snap_grid")
13 | icon_snap_place = icons.get("icon_snap_place")
14 | icon_snap_retopo = icons.get("icon_snap_retopo")
15 | icon_snap_cursor = icons.get("icon_snap_cursor")
16 | icon_snap_closest = icons.get("icon_snap_closest")
17 | icon_snap_active = icons.get("icon_snap_active")
18 | icon_snap_center = icons.get("icon_snap_center")
19 | icon_snap_perpendic = icons.get("icon_snap_perpendic")
20 | icon_snap_pcursor = icons.get("icon_snap_pcursor")
21 | icon_snap_custom = icons.get("icon_snap_custom")
22 |
23 | addon_prefs = get_addon_prefs()
24 |
25 | layout.operator_context = 'INVOKE_REGION_WIN'
26 |
27 | tx_snapset_grid = addon_prefs.name_bta
28 | tx_snapset_place = addon_prefs.name_btb
29 | tx_snapset_cursor = addon_prefs.name_btc
30 | tx_snapset_closet = addon_prefs.name_btd
31 | tx_snapset_active = addon_prefs.name_bte
32 | tx_snapset_retopo = addon_prefs.name_btf
33 | tx_snapset_center = addon_prefs.name_btg
34 | tx_snapset_perpendic = addon_prefs.name_bth
35 | tx_snapset_pcursor = addon_prefs.name_bti
36 | tx_snapset_custom = addon_prefs.name_btM
37 |
38 | tx_snapset_gridm = "Grid*"
39 | tx_snapset_placem = "Place*"
40 | tx_snapset_retopom = "Retopo*"
41 | tx_snapset_centerm = "MidPoint*"
42 | tx_snapset_perpendicm = "Perpendic*"
43 | tx_snapset_pcursorm = "PlaceCursor*"
44 | tx_snapset_customM = "Custom*"
45 |
46 |
47 | if addon_prefs.toggle_special_type_layout != 'switch':
48 |
49 | if addon_prefs.toggle_special_type_layout == 'column':
50 |
51 | row = layout.column(align=addon_prefs.row_align_special)
52 | row.scale_y = addon_prefs.ui_scale_y_special
53 |
54 |
55 | if addon_prefs.toggle_special_type_layout == 'flow':
56 |
57 | row = layout.column_flow(columns=2, align=addon_prefs.row_align_special)
58 | row.scale_y = addon_prefs.ui_scale_y_special
59 |
60 |
61 | if addon_prefs.tpc_use_grid_special == True:
62 | if addon_prefs.toggle_special_name == 'namend':
63 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid)
64 | else:
65 | if addon_prefs.use_internal_icon_bta == True:
66 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon=addon_prefs.icon_bta)
67 | else:
68 | row.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon_value=icon_snap_grid.icon_id)
69 |
70 |
71 | # mode switch
72 | if context.mode == 'OBJECT':
73 | if addon_prefs.tpc_use_place_special == True:
74 | if addon_prefs.toggle_special_name == 'namend':
75 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place)
76 | else:
77 | if addon_prefs.use_internal_icon_btb == True:
78 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon=addon_prefs.icon_btb)
79 | else:
80 | row.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon_value=icon_snap_place.icon_id)
81 | else:
82 | if addon_prefs.tpc_use_retopo_special == True:
83 | if addon_prefs.toggle_special_name == 'namend':
84 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo)
85 | else:
86 | if addon_prefs.use_internal_icon_btf == True:
87 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon=addon_prefs.icon_btf)
88 | else:
89 | row.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon_value=icon_snap_retopo.icon_id)
90 |
91 |
92 |
93 | if addon_prefs.tpc_use_cursor_special == True:
94 | if addon_prefs.toggle_special_name == 'namend':
95 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor)
96 | else:
97 | if addon_prefs.use_internal_icon_btc == True:
98 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon=addon_prefs.icon_btc)
99 | else:
100 | row.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon_value=icon_snap_cursor.icon_id)
101 |
102 | if addon_prefs.tpc_use_closest_special == True:
103 | if addon_prefs.toggle_special_name == 'namend':
104 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet)
105 | else:
106 | if addon_prefs.use_internal_icon_bte == True:
107 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon=addon_prefs.icon_bte)
108 | else:
109 | row.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon_value=icon_snap_closest.icon_id)
110 |
111 |
112 | if addon_prefs.tpc_use_active_special == True:
113 | if addon_prefs.toggle_special_name == 'namend':
114 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active)
115 | else:
116 | if addon_prefs.use_internal_icon_btd == True:
117 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon=addon_prefs.icon_btd)
118 | else:
119 | row.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon_value=icon_snap_active.icon_id)
120 |
121 | if addon_prefs.tpc_use_center_special == True:
122 | if addon_prefs.toggle_special_name == 'namend':
123 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center)
124 | else:
125 | if addon_prefs.use_internal_icon_btg == True:
126 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon=addon_prefs.icon_btg)
127 | else:
128 | row.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon_value=icon_snap_center.icon_id)
129 |
130 | if addon_prefs.tpc_use_perpendic_special == True:
131 | if addon_prefs.toggle_special_name == 'namend':
132 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic)
133 | else:
134 | if addon_prefs.use_internal_icon_bth == True:
135 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon=addon_prefs.icon_bth)
136 | else:
137 | row.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon_value=icon_snap_perpendic.icon_id)
138 |
139 | if addon_prefs.tpc_use_pcursor_special == True:
140 | if addon_prefs.toggle_special_name == 'namend':
141 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor)
142 | else:
143 | if addon_prefs.use_internal_icon_bti == True:
144 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon=addon_prefs.icon_bti)
145 | else:
146 | row.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon_value=icon_snap_pcursor.icon_id)
147 |
148 |
149 |
150 |
151 | if addon_prefs.toggle_special_type_layout == 'flow':
152 | row.label(text='')
153 |
154 | if addon_prefs.toggle_special_type_layout == 'column':
155 | if addon_prefs.tpc_use_separator_modal_special == True:
156 | row.separator()
157 |
158 | # MODAL BUTTONS #
159 | if addon_prefs.tpc_use_grid_modal_special == True:
160 | if addon_prefs.toggle_special_name == 'namend':
161 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm).mode = "GRID"
162 | else:
163 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm, icon_value=icon_snap_grid.icon_id).mode = "GRID"
164 |
165 | if context.mode == 'OBJECT':
166 | if addon_prefs.tpc_use_place_modal_special == True:
167 | if addon_prefs.toggle_special_name == 'namend':
168 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_placem).mode = "PLACE"
169 | else:
170 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_placem, icon_value=icon_snap_place.icon_id).mode = "PLACE"
171 | else:
172 | if addon_prefs.tpc_use_retopo_modal_special == True:
173 | if addon_prefs.toggle_special_name == 'namend':
174 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom).mode = "RETOPO"
175 | else:
176 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom, icon_value=icon_snap_retopo.icon_id).mode = "RETOPO"
177 |
178 | if addon_prefs.tpc_use_center_modal_special == True:
179 | if addon_prefs.toggle_special_name == 'namend':
180 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm).mode = "CENTER"
181 | else:
182 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm, icon_value=icon_snap_center.icon_id).mode = "CENTER"
183 |
184 | if addon_prefs.tpc_use_perpendic_modal_special == True:
185 | if addon_prefs.toggle_special_name == 'namend':
186 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm).mode = "PERPENDICULAR"
187 | else:
188 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm, icon_value=icon_snap_perpendic.icon_id).mode = "PERPENDICULAR"
189 |
190 | if addon_prefs.tpc_use_pcursor_modal_special == True:
191 | if addon_prefs.toggle_special_name == 'namend':
192 | row.operator("tpc_ot.place_cursor_modal", text=tx_snapset_pcursorm)
193 | else:
194 | row.operator("tpc_ot.place_cursor_modal", text=tx_snapset_pcursorm, icon_value=icon_snap_pcursor.icon_id)
195 |
196 | if addon_prefs.tpc_use_custom_modal_special == True:
197 | if addon_prefs.toggle_special_name == 'namend':
198 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_customM).mode = "CUSTOM"
199 | else:
200 | row.operator("tpc_ot.snapset_modal", text=tx_snapset_customM, icon_value=icon_snap_custom.icon_id).mode = "CUSTOM"
201 |
202 | if addon_prefs.tpc_use_settings_special == True:
203 | if addon_prefs.toggle_special_type_layout == 'column':
204 | if addon_prefs.tpc_use_separator_settings_special == True:
205 | row.separator()
206 |
207 | if addon_prefs.toggle_special_name == 'namend':
208 | row.operator("preferences.addon_show", text="Settings").module="view3d_snapset"
209 | else:
210 | row.operator("preferences.addon_show", text="Settings", icon="LAYER_USED").module="view3d_snapset"
211 |
212 |
213 |
214 |
215 |
216 |
217 | if addon_prefs.toggle_special_type_layout == 'switch':
218 |
219 | # DIRECT VERSION #
220 | if addon_prefs.toggle_layout_type == True:
221 |
222 | if addon_prefs.tpc_use_grid == True:
223 | if addon_prefs.toggle_special_name == 'namend':
224 | layout.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid)
225 | else:
226 | if addon_prefs.use_internal_icon_bta == True:
227 | layout.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon=addon_prefs.icon_bta)
228 | else:
229 | layout.operator("tpc_ot.snapset_button_a", text=tx_snapset_grid, icon_value=icon_snap_grid.icon_id)
230 |
231 |
232 | # mode switch
233 | if context.mode == 'OBJECT':
234 | if addon_prefs.tpc_use_place == True:
235 | if addon_prefs.toggle_special_name == 'namend':
236 | layout.operator("tpc_ot.snapset_button_b", text=tx_snapset_place)
237 | else:
238 | if addon_prefs.use_internal_icon_btb == True:
239 | layout.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon=addon_prefs.icon_btb)
240 | else:
241 | layout.operator("tpc_ot.snapset_button_b", text=tx_snapset_place, icon_value=icon_snap_place.icon_id)
242 | else:
243 | if addon_prefs.tpc_use_retopo == True:
244 | if addon_prefs.toggle_special_name == 'namend':
245 | layout.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo)
246 | else:
247 | if addon_prefs.use_internal_icon_btf == True:
248 | layout.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon=addon_prefs.icon_btf)
249 | else:
250 | layout.operator("tpc_ot.snapset_button_f", text=tx_snapset_retopo, icon_value=icon_snap_retopo.icon_id)
251 |
252 |
253 |
254 | if addon_prefs.tpc_use_cursor == True:
255 | if addon_prefs.toggle_special_name == 'namend':
256 | layout.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor)
257 | else:
258 | if addon_prefs.use_internal_icon_btc == True:
259 | layout.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon=addon_prefs.icon_btc)
260 | else:
261 | layout.operator("tpc_ot.snapset_button_c", text=tx_snapset_cursor, icon_value=icon_snap_cursor.icon_id)
262 |
263 | if addon_prefs.tpc_use_closest == True:
264 | if addon_prefs.toggle_special_name == 'namend':
265 | layout.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet)
266 | else:
267 | if addon_prefs.use_internal_icon_bte == True:
268 | layout.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon=addon_prefs.icon_bte)
269 | else:
270 | layout.operator("tpc_ot.snapset_button_e", text=tx_snapset_closet, icon_value=icon_snap_closest.icon_id)
271 |
272 |
273 | if addon_prefs.tpc_use_active == True:
274 | if addon_prefs.toggle_special_name == 'namend':
275 | layout.operator("tpc_ot.snapset_button_d", text=tx_snapset_active)
276 | else:
277 | if addon_prefs.use_internal_icon_btd == True:
278 | layout.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon=addon_prefs.icon_btd)
279 | else:
280 | layout.operator("tpc_ot.snapset_button_d", text=tx_snapset_active, icon_value=icon_snap_active.icon_id)
281 |
282 | if addon_prefs.tpc_use_center == True:
283 | if addon_prefs.toggle_special_name == 'namend':
284 | layout.operator("tpc_ot.snapset_button_g", text=tx_snapset_center)
285 | else:
286 | if addon_prefs.use_internal_icon_btg == True:
287 | layout.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon=addon_prefs.icon_btg)
288 | else:
289 | layout.operator("tpc_ot.snapset_button_g", text=tx_snapset_center, icon_value=icon_snap_center.icon_id)
290 |
291 | if addon_prefs.tpc_use_perpendic == True:
292 | if addon_prefs.toggle_special_name == 'namend':
293 | layout.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic)
294 | else:
295 | if addon_prefs.use_internal_icon_bth == True:
296 | layout.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon=addon_prefs.icon_bth)
297 | else:
298 | layout.operator("tpc_ot.snapset_button_h", text=tx_snapset_perpendic, icon_value=icon_snap_perpendic.icon_id)
299 |
300 | if addon_prefs.tpc_use_pcursor == True:
301 | if addon_prefs.toggle_special_name == 'namend':
302 | layout.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor)
303 | else:
304 | if addon_prefs.use_internal_icon_bti == True:
305 | layout.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon=addon_prefs.icon_bti)
306 | else:
307 | layout.operator("tpc_ot.place_cursor", text=tx_snapset_pcursor, icon_value=icon_snap_pcursor.icon_id)
308 |
309 |
310 | else:
311 |
312 | # MODAL BUTTONS #
313 | if addon_prefs.tpc_use_grid_modal == True:
314 | if addon_prefs.toggle_special_name == 'namend':
315 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm).mode = "GRID"
316 | else:
317 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_gridm, icon_value=icon_snap_grid.icon_id).mode = "GRID"
318 |
319 | if context.mode == 'OBJECT':
320 | if addon_prefs.tpc_use_place_modal == True:
321 | if addon_prefs.toggle_special_name == 'namend':
322 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_placem).mode = "PLACE"
323 | else:
324 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_placem, icon_value=icon_snap_place.icon_id).mode = "PLACE"
325 | else:
326 | if addon_prefs.tpc_use_retopo_modal == True:
327 | if addon_prefs.toggle_special_name == 'namend':
328 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom).mode = "RETOPO"
329 | else:
330 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_retopom, icon_value=icon_snap_retopo.icon_id).mode = "RETOPO"
331 |
332 | if addon_prefs.tpc_use_center_modal == True:
333 | if addon_prefs.toggle_special_name == 'namend':
334 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm).mode = "CENTER"
335 | else:
336 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_centerm, icon_value=icon_snap_center.icon_id).mode = "CENTER"
337 |
338 | if addon_prefs.tpc_use_perpendic_modal == True:
339 | if addon_prefs.toggle_special_name == 'namend':
340 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm).mode = "PERPENDICULAR"
341 | else:
342 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_perpendicm, icon_value=icon_snap_perpendic.icon_id).mode = "PERPENDICULAR"
343 |
344 | if addon_prefs.tpc_use_pcursor_modal_special == True:
345 | if addon_prefs.toggle_special_name == 'namend':
346 | layout.operator("tpc_ot.place_cursor_modal", text=tx_snapset_pcursorm)
347 | else:
348 | layout.operator("tpc_ot.place_cursor_modal", text=tx_snapset_pcursorm, icon_value=icon_snap_pcursor.icon_id)
349 |
350 | if addon_prefs.tpc_use_custom_modal == True:
351 | if addon_prefs.toggle_special_name == 'namend':
352 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_customM).mode = "CUSTOM"
353 | else:
354 | layout.operator("tpc_ot.snapset_modal", text=tx_snapset_customM, icon_value=icon_snap_custom.icon_id).mode = "CUSTOM"
355 |
356 |
357 |
358 | if addon_prefs.tpc_use_separator_settings_special == True:
359 | layout.separator()
360 |
361 | if addon_prefs.tpc_use_settings_special == True:
362 | if addon_prefs.toggle_special_name == 'namend':
363 | layout.operator("preferences.addon_show", text="Settings").module="view3d_snapset"
364 | else:
365 | layout.operator("preferences.addon_show", text="Settings", icon="LAYER_USED").module="view3d_snapset"
366 |
367 | layout.prop(addon_prefs, "toggle_layout_type", text="", icon='GRIP')
368 | #layout.popover(panel="VIEW3D_PT_snapset_header_panel", text=" SnapSet")
369 |
370 |
371 |
372 | # UI: HOTKEY MENU #
373 | class VIEW3D_MT_snapset_menu(bpy.types.Menu):
374 | bl_label = "SnapSet"
375 | bl_idname = "VIEW3D_MT_snapset_menu"
376 |
377 | def draw(self, context):
378 | layout = self.layout
379 | layout.operator_context = 'INVOKE_REGION_WIN'
380 |
381 | draw_snapset_menu_ui(context, layout)
382 | #layout.popover(panel="VIEW3D_PT_snapset_panel_ui", text="Menu Panel")
383 |
384 |
385 | class VIEW3D_MT_snapset_menu_panel(bpy.types.Menu):
386 | bl_label = "SnapSet"
387 | bl_idname = "VIEW3D_MT_snapset_menu_panel"
388 |
389 | def draw(self, context):
390 | layout = self.layout
391 | layout.operator_context = 'INVOKE_REGION_WIN'
392 |
393 | draw_snapset_menu_ui(context, layout)
394 |
395 |
396 | # LAYOUT #
397 | def draw_snapset_item_special(self, context):
398 | layout = self.layout
399 |
400 | icons = load_icons()
401 |
402 | addon_prefs = get_addon_prefs()
403 |
404 | if addon_prefs.toggle_special_type == 'append':
405 | if addon_prefs.toggle_special_separator == True:
406 | layout.separator()
407 |
408 | if addon_prefs.toggle_special_icon == True:
409 | button_snap_set = icons.get("icon_snap_set")
410 | layout.menu("VIEW3D_MT_snapset_menu_special", text="SnapSet", icon_value=button_snap_set.icon_id)
411 | else:
412 | layout.menu("VIEW3D_MT_snapset_menu_special", text="SnapSet")
413 |
414 | if addon_prefs.toggle_special_type == 'prepend':
415 | if addon_prefs.toggle_special_separator == True:
416 | layout.separator()
417 |
418 |
419 | # MENU #
420 | class VIEW3D_MT_snapset_menu_special(bpy.types.Menu):
421 | bl_label = "SnapSet"
422 | bl_idname = "VIEW3D_MT_snapset_menu_special"
423 |
424 | def draw(self, context):
425 | layout = self.layout
426 | layout.operator_context = 'INVOKE_REGION_WIN'
427 |
428 | draw_snapset_menu_ui(context, layout)
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 | Blender Addon Updater
635 | Copyright (C) 2016 Patrick W. Crawford
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Blender Addon Updater Copyright (C) 2016 Patrick W. Crawford
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------