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:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user