== Radial control ==
authorNicholas Bishop <nicholasbishop@gmail.com>
Thu, 12 May 2011 01:57:47 +0000 (01:57 +0000)
committerNicholas Bishop <nicholasbishop@gmail.com>
Thu, 12 May 2011 01:57:47 +0000 (01:57 +0000)
Patch to make the radial control more generic with RNA. Patch was
reviewed here: http://codereview.appspot.com/4280080/

Prior to this update, the radial control code in trunk had generic
parts of the radial control implemented as an incomplete operator
within WM. Then each different user of the radial control had to
implement a separate operator to actually pass in specific brush data
-- e.g. sculpt's brush size, vpaint's brush size, etc.

This patch removes all the extra operators and makes the WM operator
do everything. It now takes several RNA path strings as its properties
-- the only required property is data_path, which specifies the data
to be modified by the radial control. The other paths affect display
in various ways, e.g. rotation, color, etc.

In addition to decreasing some duplicate paint brush code, these
updates make it pretty easy to enable radial control for other
purposes (and it can be set up entirely though python or keymaps, no
extra C code needed.)

16 files changed:
source/blender/blenkernel/BKE_brush.h
source/blender/blenkernel/intern/brush.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/physics_intern.h
source/blender/editors/physics/physics_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_intern.h
source/blender/editors/sculpt_paint/paint_ops.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/intern/rna_sculpt_paint.c
source/blender/makesrna/intern/rna_space.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_operators.c
source/blenderplayer/bad_level_call_stubs/stubs.c

index a9d379e6c694ec8d559f0ca6a634e7944987b85b..ad736cd07bf47c81a79623bd5597ac89f9d6b9da 100644 (file)
@@ -90,8 +90,7 @@ void brush_painter_free(BrushPainter *painter);
 unsigned int *brush_gen_texture_cache(struct Brush *br, int half_side);
 
 /* radial control */
-void brush_radial_control_invoke(struct wmOperator *op, struct Brush *br, float size_weight);
-int brush_radial_control_exec(struct wmOperator *op, struct Brush *br, float size_weight);
+struct ImBuf *brush_gen_radial_control_imbuf(struct Brush *br);
 
 /* unified strength and size */
 
index fa3b756ae27980eb6e98cb5d0b02a1919c468a56..98c540f53b72ff1680b4d03b40c715c8bbf32362 100644 (file)
@@ -426,13 +426,6 @@ void brush_curve_preset(Brush *b, /*CurveMappingPreset*/int preset)
        curvemapping_changed(b->curve, 0);
 }
 
-static MTex *brush_active_texture(Brush *brush)
-{
-       if(brush)
-               return &brush->mtex;
-       return NULL;
-}
-
 int brush_texture_set_nr(Brush *brush, int nr)
 {
        ID *idtest, *id=NULL;
@@ -1185,7 +1178,7 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
 }
 
 /**** Radial Control ****/
-static struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
+struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
 {
        ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture");
        unsigned int *texcache;
@@ -1219,50 +1212,6 @@ static struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
        return im;
 }
 
-void brush_radial_control_invoke(wmOperator *op, Brush *br, float size_weight)
-{
-       int mode = RNA_enum_get(op->ptr, "mode");
-       float original_value= 0;
-
-       if(mode == WM_RADIALCONTROL_SIZE)
-               original_value = brush_size(br) * size_weight;
-       else if(mode == WM_RADIALCONTROL_STRENGTH)
-               original_value = brush_alpha(br);
-       else if(mode == WM_RADIALCONTROL_ANGLE) {
-               MTex *mtex = brush_active_texture(br);
-               if(mtex)
-                       original_value = mtex->rot;
-       }
-
-       RNA_float_set(op->ptr, "initial_value", original_value);
-       op->customdata = brush_gen_radial_control_imbuf(br);
-}
-
-int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight)
-{
-       int mode = RNA_enum_get(op->ptr, "mode");
-       float new_value = RNA_float_get(op->ptr, "new_value");
-       const float conv = 0.017453293;
-
-       if(mode == WM_RADIALCONTROL_SIZE)
-               if (brush_use_locked_size(br)) {
-                       float initial_value = RNA_float_get(op->ptr, "initial_value");
-                       const float unprojected_radius = brush_unprojected_radius(br);
-                       brush_set_unprojected_radius(br, unprojected_radius * new_value/initial_value * size_weight);
-               }
-               else
-                       brush_set_size(br, new_value * size_weight);
-       else if(mode == WM_RADIALCONTROL_STRENGTH)
-               brush_set_alpha(br, new_value);
-       else if(mode == WM_RADIALCONTROL_ANGLE) {
-               MTex *mtex = brush_active_texture(br);
-               if(mtex)
-                       mtex->rot = new_value * conv;
-       }
-
-       return OPERATOR_FINISHED;
-}
-
 /* Unified Size and Strength */
 
 static void set_unified_settings(Brush *brush, short flag, int value)
index 1c9f9e60e14f88272fc979c591fc5cae7466eebc..733919ff166391d5ef428cf9ab226f2b178e901e 100644 (file)
@@ -2521,80 +2521,6 @@ static void toggle_particle_cursor(bContext *C, int enable)
                pset->paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), PE_poll_view3d, brush_drawcursor, NULL);
 }
 
