diff options
Diffstat (limited to 'archipack/archipack_snap.py')
-rw-r--r-- | archipack/archipack_snap.py | 347 |
1 files changed, 0 insertions, 347 deletions
diff --git a/archipack/archipack_snap.py b/archipack/archipack_snap.py deleted file mode 100644 index 9d50add7..00000000 --- a/archipack/archipack_snap.py +++ /dev/null @@ -1,347 +0,0 @@ -# -*- coding:utf-8 -*- - -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110- 1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -# <pep8 compliant> - -# ---------------------------------------------------------- -# Author: Stephen Leger (s-leger) -# Inspired by Okavango's np_point_move -# ---------------------------------------------------------- -""" - Usage: - from .archipack_snap import snap_point - - snap_point(takeloc, draw_callback, action_callback, constraint_axis) - - arguments: - - takeloc Vector3d location of point to snap - - constraint_axis boolean tuple for each axis - eg: (True, True, False) to constrtaint to xy plane - - draw_callback(context, sp) - sp.takeloc - sp.placeloc - sp.delta - - action_callback(context, event, state, sp) - state in {'RUNNING', 'SUCCESS', 'CANCEL'} - sp.takeloc - sp.placeloc - sp.delta - - with 3d Vectors - - delta = placeloc - takeloc - - takeloc - - placeloc - - - NOTE: - may change grid size to 0.1 round feature (SHIFT) - see https://blenderartists.org/forum/showthread.php?205158-Blender-2-5-Snap-mode-increment - then use a SHIFT use grid snap - -""" - -import bpy -from bpy.types import Operator -from mathutils import Vector, Matrix -import logging - -logger = logging.getLogger("archipack") - - -def dumb_callback(context, event, state, sp): - return - - -def dumb_draw(sp, context): - return - - -class SnapStore: - """ - Global store - """ - callback = None - draw = None - helper = None - takeloc = Vector() - placeloc = Vector() - constraint_axis = (True, True, False) - helper_matrix = Matrix() - transform_orientation = 'GLOBAL' - release_confirm = True - instances_running = 0 - - # context related - act = None - sel = [] - use_snap = False - snap_elements = None - snap_target = None - pivot_point = None - trans_orientation = None - - -def snap_point(takeloc=None, - draw=None, - callback=dumb_callback, - takemat=None, - constraint_axis=(True, True, False), - transform_orientation='GLOBAL', - mode='OBJECT', - release_confirm=True): - """ - Invoke op from outside world - in a convenient importable function - - transform_orientation in [‘GLOBAL’, ‘LOCAL’, ‘NORMAL’, ‘GIMBAL’, ‘VIEW’] - - draw(sp, context) a draw callback - callback(context, event, state, sp) action callback - - Use either : - takeloc Vector, unconstraint or system axis constraints - takemat Matrix, constaint to this matrix as 'LOCAL' coordsys - The snap source helper use it as world matrix - so it is possible to constraint to user defined coordsys. - """ - SnapStore.draw = draw - SnapStore.callback = callback - SnapStore.constraint_axis = constraint_axis - SnapStore.release_confirm = release_confirm - - if takemat is not None: - SnapStore.helper_matrix = takemat - takeloc = takemat.translation.copy() - transform_orientation = 'LOCAL' - elif takeloc is not None: - SnapStore.helper_matrix = Matrix.Translation(takeloc) - else: - raise ValueError("ArchipackSnap: Either takeloc or takemat must be defined") - - SnapStore.takeloc = takeloc - SnapStore.placeloc = takeloc.copy() - - SnapStore.transform_orientation = transform_orientation - - # @NOTE: unused mode var to switch between OBJECT and EDIT mode - # for ArchipackSnapBase to be able to handle both modes - # must implements corresponding helper create and delete actions - SnapStore.mode = mode - bpy.ops.archipack.snap('INVOKE_DEFAULT') - # return helper so we are able to move it "live" - return SnapStore.helper - - -class ArchipackSnapBase(): - """ - Helper class for snap Operators - store and restore context - create and destroy helper - install and remove a draw_callback working while snapping - - store and provide access to 3d Vectors - in draw_callback and action_callback - - delta = placeloc - takeloc - - takeloc - - placeloc - """ - - def __init__(self): - self._draw_handler = None - - def init(self, context, event): - # Store context data - # if SnapStore.instances_running < 1: - SnapStore.sel = context.selected_objects[:] - SnapStore.act = context.object - bpy.ops.object.select_all(action="DESELECT") - ts = context.tool_settings - SnapStore.use_snap = ts.use_snap - SnapStore.snap_elements = ts.snap_elements - SnapStore.snap_target = ts.snap_target - SnapStore.pivot_point = ts.transform_pivot_point - SnapStore.trans_orientation = context.scene.transform_orientation_slots[0].type - self.create_helper(context) - # Use a timer to broadcast a TIMER event while transform.translate is running - self._timer = context.window_manager.event_timer_add(0.1, window=context.window) - - if SnapStore.draw is not None: - args = (self, context) - self._draw_handler = bpy.types.SpaceView3D.draw_handler_add(SnapStore.draw, args, 'WINDOW', 'POST_PIXEL') - - def remove_timer(self, context): - if self._timer is not None: - context.window_manager.event_timer_remove(self._timer) - - def exit(self, context): - - self.remove_timer(context) - - if self._draw_handler is not None: - bpy.types.SpaceView3D.draw_handler_remove(self._draw_handler, 'WINDOW') - - # Restore original context - if hasattr(context, "tool_settings"): - ts = context.tool_settings - ts.use_snap = SnapStore.use_snap - ts.snap_elements = SnapStore.snap_elements - ts.snap_target = SnapStore.snap_target - ts.transform_pivot_point = SnapStore.pivot_point - context.scene.transform_orientation_slots[0].type = SnapStore.trans_orientation - for o in SnapStore.sel: - o.select_set(state=True) - if SnapStore.act is not None: - SnapStore.act.select_set(state=True) - context.view_layer.objects.active = SnapStore.act - self.destroy_helper(context) - logger.debug("Snap.exit %s", context.object.name) - - def create_helper(self, context): - """ - Create a helper with fake user - or find older one in bpy data and relink to scene - currently only support OBJECT mode - - Do target helper be linked to scene in order to work ? - - """ - helper = bpy.data.objects.get('Archipack_snap_helper') - if helper is not None: - # print("helper found") - if context.scene.objects.get('Archipack_snap_helper') is None: - # print("link helper") - # self.link_object_to_scene(context, helper) - context.scene.collection.objects.link(helper) - else: - # print("create helper") - m = bpy.data.meshes.new("Archipack_snap_helper") - m.vertices.add(count=1) - helper = bpy.data.objects.new("Archipack_snap_helper", m) - context.scene.collection.objects.link(helper) - helper.use_fake_user = True - helper.data.use_fake_user = True - - helper.matrix_world = SnapStore.helper_matrix - helper.select_set(state=True) - context.view_layer.objects.active = helper - SnapStore.helper = helper - - def destroy_helper(self, context): - """ - Unlink helper - currently only support OBJECT mode - """ - if SnapStore.helper is not None: - # @TODO: Fix this - # self.unlink_object_from_scene(context, SnapStore.helper) - SnapStore.helper = None - - @property - def delta(self): - return self.placeloc - self.takeloc - - @property - def takeloc(self): - return SnapStore.takeloc - - @property - def placeloc(self): - # take from helper when there so the delta - # is working even while modal is running - if SnapStore.helper is not None: - return SnapStore.helper.location - else: - return SnapStore.placeloc - - -class ARCHIPACK_OT_snap(ArchipackSnapBase, Operator): - bl_idname = 'archipack.snap' - bl_label = 'Archipack snap' - bl_options = {'INTERNAL'} # , 'UNDO' - - def modal(self, context, event): - - if SnapStore.helper is not None: - logger.debug("Snap.modal event %s %s location:%s", - event.type, - event.value, - SnapStore.helper.location) - - context.area.tag_redraw() - - if event.type in ('TIMER', 'NOTHING'): - SnapStore.callback(context, event, 'RUNNING', self) - return {'PASS_THROUGH'} - - if event.type not in ('ESC', 'RIGHTMOUSE', 'LEFTMOUSE', 'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'): - return {'PASS_THROUGH'} - - if event.type in ('ESC', 'RIGHTMOUSE'): - SnapStore.callback(context, event, 'CANCEL', self) - else: - SnapStore.placeloc = SnapStore.helper.location - # on tt modal exit with right click, the delta is 0 so exit - if self.delta.length == 0: - SnapStore.callback(context, event, 'CANCEL', self) - else: - SnapStore.callback(context, event, 'SUCCESS', self) - - self.exit(context) - # self.report({'INFO'}, "ARCHIPACK_OT_snap exit") - return {'FINISHED'} - - def invoke(self, context, event): - if context.area.type == 'VIEW_3D': - - if event.type in ('ESC', 'RIGHTMOUSE'): - return {'FINISHED'} - - self.init(context, event) - - logger.debug("Snap.invoke event %s %s location:%s act:%s", - event.type, - event.value, - SnapStore.helper.location, context.object.name) - - context.window_manager.modal_handler_add(self) - - bpy.ops.transform.translate('INVOKE_DEFAULT', - constraint_axis=SnapStore.constraint_axis, - orient_type=SnapStore.transform_orientation, - release_confirm=SnapStore.release_confirm) - - logger.debug("Snap.invoke transform.translate done") - - return {'RUNNING_MODAL'} - else: - self.report({'WARNING'}, "View3D not found, cannot run operator") - return {'FINISHED'} - - -def register(): - bpy.utils.register_class(ARCHIPACK_OT_snap) - - -def unregister(): - bpy.utils.unregister_class(ARCHIPACK_OT_snap) |