generic modal operator to make adjusting almost any rna property with the mouse possible with a few lines.

Example which is similar to interactive lamp adjusting in 2.4x ...
  wm.context_modal_mouse(path_iter="selected_editable_objects", path_item="data.spot_size")

Added lamp Wkey menu back.
This commit is contained in:
Campbell Barton
2010-02-21 14:05:02 +00:00
parent 1bb37bc10e
commit 0cc59b9bb7
3 changed files with 125 additions and 0 deletions

View File

@@ -297,6 +297,91 @@ doc_new = StringProperty(name="Edit Description",
description="", maxlen=1024, default="")
class WM_OT_context_modal_mouse(bpy.types.Operator):
'''Adjust arbitrary values with mouse input'''
bl_idname = "wm.context_modal_mouse"
bl_label = "Context Modal Mouse"
path_iter = StringProperty(description="The path relative to the context, must point to an iterable.")
path_item = StringProperty(description="The path from each iterable to the value (int or float)")
input_scale = FloatProperty(default=0.01, description="Scale the mouse movement by this value before applying the delta")
invert = BoolProperty(default=False, description="Invert the mouse input")
initial_x = IntProperty(options={'HIDDEN'})
_values = {}
def _values_store(self, context):
path_iter = self.properties.path_iter
path_item = self.properties.path_item
self._values.clear()
values = self._values
for item in getattr(context, path_iter):
try:
value_orig = eval("item." + path_item)
except:
continue
# check this can be set, maybe this is library data.
try:
exec("item.%s = %s" % (path_item, value_orig))
except:
continue
values[item] = value_orig
def _values_delta(self, delta):
delta *= self.properties.input_scale
if self.properties.invert:
delta = -delta
path_item = self.properties.path_item
for item, value_orig in self._values.items():
exec("item.%s = %s" % (path_item, value_orig + delta))
def _values_restore(self):
path_item = self.properties.path_item
for item, value_orig in self._values.items():
exec("item.%s = %s" % (path_item, value_orig))
self._values.clear()
def _values_clear(self):
self._values.clear()
def modal(self, context, event):
event_type = event.type
if event_type == 'MOUSEMOVE':
delta = event.mouse_x - self.properties.initial_x
self._values_delta(delta)
elif 'LEFTMOUSE' == event_type:
self._values_clear()
return {'FINISHED'}
elif event_type in ('RIGHTMOUSE', 'ESCAPE'):
self._values_restore()
return {'FINISHED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
self._values_store(context)
if not self._values:
self.report({'WARNING'}, "Nothing to operate on: %s[ ].%s" % (self.properties.path_iter, self.properties.path_item))
return {'CANCELLED'}
else:
self.properties.initial_x = event.mouse_x
context.manager.add_modal_handler(self)
return {'RUNNING_MODAL'}
class WM_OT_doc_view(bpy.types.Operator):
'''Load online reference docs'''
bl_idname = "wm.doc_view"
@@ -433,6 +518,7 @@ classes = [
WM_OT_context_toggle_enum,
WM_OT_context_cycle_enum,
WM_OT_context_cycle_int,
WM_OT_context_modal_mouse,
WM_OT_doc_view,
WM_OT_doc_edit,

View File

@@ -700,6 +700,42 @@ class VIEW3D_MT_object_clear(bpy.types.Menu):
layout.operator("object.origin_clear", text="Origin")
class VIEW3D_MT_object_specials(bpy.types.Menu):
bl_label = "Specials"
def poll(self, context):
# add more special types
obj = context.object
return bool(obj and obj.type == 'LAMP')
def draw(self, context):
layout = self.layout
obj = context.object
if obj and obj.type == 'LAMP':
layout.operator_context = 'INVOKE_REGION_WIN'
props = layout.operator("wm.context_modal_mouse", text="Spot Size")
props.path_iter = "selected_editable_objects"
props.path_item = "data.spot_size"
props.input_scale = 0.01
props = layout.operator("wm.context_modal_mouse", text="Distance")
props.path_iter = "selected_editable_objects"
props.path_item = "data.distance"
props.input_scale = 0.1
props = layout.operator("wm.context_modal_mouse", text="Clip Start")
props.path_iter = "selected_editable_objects"
props.path_item = "data.shadow_buffer_clip_start"
props.input_scale = 0.05
props = layout.operator("wm.context_modal_mouse", text="Clip End")
props.path_iter = "selected_editable_objects"
props.path_item = "data.shadow_buffer_clip_end"
props.input_scale = 0.05
class VIEW3D_MT_object_apply(bpy.types.Menu):
bl_label = "Apply"
@@ -2141,6 +2177,7 @@ classes = [
VIEW3D_MT_uv_map, # Edit Menus
VIEW3D_MT_object, # Object Menu
VIEW3D_MT_object_specials,
VIEW3D_MT_object_apply,
VIEW3D_MT_object_clear,
VIEW3D_MT_object_parent,

View File

@@ -336,6 +336,8 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);
for(i=0; i<=5; i++) {
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY+i, KM_PRESS, KM_CTRL, 0);
RNA_int_set(kmi->ptr, "level", i);