-/********************* radial control operator *********************/
-
-static int brush_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
-       ParticleBrushData *brush;
-       int mode = RNA_enum_get(op->ptr, "mode");
-       float original_value=1.0f;
-
-       if(pset->brushtype < 0)
-               return OPERATOR_CANCELLED;
-
-       brush= &pset->brush[pset->brushtype];
-
-       toggle_particle_cursor(C, 0);
-
-       if(mode == WM_RADIALCONTROL_SIZE)
-               original_value = brush->size;
-       else if(mode == WM_RADIALCONTROL_STRENGTH)
-               original_value = brush->strength;
-
-       RNA_float_set(op->ptr, "initial_value", original_value);
-
-       return WM_radial_control_invoke(C, op, event);
-}
-
-static int brush_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       int ret = WM_radial_control_modal(C, op, event);
-
-       if(ret != OPERATOR_RUNNING_MODAL)
-               toggle_particle_cursor(C, 1);
-
-       return ret;
-}
-
-static int brush_radial_control_exec(bContext *C, wmOperator *op)
-{
-       ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
-       ParticleBrushData *brush;
-       int mode = RNA_enum_get(op->ptr, "mode");
-       float new_value = RNA_float_get(op->ptr, "new_value");
-
-       if(pset->brushtype < 0)
-               return OPERATOR_CANCELLED;
-
-       brush= &pset->brush[pset->brushtype];
-
-       if(mode == WM_RADIALCONTROL_SIZE)
-               brush->size= new_value;
-       else if(mode == WM_RADIALCONTROL_STRENGTH)
-               brush->strength= new_value;
-
-       WM_event_add_notifier(C, NC_WINDOW, NULL);
-
-       return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_brush_radial_control(wmOperatorType *ot)
-{
-       WM_OT_radial_control_partial(ot);
-
-       ot->name= "Brush Radial Control";
-       ot->idname= "PARTICLE_OT_brush_radial_control";
-
-       ot->invoke= brush_radial_control_invoke;
-       ot->modal= brush_radial_control_modal;
-       ot->exec= brush_radial_control_exec;
-       ot->poll= PE_poll;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-}
-
 /*************************** delete operator **************************/
 
 enum { DEL_PARTICLE, DEL_KEY };
index d447da3f8c4af513e1fbdd6b29e5fa4f06dd5cd0..71f1128baf0a1669fdb8942a0c7b35c39702a5aa 100644 (file)
@@ -60,7 +60,6 @@ void PARTICLE_OT_delete(struct wmOperatorType *ot);
 void PARTICLE_OT_mirror(struct wmOperatorType *ot);
 
 void PARTICLE_OT_brush_edit(struct wmOperatorType *ot);
-void PARTICLE_OT_brush_radial_control(struct wmOperatorType *ot);
 
 void PARTICLE_OT_particle_edit_toggle(struct wmOperatorType *ot);
 void PARTICLE_OT_edited_clear(struct wmOperatorType *ot);
index 02b2fad7a00cd7e5600e9dad7d3269d818315e68..aafa5a185edb0a37886ad221ca908189ddcaeb34 100644 (file)
@@ -66,7 +66,6 @@ static void operatortypes_particle(void)
        WM_operatortype_append(PARTICLE_OT_mirror);
 
        WM_operatortype_append(PARTICLE_OT_brush_edit);
-       WM_operatortype_append(PARTICLE_OT_brush_radial_control);
 
        WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
        WM_operatortype_append(PARTICLE_OT_edited_clear);
@@ -91,6 +90,7 @@ static void operatortypes_particle(void)
 
 static void keymap_particle(wmKeyConfig *keyconf)
 {
+       wmKeyMapItem *kmi;
        wmKeyMap *keymap;
        
        keymap= WM_keymap_find(keyconf, "Particle", 0, 0);
@@ -112,8 +112,14 @@ static void keymap_particle(wmKeyConfig *keyconf)
 
        WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
-       RNA_enum_set(WM_keymap_add_item(keymap, "PARTICLE_OT_brush_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
-       RNA_enum_set(WM_keymap_add_item(keymap, "PARTICLE_OT_brush_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
+
+       /* size radial control */
+       kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
+       RNA_string_set(kmi->ptr, "data_path", "tool_settings.particle_edit.brush.size");
+
+       /* size radial control */
+       kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "data_path", "tool_settings.particle_edit.brush.strength");
 
        WM_keymap_add_menu(keymap, "VIEW3D_MT_particle_specials", WKEY, KM_PRESS, 0, 0);
        
index cb8071171981e4b585858c7ce6cdb9ee9f51950c..66a0044d55e99490fa3d539d4dc7955430bdfabb 100644 (file)
@@ -5068,56 +5068,6 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
        }
 }
 
-/* ************ image paint radial control *************/
-static int paint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       float zoom;
-       ToolSettings *ts = CTX_data_scene(C)->toolsettings;
-       get_imapaint_zoom(C, &zoom, &zoom);
-       toggle_paint_cursor(C, 0);
-       brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), zoom);
-       return WM_radial_control_invoke(C, op, event);
-}
-
-static int paint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       int ret = WM_radial_control_modal(C, op, event);
-       if(ret != OPERATOR_RUNNING_MODAL)
-               toggle_paint_cursor(C, 1);
-       return ret;
-}
-
-static int paint_radial_control_exec(bContext *C, wmOperator *op)
-{
-       Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint);
-       float zoom;
-       int ret;
-       char str[64];
-       get_imapaint_zoom(C, &zoom, &zoom);
-       ret = brush_radial_control_exec(op, brush, 1.0f / zoom);
-       WM_radial_control_string(op, str, sizeof(str));
-       
-       WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
-
-       return ret;
-}
-
-void PAINT_OT_image_paint_radial_control(wmOperatorType *ot)
-{
-       WM_OT_radial_control_partial(ot);
-
-       ot->name= "Image Paint Radial Control";
-       ot->idname= "PAINT_OT_image_paint_radial_control";
-
-       ot->invoke= paint_radial_control_invoke;
-       ot->modal= paint_radial_control_modal;
-       ot->exec= paint_radial_control_exec;
-       ot->poll= image_paint_poll;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-}
-
 /************************ grab clone operator ************************/
 
 typedef struct GrabClone {
@@ -5445,28 +5395,6 @@ void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-/************* texture paint radial control *************/
-
-static int texture_paint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       ToolSettings *ts = CTX_data_scene(C)->toolsettings;
-       toggle_paint_cursor(C, !ts->imapaint.paintcursor);
-       brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), 1);
-       return WM_radial_control_invoke(C, op, event);
-}
-
-static int texture_paint_radial_control_exec(bContext *C, wmOperator *op)
-{
-       Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint);
-       int ret = brush_radial_control_exec(op, brush, 1);
-       char str[64];
-       WM_radial_control_string(op, str, sizeof(str));
-
-       WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
-
-       return ret;
-}
-
 static int texture_paint_poll(bContext *C)
 {
        if(texture_paint_toggle_poll(C))
@@ -5481,23 +5409,6 @@ int image_texture_paint_poll(bContext *C)
        return (texture_paint_poll(C) || image_paint_poll(C));
 }
 
-void PAINT_OT_texture_paint_radial_control(wmOperatorType *ot)
-{
-       WM_OT_radial_control_partial(ot);
-
-       ot->name= "Texture Paint Radial Control";
-       ot->idname= "PAINT_OT_texture_paint_radial_control";
-
-       ot->invoke= texture_paint_radial_control_invoke;
-       ot->modal= paint_radial_control_modal;
-       ot->exec= texture_paint_radial_control_exec;
-       ot->poll= texture_paint_poll;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-}
-
-
 int facemask_paint_poll(bContext *C)
 {
        return paint_facesel_test(CTX_data_active_object(C));
index 48fca04ac874033dedde2f4ecc8e73e20e66a060..ba7235a3161b1841ad4cd4a158364ed8980b3358 100644 (file)
@@ -81,12 +81,10 @@ void vpaint_fill(struct Object *ob, unsigned int paintcol);
 void wpaint_fill(struct VPaint *wp, struct Object *ob, float paintweight);
 
 void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot);
-void PAINT_OT_weight_paint_radial_control(struct wmOperatorType *ot);
 void PAINT_OT_weight_paint(struct wmOperatorType *ot);
 void PAINT_OT_weight_set(struct wmOperatorType *ot);
 void PAINT_OT_weight_from_bones(struct wmOperatorType *ot);
 
-void PAINT_OT_vertex_paint_radial_control(struct wmOperatorType *ot);
 void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
 void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
 
@@ -96,12 +94,10 @@ unsigned int vpaint_get_current_col(struct VPaint *vp);
 int image_texture_paint_poll(struct bContext *C);
 
 void PAINT_OT_image_paint(struct wmOperatorType *ot);
-void PAINT_OT_image_paint_radial_control(struct wmOperatorType *ot);
 void PAINT_OT_grab_clone(struct wmOperatorType *ot);
 void PAINT_OT_sample_color(struct wmOperatorType *ot);
 void PAINT_OT_clone_cursor_set(struct wmOperatorType *ot);
 void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot);
-void PAINT_OT_texture_paint_radial_control(struct wmOperatorType *ot);
 void PAINT_OT_project_image(struct wmOperatorType *ot);
 void PAINT_OT_image_from_view(struct wmOperatorType *ot);
 
index 9a1de939067b2ff42be25f1f28fc320e2421b27d..e4a21b1f1a7e0eedc5b0964a28088d2607c27127 100644 (file)
  *  \ingroup edsculpt
  */
 
+#include "MEM_guardedalloc.h"
 
+#include <stdlib.h>
+#include "BLI_string.h"
 #include "BLI_utildefines.h"
 
 #include "DNA_object_types.h"
@@ -355,9 +358,7 @@ void ED_operatortypes_paint(void)
 
        /* image */
        WM_operatortype_append(PAINT_OT_texture_paint_toggle);
