patch D2380 Added display options for the Math Vis Addon
This commit is contained in:
parent
07c0aac78a
commit
ed9bcd88c7
|
@ -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__)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
# <pep8 compliant>
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue