Move modules into 'space_view3d_cursor_control' addon
authorCampbell Barton <ideasman42@gmail.com>
Tue, 10 Feb 2015 13:33:53 +0000 (00:33 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 10 Feb 2015 13:33:53 +0000 (00:33 +1100)
These were meant to be generic but ended up being a fairly small set of modules only used by this addon.

space_view3d_cursor_control/constants_utils.py [new file with mode: 0644]
space_view3d_cursor_control/cursor_utils.py [new file with mode: 0644]
space_view3d_cursor_control/data.py
space_view3d_cursor_control/geometry_utils.py [new file with mode: 0644]
space_view3d_cursor_control/history.py
space_view3d_cursor_control/misc_utils.py [new file with mode: 0644]
space_view3d_cursor_control/operators.py
space_view3d_cursor_control/ui.py
space_view3d_cursor_control/ui_utils.py [new file with mode: 0644]

diff --git a/space_view3d_cursor_control/constants_utils.py b/space_view3d_cursor_control/constants_utils.py
new file mode 100644 (file)
index 0000000..153553e
--- /dev/null
@@ -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
diff --git a/space_view3d_cursor_control/cursor_utils.py b/space_view3d_cursor_control/cursor_utils.py
new file mode 100644 (file)
index 0000000..b2f4ca0
--- /dev/null
@@ -0,0 +1,58 @@
+# -*- 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
index fcd82d1..2a7106b 100644 (file)
@@ -42,11 +42,11 @@ import bgl
 import math
 from mathutils import Vector, Matrix
 from mathutils import geometry
-from misc_utils import *
-from constants_utils import *
-from cursor_utils import *
-from ui_utils import *
-from geometry_utils import *
+from .misc_utils import *
+from .constants_utils import *
+from .cursor_utils import *
+from .ui_utils import *
+from .geometry_utils import *
 
 
 PRECISION = 4
diff --git a/space_view3d_cursor_control/geometry_utils.py b/space_view3d_cursor_control/geometry_utils.py
new file mode 100644 (file)
index 0000000..163d2b7
--- /dev/null
@@ -0,0 +1,217 @@
+# -*- 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
+
+    # Poor mans approach of finding center of circle
+    @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)
+
+    # Poor mans approach of finding center of sphere
+    @classmethod
+    def centerOfSphere(cls, fv):
+        try:
+            if len(fv)==3:
+                return G3.circumCenter(fv) # Equator
+            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]))
+
+
+
index 424785e..ce6a2ca 100644 (file)
@@ -50,10 +50,10 @@ import bgl
 import math
 from mathutils import Vector, Matrix
 from mathutils import geometry
-from misc_utils import *
-from constants_utils import *
-from cursor_utils import *
-from ui_utils import *
+from .misc_utils import *
+from .constants_utils import *
+from .cursor_utils import *
+from .ui_utils import *
 
 
 
diff --git a/space_view3d_cursor_control/misc_utils.py b/space_view3d_cursor_control/misc_utils.py
new file mode 100644 (file)
index 0000000..e15998f
--- /dev/null
@@ -0,0 +1,72 @@
+# -*- 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
+from .cursor_utils import *
+
+
+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 = total_mat * Vector((loc_3d[0], loc_3d[1], loc_3d[2], 1.0))
+
+    # 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))
index 3840db5..a27c84d 100644 (file)
@@ -42,11 +42,11 @@ import bgl
 import math
 from mathutils import Vector, Matrix
 from mathutils import geometry
-from misc_utils import *
-from constants_utils import *
-from cursor_utils import *
-from ui_utils import *
-from geometry_utils import *
+from .misc_utils import *
+from .constants_utils import *
+from .cursor_utils import *
+from .ui_utils import *
+from .geometry_utils import *
 
 
 class VIEW3D_OT_cursor_to_origin(bpy.types.Operator):
index 4863836..b5c7358 100644 (file)
@@ -42,11 +42,11 @@ import bgl
 import math
 from mathutils import Vector, Matrix
 from mathutils import geometry
-from misc_utils import *
-from constants_utils import *
-from cursor_utils import *
-from ui_utils import *
-from geometry_utils import *
+from .misc_utils import *
+from .constants_utils import *
+from .cursor_utils import *
+from .ui_utils import *
+from .geometry_utils import *
 
 
 class VIEW3D_PT_cursor(bpy.types.Panel):
diff --git a/space_view3d_cursor_control/ui_utils.py b/space_view3d_cursor_control/ui_utils.py
new file mode 100644 (file)
index 0000000..0fd7582
--- /dev/null
@@ -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)
+
+
+