mirror of
https://github.com/blender/blender-addons.git
synced 2025-08-16 15:35:05 +00:00
Added Cursor Control, Cursor History and Cursor Memory along with the shared modules.
[[Split portion of a mixed commit.]]
This commit is contained in:
34
modules/constants_utils.py
Normal file
34
modules/constants_utils.py
Normal file
@ -0,0 +1,34 @@
|
||||
# -*- 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 #####
|
||||
|
||||
'''
|
||||
constants_utils.py
|
||||
|
||||
Useful constants...
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
|
||||
# Golden mean
|
||||
PHI_INV = 0.61803398874989484820
|
||||
PHI = 1.61803398874989484820
|
||||
PHI_SQR = 2.61803398874989484820
|
61
modules/cursor_utils.py
Normal file
61
modules/cursor_utils.py
Normal file
@ -0,0 +1,61 @@
|
||||
# -*- 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 #####
|
||||
|
||||
'''
|
||||
cursor_utils.py
|
||||
|
||||
Helper methods for accessing the 3D cursor
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class CursorAccess:
|
||||
|
||||
@classmethod
|
||||
def findSpace(cls):
|
||||
area = None
|
||||
for area in bpy.data.window_managers[0].windows[0].screen.areas:
|
||||
if area.type == 'VIEW_3D':
|
||||
break
|
||||
if area.type != 'VIEW_3D':
|
||||
return None
|
||||
for space in area.spaces:
|
||||
if space.type == 'VIEW_3D':
|
||||
break
|
||||
if space.type != 'VIEW_3D':
|
||||
return None
|
||||
return space
|
||||
|
||||
@classmethod
|
||||
def setCursor(cls,coordinates):
|
||||
spc = cls.findSpace()
|
||||
spc.cursor_location = coordinates
|
||||
|
||||
@classmethod
|
||||
def getCursor(cls):
|
||||
spc = cls.findSpace()
|
||||
return spc.cursor_location
|
||||
|
||||
|
||||
|
215
modules/geometry_utils.py
Normal file
215
modules/geometry_utils.py
Normal file
@ -0,0 +1,215 @@
|
||||
# -*- 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 #####
|
||||
|
||||
'''
|
||||
geometry_utils.py
|
||||
|
||||
3d geometry calculations
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
from mathutils import Vector, Matrix
|
||||
from mathutils import geometry
|
||||
|
||||
|
||||
# 3D Geometry
|
||||
class G3:
|
||||
|
||||
@classmethod
|
||||
def distanceP2P(cls, p1, p2):
|
||||
return (p1-p2).length
|
||||
|
||||
@classmethod
|
||||
def closestP2L(cls, p, l1, l2):
|
||||
vA = p - l1
|
||||
vL = l2- l1
|
||||
vL.normalize()
|
||||
return vL * (vL.dot(vA)) + l1
|
||||
|
||||
@classmethod
|
||||
def closestP2E(cls, p, e1, e2):
|
||||
q = G3.closestP2L(p, e1, e2)
|
||||
de = G3.distanceP2P(e1, e2)
|
||||
d1 = G3.distanceP2P(q, e1)
|
||||
d2 = G3.distanceP2P(q, e2)
|
||||
if d1>de and d1>d2:
|
||||
q = e2
|
||||
if d2>de and d2>d1:
|
||||
q = e1
|
||||
return q
|
||||
|
||||
@classmethod
|
||||
def heightP2S(cls, p, sO, sN):
|
||||
return (p-sO).dot(sN) / sN.dot(sN)
|
||||
|
||||
@classmethod
|
||||
def closestP2S(cls, p, sO, sN):
|
||||
k = - G3.heightP2S(p, sO, sN)
|
||||
q = p+sN*k
|
||||
return q
|
||||
|
||||
@classmethod
|
||||
def closestP2F(cls, p, fv, sN):
|
||||
q = G3.closestP2S(p, fv[0], sN)
|
||||
#pi = MeshEditor.addVertex(p)
|
||||
#qi = MeshEditor.addVertex(q)
|
||||
#MeshEditor.addEdge(pi, qi)
|
||||
#print ([d0,d1,d2])
|
||||
|
||||
if len(fv)==3:
|
||||
h = G3.closestP2L(fv[0], fv[1], fv[2])
|
||||
d = (fv[0]-h).dot(q-h)
|
||||
if d<=0:
|
||||
return G3.closestP2E(q, fv[1], fv[2])
|
||||
h = G3.closestP2L(fv[1], fv[2], fv[0])
|
||||
d = (fv[1]-h).dot(q-h)
|
||||
if d<=0:
|
||||
return G3.closestP2E(q, fv[2], fv[0])
|
||||
h = G3.closestP2L(fv[2], fv[0], fv[1])
|
||||
d = (fv[2]-h).dot(q-h)
|
||||
if d<=0:
|
||||
return G3.closestP2E(q, fv[0], fv[1])
|
||||
return q
|
||||
if len(fv)==4:
|
||||
h = G3.closestP2L(fv[0], fv[1], fv[2])
|
||||
d = (fv[0]-h).dot(q-h)
|
||||
if d<=0:
|
||||
return G3.closestP2E(q, fv[1], fv[2])
|
||||
h = G3.closestP2L(fv[1], fv[2], fv[3])
|
||||
d = (fv[1]-h).dot(q-h)
|
||||
if d<=0:
|
||||
return G3.closestP2E(q, fv[2], fv[3])
|
||||
h = G3.closestP2L(fv[2], fv[3], fv[0])
|
||||
d = (fv[2]-h).dot(q-h)
|
||||
if d<=0:
|
||||
return G3.closestP2E(q, fv[3], fv[0])
|
||||
h = G3.closestP2L(fv[3], fv[0], fv[1])
|
||||
d = (fv[3]-h).dot(q-h)
|
||||
if d<=0:
|
||||
return G3.closestP2E(q, fv[0], fv[1])
|
||||
return q
|
||||
|
||||
@classmethod
|
||||
def medianTriangle(cls, vv):
|
||||
m0 = (vv[1]+vv[2])/2
|
||||
m1 = (vv[0]+vv[2])/2
|
||||
m2 = (vv[0]+vv[1])/2
|
||||
return [m0, m1, m2]
|
||||
|
||||
@classmethod
|
||||
def orthoCenter(cls, fv):
|
||||
try:
|
||||
h0 = G3.closestP2L(fv[0], fv[1], fv[2])
|
||||
h1 = G3.closestP2L(fv[1], fv[0], fv[2])
|
||||
#h2 = G3.closestP2L(fm[2], fm[0], fm[1])
|
||||
return geometry.intersect_line_line (fv[0], h0, fv[1], h1)[0]
|
||||
except(RuntimeError, TypeError):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def circumCenter(cls, fv):
|
||||
fm = G3.medianTriangle(fv)
|
||||
return G3.orthoCenter(fm)
|
||||
|
||||
@classmethod
|
||||
def ThreePnormal(cls, fv):
|
||||
n = (fv[1]-fv[0]).cross(fv[2]-fv[0])
|
||||
n.normalize()
|
||||
return n
|
||||
|
||||
@classmethod
|
||||
def closestP2CylinderAxis(cls, p, fv):
|
||||
n = G3.ThreePnormal(fv)
|
||||
c = G3.circumCenter(fv)
|
||||
if(c==None):
|
||||
return None
|
||||
return G3.closestP2L(p, c, c+n)
|
||||
|
||||
@classmethod
|
||||
def centerOfSphere(cls, fv):
|
||||
try:
|
||||
if len(fv)==3:
|
||||
return G3.circumCenter(fv)
|
||||
if len(fv)==4:
|
||||
fv3 = [fv[0],fv[1],fv[2]]
|
||||
c1 = G3.circumCenter(fv)
|
||||
n1 = G3.ThreePnormal(fv)
|
||||
fv3 = [fv[1],fv[2],fv[3]]
|
||||
c2 = G3.circumCenter(fv3)
|
||||
n2 = G3.ThreePnormal(fv3)
|
||||
d1 = c1+n1
|
||||
d2 = c2+n2
|
||||
return geometry.intersect_line_line (c1, d1, c2, d2)[0]
|
||||
except(RuntimeError, TypeError):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def closestP2Sphere(cls, p, fv):
|
||||
#print ("G3.closestP2Sphere")
|
||||
try:
|
||||
c = G3.centerOfSphere(fv)
|
||||
if c==None:
|
||||
return None
|
||||
pc = p-c
|
||||
if pc.length == 0:
|
||||
pc = pc + Vector((1,0,0))
|
||||
else:
|
||||
pc.normalize()
|
||||
return c + (pc * G3.distanceP2P(c, fv[0]))
|
||||
except(RuntimeError, TypeError):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def closestP2Cylinder(cls, p, fv):
|
||||
#print ("G3.closestP2Sphere")
|
||||
c = G3.closestP2CylinderAxis(p, fv)
|
||||
if c==None:
|
||||
return None
|
||||
r = (fv[0] - G3.centerOfSphere(fv)).length
|
||||
pc = p-c
|
||||
if pc.length == 0:
|
||||
pc = pc + Vector((1,0,0))
|
||||
else:
|
||||
pc.normalize()
|
||||
return c + (pc * r)
|
||||
|
||||
#@classmethod
|
||||
#def closestP2Sphere4(cls, p, fv4):
|
||||
##print ("G3.closestP2Sphere")
|
||||
#fv = [fv4[0],fv4[1],fv4[2]]
|
||||
#c1 = G3.circumCenter(fv)
|
||||
#n1 = G3.ThreePnormal(fv)
|
||||
#fv = [fv4[1],fv4[2],fv4[3]]
|
||||
#c2 = G3.circumCenter(fv)
|
||||
#n2 = G3.ThreePnormal(fv)
|
||||
#d1 = c1+n1
|
||||
#d2 = c2+n2
|
||||
#c = geometry.intersect_line_line (c1, d1, c2, d2)[0]
|
||||
#pc = p-c
|
||||
#if pc.length == 0:
|
||||
#pc = pc + Vector((1,0,0))
|
||||
#else:
|
||||
#pc.normalize()
|
||||
#return c + (pc * G3.distanceP2P(c, fv[0]))
|
||||
|
||||
|
||||
|
77
modules/misc_utils.py
Normal file
77
modules/misc_utils.py
Normal file
@ -0,0 +1,77 @@
|
||||
# -*- 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 #####
|
||||
|
||||
'''
|
||||
misc_util.py
|
||||
|
||||
Miscellaneous helper methods.
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
|
||||
import bpy
|
||||
from mathutils import Vector, Matrix
|
||||
|
||||
|
||||
|
||||
class BlenderFake:
|
||||
|
||||
@classmethod
|
||||
def forceUpdate(cls):
|
||||
if bpy.context.mode == 'EDIT_MESH':
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
@classmethod
|
||||
def forceRedraw(cls):
|
||||
CursorAccess.setCursor(CursorAccess.getCursor())
|
||||
|
||||
|
||||
|
||||
# Converts 3D coordinates in a 3DRegion
|
||||
# into 2D screen coordinates for that region.
|
||||
# Borrowed from Buerbaum Martin (Pontiac)
|
||||
def region3d_get_2d_coordinates(context, loc_3d):
|
||||
# Get screen information
|
||||
mid_x = context.region.width / 2.0
|
||||
mid_y = context.region.height / 2.0
|
||||
width = context.region.width
|
||||
height = context.region.height
|
||||
|
||||
# Get matrices
|
||||
view_mat = context.space_data.region_3d.perspective_matrix
|
||||
total_mat = view_mat
|
||||
|
||||
# order is important
|
||||
vec = Vector((loc_3d[0], loc_3d[1], loc_3d[2], 1.0)) * total_mat
|
||||
|
||||
# dehomogenise
|
||||
vec = Vector((
|
||||
vec[0] / vec[3],
|
||||
vec[1] / vec[3],
|
||||
vec[2] / vec[3]))
|
||||
|
||||
x = int(mid_x + vec[0] * width / 2.0)
|
||||
y = int(mid_y + vec[1] * height / 2.0)
|
||||
z = vec[2]
|
||||
|
||||
return Vector((x, y, z))
|
51
modules/ui_utils.py
Normal file
51
modules/ui_utils.py
Normal file
@ -0,0 +1,51 @@
|
||||
# -*- 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 #####
|
||||
|
||||
'''
|
||||
ui_utils.py
|
||||
|
||||
Some UI utility functions
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
|
||||
class GUI:
|
||||
|
||||
@classmethod
|
||||
def drawIconButton(cls, enabled, layout, iconName, operator, frame=True):
|
||||
col = layout.column()
|
||||
col.enabled = enabled
|
||||
bt = col.operator(operator,
|
||||
text='',
|
||||
icon=iconName,
|
||||
emboss=frame)
|
||||
|
||||
@classmethod
|
||||
def drawTextButton(cls, enabled, layout, text, operator, frame=True):
|
||||
col = layout.column()
|
||||
col.enabled = enabled
|
||||
bt = col.operator(operator,
|
||||
text=text,
|
||||
emboss=frame)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user