diff --git a/space_view3d_math_vis/__init__.py b/space_view3d_math_vis/__init__.py new file mode 100644 index 000000000..a73ec1cc6 --- /dev/null +++ b/space_view3d_math_vis/__init__.py @@ -0,0 +1,100 @@ +#====================== 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 ======================== + +bl_addon_info = { + "name": "Math Vis (Console)", + "author": "Campbell Barton", + "version": (0, 1), + "blender": (2, 5, 5), + "api": 33110, + "location": "3D View Toolbar, Python Console", + "description": "Display console defined mathutils variables in the 3D view", + "wiki_url": "", + "tracker_url": "", + "category": "3D View"} + +if "bpy" in locals(): + from imp import reload + reload(utils) + reload(draw) +else: + from . import utils, draw + + +import bpy + + +class VIEW3D_PT_math_vis(bpy.types.Panel): + bl_space_type = "VIEW_3D" + bl_region_type = "TOOLS" + bl_label = "Math View" + + def draw(self, context): + layout = self.layout + view = context.space_data + + col = layout.column(align=True) + + callbacks = draw.callbacks + ok = False + for region in context.area.regions: + if callbacks.get(hash(region)): + ok = True + break + + col.operator("view3d.math_vis_toggle", emboss=False, icon='CHECKBOX_HLT' if ok else 'CHECKBOX_DEHLT') + + + +class SetupMathView(bpy.types.Operator): + '''Draw a line with the mouse''' + bl_idname = "view3d.math_vis_toggle" + bl_label = "Use Math Vis" + + def execute(self, context): + callbacks = draw.callbacks + region = context.region + region_id = hash(region) + cb_data = callbacks.get(region_id) + if cb_data is None: + handle_pixel = region.callback_add(draw.draw_callback_px, (self, context), 'POST_PIXEL') + handle_view = region.callback_add(draw.draw_callback_view, (self, context), 'POST_VIEW') + callbacks[region_id] = region, handle_pixel, handle_view + else: + region.callback_remove(cb_data[1]) + region.callback_remove(cb_data[2]) + del callbacks[region_id] + + context.area.tag_redraw() + return {'FINISHED'} + + +def console_hook(): + for region, handle_pixel, handle_view in draw.callbacks.values(): + region.tag_redraw() + + +def register(): + import console_python + console_python.execute.hooks.append((console_hook, ())) + +def unregister(): + import console_python + console_python.execute.hooks.remove((console_hook, ())) + + draw.callbacks_clear() diff --git a/space_view3d_math_vis/draw.py b/space_view3d_math_vis/draw.py new file mode 100644 index 000000000..c8c23bbfe --- /dev/null +++ b/space_view3d_math_vis/draw.py @@ -0,0 +1,231 @@ +#====================== 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 ======================== + +import bpy +import blf + +from . import utils +from mathutils import Vector, Matrix + +callbacks = {} + +def callbacks_clear(): + for region, handle_pixel, handle_view in callbacks.values(): + region.callback_remove(handle_pixel) + region.callback_remove(handle_view) + callbacks.clear() + + +def draw_callback_px(self, context): + from bgl import glColor3f + font_id = 0 # XXX, need to find out how best to get this. + blf.size(font_id, 12, 72) + + data_matrix, data_quat, data_euler, data_vector, data_vector_array = utils.console_math_data() + + if not data_matrix and not data_quat and not data_euler and not data_vector and not data_vector_array: + + # draw some text + glColor3f(1.0, 0.0, 0.0) + blf.position(font_id, 180, 10, 0) + blf.draw(font_id, "Python Console has no mathutils definitions") + return + + glColor3f(1.0, 1.0, 1.0) + + region = context.region + region3d = context.space_data.region_3d + + region_mid_width = region.width / 2.0 + region_mid_height = region.height / 2.0 + + # vars for projection + perspective_matrix = region3d.perspective_matrix.copy() + + def draw_text(text, vec): + vec_4d = Vector((vec.x, vec.y, vec.z, 1.0)) + vec_4d *= perspective_matrix + if vec_4d.w > 0.0: + x = region_mid_width + region_mid_width * (vec_4d.x / vec_4d.w) + y = region_mid_height + region_mid_height * (vec_4d.y / vec_4d.w) + + blf.position(font_id, x + 3.0, y - 4.0, 0.0) + blf.draw(font_id, text) + + # points + if data_vector: + for key, vec in data_vector.items(): + draw_text(key, vec) + + # lines + if data_vector_array: + for key, vec in data_vector_array.items(): + draw_text(key, vec[0]) + + # matrix + if data_matrix: + for key, mat in data_matrix.items(): + draw_text(key, mat[3]) + + if data_quat: + loc = context.scene.cursor_location.copy() + for key, mat in data_quat.items(): + draw_text(key, loc) + + if data_euler: + loc = context.scene.cursor_location.copy() + for key, mat in data_euler.items(): + draw_text(key, loc) + + +def draw_callback_view(self, context): + from bgl import glEnable, glDisable, glColor3f, glVertex3f, glPointSize, glLineWidth, glBegin, glEnd, glLineStipple, GL_POINTS, GL_LINE_STRIP, GL_LINES, GL_LINE_STIPPLE + + data_matrix, data_quat, data_euler, data_vector, data_vector_array = utils.console_math_data() + + + # draw_matrix vars + zero = Vector((0.0, 0.0, 0.0)) + x_p = Vector((1.0, 0.0, 0.0)) + x_n = Vector((-1.0, 0.0, 0.0)) + y_p = Vector((0.0, 1.0, 0.0)) + y_n = Vector((0.0, -1.0, 0.0)) + z_p = Vector((0.0, 0.0, 1.0)) + z_n = Vector((0.0, 0.0, -1.0)) + bb = [Vector() for i in range(8)] + + def draw_matrix(mat): + zero_tx = zero * mat + + glLineWidth(2.0) + + # x + glColor3f(1.0, 0.2, 0.2) + glBegin(GL_LINES) + glVertex3f(*(zero_tx)) + glVertex3f(*(x_p * mat)) + glEnd() + + glColor3f(0.6, 0.0, 0.0) + glBegin(GL_LINES) + glVertex3f(*(zero_tx)) + glVertex3f(*(x_n * mat)) + glEnd() + + # y + glColor3f(0.2, 1.0, 0.2) + glBegin(GL_LINES) + glVertex3f(*(zero_tx)) + glVertex3f(*(y_p * mat)) + glEnd() + + glColor3f(0.0, 0.6, 0.0) + glBegin(GL_LINES) + glVertex3f(*(zero_tx)) + glVertex3f(*(y_n * mat)) + glEnd() + + # z + glColor3f(0.2, 0.2, 1.0) + glBegin(GL_LINES) + glVertex3f(*(zero_tx)) + glVertex3f(*(z_p * mat)) + glEnd() + + glColor3f(0.0, 0.0, 0.6) + glBegin(GL_LINES) + glVertex3f(*(zero_tx)) + glVertex3f(*(z_n * mat)) + glEnd() + + # bounding box + i = 0 + glColor3f(1.0, 1.0, 1.0) + for x in (-1.0, 1.0): + for y in (-1.0, 1.0): + for z in (-1.0, 1.0): + bb[i][:] = x, y, z + bb[i] *= mat + i += 1 + + # strip + glLineWidth(1.0) + glLineStipple(1, 0xAAAA) + glEnable(GL_LINE_STIPPLE) + + glBegin(GL_LINE_STRIP) + for i in 0, 1, 3, 2, 0, 4, 5, 7, 6, 4: + glVertex3f(*bb[i]) + glEnd() + + # not done by the strip + glBegin(GL_LINES) + glVertex3f(*bb[1]) + glVertex3f(*bb[5]) + + glVertex3f(*bb[2]) + glVertex3f(*bb[6]) + + glVertex3f(*bb[3]) + glVertex3f(*bb[7]) + glEnd() + glDisable(GL_LINE_STIPPLE) + + + # points + if data_vector: + glPointSize(3.0); + glBegin(GL_POINTS) + glColor3f(0.5, 0.5, 1) + for key, vec in data_vector.items(): + glVertex3f(*vec) + glEnd(); + glPointSize(1.0) + + # lines + if data_vector_array: + glColor3f(0.5, 0.5, 1) + glLineWidth(2.0) + + for line in data_vector_array.values(): + glBegin(GL_LINE_STRIP) + for vec in line: + glVertex3f(*vec) + glEnd(); + glPointSize(1.0) + + glLineWidth(1.0) + + # matrix + if data_matrix: + for mat in data_matrix.values(): + draw_matrix(mat) + + if data_quat: + loc = context.scene.cursor_location.copy() + for quat in data_quat.values(): + mat = quat.to_matrix().resize4x4() + mat[3][0:3] = loc + draw_matrix(mat) + + if data_euler: + loc = context.scene.cursor_location.copy() + for eul in data_euler.values(): + mat = eul.to_matrix().resize4x4() + mat[3][0:3] = loc + draw_matrix(mat) \ No newline at end of file diff --git a/space_view3d_math_vis/utils.py b/space_view3d_math_vis/utils.py new file mode 100644 index 000000000..a9c26ae40 --- /dev/null +++ b/space_view3d_math_vis/utils.py @@ -0,0 +1,64 @@ +#====================== 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 ======================== + +import sys + +def console_namespace(): + import console_python + get_consoles = console_python.get_console + consoles = getattr(get_consoles, "consoles", None) + if consoles: + for console, stdout, stderr in get_consoles.consoles.values(): + return console.locals + return {} + +def console_math_data(): + from mathutils import Matrix, Vector, Quaternion, Euler + + data_matrix = {} + data_quat = {} + data_euler = {} + data_vector = {} + data_vector_array = {} + + for key, var in console_namespace().items(): + if key[0] == "_": + continue + + var_type = type(var) + + if var_type is Matrix: + data_matrix[key] = var + elif var_type is Vector: + data_vector[key] = var + elif var_type is Quaternion: + data_quat[key] = var + elif var_type is Euler: + data_euler[key] = var + elif var_type in (list, tuple): + if var: + ok = True + for item in var: + if type(item) is not Vector: + ok = False + break + if ok: + data_vector_array[key] = var + + return data_matrix, data_quat, data_euler, data_vector, data_vector_array +