[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3146] trunk/py/scripts/addons/ space_view3d_panel_measure.py: * Measure Panel - Version 0.8.7

Martin Buerbaum martin.buerbaum at gmx.at
Wed Mar 21 12:10:55 CET 2012


Revision: 3146
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3146
Author:   pontiac
Date:     2012-03-21 11:10:53 +0000 (Wed, 21 Mar 2012)
Log Message:
-----------
* Measure Panel - Version 0.8.7
* API change: ngon_tesselate -> ngon_tessellate
* Use persistent handler (scene_update in scene_update_post) for geometry calculation to reduce CPU load when idle.
* Remove all properties when add-on is unregistered.
* Minor: Moved text offset constants to the other script constants.
* TODO: Still heavy load while doing simple translation/scaling/rotation though. Is there a way to avoid that?

Modified Paths:
--------------
    trunk/py/scripts/addons/space_view3d_panel_measure.py

Modified: trunk/py/scripts/addons/space_view3d_panel_measure.py
===================================================================
--- trunk/py/scripts/addons/space_view3d_panel_measure.py	2012-03-21 10:51:40 UTC (rev 3145)
+++ trunk/py/scripts/addons/space_view3d_panel_measure.py	2012-03-21 11:10:53 UTC (rev 3146)
@@ -27,7 +27,7 @@
     "author": "Buerbaum Martin (Pontiac), TNae (Normal patch)," \
         " Benjamin Lauritzen (Loonsbury; Volume code)," \
         " Alessandro Sala (patch: Units in 3D View)",
-    "version": (0, 8, 6),
+    "version": (0, 8, 7),
     "blender": (2, 6, 0),
     "location": "View3D > Properties > Measure Panel",
     "description": "Measure distances between objects",
@@ -73,11 +73,12 @@
 
 import bpy
 from bpy.props import *
+from bpy.app.handlers import persistent
 from mathutils import Vector, Matrix
 import bgl
 import blf
 from bpy_extras.view3d_utils import location_3d_to_region_2d
-from bpy_extras.mesh_utils import ngon_tesselate
+from bpy_extras.mesh_utils import ngon_tessellate
 
 
 # Precicion for display of float values.
@@ -87,7 +88,16 @@
 COLOR_LOCAL = (1.0, 0.5, 0.0, 0.8)
 COLOR_GLOBAL = (0.5, 0.0, 1.0, 0.8)
 
+# 3D View - text offset
+OFFSET_LINE = 10   # Offset the text a bit to the right.
+OFFSET_Y = 15      # Offset of the lines.
+OFFSET_VALUE = 30  # Offset of value(s) from the text.
 
+# 3D View - line width
+LINE_WIDTH_XYZ = 1
+LINE_WIDTH_DIST = 2
+
+
 # Returns a tuple describing the current measuring system
 # and formatting options.
 # Returned data is meant to be passed to formatDistance().
@@ -146,9 +156,9 @@
 # Returns a single selected object.
 # Returns None if more than one (or nothing) is selected.
 # Note: Ignores the active object.
-def getSingleObject(context):
-    if len(context.selected_objects) == 1:
-        return context.selected_objects[0]
+def getSingleObject():
+    if len(bpy.context.selected_objects) == 1:
+        return bpy.context.selected_objects[0]
 
     return None
 
@@ -157,11 +167,12 @@
 # depending on the current view mode and the selection.
 def getMeasurePoints(context):
     sce = context.scene
+    mode = context.mode
 
     # Get a single selected object (or nothing).
-    obj = getSingleObject(context)
+    obj = getSingleObject()
 
-    if context.mode == 'EDIT_MESH':
+    if mode == 'EDIT_MESH':
         obj = context.active_object
 
         if obj and obj.type == 'MESH' and obj.data:
@@ -231,7 +242,7 @@
             else:
                 return None
 
-    elif context.mode == 'OBJECT':
+    elif mode == 'OBJECT':
         # We are working in object mode.
 
         if len(context.selected_objects) > 2:
@@ -324,7 +335,7 @@
 
     if len(poly.vertices) > 3:
         # Tesselate the polygon into multiple tris
-        tris = ngon_tesselate(mesh, poly.vertices)
+        tris = ngon_tessellate(mesh, poly.vertices)
 
         for tri in tris:
             # Get vertex data
