diff options
author | Martin Buerbaum <martin.buerbaum@gmx.at> | 2010-04-14 17:44:02 +0400 |
---|---|---|
committer | Martin Buerbaum <martin.buerbaum@gmx.at> | 2010-04-14 17:44:02 +0400 |
commit | e702240b36ae64a85958754e33612674c5603ff4 (patch) | |
tree | aa7949e45fca84f04a8189ceb68d7aa444260bcc /space_view3d_panel_measure.py | |
parent | 0f56f2080fe4328563def9973bfbaaea8882512b (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.py | 701 |
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() |