[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