@@ -561,305 +572,331 @@
     return (sce.measure_panel_transform == "measure_local")
 
 
-def draw_measurements_callback(self, context):
-    sce = context.scene
+# Calculate values if geometry, selection or cursor changed.
+ at persistent
+def scene_update(context):
+    sce = context
+    mode = bpy.context.mode
 
-    draw = 0
-    if hasattr(sce, "measure_panel_draw"):
-        draw = sce.measure_panel_draw
+    if (mode == 'EDIT_MESH' and not sce.measure_panel_update):
+        return
 
-    # 2D drawing code example
-    #bgl.glBegin(bgl.GL_LINE_STRIP)
-    #bgl.glVertex2i(0, 0)
-    #bgl.glVertex2i(80, 100)
-    #bgl.glEnd()
+    if (bpy.data.objects.is_updated
+        or bpy.context.scene.is_updated
+        or sce.measure_panel_update):
+        # TODO: Better way to check selection changes and cursor changes?
 
-    # Get measured 3D points and colors.
-    line = getMeasurePoints(context)
-    if line and draw:
-        p1, p2, color = line
+        sel_objs = bpy.context.selected_objects
 
-        # Get and convert the Perspective Matrix of the current view/region.
-        view3d = bpy.context
-        region = view3d.region_data
-        perspMatrix = region.perspective_matrix
-        tempMat = [perspMatrix[j][i] for i in range(4) for j in range(4)]
-        perspBuff = bgl.Buffer(bgl.GL_FLOAT, 16, tempMat)
+        # EDGE LENGTH
+        if sce.measure_panel_calc_edge_length:
+            if (mode == 'EDIT_MESH'
+                and sce.measure_panel_update):
+                sce.measure_panel_update = 0
+                obj = context.active_object
 
-        # ---
-        # Store previous OpenGL settings.
-        # Store MatrixMode
-        MatrixMode_prev = bgl.Buffer(bgl.GL_INT, [1])
-        bgl.glGetIntegerv(bgl.GL_MATRIX_MODE, MatrixMode_prev)
-        MatrixMode_prev = MatrixMode_prev[0]
+                #if obj.is_updated:
+                length_total = objectEdgeLength(obj, True,
+                    measureGlobal(sce))
+                sce.measure_panel_edge_length = length_total
 
-        # Store projection matrix
-        ProjMatrix_prev = bgl.Buffer(bgl.GL_DOUBLE, [16])
-        bgl.glGetFloatv(bgl.GL_PROJECTION_MATRIX, ProjMatrix_prev)
+            elif mode == 'OBJECT':
+                length_total = -1
 
-        # Store Line width
-        lineWidth_prev = bgl.Buffer(bgl.GL_FLOAT, [1])
-        bgl.glGetFloatv(bgl.GL_LINE_WIDTH, lineWidth_prev)
-        lineWidth_prev = lineWidth_prev[0]
+                for o in sel_objs:
+                    if o.type == 'MESH':
+                        length = objectEdgeLength(o, False, measureGlobal(sce))
 
-        # Store GL_BLEND
-        blend_prev = bgl.Buffer(bgl.GL_BYTE, [1])
-        bgl.glGetFloatv(bgl.GL_BLEND, blend_prev)
-        blend_prev = blend_prev[0]
+                        if length >= 0:
+                            if length_total < 0:
+                                length_total = 0
 
-        line_stipple_prev = bgl.Buffer(bgl.GL_BYTE, [1])
-        bgl.glGetFloatv(bgl.GL_LINE_STIPPLE, line_stipple_prev)
-        line_stipple_prev = line_stipple_prev[0]
+                            length_total += length
 
-        # Store glColor4f
-        color_prev = bgl.Buffer(bgl.GL_FLOAT, [4])
-        bgl.glGetFloatv(bgl.GL_COLOR, color_prev)
+                sce.measure_panel_edge_length = length_total
 
-        # ---
-        # Prepare for 3D drawing
-        bgl.glLoadIdentity()
-        bgl.glMatrixMode(bgl.GL_PROJECTION)
-        bgl.glLoadMatrixf(perspBuff)
+        # AREA
+        # Handle mesh surface area calulations
+        if sce.measure_panel_calc_area:
+            if (mode == 'EDIT_MESH'
+                and sce.measure_panel_update):
+                sce.measure_panel_update = 0
+                obj = bpy.context.active_object
 
