From ed9bcd88c7fb1f8b48b96051b61f4d7d724e2e52 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Wed, 30 Nov 2016 22:50:46 +0100 Subject: patch D2380 Added display options for the Math Vis Addon --- space_view3d_math_vis/__init__.py | 160 +++++++++++++++++++++++++++++++++++++- space_view3d_math_vis/draw.py | 72 +++++++++++------ space_view3d_math_vis/utils.py | 143 +++++++++++++++++++++++++++++++--- 3 files changed, 342 insertions(+), 33 deletions(-) (limited to 'space_view3d_math_vis') diff --git a/space_view3d_math_vis/__init__.py b/space_view3d_math_vis/__init__.py index 056e83fb..88f90efe 100644 --- a/space_view3d_math_vis/__init__.py +++ b/space_view3d_math_vis/__init__.py @@ -40,20 +40,178 @@ else: from . import utils, draw import bpy +from bpy.props import StringProperty, BoolProperty, BoolVectorProperty, FloatProperty, PointerProperty, CollectionProperty +from .utils import get_var_states + + +class PanelConsoleVars(bpy.types.Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'TOOLS' + bl_label = "Console Vars" + bl_idname = "mathvis.panel_console_vars" + bl_category = "Math Vis" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + layout = self.layout + box = layout.box() + col = box.column(align=True) + variables = utils.get_math_data() + var_states = get_var_states() + + for key in sorted(variables): + ktype = variables[key] + row = col.row(align=True) + row.label(text='%s - %s' % (key, ktype.__name__)) + + icon = 'RESTRICT_VIEW_OFF' if var_states.is_visible(key) else 'RESTRICT_VIEW_ON' + prop = row.operator("mathvis.toggle_display", text='', icon=icon, emboss=False) + prop.key = key + + icon = 'LOCKED' if var_states.is_locked(key) else 'UNLOCKED' + prop = row.operator("mathvis.toggle_lock", text='', icon=icon, emboss=False) + prop.key = key + + if var_states.is_locked(key): + row.label(text='', icon='BLANK1') + else: + prop = row.operator("mathvis.delete_var", text='', icon='X', emboss=False) + prop.key = key + + col = layout.column() + col.prop(bpy.context.scene.MathVisProp, "name_hide") + col.prop(bpy.context.scene.MathVisProp, "bbox_hide") + col.prop(bpy.context.scene.MathVisProp, "bbox_scale") + col.operator("mathvis.cleanup_console") + + +class DeleteVar(bpy.types.Operator): + bl_idname = "mathvis.delete_var" + bl_label = "Delete Var" + bl_description = "Remove the variable from the Console." + bl_options = {'REGISTER'} + + key = StringProperty(name="Key") + + def execute(self, context): + locals = utils.console_namespace() + var_states = get_var_states() + var_states.delete(self.key) + del locals[self.key] + draw.tag_redraw_all_view3d_areas() + return {'FINISHED'} + + +class ToggleDisplay(bpy.types.Operator): + bl_idname = "mathvis.toggle_display" + bl_label = "Hide/Unhide" + bl_description = "Change the display state of the var" + bl_options = {'REGISTER'} + + key = StringProperty(name="Key") + + def execute(self, context): + var_states = get_var_states() + var_states.toggle_display_state(self.key) + draw.tag_redraw_all_view3d_areas() + return {'FINISHED'} + + +class ToggleLock(bpy.types.Operator): + bl_idname = "mathvis.toggle_lock" + bl_label = "Lock/Unlock" + bl_description = "Lock the var from being deleted" + bl_options = {'REGISTER'} + + key = StringProperty(name="Key") + + def execute(self, context): + var_states = get_var_states() + var_states.toggle_lock_state(self.key) + draw.tag_redraw_all_view3d_areas() + return {'FINISHED'} + + +class ToggleMatrixBBoxDisplay(bpy.types.Operator): + bl_idname = "mathvis.show_bbox" + bl_label = "Show BBox" + bl_description = "Show/Hide the BBox of Matrix items" + bl_options = {'REGISTER'} + + def execute(self, context): + var_states = get_var_states() + var_states.toggle_show_bbox() + draw.tag_redraw_all_view3d_areas() + return {'FINISHED'} + + +class CleanupConsole(bpy.types.Operator): + bl_idname = "mathvis.cleanup_console" + bl_label = "Cleanup Math Vis Console" + bl_description = "Remove all visualised variables from the Console." + bl_options = {'REGISTER'} + + def execute(self, context): + utils.cleanup_math_data() + draw.tag_redraw_all_view3d_areas() + return {'FINISHED'} + + +def menu_func_cleanup(self, context): + self.layout.operator("mathvis.cleanup_console", text="Clear Math Vis") def console_hook(): - draw.tag_redraw_all_view3d() + draw.tag_redraw_all_view3d_areas() + context = bpy.context + for window in context.window_manager.windows: + window.screen.areas.update() + + +def call_console_hook(self, context): + console_hook() + + +class MathVisStateProp(bpy.types.PropertyGroup): + key = StringProperty() + state = BoolVectorProperty(default=(False, False), size=2) + + +class MathVisProp(bpy.types.PropertyGroup): + + bbox_hide = BoolProperty(name="Hide BBoxes", + default=False, + description="Hide the bounding boxes rendered for Matrix like items", + update=call_console_hook) + + name_hide = BoolProperty(name="Hide Names", + default=False, + description="Hide the names of the rendered items", + update=call_console_hook) + + bbox_scale = FloatProperty(name="Scale factor", min=0, default=1, + description="Resize the Bounding Box and the coordinate lines for the display of Matrix items") + def register(): draw.callback_enable() import console_python console_python.execute.hooks.append((console_hook, ())) + bpy.utils.register_module(__name__) + if not 'MathVisStateProp' in dir(bpy.types.WindowManager): + bpy.types.Scene.MathVisProp = PointerProperty(type=MathVisProp) + bpy.types.WindowManager.MathVisStateProp = CollectionProperty(type=MathVisStateProp) + bpy.types.CONSOLE_MT_console.prepend(menu_func_cleanup) def unregister(): + context = bpy.context + var_states = get_var_states() + var_states.store_states() draw.callback_disable() import console_python console_python.execute.hooks.remove((console_hook, ())) + bpy.types.CONSOLE_MT_console.remove(menu_func_cleanup) + bpy.utils.unregister_module(__name__) diff --git a/space_view3d_math_vis/draw.py b/space_view3d_math_vis/draw.py index 40c44f3f..1890c3e9 100644 --- a/space_view3d_math_vis/draw.py +++ b/space_view3d_math_vis/draw.py @@ -27,16 +27,14 @@ SpaceView3D = bpy.types.SpaceView3D callback_handle = [] -def tag_redraw_all_view3d(): +def tag_redraw_all_view3d_areas(): context = bpy.context # Py cant access notifers for window in context.window_manager.windows: for area in window.screen.areas: if area.type == 'VIEW_3D': - for region in area.regions: - if region.type == 'WINDOW': - region.tag_redraw() + area.tag_redraw() def callback_enable(): @@ -47,7 +45,7 @@ def callback_enable(): handle_view = SpaceView3D.draw_handler_add(draw_callback_view, (), 'WINDOW', 'POST_VIEW') callback_handle[:] = handle_pixel, handle_view - tag_redraw_all_view3d() + tag_redraw_all_view3d_areas() def callback_disable(): @@ -59,7 +57,7 @@ def callback_disable(): SpaceView3D.draw_handler_remove(handle_view, 'WINDOW') callback_handle[:] = [] - tag_redraw_all_view3d() + tag_redraw_all_view3d_areas() def draw_callback_px(): @@ -71,6 +69,11 @@ def draw_callback_px(): data_matrix, data_quat, data_euler, data_vector, data_vector_array = utils.console_math_data() + name_hide = context.scene.MathVisProp.name_hide + + if name_hide: + return + if not data_matrix and not data_quat and not data_euler and not data_vector and not data_vector_array: ''' @@ -92,13 +95,13 @@ def draw_callback_px(): # vars for projection perspective_matrix = region3d.perspective_matrix.copy() - def draw_text(text, vec): + def draw_text(text, vec, dx=3.0, dy=-4.0): vec_4d = perspective_matrix * vec.to_4d() 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.position(font_id, x + dx, y + dy, 0.0) blf.draw(font_id, text) # points @@ -114,34 +117,56 @@ def draw_callback_px(): # matrix if data_matrix: for key, mat in data_matrix.items(): - draw_text(key, mat[3]) + loc = Vector((mat[0][3], mat[1][3], mat[2][3])) + draw_text(key, loc, dx=10, dy=-20) + line = 20 if data_quat: loc = context.scene.cursor_location.copy() for key, mat in data_quat.items(): - draw_text(key, loc) + draw_text(key, loc, dy=-line) + line += 20 if data_euler: loc = context.scene.cursor_location.copy() for key, mat in data_euler.items(): - draw_text(key, loc) + draw_text(key, loc, dy=-line) + line += 20 def draw_callback_view(): context = bpy.context - from bgl import glEnable, glDisable, glColor3f, glVertex3f, glPointSize, glLineWidth, glBegin, glEnd, glLineStipple, GL_POINTS, GL_LINE_STRIP, GL_LINES, GL_LINE_STIPPLE + 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 modifiers + bbox_hide = context.scene.MathVisProp.bbox_hide + bbox_scale = context.scene.MathVisProp.bbox_scale + # 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)) + x_p = Vector((bbox_scale, 0.0, 0.0)) + x_n = Vector((-bbox_scale, 0.0, 0.0)) + y_p = Vector((0.0, bbox_scale, 0.0)) + y_n = Vector((0.0, -bbox_scale, 0.0)) + z_p = Vector((0.0, 0.0, bbox_scale)) + z_n = Vector((0.0, 0.0, -bbox_scale)) bb = [Vector() for i in range(8)] def draw_matrix(mat): @@ -176,7 +201,7 @@ def draw_callback_view(): glEnd() # z - glColor3f(0.2, 0.2, 1.0) + glColor3f(0.4, 0.4, 1.0) glBegin(GL_LINES) glVertex3f(*(zero_tx)) glVertex3f(*(mat * z_p)) @@ -189,11 +214,14 @@ def draw_callback_view(): glEnd() # bounding box + if bbox_hide: + return + 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): + for x in (-bbox_scale, bbox_scale): + for y in (-bbox_scale, bbox_scale): + for z in (-bbox_scale, bbox_scale): bb[i][:] = x, y, z bb[i] = mat * bb[i] i += 1 diff --git a/space_view3d_math_vis/utils.py b/space_view3d_math_vis/utils.py index 318beffa..12c1c62a 100644 --- a/space_view3d_math_vis/utils.py +++ b/space_view3d_math_vis/utils.py @@ -18,6 +18,10 @@ # +import bpy +from bpy.props import BoolProperty + + def console_namespace(): import console_python get_consoles = console_python.get_console @@ -28,6 +32,127 @@ def console_namespace(): return {} +def is_display_list(listvar): + from mathutils import Vector + + for var in listvar: + if type(var) is not Vector: + return False + return True + + +class VarStates: + + states = {} + + def store_states(self): + # Store the display states, called upon unregister the Addon + # This is useful when you press F8 to reload the Addons. + # Then this function preserves the display states of the + # console variables. + context = bpy.context + if len(self.states) > 0: + state_props = context.window_manager.MathVisStateProp + state_props.clear() + for key, state in self.states.items(): + if key: + state_prop = state_props.add() + state_prop.key = key + state_prop.state = state + + def __init__(self): + # Get the display state from the stored values (if exists) + # This happens after you pressed F8 to reload the Addons. + context = bpy.context + if 'MathVisStateProp' in dir(bpy.types.WindowManager): + state_props = context.window_manager.MathVisStateProp + if state_props: + for state_prop in state_props: + key = state_prop.key + state = state_prop.state + self.states[key] = [state[0], state[1]] + state_props.clear() + + def get(self, key, default): + return self.states.get(key, default) + + def delete(self, key): + if key in self.states: + del self.states[key] + + def is_visible(self, key): + if key in self.states: + disp, lock = self.states[key] + return disp + return True + + def toggle_display_state(self, key): + if key in self.states: + disp, lock = self.states[key] + self.states[key] = [not disp, lock] + else: + self.states[key] = [False, False] + + def is_locked(self, key): + if key in self.states: + disp, lock = self.states[key] + return lock + return False + + def toggle_lock_state(self, key): + if key in self.states: + disp, lock = self.states[key] + self.states[key] = [disp, not lock] + else: + self.states[key] = [True, True] + +global g_var_states +g_var_states = None + + +def get_var_states(): + global g_var_states + if g_var_states == None: + g_var_states = VarStates() + return g_var_states + + +def get_math_data(): + from mathutils import Matrix, Vector, Quaternion, Euler + + locals = console_namespace() + if not locals: + return {} + + variables = {} + for key, var in locals.items(): + if key[0] == "_" or not var: + continue + if type(var) in {Matrix, Vector, Quaternion, Euler} or \ + type(var) in {tuple, list} and is_display_list(var): + + variables[key] = type(var) + + return variables + + +def cleanup_math_data(): + from mathutils import Matrix, Vector, Quaternion, Euler + + locals = console_namespace() + if not locals: + return + + var_states = get_var_states() + variables = get_math_data() + for key in variables.keys(): + if var_states.is_locked(key): + continue + + del locals[key] + var_states.delete(key) + + def console_math_data(): from mathutils import Matrix, Vector, Quaternion, Euler @@ -36,17 +161,22 @@ def console_math_data(): data_euler = {} data_vector = {} data_vector_array = {} + var_states = get_var_states() for key, var in console_namespace().items(): if key[0] == "_": continue + disp, lock = var_states.get(key, [True, False]) + if not disp: + continue + var_type = type(var) if var_type is Matrix: if len(var.col) != 4 or len(var.row) != 4: if len(var.col) == len(var.row): - var = var.to_4x4() + var = var.to_4x4() else: # todo, support 4x3 matrix continue data_matrix[key] = var @@ -58,14 +188,7 @@ def console_math_data(): 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 + elif var_type in {list, tuple} and is_display_list(var): + data_vector_array[key] = var return data_matrix, data_quat, data_euler, data_vector, data_vector_array -- cgit v1.2.3