-       WM_operatortype_append(PAINT_OT_texture_paint_radial_control);
        WM_operatortype_append(PAINT_OT_image_paint);
-       WM_operatortype_append(PAINT_OT_image_paint_radial_control);
        WM_operatortype_append(PAINT_OT_sample_color);
        WM_operatortype_append(PAINT_OT_grab_clone);
        WM_operatortype_append(PAINT_OT_clone_cursor_set);
@@ -366,13 +367,11 @@ void ED_operatortypes_paint(void)
 
        /* weight */
        WM_operatortype_append(PAINT_OT_weight_paint_toggle);
-       WM_operatortype_append(PAINT_OT_weight_paint_radial_control);
        WM_operatortype_append(PAINT_OT_weight_paint);
        WM_operatortype_append(PAINT_OT_weight_set);
        WM_operatortype_append(PAINT_OT_weight_from_bones);
 
        /* vertex */
-       WM_operatortype_append(PAINT_OT_vertex_paint_radial_control);
        WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
        WM_operatortype_append(PAINT_OT_vertex_paint);
        WM_operatortype_append(PAINT_OT_vertex_color_set);
@@ -464,6 +463,59 @@ static void ed_keymap_paint_brush_size(wmKeyMap *keymap, const char *UNUSED(path
        RNA_float_set(kmi->ptr, "scalar", 10.0/9.0); // 1.1111....
 }
 
+typedef enum {
+       RC_COLOR = 1,
+       RC_ROTATION = 2,
+       RC_ZOOM = 4,
+} RCFlags;
+
+static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path,
+                             const char *output_name, const char *input_name)
+{
+       char *path;
+
+       path = BLI_sprintfN("%s.%s", brush_path, input_name);
+       RNA_string_set(ptr, output_name, path);
+       MEM_freeN(path);
+}
+
+static void set_brush_rc_props(PointerRNA *ptr, const char *paint,
+                              const char *prop, RCFlags flags)
+{
+       char *brush_path;
+
+       brush_path = BLI_sprintfN("tool_settings.%s.brush", paint);
+
+       set_brush_rc_path(ptr, brush_path, "data_path", prop);
+       set_brush_rc_path(ptr, brush_path, "color_path", "cursor_color_add");
+       set_brush_rc_path(ptr, brush_path, "rotation_path", "texture_slot.angle");
+       RNA_string_set(ptr, "image_id", brush_path);
+
+       if(flags & RC_COLOR)
+               set_brush_rc_path(ptr, brush_path, "fill_color_path", "color");
+       if(flags & RC_ZOOM)
+               RNA_string_set(ptr, "zoom_path", "space_data.zoom");
+
+       MEM_freeN(brush_path);
+}
+
+static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *paint,
+                                                RCFlags flags)
+{
+       wmKeyMapItem *kmi;
+
+       kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
+       set_brush_rc_props(kmi->ptr, paint, "size", flags);
+
+       kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
+       set_brush_rc_props(kmi->ptr, paint, "strength", flags);
+
+       if(flags & RC_ROTATION) {
+               kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0);
+               set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", flags);
+       }
+}
+
 void ED_keymap_paint(wmKeyConfig *keyconf)
 {
        wmKeyMap *keymap;
@@ -474,10 +526,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
        keymap= WM_keymap_find(keyconf, "Sculpt", 0, 0);
        keymap->poll= sculpt_poll;
 
-       RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, 0, 0)->ptr,        "mode", WM_RADIALCONTROL_SIZE);
-       RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
-       RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0)->ptr,  "mode", WM_RADIALCONTROL_ANGLE);
-
        RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0,        0)->ptr, "mode", BRUSH_STROKE_NORMAL);
        RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_CTRL,  0)->ptr, "mode", BRUSH_STROKE_INVERT);
        RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", BRUSH_STROKE_SMOOTH);
@@ -496,6 +544,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
 
        ed_keymap_paint_brush_switch(keymap, "sculpt");
        ed_keymap_paint_brush_size(keymap, "tool_settings.sculpt.brush.size");
+       ed_keymap_paint_brush_radial_control(keymap, "sculpt", RC_ROTATION);
 
        RNA_enum_set(WM_keymap_add_item(keymap, "BRUSH_OT_sculpt_tool_set", DKEY, KM_PRESS, 0, 0)->ptr, "tool", SCULPT_TOOL_DRAW);
        RNA_enum_set(WM_keymap_add_item(keymap, "BRUSH_OT_sculpt_tool_set", SKEY, KM_PRESS, 0, 0)->ptr, "tool", SCULPT_TOOL_SMOOTH);
@@ -521,8 +570,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
        keymap= WM_keymap_find(keyconf, "Vertex Paint", 0, 0);
        keymap->poll= vertex_paint_mode_poll;
 
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
        WM_keymap_verify_item(keymap, "PAINT_OT_vertex_paint", LEFTMOUSE, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0);
 
@@ -531,6 +578,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
 
        ed_keymap_paint_brush_switch(keymap, "vertex_paint");
        ed_keymap_paint_brush_size(keymap, "tool_settings.vertex_paint.brush.size");
+       ed_keymap_paint_brush_radial_control(keymap, "vertex_paint", RC_COLOR);
 
        kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */
        RNA_string_set(kmi->ptr, "data_path", "vertex_paint_object.data.use_paint_mask");
@@ -539,9 +587,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
        keymap= WM_keymap_find(keyconf, "Weight Paint", 0, 0);
        keymap->poll= weight_paint_mode_poll;
 
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
-
        WM_keymap_verify_item(keymap, "PAINT_OT_weight_paint", LEFTMOUSE, KM_PRESS, 0, 0);
 
        WM_keymap_add_item(keymap,
@@ -549,6 +594,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
 
        ed_keymap_paint_brush_switch(keymap, "weight_paint");
        ed_keymap_paint_brush_size(keymap, "tool_settings.weight_paint.brush.size");
+       ed_keymap_paint_brush_radial_control(keymap, "weight_paint", 0);
 
        kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */
        RNA_string_set(kmi->ptr, "data_path", "weight_paint_object.data.use_paint_mask");
@@ -559,12 +605,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
        keymap= WM_keymap_find(keyconf, "Image Paint", 0, 0);
        keymap->poll= image_texture_paint_poll;
 
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
-
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
-       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
-
        WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0);
@@ -572,6 +612,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
 
        ed_keymap_paint_brush_switch(keymap, "image_paint");
        ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size");
+       ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR|RC_ZOOM);
 
        kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */
        RNA_string_set(kmi->ptr, "data_path", "image_paint_object.data.use_paint_mask");
index 19c726616daa031b7c31733acd2b6532f687448a..90cfdda78a872ae7fda039f6c40ef7ea51de2282 100644 (file)
@@ -1147,110 +1147,6 @@ void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
        
 }
 