-        bgl.glEnable(bgl.GL_BLEND)
-        bgl.glEnable(bgl.GL_LINE_STIPPLE)
+                if obj and obj.type == 'MESH' and obj.data:
+                    # "Note: a Mesh will return the selection state of the mesh
+                    # when EditMode was last exited. A Python script operating
+                    # in EditMode must exit EditMode before getting the current
+                    # selection state of the mesh."
+                    # http://www.blender.org/documentation/249PythonDoc/
+                    # /Mesh.MVert-class.html#sel
+                    # We can only provide this by existing &
+                    # re-entering EditMode.
+                    # @todo: Better way to do this?
 
-        # ---
-        # Draw 3D stuff.
-        width = 1
-        bgl.glLineWidth(width)
-        # X
-        bgl.glColor4f(1, 0, 0, 0.8)
-        bgl.glBegin(bgl.GL_LINE_STRIP)
-        bgl.glVertex3f(p1[0], p1[1], p1[2])
-        bgl.glVertex3f(p2[0], p1[1], p1[2])
-        bgl.glEnd()
-        # Y
-        bgl.glColor4f(0, 1, 0, 0.8)
-        bgl.glBegin(bgl.GL_LINE_STRIP)
-        bgl.glVertex3f(p1[0], p1[1], p1[2])
-        bgl.glVertex3f(p1[0], p2[1], p1[2])
-        bgl.glEnd()
-        # Z
-        bgl.glColor4f(0, 0, 1, 0.8)
-        bgl.glBegin(bgl.GL_LINE_STRIP)
-        bgl.glVertex3f(p1[0], p1[1], p1[2])
-        bgl.glVertex3f(p1[0], p1[1], p2[2])
-        bgl.glEnd()
+                    # Get mesh data from Object.
+                    me = obj.data
 
-        # Dist
-        width = 2
-        bgl.glLineWidth(width)
-        bgl.glColor4f(color[0], color[1], color[2], color[3])
-        bgl.glBegin(bgl.GL_LINE_STRIP)
-        bgl.glVertex3f(p1[0], p1[1], p1[2])
-        bgl.glVertex3f(p2[0], p2[1], p2[2])
-        bgl.glEnd()
+                    # Get transformation matrix from object.
+                    ob_mat = obj.matrix_world
+                    # Also make an inversed copy! of the matrix.
+                    ob_mat_inv = ob_mat.copy()
+                    Matrix.invert(ob_mat_inv)
 
-        # ---
-        # Restore previous OpenGL settings
-        bgl.glLoadIdentity()
-        bgl.glMatrixMode(MatrixMode_prev)
-        bgl.glLoadMatrixf(ProjMatrix_prev)
-        bgl.glLineWidth(lineWidth_prev)
-        if not blend_prev:
-            bgl.glDisable(bgl.GL_BLEND)
-        if not line_stipple_prev:
-            bgl.glDisable(bgl.GL_LINE_STIPPLE)
-        bgl.glColor4f(color_prev[0],
-            color_prev[1],
-            color_prev[2],
-            color_prev[3])
+                    # Get the selected vertices.
+                    # @todo: Better (more efficient) way to do this?
+                    verts_selected = [v for v in me.vertices if v.select == 1]
 
-        # ---
-        # Draw (2D) text
-        # We do this after drawing the lines so
-        # we can draw it OVER the line.
-        coord_2d = location_3d_to_region_2d(context.region,
-                                            context.space_data.region_3d,
-                                            p1.lerp(p2, 0.5),
-                                            )
-        OFFSET_LINE = 10   # Offset the text a bit to the right.
-        OFFSET_Y = 15      # Offset of the lines.
-        OFFSET_VALUE = 30  # Offset of value(s) from the text.
-        dist = (p1 - p2).length
+                    if len(verts_selected) >= 3:
+                        # Get selected faces
+                        # @todo: Better (more efficient) way to do this?
+                        polys_selected = [p for p in me.polygons
+                            if p.select == 1]
 
-        # Write distance value into the scene property,
-        # so we can display it in the panel & refresh the panel.
-        if hasattr(sce, "measure_panel_dist"):

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list