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:
authorMartin Buerbaum <martin.buerbaum@gmx.at>2010-04-14 17:44:02 +0400
committerMartin Buerbaum <martin.buerbaum@gmx.at>2010-04-14 17:44:02 +0400
commite702240b36ae64a85958754e33612674c5603ff4 (patch)
treeaa7949e45fca84f04a8189ceb68d7aa444260bcc /space_view3d_panel_measure.py
parent0f56f2080fe4328563def9973bfbaaea8882512b (diff)
* Version 0.7 (0.7 final)
* Summary of changes: * Initial support for drawing lines. (Thanks to Algorith for applying my perspective_matrix patch.) * The distance value (in BUs) is also drawn in the 3D view now. * Also fixed some wrong calculations of global/local distances. * Now it's really "what you see is what is calculated". * Use bl_addon_info for Add-On information. Use "3D View" in category & name * Renamed reenter_editmode to view3d.reenter_editmode. * Renamed panel_measure.py into space_view3d_panel_measure.py * Active object is only used for edit-mode now. Measurement with exactly one sel. (but not necessarily active) object now gets the obj via the sel-object array. * API change Mathutils -> mathutils (r557) * Reduced PRECISION to 4 * Deselecting 1 of 2 objects now works correctly (active object is ignored). * Force a redraw of the area so disabling the "measure_panel_draw" checkbox will clear the line/text. * Only calculate area (CPU heavy) if a "area" checkbox is enabled.
Diffstat (limited to 'space_view3d_panel_measure.py')
-rw-r--r--space_view3d_panel_measure.py701
1 files changed, 541 insertions, 160 deletions
diff --git a/space_view3d_panel_measure.py b/space_view3d_panel_measure.py
index 16dd623f..e4cfe1be 100644
--- a/space_view3d_panel_measure.py
+++ b/space_view3d_panel_measure.py
@@ -19,14 +19,13 @@
import bpy
from bpy.props import *
from mathutils import Vector, Matrix
-
-# Precicion for display of float values.
-PRECISION = 5
+import bgl
+import blf
bl_addon_info = {
'name': '3D View: Measure panel',
'author': 'Buerbaum Martin (Pontiac)',
- 'version': '0.6.4',
+ 'version': '0.7',
'blender': (2, 5, 3),
'location': 'View3D > Properties > Measure',
'description': 'Measure distances between objects',
@@ -34,6 +33,10 @@ bl_addon_info = {
'Scripts/3D_interaction/Panel_Measure',
'category': '3D View'}
+# More links:
+# http://gitorious.org/blender-scripts/blender-measure-panel-script
+# http://blenderartists.org/forum/showthread.php?t=177800
+
__bpydoc__ = """
Measure panel
@@ -61,6 +64,23 @@ It's very helpful to use one or two "Empty" objects with
"Snap during transform" enabled for fast measurement.
Version history:
+v0.7 - Initial support for drawing lines.
+ (Thanks to Algorith for applying my perspective_matrix patch.)
+ The distance value (in BUs) is also drawn in the 3D view now.
+ Also fixed some wrong calculations of global/local distances.
+ Now it's really "what you see is what is calculated".
+ Use bl_addon_info for Add-On information.
+ Use "3D View" in category & name
+ Renamed reenter_editmode to view3d.reenter_editmode.
+ Renamed panel_measure.py into space_view3d_panel_measure.py
+ Active object is only used for edit-mode now. Measurement
+ with exactly one sel. (but not neccessarily active) object
+ now gets the obj via the sel-object array.
+ API change Mathutils -> mathutils (r557)
+ Deselecting 1 of 2 objects now works correctly (active object is ignored).
+ Force a redraw of the area so disabling the "measure_panel_draw"
+ checkbox will clear the line/text.
+ Only calculate area (CPU heavy) if a "area" checkbox is enabled.
v0.6.4 - Fixed unneeded meshdata duplication (sometimes crashes Blender).
The script now correctly calculated the surface area (faceAreaGlobal)
of scaled meshes.
@@ -124,6 +144,144 @@ manipulator. There may be other cases though.
See the other "todo" comments below.
"""
+# Precicion for display of float values.
+PRECISION = 4
+
+# Name of the custom properties as stored in the scene.
+COLOR_LOCAL = (1.0, 0.0, 0.0, 0.8)
+COLOR_GLOBAL = (0.0, 0.0, 1.0, 0.8)
+
+
+# Returns a single selected object.
+# Returns None if more than one (or nothing) is selected.
+# Note: Ignores the active object.
+def getSingleObject(context):
+ if (context.selected_objects
+ and len(context.selected_objects) == 1):
+ return context.selected_objects[0]
+
+ return None
+
+
+# Returns a list with 2 3D points (Vector) and a color (RGBA)
+# depending on the current view mode and the selection.
+def getMeasurePoints(context):
+ sce = context.scene
+
+ # Get a single selected object (or nothing).
+ obj = getSingleObject(context)
+
+ if (context.mode == 'EDIT_MESH'):
+ obj = context.active_object
+
+ if (obj and obj.type == 'MESH' and obj.data):
+ # Get mesh data from Object.
+ mesh = obj.data
+
+ # Get transformation matrix from object.
+ ob_mat = obj.matrix
+ # Also make an inversed copy! of the matrix.
+ ob_mat_inv = ob_mat.copy()
+ Matrix.invert(ob_mat_inv)
+
+ # Get the selected vertices.
+ # @todo: Better (more efficient) way to do this?
+ verts_selected = [v for v in mesh.verts if v.selected == 1]
+
+ if len(verts_selected) == 0:
+ # Nothing selected.
+ # We measure the distance from...
+ # local ... the object center to the 3D cursor.
+ # global ... the origin to the 3D cursor.
+ cur_loc = sce.cursor_location
+ obj_loc = Vector(tuple(obj.location))
+
+ # Convert to local space, if needed.
+ if measureLocal(sce):
+ p1 = cur_loc
+ p2 = obj_loc
+ return (p1, p2, COLOR_GLOBAL)
+
+ else:
+ p1 = Vector(0, 0, 0)
+ p2 = cur_loc
+ return (p1, p2, COLOR_GLOBAL)
+
+ elif len(verts_selected) == 1:
+ # One vertex selected.
+ # We measure the distance from the
+ # selected vertex object to the 3D cursor.
+ cur_loc = sce.cursor_location
+ vert_loc = Vector(tuple(verts_selected[0].co))
+ obj_loc = Vector(tuple(obj.location))
+
+ # Convert to local or global space.
+ if measureLocal(sce):
+ p1 = obj_loc + vert_loc
+ p2 = cur_loc
+ return (p1, p2, COLOR_LOCAL)
+
+ else:
+ p1 = vert_loc * ob_mat + obj_loc
+ p2 = cur_loc
+ return (p1, p2, COLOR_GLOBAL)
+
+ elif len(verts_selected) == 2:
+ # Two vertices selected.
+ # We measure the distance between the
+ # two selected vertices.
+ obj_loc = Vector(tuple(obj.location))
+ vert1_loc = Vector(tuple(verts_selected[0].co))
+ vert2_loc = Vector(tuple(verts_selected[1].co))
+
+ # Convert to local or global space.
+ if measureLocal(sce):
+ p1 = obj_loc + vert1_loc
+ p2 = obj_loc + vert2_loc
+ return (p1, p2, COLOR_LOCAL)
+
+ else:
+ p1 = obj_loc + vert1_loc * ob_mat
+ p2 = obj_loc + vert2_loc * ob_mat
+ return (p1, p2, COLOR_GLOBAL)
+
+ else:
+ return None
+
+ elif (context.mode == 'OBJECT'):
+ # We are working on object mode.
+
+ if (context.selected_objects
+ and len(context.selected_objects) > 2):
+ return None
+ elif (context.selected_objects
+ and len(context.selected_objects) == 2):
+ # 2 objects selected.
+ # We measure the distance between the 2 selected objects.
+ obj1 = context.selected_objects[0]
+ obj2 = context.selected_objects[1]
+ obj1_loc = Vector(tuple(obj1.location))
+ obj2_loc = Vector(tuple(obj2.location))
+ return (obj1_loc, obj2_loc, COLOR_GLOBAL)
+
+ elif (obj):
+ # One object selected.
+ # We measure the distance from the object to the 3D cursor.
+ cur_loc = sce.cursor_location
+ obj_loc = Vector(tuple(obj.location))
+ return (obj_loc, cur_loc, COLOR_GLOBAL)
+
+ elif (not context.selected_objects
+ or len(context.selected_objects) == 0):
+ # Nothing selected.
+ # We measure the distance from the origin to the 3D cursor.
+ p1 = Vector(0, 0, 0)
+ p2 = sce.cursor_location
+ return (p1, p2, COLOR_GLOBAL)
+
+ else:
+ return None
+
# Return the area of a face (in global space).
# @note Copies the functionality of the following functions,
@@ -222,20 +380,181 @@ def objectSurfaceArea(obj, selectedOnly, globalSpace):
# User friendly access to the "space" setting.
-def measureGlobal(scene):
- return (scene.measure_panel_transform == "measure_global")
+def measureGlobal(sce):
+ return (sce.measure_panel_transform == "measure_global")
# User friendly access to the "space" setting.
-def measureLocal(scene):
- return (scene.measure_panel_transform == "measure_local")
-
-
-class OBJECT_OT_reenter_editmode(bpy.types.Operator):
+def measureLocal(sce):
+ return (sce.measure_panel_transform == "measure_local")
+
+
+# Converts 3D coordinates in a 3DRegion
+# into 2D screen coordinates for that region.
+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)
+
+ return Vector(x, y, 0)
+
+
+def draw_measurements_callback(self, context):
+ sce = context.scene
+
+ draw = 0
+ if hasattr(sce, "measure_panel_draw"):
+ draw = sce.measure_panel_draw
+
+ # 2D drawing code example
+ #bgl.glBegin(bgl.GL_LINE_STRIP)
+ #bgl.glVertex2i(0, 0)
+ #bgl.glVertex2i(80, 100)
+ #bgl.glEnd()
+
+ # Get measured 3D points and colors.
+ line = getMeasurePoints(context)
+ if (line and draw):
+ p1, p2, color = line
+
+ # Get and convert the Perspective Matrix of the current view/region.
+ view3d = bpy.context.space_data
+ region = view3d.region_3d
+ perspMatrix = region.perspective_matrix
+ tempMat = [perspMatrix[i][j] for i in range(4) for j in range(4)]
+ perspBuff = bgl.Buffer(bgl.GL_FLOAT, 16, tempMat)
+
+ # ---
+ # 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]
+
+ # Store projection matrix
+ ProjMatrix_prev = bgl.Buffer(bgl.GL_DOUBLE, [16])
+ bgl.glGetFloatv(bgl.GL_PROJECTION_MATRIX, ProjMatrix_prev)
+
+ # Store Line width
+ lineWidth_prev = bgl.Buffer(bgl.GL_FLOAT, [1])
+ bgl.glGetFloatv(bgl.GL_LINE_WIDTH, lineWidth_prev)
+ lineWidth_prev = lineWidth_prev[0]
+
+ # Store GL_BLEND
+ blend_prev = bgl.Buffer(bgl.GL_BYTE, [1])
+ bgl.glGetFloatv(bgl.GL_BLEND, blend_prev)
+ blend_prev = blend_prev[0]
+
+ # Store glColor4f
+ color_prev = bgl.Buffer(bgl.GL_FLOAT, [4])
+ bgl.glGetFloatv(bgl.GL_COLOR, color_prev)
+
+ # ---
+ # Prepare for 3D drawing
+ bgl.glLoadIdentity()
+ bgl.glMatrixMode(bgl.GL_PROJECTION)
+ bgl.glLoadMatrixf(perspBuff)
+
+ bgl.glColor4f(color[0], color[1], color[2], color[3])
+ bgl.glEnable(bgl.GL_BLEND)
+
+ # ---
+ # Draw 3D stuff.
+ width = 2
+ bgl.glLineWidth(width)
+ bgl.glBegin(bgl.GL_LINE_STRIP)
+ bgl.glVertex3f(p1[0], p1[1], p1[2])
+ bgl.glVertex3f(p2[0], p2[1], p2[2])
+ bgl.glEnd()
+
+ # ---
+ # 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)
+ bgl.glColor4f(color_prev[0],
+ color_prev[1],
+ color_prev[2],
+ color_prev[3])
+
+ # ---
+ # Draw (2D) text
+ # We do this after drawing the lines so
+ # we can draw it OVER the line.
+ coord_2d = region3d_get_2d_coordinates(context, p2 + (p1 - p2) * 0.5)
+ offset = 10 # Offset the text a bit to the right.
+ blf.position(coord_2d[0] + offset, coord_2d[1], 0)
+
+ dist = (p1 - p2).length
+ text = "Distance: " + str(round(dist, PRECISION)) + " BU"
+ # @todo Get user pref for text color in 3D View
+ bgl.glColor4f(1.0, 1.0, 1.0, 1.0)
+ blf.size(12, 72) # Prevent font size to randomly change.
+ blf.draw(text)
+
+
+class VIEW3D_OT_display_measurements(bpy.types.Operator):
+ '''Display the measurements made in the 'Measure' panel'''
+ bl_idname = "view3d.display_measurements"
+ bl_label = "Display the measurements made in the" \
+ " 'Measure' panel in the 3D View."
+ bl_options = {'REGISTER'}
+
+ def modal(self, context, event):
+ context.area.tag_redraw()
+
+ return {'FINISHED'}
+
+ def execute(self, context):
+ if context.area.type == 'VIEW_3D':
+ if not self.bl_label in context.manager.operators.keys():
+ # Add the region OpenGL drawing callback
+ for WINregion in context.area.regions:
+ if WINregion.type == 'WINDOW':
+ break
+
+ context.manager.add_modal_handler(self)
+ self._handle = WINregion.callback_add(
+ draw_measurements_callback,
+ (self, context),
+ 'POST_PIXEL')
+
+ print("Measure panel display callback added")
+
+ return {'RUNNING_MODAL'}
+
+ else:
+ self.report({'WARNING'}, "View3D not found, cannot run operator")
+ return {'CANCELLED'}
+
+
+class VIEW3D_OT_reenter_editmode(bpy.types.Operator):
bl_label = "Re-enter EditMode"
- bl_idname = "reenter_editmode"
+ bl_idname = "view3d.reenter_editmode"
bl_description = "Update mesh data of an active mesh object." \
" This is done by exiting and re-entering mesh edit mode."
+ bl_options = {'REGISTER'}
def invoke(self, context, event):
@@ -257,24 +576,63 @@ class VIEW3D_PT_measure(bpy.types.Panel):
bl_label = "Measure"
bl_default_closed = True
+ def poll(self, context):
+ # Only display this panel in the object and edit mode 3D view.
+ if (context.area.type == 'VIEW_3D' and
+ (context.mode == 'EDIT_MESH'
+ or context.mode == 'OBJECT')):
+ return 1
+
+ return 0
+
+ def draw_header(self, context):
+ layout = self.layout
+ sce = context.scene
+
+ # Execute operator (this adds the callback)
+ # if it wasn't done yet.
+ bpy.ops.view3d.display_measurements()
+
+ # Define property for the draw setting.
+ sce.BoolProperty(
+ attr="measure_panel_draw",
+ description="Draw distances in 3D View",
+ default=1)
+
+ # Define property for the calc-area setting.
+ # @todo prevent double calculations for each refresh automatically?
+ sce.BoolProperty(
+ attr="measure_panel_calc_area",
+ description="Calculate mesh surface area (heavy CPU" \
+ " usage on bigger meshes)",
+ default=0)
+
+ layout.prop(sce, "measure_panel_draw")
+
def draw(self, context):
layout = self.layout
- scene = context.scene
+ sce = context.scene
- # Get the active object.
- obj = context.active_object
+ # Force a redraw.
+ # This prevents the lines still be drawn after
+ # disabling the "measure_panel_draw" checkbox.
+ # @todo Better solution?
+ context.area.tag_redraw()
+
+ # Get a single selected object (or nothing).
+ obj = getSingleObject(context)
# Define a temporary attribute for the distance value
- scene.FloatProperty(
+ sce.FloatProperty(
name="Distance",
attr="measure_panel_dist",
precision=PRECISION,
unit="LENGTH")
- scene.FloatProperty(
+ sce.FloatProperty(
attr="measure_panel_area1",
precision=PRECISION,
unit="AREA")
- scene.FloatProperty(
+ sce.FloatProperty(
attr="measure_panel_area2",
precision=PRECISION,
unit="AREA")
@@ -294,6 +652,8 @@ class VIEW3D_PT_measure(bpy.types.Panel):
default='measure_global')
if (context.mode == 'EDIT_MESH'):
+ obj = context.active_object
+
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
@@ -319,26 +679,30 @@ class VIEW3D_PT_measure(bpy.types.Panel):
if len(verts_selected) == 0:
# Nothing selected.
- # We measure the distance from the origin to the 3D cursor.
- dist_vec = scene.cursor_location
+ # We measure the distance from...
+ # local ... the object center to the 3D cursor.
+ # global ... the origin to the 3D cursor.
- # Convert to local space, if needed.
- if measureLocal(scene):
- obj_loc = Vector(tuple(obj.location))
- dist_vec = (dist_vec - obj_loc) * ob_mat_inv
+ # Get the 2 measure points
+ line = getMeasurePoints(context)
+ if line != 0:
+ dist_vec = line[0] - line[1]
- scene.measure_panel_dist = dist_vec.length
+ sce.measure_panel_dist = dist_vec.length
row = layout.row()
- row.prop(scene, "measure_panel_dist")
+ row.prop(sce, "measure_panel_dist")
row = layout.row()
row.label(text="", icon='CURSOR')
row.label(text="", icon='ARROW_LEFTRIGHT')
- row.label(text="Origin [0,0,0]")
+ if measureLocal(sce):
+ row.label(text="Obj. Center")
+ else:
+ row.label(text="Origin [0,0,0]")
row = layout.row()
- row.operator("reenter_editmode",
+ row.operator("view3d.reenter_editmode",
text="Update selection & distance")
# @todo
# description="The surface area value can" \
@@ -348,7 +712,7 @@ class VIEW3D_PT_measure(bpy.types.Panel):
# " the selection.")
row = layout.row()
- row.prop(scene,
+ row.prop(sce,
"measure_panel_transform",
expand=True)
@@ -356,20 +720,16 @@ class VIEW3D_PT_measure(bpy.types.Panel):
# One vertex selected.
# We measure the distance from the
# selected vertex object to the 3D cursor.
- cur_loc = scene.cursor_location
- vert_loc = Vector(tuple(verts_selected[0].co))
- obj_loc = Vector(tuple(obj.location))
- # Convert to local or global space.
- if measureLocal(scene):
- dist_vec = vert_loc - (cur_loc - obj_loc) * ob_mat_inv
- else:
- dist_vec = vert_loc * ob_mat + obj_loc - cur_loc
+ # Get the 2 measure points
+ line = getMeasurePoints(context)
+ if line != 0:
+ dist_vec = line[0] - line[1]
- scene.measure_panel_dist = dist_vec.length
+ sce.measure_panel_dist = dist_vec.length
row = layout.row()
- row.prop(scene, "measure_panel_dist")
+ row.prop(sce, "measure_panel_dist")
row = layout.row()
row.label(text="", icon='CURSOR')
@@ -377,11 +737,11 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.label(text="", icon='VERTEXSEL')
row = layout.row()
- row.operator("reenter_editmode",
+ row.operator("view3d.reenter_editmode",
text="Update selection & distance")
row = layout.row()
- row.prop(scene,
+ row.prop(sce,
"measure_panel_transform",
expand=True)
@@ -389,19 +749,16 @@ class VIEW3D_PT_measure(bpy.types.Panel):
# Two vertices selected.
# We measure the distance between the
# two selected vertices.
- vert1_loc = Vector(tuple(verts_selected[0].co))
- vert2_loc = Vector(tuple(verts_selected[1].co))
- # Convert to local or global space.
- if measureLocal(scene):
- dist_vec = vert1_loc - vert2_loc
- else:
- dist_vec = vert1_loc * ob_mat - vert2_loc * ob_mat
+ # Get the 2 measure points
+ line = getMeasurePoints(context)
+ if line != 0:
+ dist_vec = line[0] - line[1]
- scene.measure_panel_dist = dist_vec.length
+ sce.measure_panel_dist = dist_vec.length
row = layout.row()
- row.prop(scene, "measure_panel_dist")
+ row.prop(sce, "measure_panel_dist")
row = layout.row()
row.label(text="", icon='VERTEXSEL')
@@ -409,48 +766,57 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.label(text="", icon='VERTEXSEL')
row = layout.row()
- row.operator("reenter_editmode",
+ row.operator("view3d.reenter_editmode",
text="Update selection & distance")
row = layout.row()
- row.prop(scene,
+ row.prop(sce,
"measure_panel_transform",
expand=True)
else:
- # Get selected faces
- # @todo: Better (more efficient) way to do this?
- faces_selected = [f for f in mesh.faces if f.selected == 1]
-
- if len(faces_selected) > 0:
- area = objectSurfaceArea(obj, True,
- measureGlobal(scene))
- if (area >= 0):
- row = layout.row()
- row.label(text="Surface area (selected faces):")
-
- row = layout.row()
- row.label(
- text=str(len(faces_selected)),
- icon='FACESEL')
- scene.measure_panel_area1 = area
- row.prop(scene, "measure_panel_area1")
-
+ row = layout.row()
+ row.prop(sce, "measure_panel_calc_area",
+ text="Surface area (selected faces):")
+
+ if (sce.measure_panel_calc_area):
+ # Get selected faces
+ # @todo: Better (more efficient) way to do this?
+ faces_selected = [f for f in mesh.faces
+ if f.selected == 1]
+
+ if len(faces_selected) > 0:
+ area = objectSurfaceArea(obj, True,
+ measureGlobal(sce))
+ if (area >= 0):
+ row = layout.row()
+ row.label(
+ text=str(len(faces_selected)),
+ icon='FACESEL')
+ sce.measure_panel_area1 = area
+ row.prop(sce, "measure_panel_area1")
+
+ row = layout.row()
+ row.operator("view3d.reenter_editmode",
+ text="Update selection & area")
+
+ row = layout.row()
+ row.prop(sce,
+ "measure_panel_transform",
+ expand=True)
+
+ else:
row = layout.row()
- row.operator("reenter_editmode",
- text="Update selection & area")
+ row.label(text="Selection not supported.",
+ icon='INFO')
row = layout.row()
- row.prop(scene,
- "measure_panel_transform",
- expand=True)
+ row.operator("view3d.reenter_editmode",
+ text="Update selection")
else:
row = layout.row()
- row.label(text="Selection not supported.", icon='INFO')
-
- row = layout.row()
- row.operator("reenter_editmode",
+ row.operator("view3d.reenter_editmode",
text="Update selection")
elif (context.mode == 'OBJECT'):
@@ -460,47 +826,54 @@ class VIEW3D_PT_measure(bpy.types.Panel):
and len(context.selected_objects) > 2):
# We have more that 2 objects selected...
- mesh_objects = [o for o in context.selected_objects
- if (o.type == 'MESH' and o.data)]
+ row = layout.row()
+ row.prop(sce, "measure_panel_calc_area",
+ text="Surface area (selected faces):")
- if (len(mesh_objects) > 0):
- # ... and at least one of them is a mesh.
+ if (sce.measure_panel_calc_area):
- # Calculate and display surface area of the objects.
- # @todo: Convert to scene units! We do not have a
- # FloatProperty field here for automatic conversion.
- row = layout.row()
- row.label(text="Surface area:")
+ mesh_objects = [o for o in context.selected_objects
+ if (o.type == 'MESH' and o.data)]
- row = layout.row()
- for o in mesh_objects:
- area = objectSurfaceArea(o, False,
- measureGlobal(scene))
- if (area >= 0):
- row = layout.row()
- row.label(text=o.name, icon='OBJECT_DATA')
- row.label(text=str(round(area, PRECISION))
- + " BU^2")
+ if (len(mesh_objects) > 0):
+ # ... and at least one of them is a mesh.
- row = layout.row()
- row.prop(scene,
- "measure_panel_transform",
- expand=True)
+ # Calculate and display surface area of the objects.
+ # @todo: Convert to scene units! We do not have a
+ # FloatProperty field here for automatic conversion.
+
+ row = layout.row()
+ for o in mesh_objects:
+ area = objectSurfaceArea(o, False,
+ measureGlobal(sce))
+ if (area >= 0):
+ row = layout.row()
+ row.label(text=o.name, icon='OBJECT_DATA')
+ row.label(text=str(round(area, PRECISION))
+ + " BU^2")
+
+ row = layout.row()
+ row.prop(sce,
+ "measure_panel_transform",
+ expand=True)
elif (context.selected_objects
and len(context.selected_objects) == 2):
# 2 objects selected.
# We measure the distance between the 2 selected objects.
+
obj1 = context.selected_objects[0]
obj2 = context.selected_objects[1]
- obj1_loc = Vector(tuple(obj1.location))
- obj2_loc = Vector(tuple(obj2.location))
- dist_vec = obj1_loc - obj2_loc
- scene.measure_panel_dist = dist_vec.length
+ # Get the 2 measure points
+ line = getMeasurePoints(context)
+ if line != 0:
+ dist_vec = line[0] - line[1]
+
+ sce.measure_panel_dist = dist_vec.length
row = layout.row()
- row.prop(scene, "measure_panel_dist")
+ row.prop(sce, "measure_panel_dist")
row = layout.row()
row.label(text="", icon='OBJECT_DATA')
@@ -511,45 +884,46 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.label(text="", icon='OBJECT_DATA')
row.prop(obj2, "name", text="")
- # Calculate and display surface area of the objects.
- area1 = objectSurfaceArea(obj1, False, measureGlobal(scene))
- area2 = objectSurfaceArea(obj2, False, measureGlobal(scene))
- if (area1 >= 0 or area2 >= 0):
- row = layout.row()
- row.label(text="Surface area:")
+ row = layout.row()
+ row.prop(sce, "measure_panel_calc_area",
+ text="Surface area:")
- if (area1 >= 0):
- row = layout.row()
- row.label(text=obj1.name, icon='OBJECT_DATA')
- scene.measure_panel_area1 = area1
- row.prop(scene, "measure_panel_area1")
+ if (sce.measure_panel_calc_area):
+ # Calculate and display surface area of the objects.
+ area1 = objectSurfaceArea(obj1, False, measureGlobal(sce))
+ area2 = objectSurfaceArea(obj2, False, measureGlobal(sce))
+ if (area1 >= 0 or area2 >= 0):
+ if (area1 >= 0):
+ row = layout.row()
+ row.label(text=obj1.name, icon='OBJECT_DATA')
+ sce.measure_panel_area1 = area1
+ row.prop(sce, "measure_panel_area1")
- if (area2 >= 0):
- row = layout.row()
- row.label(text=obj2.name, icon='OBJECT_DATA')
- scene.measure_panel_area2 = area2
- row.prop(scene, "measure_panel_area2")
+ if (area2 >= 0):
+ row = layout.row()
+ row.label(text=obj2.name, icon='OBJECT_DATA')
+ sce.measure_panel_area2 = area2
+ row.prop(sce, "measure_panel_area2")
- row = layout.row()
- row.prop(scene,
- "measure_panel_transform",
- expand=True)
+ row = layout.row()
+ row.prop(sce,
+ "measure_panel_transform",
+ expand=True)
- elif (obj and obj.selected
- and context.selected_objects
- and len(context.selected_objects) == 1):
+ elif (obj):
# One object selected.
- # We measure the distance from the
- # selected & active) object to the 3D cursor.
- cur_loc = scene.cursor_location
- obj_loc = Vector(tuple(obj.location))
- dist_vec = obj_loc - cur_loc
+ # We measure the distance from the object to the 3D cursor.
+
+ # Get the 2 measure points
+ line = getMeasurePoints(context)
+ if line != 0:
+ dist_vec = line[0] - line[1]
- scene.measure_panel_dist = dist_vec.length
+ sce.measure_panel_dist = dist_vec.length
row = layout.row()
#row.label(text=str(dist_vec.length))
- row.prop(scene, "measure_panel_dist")
+ row.prop(sce, "measure_panel_dist")
row = layout.row()
row.label(text="", icon='CURSOR')
@@ -559,31 +933,38 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.label(text="", icon='OBJECT_DATA')
row.prop(obj, "name", text="")
- # Calculate and display surface area of the object.
- area = objectSurfaceArea(obj, False, measureGlobal(scene))
- if (area >= 0):
- row = layout.row()
- row.label(text="Surface area:")
+ row = layout.row()
+ row.prop(sce, "measure_panel_calc_area",
+ text="Surface area:")
- row = layout.row()
- row.label(text=obj.name, icon='OBJECT_DATA')
- scene.measure_panel_area1 = area
- row.prop(scene, "measure_panel_area1")
+ if (sce.measure_panel_calc_area):
+ # Calculate and display surface area of the object.
+ area = objectSurfaceArea(obj, False, measureGlobal(sce))
+ if (area >= 0):
+ row = layout.row()
+ row.label(text=obj.name, icon='OBJECT_DATA')
+ sce.measure_panel_area1 = area
+ row.prop(sce, "measure_panel_area1")
- row = layout.row()
- row.prop(scene,
- "measure_panel_transform",
- expand=True)
+ row = layout.row()
+ row.prop(sce,
+ "measure_panel_transform",
+ expand=True)
elif (not context.selected_objects
or len(context.selected_objects) == 0):
# Nothing selected.
# We measure the distance from the origin to the 3D cursor.
- dist_vec = scene.cursor_location
- scene.measure_panel_dist = dist_vec.length
+
+ # Get the 2 measure points
+ line = getMeasurePoints(context)
+ if line != 0:
+ dist_vec = line[0] - line[1]
+
+ sce.measure_panel_dist = dist_vec.length
row = layout.row()
- row.prop(scene, "measure_panel_dist")
+ row.prop(sce, "measure_panel_dist")
row = layout.row()
row.label(text="", icon='CURSOR')
@@ -592,20 +973,20 @@ class VIEW3D_PT_measure(bpy.types.Panel):
else:
row = layout.row()
- row.label(text="Selection not supported.", icon='INFO')
+ row.label(text="Selection not supported.",
+ icon='INFO')
def register():
bpy.types.register(VIEW3D_PT_measure)
- bpy.types.register(OBJECT_OT_reenter_editmode)
+ bpy.types.register(VIEW3D_OT_reenter_editmode)
+ bpy.types.register(VIEW3D_OT_display_measurements)
def unregister():
bpy.types.unregister(VIEW3D_PT_measure)
- bpy.types.unregister(OBJECT_OT_reenter_editmode)
+ bpy.types.unregister(VIEW3D_OT_reenter_editmode)
+ bpy.types.unregister(VIEW3D_OT_display_measurements)
-## @todo Register keypress for EditMode seletion refresh.
-## @todo Check if we overwrite a setting?
-#wm = bpy.data.window_managers['WinMan']
-#keymap = wm.keyconfigs['Blender'].keymaps['Window']
-#keymap.items.add('reenter_editmode', 'F5', 'PRESS')
+if __name__ == "__main__":
+ register()