-/* ************ paint radial controls *************/
-
-static int vpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       Paint *p = paint_get_active(CTX_data_scene(C));
-       Brush *brush = paint_brush(p);
-       float col[4];
-       
-       WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor);
-       p->paint_cursor = NULL;
-       brush_radial_control_invoke(op, brush, 1);
-
-       copy_v3_v3(col, brush->add_col);
-       col[3]= 0.5f;
-       RNA_float_set_array(op->ptr, "color", col);
-
-       return WM_radial_control_invoke(C, op, event);
-}
-
-static int vpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       int ret = WM_radial_control_modal(C, op, event);
-       if(ret != OPERATOR_RUNNING_MODAL)
-               paint_cursor_start(C, vertex_paint_poll);
-       return ret;
-}
-
-static int vpaint_radial_control_exec(bContext *C, wmOperator *op)
-{
-       Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->vpaint->paint);
-       int ret = brush_radial_control_exec(op, brush, 1);
-       
-       WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
-       
-       return ret;
-}
-
-static int wpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       Paint *p = paint_get_active(CTX_data_scene(C));
-       Brush *brush = paint_brush(p);
-       float col[4];
-       
-       WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor);
-       p->paint_cursor = NULL;
-       brush_radial_control_invoke(op, brush, 1);
-
-       copy_v3_v3(col, brush->add_col);
-       col[3]= 0.5f;
-       RNA_float_set_array(op->ptr, "color", col);
-
-       return WM_radial_control_invoke(C, op, event);
-}
-
-static int wpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       int ret = WM_radial_control_modal(C, op, event);
-       if(ret != OPERATOR_RUNNING_MODAL)
-               paint_cursor_start(C, weight_paint_poll);
-       return ret;
-}
-
-static int wpaint_radial_control_exec(bContext *C, wmOperator *op)
-{
-       Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->wpaint->paint);
-       int ret = brush_radial_control_exec(op, brush, 1);
-       
-       WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
-       
-       return ret;
-}
-
-void PAINT_OT_weight_paint_radial_control(wmOperatorType *ot)
-{
-       WM_OT_radial_control_partial(ot);
-
-       ot->name= "Weight Paint Radial Control";
-       ot->idname= "PAINT_OT_weight_paint_radial_control";
-
-       ot->invoke= wpaint_radial_control_invoke;
-       ot->modal= wpaint_radial_control_modal;
-       ot->exec= wpaint_radial_control_exec;
-       ot->poll= weight_paint_poll;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-}
-
-void PAINT_OT_vertex_paint_radial_control(wmOperatorType *ot)
-{
-       WM_OT_radial_control_partial(ot);
-
-       ot->name= "Vertex Paint Radial Control";
-       ot->idname= "PAINT_OT_vertex_paint_radial_control";
-
-       ot->invoke= vpaint_radial_control_invoke;
-       ot->modal= vpaint_radial_control_modal;
-       ot->exec= vpaint_radial_control_exec;
-       ot->poll= vertex_paint_poll;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-}
-
 /* ************ weight paint operator ********** */
 
 struct WPaintData {
index 7156b49c0264b49f1ff7b57f87eea86ad1b4829f..00607d660493a8ea93372a3a4d1029fafb7d83e9 100644 (file)
@@ -2816,65 +2816,6 @@ static const char *sculpt_tool_name(Sculpt *sd)
        }
 }
 
-/**** Radial control ****/
-static int sculpt_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       Paint *p = paint_get_active(CTX_data_scene(C));
-       Brush *brush = paint_brush(p);
-       float col[4], tex_col[4];
-
-       WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor);
-       p->paint_cursor = NULL;
-       brush_radial_control_invoke(op, brush, 1);
-
-       if((brush->flag & BRUSH_DIR_IN) && ELEM4(brush->sculpt_tool, SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY, SCULPT_TOOL_PINCH))
-               copy_v3_v3(col, brush->sub_col);
-       else
-               copy_v3_v3(col, brush->add_col);
-       col[3]= 0.5f;
-                                                                           
-       copy_v3_v3(tex_col, U.sculpt_paint_overlay_col);
-       tex_col[3]= (brush->texture_overlay_alpha / 100.0f);
-
-       RNA_float_set_array(op->ptr, "color", col);
-       RNA_float_set_array(op->ptr, "texture_color", tex_col);
-
-       return WM_radial_control_invoke(C, op, event);
-}
-
-static int sculpt_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       int ret = WM_radial_control_modal(C, op, event);
-       if(ret != OPERATOR_RUNNING_MODAL)
-               paint_cursor_start(C, sculpt_poll);
-       return ret;
-}
-
-static int sculpt_radial_control_exec(bContext *C, wmOperator *op)
-{
-       Brush *brush = paint_brush(&CTX_data_tool_settings(C)->sculpt->paint);
-       int ret = brush_radial_control_exec(op, brush, 1);
-
-       WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
-
-       return ret;
-}
-
-static void SCULPT_OT_radial_control(wmOperatorType *ot)
-{
-       WM_OT_radial_control_partial(ot);
-
-       ot->name= "Sculpt Radial Control";
-       ot->idname= "SCULPT_OT_radial_control";
-
-       ot->invoke= sculpt_radial_control_invoke;
-       ot->modal= sculpt_radial_control_modal;
-       ot->exec= sculpt_radial_control_exec;
-       ot->poll= sculpt_poll;
-
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-}
-
 /**** Operator for applying a stroke (various attributes including mouse path)
          using the current brush. ****/
 
