Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'modules/snap_context/__init__.py')
-rw-r--r--modules/snap_context/__init__.py322
1 files changed, 0 insertions, 322 deletions
diff --git a/modules/snap_context/__init__.py b/modules/snap_context/__init__.py
deleted file mode 100644
index 77e84726..00000000
--- a/modules/snap_context/__init__.py
+++ /dev/null
@@ -1,322 +0,0 @@
-# ##### 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 3
-# 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, see <http://www.gnu.org/licenses/>.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-__all__ = (
- "SnapContext",
- )
-
-import bgl
-from mathutils import Vector
-
-VERT = 1
-EDGE = 2
-FACE = 4
-
-
-class _Internal:
- from .mesh_drawing import (
- gpu_Indices_enable_state,
- gpu_Indices_restore_state,
- gpu_Indices_use_clip_planes,
- gpu_Indices_set_ProjectionMatrix,
- )
-
- from .utils_projection import (
- region_2d_to_orig_and_view_vector,
- intersect_boundbox_threshold,
- intersect_ray_segment_fac,
- project_co_v3,
- )
-
- from mathutils.geometry import intersect_line_plane
-
-
-class _SnapObjectData():
- __slots__ = ('data', 'mat')
- def __init__(self, data, omat):
- self.data = data
- self.mat = omat
-
-
-class SnapContext():
- """
- Initializes the snap context with the region and space where the snap objects will be added.
-
- .. note::
- After the context has been created, add the objects with the `add_obj` method.
-
- :arg region: region of the 3D viewport, typically bpy.context.region.
- :type region: :class:`bpy.types.Region`
- :arg space: 3D region data, typically bpy.context.space_data.
- :type space: :class:`bpy.types.SpaceView3D`
- """
-
- def __init__(self, region, space):
- import gpu
- import ctypes
-
- self.freed = False
- self.snap_objects = []
- self.drawn_count = 0
- self._offset_cur = 1 # Starts with index 1
- self.region = region
- self.rv3d = space.region_3d
-
- if self.rv3d.is_perspective:
- self.depth_range = Vector((space.clip_start, space.clip_end))
- else:
- self.depth_range = Vector((-space.clip_end, space.clip_end))
-
- self.proj_mat = None
- self.mval = Vector((0, 0))
- self._snap_mode = VERT | EDGE | FACE
-
- self.set_pixel_dist(12)
-
- self._offscreen = gpu.offscreen.new(self.region.width, self.region.height)
-
- self._texture = self._offscreen.color_texture
- bgl.glBindTexture(bgl.GL_TEXTURE_2D, self._texture)
-
- NULL = bgl.Buffer(bgl.GL_INT, 1, (ctypes.c_int32 * 1).from_address(0))
- bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_R32UI, self.region.width, self.region.height, 0, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, NULL)
- del NULL
-
- bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_NEAREST)
- bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_NEAREST)
- bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
-
- self.winsize = Vector((self._offscreen.width, self._offscreen.height))
-
- ## PRIVATE ##
-
- def _get_snap_obj_by_index(self, index):
- for snap_obj in self.snap_objects[:self.drawn_count]:
- data = snap_obj.data[1]
- if index < data.first_index + data.get_tot_elems():
- return snap_obj
- return None
-
- def _get_nearest_index(self):
- loc = [self._dist_px, self._dist_px]
- d = 1
- m = self.threshold
- max = 2 * m - 1
- offset = 1
- last_snap_obj = None
- r_value = 0
- while m < max:
- for i in range(2):
- while 2 * loc[i] * d < m:
- value = int(self._snap_buffer[loc[0]][loc[1]])
- loc[i] += d
- if value >= offset:
- r_value = value
- snap_obj = self._get_snap_obj_by_index(r_value)
-
- if self._snap_mode & FACE and self._snap_mode & (VERT | EDGE) and last_snap_obj != snap_obj:
- data = snap_obj.data[1]
- offset = data.first_index + data.num_tris
- last_snap_obj = snap_obj
- continue
- return snap_obj, r_value
- d = -d
- m += 4 * self._dist_px * d + 1
-
- return last_snap_obj, r_value
-
- def _get_loc(self, snap_obj, index):
- index -= snap_obj.data[1].first_index
- gpu_data = snap_obj.data[1]
-
- if gpu_data.draw_tris:
- if index < snap_obj.data[1].num_tris:
- tri_verts = gpu_data.get_tri_verts(index)
- tri_co = [snap_obj.mat * Vector(v) for v in gpu_data.get_tri_co(index)]
- nor = (tri_co[1] - tri_co[0]).cross(tri_co[2] - tri_co[0])
- return _Internal.intersect_line_plane(self.last_ray[1], self.last_ray[1] + self.last_ray[0], tri_co[0], nor), tri_verts
-
- index -= gpu_data.num_tris
-
- if gpu_data.draw_edges:
- if index < snap_obj.data[1].num_edges:
- edge_verts = gpu_data.get_edge_verts(index)
- edge_co = [snap_obj.mat * Vector(v) for v in gpu_data.get_edge_co(index)]
- fac = _Internal.intersect_ray_segment_fac(*edge_co, *self.last_ray)
-
- if (self._snap_mode) & VERT and (fac < 0.25 or fac > 0.75):
- co = edge_co[0] if fac < 0.5 else edge_co[1]
- proj_co = _Internal.project_co_v3(self, co)
- dist = self.mval - proj_co
- if abs(dist.x) < self._dist_px and abs(dist.y) < self._dist_px:
- return co, (edge_verts[0] if fac < 0.5 else edge_verts[1],)
-
- if fac <= 0.0:
- co = edge_co[0]
- elif fac >= 1.0:
- co = edge_co[1]
- else:
- co = edge_co[0] + fac * (edge_co[1] - edge_co[0])
-
- return co, edge_verts
-
- index -= gpu_data.num_edges
-
- if gpu_data.draw_verts:
- if index < snap_obj.data[1].num_verts:
- return snap_obj.mat * Vector(gpu_data.get_loosevert_co(index)), (gpu_data.get_loosevert_index(index),)
-
- return None, None
-
-
- def _get_snap_obj_by_obj(self, obj):
- for snap_obj in self.snap_objects:
- if obj == snap_obj.data[0]:
- return snap_obj
-
- def __del__(self):
- if not self.freed:
- self._offscreen.free()
- # Some objects may still be being referenced
- for snap_obj in self.snap_objects:
- del snap_obj.data
- del snap_obj.mat
- del snap_obj
- del self.snap_objects
-
- ## PUBLIC ##
-
- def update_all(self):
- self.drawn_count = 0
- self._offset_cur = 1
-
- bgl.glClearColor(0.0, 0.0, 0.0, 0.0)
- bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT)
-
- def update_drawn_snap_object(self, snap_obj):
- if len(snap_obj.data) > 1:
- del snap_obj.data[1:]
- #self.update_all()
- # Update on next snap_get call #
- self.proj_mat = None
-
- def use_clip_planes(self, value):
- _Internal.gpu_Indices_use_clip_planes(self.rv3d, value)
-
- def set_pixel_dist(self, dist_px):
- self._dist_px = int(dist_px)
- self._dist_px_sq = self._dist_px ** 2
- self.threshold = 2 * self._dist_px + 1
- self._snap_buffer = bgl.Buffer(bgl.GL_FLOAT, (self.threshold, self.threshold))
-
- def set_snap_mode(self, snap_to_vert, snap_to_edge, snap_to_face):
- snap_mode = 0
- if snap_to_vert:
- snap_mode |= VERT
- if snap_to_edge:
- snap_mode |= EDGE
- if snap_to_face:
- snap_mode |= FACE
-
- if snap_mode != self._snap_mode:
- self._snap_mode = snap_mode
- self.update_all()
-
- def add_obj(self, obj, matrix):
- matrix = matrix.copy()
- snap_obj = self._get_snap_obj_by_obj(obj)
- if not snap_obj:
- self.snap_objects.append(_SnapObjectData([obj], matrix))
- else:
- self.snap_objects.append(_SnapObjectData(snap_obj.data, matrix))
-
- return self.snap_objects[-1]
-
- def get_ray(self, mval):
- self.last_ray = _Internal.region_2d_to_orig_and_view_vector(self.region, self.rv3d, mval)
- return self.last_ray
-
- def snap_get(self, mval):
- ret = None, None
- self.mval[:] = mval
- snap_vert = self._snap_mode & VERT != 0
- snap_edge = self._snap_mode & EDGE != 0
- snap_face = self._snap_mode & FACE != 0
-
- _Internal.gpu_Indices_enable_state()
- self._offscreen.bind()
-
- #bgl.glDisable(bgl.GL_DITHER) # dithering and AA break color coding, so disable #
- #multisample_enabled = bgl.glIsEnabled(bgl.GL_MULTISAMPLE)
- #bgl.glDisable(bgl.GL_MULTISAMPLE)
- bgl.glEnable(bgl.GL_DEPTH_TEST)
-
- proj_mat = self.rv3d.perspective_matrix.copy()
- if self.proj_mat != proj_mat:
- self.proj_mat = proj_mat
- _Internal.gpu_Indices_set_ProjectionMatrix(self.proj_mat)
- self.update_all()
-
- ray_dir, ray_orig = self.get_ray(mval)
- for i, snap_obj in enumerate(self.snap_objects[self.drawn_count:], self.drawn_count):
- obj = snap_obj.data[0]
- bbmin = Vector(obj.bound_box[0])
- bbmax = Vector(obj.bound_box[6])
-
- if bbmin != bbmax:
- MVP = proj_mat * snap_obj.mat
- mat_inv = snap_obj.mat.inverted()
- ray_orig_local = mat_inv * ray_orig
- ray_dir_local = mat_inv.to_3x3() * ray_dir
- in_threshold = _Internal.intersect_boundbox_threshold(self, MVP, ray_orig_local, ray_dir_local, bbmin, bbmax)
- else:
- proj_co = _Internal.project_co_v3(self, snap_obj.mat.translation)
- dist = self.mval - proj_co
- in_threshold = abs(dist.x) < self._dist_px and abs(dist.y) < self._dist_px
- #snap_obj.data[1] = primitive_point
-
- if in_threshold:
- if len(snap_obj.data) == 1:
- from .mesh_drawing import GPU_Indices_Mesh
- snap_obj.data.append(GPU_Indices_Mesh(obj, snap_face, snap_edge, snap_vert))
- snap_obj.data[1].set_draw_mode(snap_face, snap_edge, snap_vert)
- snap_obj.data[1].set_ModelViewMatrix(snap_obj.mat)
- snap_obj.data[1].Draw(self._offset_cur)
- self._offset_cur += snap_obj.data[1].get_tot_elems()
-
- self.snap_objects[self.drawn_count], self.snap_objects[i] = self.snap_objects[i], self.snap_objects[self.drawn_count]
- self.drawn_count += 1
-
- bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0)
- bgl.glReadPixels(
- int(self.mval[0]) - self._dist_px, int(self.mval[1]) - self._dist_px,
- self.threshold, self.threshold, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, self._snap_buffer)
- bgl.glReadBuffer(bgl.GL_BACK)
-
- snap_obj, index = self._get_nearest_index()
- #print(index)
- if snap_obj:
- ret = self._get_loc(snap_obj, index)
-
- self._offscreen.unbind()
- _Internal.gpu_Indices_restore_state()
-
- return snap_obj, ret[0], ret[1]
-
- def free(self):
- self.__del__()
- self.freed = True