generic modal operator to make adjusting almost any rna property with the mouse possi...
authorCampbell Barton <ideasman42@gmail.com>
Sun, 21 Feb 2010 14:05:02 +0000 (14:05 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 21 Feb 2010 14:05:02 +0000 (14:05 +0000)
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.

release/scripts/op/wm.py
release/scripts/ui/space_view3d.py
source/blender/editors/object/object_ops.c

index 6d2c105ea29cb27dd3fab295ff583e7de7b8c8ff..33e691f7674992eda2ce5a29dd4d02a0350b2ffc 100644 (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,
index 1fc2447bcfcb2b62152e8eac7c1f8e543b9f2c0c..3a1bca75baa3143072f5a327eb85f5960183757f 100644 (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,
index c87442c29eda23f34d8128f49e2b78d826f1ba75..d7ffa1d983bfc226965756600f561afe1a5d4c46 100644 (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);