@@ -3758,7 +3699,6 @@ static void SCULPT_OT_sculptmode_toggle(wmOperatorType *ot)
 
 void ED_operatortypes_sculpt(void)
 {
-       WM_operatortype_append(SCULPT_OT_radial_control);
        WM_operatortype_append(SCULPT_OT_brush_stroke);
        WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
        WM_operatortype_append(SCULPT_OT_set_persistent_base);
index 3072c2c343006d9b9aa8b5594b86209368869c9f..31e59f18626a61a57fdb65d7e677d8239dc348ad 100644 (file)
@@ -316,10 +316,4 @@ typedef struct wmOperator {
 /* wmOperator flag */
 #define OP_GRAB_POINTER                        1
 
-typedef enum wmRadialControlMode {
-       WM_RADIALCONTROL_SIZE,
-       WM_RADIALCONTROL_STRENGTH,
-       WM_RADIALCONTROL_ANGLE
-} wmRadialControlMode;
-
 #endif /* DNA_WINDOWMANAGER_TYPES_H */
index ce018fdfd6ef7fd8e90618c8a9af5c858d6a5426..da536f95cbae3a39660fc2192852dbb56200b5e5 100644 (file)
@@ -481,12 +481,12 @@ static void rna_def_particle_edit(BlenderRNA *brna)
        RNA_def_struct_sdna(srna, "ParticleBrushData");
        RNA_def_struct_ui_text(srna, "Particle Brush", "Particle editing brush");
 
-       prop= RNA_def_property(srna, "size", PROP_INT, PROP_NONE);
+       prop= RNA_def_property(srna, "size", PROP_INT, PROP_DISTANCE);
        RNA_def_property_range(prop, 1, SHRT_MAX);
        RNA_def_property_ui_range(prop, 1, 100, 10, 3);
        RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels");
 
-       prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
        RNA_def_property_range(prop, 0.001, 1.0);
        RNA_def_property_ui_text(prop, "Strength", "Brush strength");
 
index 59824d6a7527d25bb5b9e4fd1df39447c4cc3fa8..5281e152d543a2873d19112fc05fe60dc137e255 100644 (file)
@@ -508,6 +508,27 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *C, P
        return item;
 }
 
+static void rna_SpaceImageEditor_zoom_get(PointerRNA *ptr, float *values)
+{
+       SpaceImage *sima= (SpaceImage*)ptr->data;
+       ScrArea *sa;
+       ARegion *ar;
+
+       values[0] = values[1] = 1;
+
+       sa = rna_area_from_space(ptr);
+       if(!sa) return;
+       
+       /* find aregion */
+       for(ar=sa->regionbase.first; ar; ar=ar->next) {
+               if(ar->regiontype == RGN_TYPE_WINDOW)
+                       break;
+       }
+       if(!ar) return;
+
+       ED_space_image_zoom(sima, ar, &values[0], &values[1]);
+}
+
 static void rna_SpaceImageEditor_cursor_location_get(PointerRNA *ptr, float *values)
 {
        SpaceImage *sima= (SpaceImage*)ptr->data;
@@ -1556,6 +1577,12 @@ static void rna_def_space_image(BlenderRNA *brna)
        RNA_def_property_pointer_sdna(prop, NULL, "sample_line_hist");
        RNA_def_property_struct_type(prop, "Histogram");
        RNA_def_property_ui_text(prop, "Line sample", "Sampled colors along line");
+
+       prop= RNA_def_property(srna, "zoom", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_array(prop, 2);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_float_funcs(prop, "rna_SpaceImageEditor_zoom_get", NULL, NULL);
+       RNA_def_property_ui_text(prop, "Zoom", "Zoom factor");
        
        /* image draw */
        prop= RNA_def_property(srna, "show_repeat", PROP_BOOLEAN, PROP_NONE);
index 1b4fff8cd13a8ae03ceeb9e3a942eb1b195b570c..58645f48787992cdd372f4448d4b9b8b1ff49521 100644 (file)
@@ -293,12 +293,6 @@ struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int
 void           WM_gesture_end(struct bContext *C, struct wmGesture *gesture);
 void           WM_gestures_remove(struct bContext *C);
 
-                       /* radial control operator */
-int                    WM_radial_control_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int                    WM_radial_control_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-void           WM_OT_radial_control_partial(struct wmOperatorType *ot);
-void           WM_radial_control_string(struct wmOperator *op, char str[], int maxlen);
-
                        /* fileselecting support */
 void           WM_event_add_fileselect(struct bContext *C, struct wmOperator *op);
 void           WM_event_fileselect_event(struct bContext *C, void *ophandle, int eventval);
index d32a26549e7bcc104278c9f89e8dbfcc8d1a5bcc..fa693752ff7a17d4de3e18b6b7a20695da18a865 100644 (file)
@@ -61,6 +61,7 @@
 #include "BLO_readfile.h"
 
 #include "BKE_blender.h"
+#include "BKE_brush.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
 #include "BKE_idprop.h"
@@ -2674,272 +2675,465 @@ void WM_OT_straightline_gesture(wmOperatorType *ot)
 
 static const int WM_RADIAL_CONTROL_DISPLAY_SIZE = 200;
 
-typedef struct wmRadialControl {
-       int mode;
-       float initial_value, value, max_value;
-       float col[4], tex_col[4];
+typedef struct {
+       PropertyType type;
+       PropertySubType subtype;
+       PointerRNA ptr, col_ptr, fill_col_ptr, rot_ptr, zoom_ptr, image_id_ptr;
+       PropertyRNA *prop, *col_prop, *fill_col_prop, *rot_prop, *zoom_prop;
+       StructRNA *image_id_srna;
+       float initial_value, current_value, min_value, max_value;
        int initial_mouse[2];
+       unsigned int gltex;
+       ListBase orig_paintcursors;
        void *cursor;
-       GLuint tex;
-} wmRadialControl;
+} RadialControl;
 
-static void wm_radial_control_paint(bContext *C, int x, int y, void *customdata)
+static void radial_control_set_initial_mouse(RadialControl *rc, wmEvent *event)
 {
-       wmRadialControl *rc = (wmRadialControl*)customdata;
-       ARegion *ar = CTX_wm_region(C);
-       float r1=0.0f, r2=0.0f, r3=0.0f, angle=0.0f;
+       float d[2] = {0, 0};
+       float zoom[2] = {1, 1};
 
-       // int hit = 0;
-       
-       if(rc->mode == WM_RADIALCONTROL_STRENGTH)
-               rc->tex_col[3]= (rc->value + 0.5f);
+       rc->initial_mouse[0]= event->x;
+       rc->initial_mouse[1]= event->y;
 
-       if(rc->mode == WM_RADIALCONTROL_SIZE) {
-               r1= rc->value;
-               r2= rc->initial_value;
-               r3= r1;
-       } else if(rc->mode == WM_RADIALCONTROL_STRENGTH) {
-               r1= (1 - rc->value) * WM_RADIAL_CONTROL_DISPLAY_SIZE;
-               r2= r3= (float)WM_RADIAL_CONTROL_DISPLAY_SIZE;
-       } else if(rc->mode == WM_RADIALCONTROL_ANGLE) {
-               r1= r2= r3= (float)WM_RADIAL_CONTROL_DISPLAY_SIZE;
-               angle = rc->value;
+       switch(rc->subtype) {
+       case PROP_DISTANCE:
+               d[0] = rc->initial_value;
+               break;
+       case PROP_FACTOR:
+               d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * (1 - rc->initial_value);
+               break;
+       case PROP_ANGLE:
+               d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(rc->initial_value);
+               d[1] = WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(rc->initial_value);
+               break;
+       default:
+               return;
        }
 
-       /* Keep cursor in the original place */
-       x = rc->initial_mouse[0] - ar->winrct.xmin;
-       y = rc->initial_mouse[1] - ar->winrct.ymin;
+       if(rc->zoom_prop) {
+               RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+               d[0] *= zoom[0];
+               d[1] *= zoom[1];
+       }
 
-       glTranslatef((float)x, (float)y, 0.0f);
+       rc->initial_mouse[0]-= d[0];
+       rc->initial_mouse[1]-= d[1];
+}
 
-       glEnable(GL_BLEND);
+static void radial_control_set_tex(RadialControl *rc)
+{
+       ImBuf *ibuf;
 
-       if(rc->mode == WM_RADIALCONTROL_ANGLE) {
-               glRotatef(angle, 0, 0, 1);
+       switch(RNA_type_to_ID_code(rc->image_id_ptr.type)) {
+       case ID_BR:
+               if((ibuf = brush_gen_radial_control_imbuf(rc->image_id_ptr.data))) {
+                       glGenTextures(1, &rc->gltex);
+                       glBindTexture(GL_TEXTURE_2D, rc->gltex);
+                       glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ibuf->x, ibuf->y, 0,
+                                    GL_ALPHA, GL_FLOAT, ibuf->rect_float);
+                       MEM_freeN(ibuf->rect_float);
+                       MEM_freeN(ibuf);
+               }
+               break;
+       default:
+               break;
        }
+}
+
+static void radial_control_paint_tex(RadialControl *rc, float radius, float alpha)
+{
+       float col[3] = {0, 0, 0};
+       float rot;
+
+       /* set fill color */
+       if(rc->fill_col_prop)
+               RNA_property_float_get_array(&rc->fill_col_ptr, rc->fill_col_prop, col);
+       glColor4f(col[0], col[1], col[2], alpha);
 
-       if (rc->tex) {
-               glBindTexture(GL_TEXTURE_2D, rc->tex);
+       if(rc->gltex) {
+               glBindTexture(GL_TEXTURE_2D, rc->gltex);
 
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
+               /* set up rotation if available */
+               if(rc->rot_prop) {
+                       rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop);
+                       glPushMatrix();
+                       glRotatef(RAD2DEGF(rot), 0, 0, 1);
+               }
+
+               /* draw textured quad */
                glEnable(GL_TEXTURE_2D);
                glBegin(GL_QUADS);
-               glColor4fv(rc->tex_col);
                glTexCoord2f(0,0);
-               glVertex2f(-r3, -r3);
+               glVertex2f(-radius, -radius);
                glTexCoord2f(1,0);
-               glVertex2f(r3, -r3);
+               glVertex2f(radius, -radius);
                glTexCoord2f(1,1);
-               glVertex2f(r3, r3);
+               glVertex2f(radius, radius);
                glTexCoord2f(0,1);
-               glVertex2f(-r3, r3);
+               glVertex2f(-radius, radius);
                glEnd();
                glDisable(GL_TEXTURE_2D);
+
+               /* undo rotation */
+               if(rc->rot_prop)
+                       glPopMatrix();
        }
+       else {
+               /* flat color if no texture available */
+               glutil_draw_filled_arc(0, M_PI * 2, radius, 40);
+       }
+}
+
+static void radial_control_paint_cursor(bContext *C, int x, int y, void *customdata)
+{
+       RadialControl *rc = customdata;
+       ARegion *ar = CTX_wm_region(C);
+       float r1=0.0f, r2=0.0f, tex_radius, alpha;
+       float zoom[2], col[3] = {1, 1, 1};
 
-       if(rc->mode == WM_RADIALCONTROL_ANGLE) {
-               glColor4fv(rc->col);
-               glEnable(GL_LINE_SMOOTH);
-               glRotatef(-angle, 0, 0, 1);
+       switch(rc->subtype) {
+       case PROP_DISTANCE:
+               r1= rc->current_value;
+               r2= rc->initial_value;
+               tex_radius= r1;
+               alpha = 0.75;
+               break;
+       case PROP_FACTOR:
+               r1= (1 - rc->current_value) * WM_RADIAL_CONTROL_DISPLAY_SIZE;
+               r2= tex_radius= WM_RADIAL_CONTROL_DISPLAY_SIZE;
+               alpha = rc->current_value / 2 + 0.5;
+               break;
+       case PROP_ANGLE:
+               r1= r2= tex_radius= WM_RADIAL_CONTROL_DISPLAY_SIZE;
+               alpha = 0.75;
+               break;
+       default:
+               break;
+       }
+
+       /* Keep cursor in the original place */
+       x = rc->initial_mouse[0] - ar->winrct.xmin;
+       y = rc->initial_mouse[1] - ar->winrct.ymin;
+       glTranslatef((float)x, (float)y, 0.0f);
+
+       glEnable(GL_BLEND);
+       glEnable(GL_LINE_SMOOTH);
+
+       /* apply zoom if available */
+       if(rc->zoom_prop) {
+               RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+               glScalef(zoom[0], zoom[1], 1);
+       }
+
+       /* draw rotated texture */
+       radial_control_paint_tex(rc, tex_radius, alpha);
+
+       /* set line color */
+       if(rc->col_prop)
+               RNA_property_float_get_array(&rc->col_ptr, rc->col_prop, col);
+       glColor4f(col[0], col[1], col[2], 0.5);
+
+       if(rc->subtype == PROP_ANGLE) {
+               glPushMatrix();
+               /* draw original angle line */
+               glRotatef(RAD2DEGF(rc->initial_value), 0, 0, 1);
                fdrawline(0.0f, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
-               glRotatef(angle, 0, 0, 1);
+               /* draw new angle line */
+               glRotatef(RAD2DEGF(rc->current_value - rc->initial_value), 0, 0, 1);
                fdrawline(0.0f, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
-               glDisable(GL_LINE_SMOOTH);
+               glPopMatrix();
        }
 
-       glColor4fv(rc->col);
+       /* draw circles on top */
        glutil_draw_lined_arc(0.0, (float)(M_PI*2.0), r1, 40);
        glutil_draw_lined_arc(0.0, (float)(M_PI*2.0), r2, 40);
+
        glDisable(GL_BLEND);
+       glDisable(GL_LINE_SMOOTH);
 }
 
-int WM_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
+/* attempt to retrieve the rna pointer/property from an rna path;
+   returns 0 for failure, 1 for success, and also 1 if property is not
+   set */
+static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op,
+                                  const char *name, PointerRNA *r_ptr,
+                                  PropertyRNA **r_prop, int req_float,
+                                  int req_length, int allow_missing)
 {
-       wmRadialControl *rc = (wmRadialControl*)op->customdata;
-       int mode, initial_mouse[2], delta[2];
-       float dist;
-       double new_value = RNA_float_get(op->ptr, "new_value");
-       int ret = OPERATOR_RUNNING_MODAL;
-       // float initial_value = RNA_float_get(op->ptr, "initial_value");
+       PropertyRNA *unused_prop;
+       int len;
+       char *str;
 
-       mode = RNA_enum_get(op->ptr, "mode");
-       RNA_int_get_array(op->ptr, "initial_mouse", initial_mouse);
+       /* get an rna string path from the operator's properties */
+       if(!(str = RNA_string_get_alloc(op->ptr, name, NULL, 0)))
+               return 1;
 
-       switch(event->type) {
-       case MOUSEMOVE:
-               delta[0]= initial_mouse[0] - event->x;
-               delta[1]= initial_mouse[1] - event->y;
+       if(str[0] == '\0') {
+               MEM_freeN(str);
+               return 1;
+       }
 
-               //if (mode == WM_RADIALCONTROL_SIZE) 
-               //      delta[0]+= initial_value;
-               //else if(mode == WM_RADIALCONTROL_STRENGTH)
-               //      delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * (1 - initial_value);
-               //else if(mode == WM_RADIALCONTROL_ANGLE) {
-               //      delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(initial_value*M_PI/180.0f);
-               //      delta[1]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(initial_value*M_PI/180.0f);
-               //}
+       if(!r_prop)
+               r_prop = &unused_prop;
 
-               dist= sqrtf(delta[0]*delta[0]+delta[1]*delta[1]);
+       /* get rna from path */
+       if(!RNA_path_resolve(ctx_ptr, str, r_ptr, r_prop)) {
+               MEM_freeN(str);
+               if(allow_missing)
+                       return 1;
+               else {
+                       BKE_reportf(op->reports, RPT_ERROR, "Couldn't resolve path %s", name);
+                       return 0;
+               }
+       }
 
-               if(mode == WM_RADIALCONTROL_SIZE)
-                       new_value = dist;
-               else if(mode == WM_RADIALCONTROL_STRENGTH) {
-                       new_value = 1 - dist / WM_RADIAL_CONTROL_DISPLAY_SIZE;
-               } else if(mode == WM_RADIALCONTROL_ANGLE)
-                       new_value = ((int)(atan2f(delta[1], delta[0]) * (float)(180.0 / M_PI)) + 180);
-               
-               if(event->ctrl) {
-                       if(mode == WM_RADIALCONTROL_STRENGTH)
-                               new_value = ((int)ceilf(new_value * 10.f) * 10.0f) / 100.f;
-                       else
-                               new_value = ((int)new_value + 5) / 10*10;
+       /* if property is expected to be a float, check its type */
+       if(req_float) {
+               if(!(*r_prop) || (RNA_property_type(*r_prop) != PROP_FLOAT)) {
+                       MEM_freeN(str);
+                       BKE_reportf(op->reports, RPT_ERROR,
+                                   "Property from path %s is not a float", name);
+                       return 0;
                }
-               
-               break;
-       case ESCKEY:
-       case RIGHTMOUSE:
-               ret = OPERATOR_CANCELLED;
-               break;
-       case LEFTMOUSE:
-       case PADENTER:
-               op->type->exec(C, op);
-               ret = OPERATOR_FINISHED;
-               break;
+       }
+       
+       /* check property's array length */
+       if(*r_prop && (len = RNA_property_array_length(r_ptr, *r_prop)) != req_length) {
+               MEM_freeN(str);
+               BKE_reportf(op->reports, RPT_ERROR,
+                           "Property from path %s has length %d instead of %d",
+                           name, len, req_length);
+               return 0;
        }
 
-       /* Clamp */
-       if(new_value > rc->max_value)
-               new_value = rc->max_value;
-       else if(new_value < 0)
-               new_value = 0;
+       /* success */
+       MEM_freeN(str);
+       return 1;
+}
 
-       /* Update paint data */
-       rc->value = (float)new_value;
+/* initialize the rna pointers and properties using rna paths */
+static int radial_control_get_properties(bContext *C, wmOperator *op)
+{
+       RadialControl *rc = op->customdata;
+       PointerRNA ctx_ptr;
 
-       RNA_float_set(op->ptr, "new_value", rc->value);
+       RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
 
-       if(ret != OPERATOR_RUNNING_MODAL) {
-               WM_paint_cursor_end(CTX_wm_manager(C), rc->cursor);
-               MEM_freeN(rc);
-       }
-       
-       ED_region_tag_redraw(CTX_wm_region(C));
+       if(!radial_control_get_path(&ctx_ptr, op, "data_path", &rc->ptr, &rc->prop, 0, 0, 0))
+               return 0;
 
-       //if (ret != OPERATOR_RUNNING_MODAL) {
-       //      wmWindow *win = CTX_wm_window(C);
-       //      WM_cursor_restore(win);
-       //}
+       /* data path is required */
+       if(!rc->prop)
+               return 0;
+       
+       if(!radial_control_get_path(&ctx_ptr, op, "rotation_path", &rc->rot_ptr, &rc->rot_prop, 1, 0, 0))
+               return 0;
+       if(!radial_control_get_path(&ctx_ptr, op, "color_path", &rc->col_ptr, &rc->col_prop, 1, 3, 0))
+               return 0;
+       if(!radial_control_get_path(&ctx_ptr, op, "fill_color_path", &rc->fill_col_ptr, &rc->fill_col_prop, 1, 3, 0))
+               return 0;
+       
+       /* slightly ugly; allow this property to not resolve
+          correctly. needed because 3d texture paint shares the same
+          keymap as 2d image paint */
+       if(!radial_control_get_path(&ctx_ptr, op, "zoom_path", &rc->zoom_ptr, &rc->zoom_prop, 1, 2, 1))
+               return 0;
+       
+       if(!radial_control_get_path(&ctx_ptr, op, "image_id", &rc->image_id_ptr, NULL, 0, 0, 0))
+               return 0;
+       else if(rc->image_id_ptr.data) {
+               /* extra check, pointer must be to an ID */
+               if(!RNA_struct_is_ID(rc->image_id_ptr.type)) {
+                       BKE_report(op->reports, RPT_ERROR,
+                                  "Pointer from path image_id is not an ID");
+                       return 0;
+               }
+       }
 
-       return ret;
+       return 1;
 }
 
-/* Expects the operator customdata to be an ImBuf (or NULL) */
-int WM_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       wmRadialControl *rc = MEM_callocN(sizeof(wmRadialControl), "radial control");
-       // wmWindow *win = CTX_wm_window(C);
-       int mode = RNA_enum_get(op->ptr, "mode");
-       float initial_value = RNA_float_get(op->ptr, "initial_value");
-       //float initial_size = RNA_float_get(op->ptr, "initial_size");
-       int mouse[2];
+       wmWindowManager *wm;
+       RadialControl *rc;
+       int min_value_int, max_value_int, step_int;
+       float step_float, precision;
 
-       mouse[0]= event->x;
-       mouse[1]= event->y;
-
-       //if (initial_size == 0)
-       //      initial_size = WM_RADIAL_CONTROL_DISPLAY_SIZE;
+       if(!(op->customdata = rc = MEM_callocN(sizeof(RadialControl), "RadialControl")))
+               return OPERATOR_CANCELLED;
 
-       if(mode == WM_RADIALCONTROL_SIZE) {
-               rc->max_value = 200;
-               mouse[0]-= (int)initial_value;
-       }
-       else if(mode == WM_RADIALCONTROL_STRENGTH) {
-               rc->max_value = 1;
-               mouse[0]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * (1.0f - initial_value));
-       }
-       else if(mode == WM_RADIALCONTROL_ANGLE) {
-               rc->max_value = 360;
-               mouse[0]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(initial_value));
-               mouse[1]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(initial_value));
-               initial_value *= 180.0f/(float)M_PI;
+       if(!radial_control_get_properties(C, op)) {
+               MEM_freeN(rc);
+               return OPERATOR_CANCELLED;
        }
 
-       if(op->customdata) {
-               ImBuf *im = (ImBuf*)op->customdata;
-               /* Build GL texture */
-               glGenTextures(1, &rc->tex);
-               glBindTexture(GL_TEXTURE_2D, rc->tex);
-               glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, im->x, im->y, 0, GL_ALPHA, GL_FLOAT, im->rect_float);
-               MEM_freeN(im->rect_float);
-               MEM_freeN(im);
+       /* get type, initial, min, and max values of the property */
+       switch((rc->type = RNA_property_type(rc->prop))) {
+       case PROP_INT:
+               rc->initial_value = RNA_property_int_get(&rc->ptr, rc->prop);
+               RNA_property_int_ui_range(&rc->ptr, rc->prop, &min_value_int,
+                                         &max_value_int, &step_int);
+               rc->min_value = min_value_int;
+               rc->max_value = max_value_int;
+               break;
+       case PROP_FLOAT:
+               rc->initial_value = RNA_property_float_get(&rc->ptr, rc->prop);
+               RNA_property_float_ui_range(&rc->ptr, rc->prop, &rc->min_value,
+                                           &rc->max_value, &step_float, &precision);
+               break;
+       default:
+               BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float");
+               MEM_freeN(rc);
+               return OPERATOR_CANCELLED;
        }
 
-       RNA_float_get_array(op->ptr, "color", rc->col);
-       RNA_float_get_array(op->ptr, "texture_color", rc->tex_col);
-
-       RNA_int_set_array(op->ptr, "initial_mouse", mouse);
-       RNA_float_set(op->ptr, "new_value", initial_value);
+       /* get subtype of property */
+       rc->subtype = RNA_property_subtype(rc->prop);
+       if(!ELEM3(rc->subtype, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE)) {
+               BKE_report(op->reports, RPT_ERROR, "Property must be a distance, a factor, or an angle");
+               MEM_freeN(rc);
+               return OPERATOR_CANCELLED;
+       }
                
-       op->customdata = rc;
-       rc->mode = mode;
-       rc->initial_value = initial_value;
-       rc->initial_mouse[0] = mouse[0];
-       rc->initial_mouse[1] = mouse[1];
-       rc->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), op->type->poll,
-                                                 wm_radial_control_paint, op->customdata);
+       rc->current_value = rc->initial_value;
+       radial_control_set_initial_mouse(rc, event);
+       radial_control_set_tex(rc);
 
-       //WM_cursor_modal(win, CURSOR_NONE);
+       /* temporarily disable other paint cursors */
+       wm = CTX_wm_manager(C);
+       rc->orig_paintcursors = wm->paintcursors;
+       wm->paintcursors.first = wm->paintcursors.last = NULL;
+
+       /* add radial control paint cursor */
+       rc->cursor = WM_paint_cursor_activate(wm, op->type->poll,
+                                             radial_control_paint_cursor, rc);
 
-       /* add modal handler */
        WM_event_add_modal_handler(C, op);
-       
-       WM_radial_control_modal(C, op, event);
-       
+
        return OPERATOR_RUNNING_MODAL;
 }
 
-/* Gets a descriptive string of the operation */
-void WM_radial_control_string(wmOperator *op, char str[], int maxlen)
+static void radial_control_set_value(RadialControl *rc, float val)
 {
-       int mode = RNA_enum_get(op->ptr, "mode");
-       float v = RNA_float_get(op->ptr, "new_value");
-
-       if(mode == WM_RADIALCONTROL_SIZE)
-               BLI_snprintf(str, maxlen, "Size: %d", (int)v);
-       else if(mode == WM_RADIALCONTROL_STRENGTH)
-               BLI_snprintf(str, maxlen, "Strength: %d", (int)v);
-       else if(mode == WM_RADIALCONTROL_ANGLE)
-               BLI_snprintf(str, maxlen, "Angle: %d", (int)(v * 180.0f/(float)M_PI));
+       switch(rc->type) {
+       case PROP_INT:
+               RNA_property_int_set(&rc->ptr, rc->prop, val);
+               break;
+       case PROP_FLOAT:
+               RNA_property_float_set(&rc->ptr, rc->prop, val);
+               break;
+       default:
+               break;
+       }
 }
 
-/** Important: this doesn't define an actual operator, it
-       just sets up the common parts of the radial control op. **/
-void WM_OT_radial_control_partial(wmOperatorType *ot)
+static int radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
-       static EnumPropertyItem radial_mode_items[] = {
-               {WM_RADIALCONTROL_SIZE, "SIZE", 0, "Size", ""},
-               {WM_RADIALCONTROL_STRENGTH, "STRENGTH", 0, "Strength", ""},
-               {WM_RADIALCONTROL_ANGLE, "ANGLE", 0, "Angle", ""},
-               {0, NULL, 0, NULL, NULL}};
-       static float color[4] = {1.0f, 1.0f, 1.0f, 0.5f};
-       static float tex_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+       RadialControl *rc = op->customdata;
+       wmWindowManager *wm;
+       float new_value, dist, zoom[2];
+       float delta[2], snap, ret = OPERATOR_RUNNING_MODAL;
+
+       /* TODO: fix hardcoded events */
 
-       /* Should be set in custom invoke() */
-       RNA_def_float(ot->srna, "initial_value", 0, 0, FLT_MAX, "Initial Value", "", 0, FLT_MAX);
+       snap = event->ctrl;
 
-       /* Set internally, should be used in custom exec() to get final value */
-       RNA_def_float(ot->srna, "new_value", 0, 0, FLT_MAX, "New Value", "", 0, FLT_MAX);
+       switch(event->type) {
+       case MOUSEMOVE:
+               delta[0]= rc->initial_mouse[0] - event->x;
+               delta[1]= rc->initial_mouse[1] - event->y;
+
+               if(rc->zoom_prop) {
+                       RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+                       delta[0] /= zoom[0];
+                       delta[1] /= zoom[1];
+               }
+
+               dist= sqrt(delta[0]*delta[0]+delta[1]*delta[1]);
+
+               /* calculate new value and apply snapping  */
+               switch(rc->subtype) {
+               case PROP_DISTANCE:
+                       new_value = dist;
+                       if(snap) new_value = ((int)new_value + 5) / 10*10;
+                       break;
+               case PROP_FACTOR:
+                       new_value = 1 - dist / WM_RADIAL_CONTROL_DISPLAY_SIZE;
+                       if(snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
+                       break;
+               case PROP_ANGLE:
+                       new_value = atan2(delta[1], delta[0]) + M_PI;
+                       if(snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10*10);
+                       break;
+               default:
+                       break;
+               }
+
+               /* clamp and update */
+               CLAMP(new_value, rc->min_value, rc->max_value);
+               radial_control_set_value(rc, new_value);
+               rc->current_value = new_value;
+               break;
+
+       case ESCKEY:
+       case RIGHTMOUSE:
+               /* cancelled; restore original value */
+               radial_control_set_value(rc, rc->initial_value);
+               ret = OPERATOR_CANCELLED;
+               break;
+               
+       case LEFTMOUSE:
+       case PADENTER:
+               /* done; value already set */
+               ret = OPERATOR_FINISHED;
+               break;
+       }
+
+       ED_region_tag_redraw(CTX_wm_region(C));
+
+       if(ret != OPERATOR_RUNNING_MODAL) {
+               wm = CTX_wm_manager(C);
+
+               WM_paint_cursor_end(wm, rc->cursor);
+
+               /* restore original paint cursors */
+               wm->paintcursors = rc->orig_paintcursors;
+
+               /* not sure if this is a good notifier to use;
+                  intended purpose is to update the UI so that the
+                  new value is displayed in sliders/numfields */
+               WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+               glDeleteTextures(1, &rc->gltex);
+
+               MEM_freeN(rc);
+       }
+
+       return ret;
+}
+
+static void WM_OT_radial_control(wmOperatorType *ot)
+{
+       ot->name= "Radial Control";
+       ot->idname= "WM_OT_radial_control";
 
-       /* Should be set before calling operator */
-       RNA_def_enum(ot->srna, "mode", radial_mode_items, 0, "Mode", "");
+       ot->invoke= radial_control_invoke;
+       ot->modal= radial_control_modal;
 
-       /* Internal */
-       RNA_def_int_vector(ot->srna, "initial_mouse", 2, NULL, INT_MIN, INT_MAX, "Initial Mouse", "", INT_MIN, INT_MAX);
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
 
-       RNA_def_float_color(ot->srna, "color", 4, color, 0.0f, FLT_MAX, "Color", "Radial control color", 0.0f, 1.0f);
-       RNA_def_float_color(ot->srna, "texture_color", 4, tex_color, 0.0f, FLT_MAX, "Texture Color", "Radial control texture color", 0.0f, 1.0f);
+       /* all paths relative to the context */
+       RNA_def_string(ot->srna, "data_path", "", 0, "Data Path", "Path of property to be set by the radial control.");
+       RNA_def_string(ot->srna, "rotation_path", "", 0, "Rotation Path", "Path of property used to rotate the texture display.");
+       RNA_def_string(ot->srna, "color_path", "", 0, "Color Path", "Path of property used to set the color of the control.");
+       RNA_def_string(ot->srna, "fill_color_path", "", 0, "Fill Color Path", "Path of property used to set the fill color of the control.");
+       RNA_def_string(ot->srna, "zoom_path", "", 0, "Zoom Path", "Path of property used to set the zoom level for the control.");
+       RNA_def_string(ot->srna, "image_id", "", 0, "Image ID", "Path of ID that is used to generate an image for the control.");
 }
 
 /* ************************** timer for testing ***************** */
@@ -3133,6 +3327,7 @@ void wm_operatortype_init(void)
        WM_operatortype_append(WM_OT_splash);
        WM_operatortype_append(WM_OT_search_menu);
        WM_operatortype_append(WM_OT_call_menu);
+       WM_operatortype_append(WM_OT_radial_control);
 #if defined(WIN32)
        WM_operatortype_append(WM_OT_console_toggle);
 #endif
index 2f5d6702e3ec10e7e7f8160cf90a0915fdc0541a..7f1915b3bd0fb5b77de775b634e94754e2638e8d 100644 (file)
@@ -230,6 +230,7 @@ short ANIM_add_driver(struct ID *id, const char rna_path[], int array_index, sho
 short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag){return 0;}
 void ED_space_image_release_buffer(struct SpaceImage *sima, void *lock){}
 struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r){return (struct ImBuf *) NULL;}
+void ED_space_image_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy) {}
 char *ED_info_stats_string(struct Scene *scene){return (char *) NULL;}
 void ED_area_tag_redraw(struct ScrArea *sa){}
 void ED_area_tag_refresh(struct ScrArea *sa){}