Changeset View
Changeset View
Standalone View
Standalone View
source/blender/windowmanager/intern/wm_operators.c
| Context not available. | |||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "DNA_brush_types.h" | |||||
| #include "DNA_ID.h" | #include "DNA_ID.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_screen_types.h" | #include "DNA_screen_types.h" | ||||
| Context not available. | |||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| #include "BKE_paint.h" | |||||
| #include "BKE_report.h" | #include "BKE_report.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "BKE_screen.h" /* BKE_ST_MAXNAME */ | #include "BKE_screen.h" /* BKE_ST_MAXNAME */ | ||||
| #include "BKE_utildefines.h" | #include "BKE_utildefines.h" | ||||
| #include "BKE_unit.h" | |||||
| #include "BKE_idcode.h" | #include "BKE_idcode.h" | ||||
| Context not available. | |||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_util.h" | #include "ED_util.h" | ||||
| #include "ED_view3d.h" | #include "ED_view3d.h" | ||||
| #include "ED_numinput.h" | |||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "RNA_define.h" | #include "RNA_define.h" | ||||
psy-fi: Minor typo here | |||||
| Context not available. | |||||
| #define WM_RADIAL_CONTROL_DISPLAY_SIZE 200 | #define WM_RADIAL_CONTROL_DISPLAY_SIZE 200 | ||||
| #define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE 35 | #define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE 35 | ||||
| #define WM_RADIAL_CONTROL_DISPLAY_WIDTH (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) | #define WM_RADIAL_CONTROL_DISPLAY_WIDTH (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) | ||||
| #define WM_RADIAL_CONTROL_HEADER_LENGTH 180 | |||||
| #define WM_RADIAL_MAX_STR 6 | #define WM_RADIAL_MAX_STR 6 | ||||
| typedef struct { | typedef struct { | ||||
Not Done Inline ActionsI would use the property name instead of hardcoding those in. Same below. psy-fi: I would use the property name instead of hardcoding those in. Same below. | |||||
| Context not available. | |||||
| ListBase orig_paintcursors; | ListBase orig_paintcursors; | ||||
| bool use_secondary_tex; | bool use_secondary_tex; | ||||
| void *cursor; | void *cursor; | ||||
| NumInput num_input; | |||||
| } RadialControl; | } RadialControl; | ||||
| static void radial_control_update_header(wmOperator *op, bContext *C) | |||||
| { | |||||
| RadialControl *rc = op->customdata; | |||||
| char msg[WM_RADIAL_CONTROL_HEADER_LENGTH]; | |||||
| const char *propname; | |||||
| PointerRNA brush_ptr, tex_ptr; | |||||
| ScrArea *sa = CTX_wm_area(C); | |||||
| Scene *scene = CTX_data_scene(C); | |||||
| Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C)); | |||||
| RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mtex, &tex_ptr); | |||||
| RNA_id_pointer_create(&brush->id, &brush_ptr); | |||||
| switch (rc->subtype) { | |||||
| case PROP_NONE: | |||||
| case PROP_DISTANCE: | |||||
| case PROP_PIXEL: | |||||
| propname = RNA_property_ui_name(RNA_struct_find_property(&brush_ptr, "size")); | |||||
| break; | |||||
| case PROP_FACTOR: | |||||
| propname = RNA_property_ui_name(RNA_struct_find_property(&brush_ptr, "strength")); | |||||
| break; | |||||
| case PROP_ANGLE: | |||||
| propname = RNA_property_ui_name(RNA_struct_find_property(&tex_ptr, "angle")); | |||||
| break; | |||||
| default: /* this is a dummy case */ | |||||
| propname = ""; | |||||
| break; | |||||
| } | |||||
| if (sa && hasNumInput(&rc->num_input)) { | |||||
| char num_str[NUM_STR_REP_LEN]; | |||||
| outputNumInput(&rc->num_input, num_str, &scene->unit); | |||||
| BLI_snprintf(msg, WM_RADIAL_CONTROL_HEADER_LENGTH, "%s: %s", propname, num_str); | |||||
| ED_area_headerprint(sa, msg); | |||||
| } | |||||
| } | |||||
| static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event) | static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event) | ||||
| { | { | ||||
| float d[2] = {0, 0}; | float d[2] = {0, 0}; | ||||
Not Done Inline Actionsprobably "none" unit make sense better here psy-fi: probably "none" unit make sense better here | |||||
Not Done Inline ActionsCan I just write: rc->num_input.unit_sys = USER_UNIT_NONE ? Or is there another better way to do that? braffe: Can I just write: //rc->num_input.unit_sys = USER_UNIT_NONE// ? Or is there another better way… | |||||
| Context not available. | |||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| /* initialize numerical input */ | |||||
| initNumInput(&rc->num_input); | |||||
| rc->num_input.idx_max = 0; | |||||
| rc->num_input.val_flag[0] |= NUM_NO_NEGATIVE; | |||||
| rc->num_input.unit_sys = USER_UNIT_NONE; | |||||
| rc->num_input.unit_type[0] = B_UNIT_LENGTH; | |||||
| /* get subtype of property */ | /* get subtype of property */ | ||||
| rc->subtype = RNA_property_subtype(rc->prop); | rc->subtype = RNA_property_subtype(rc->prop); | ||||
| if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) { | if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) { | ||||
| Context not available. | |||||
| MEM_freeN(rc); | MEM_freeN(rc); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| rc->current_value = rc->initial_value; | rc->current_value = rc->initial_value; | ||||
| radial_control_set_initial_mouse(rc, event); | radial_control_set_initial_mouse(rc, event); | ||||
| radial_control_set_tex(rc); | radial_control_set_tex(rc); | ||||
| Context not available. | |||||
| { | { | ||||
| RadialControl *rc = op->customdata; | RadialControl *rc = op->customdata; | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| ScrArea *sa = CTX_wm_area(C); | |||||
| if (rc->dial) { | if (rc->dial) { | ||||
| MEM_freeN(rc->dial); | MEM_freeN(rc->dial); | ||||
| rc->dial = NULL; | rc->dial = NULL; | ||||
| } | } | ||||
| if (sa) { | |||||
| ED_area_headerprint(sa, NULL); | |||||
| } | |||||
| WM_paint_cursor_end(wm, rc->cursor); | WM_paint_cursor_end(wm, rc->cursor); | ||||
| Context not available. | |||||
| float delta[2], ret = OPERATOR_RUNNING_MODAL; | float delta[2], ret = OPERATOR_RUNNING_MODAL; | ||||
| bool snap; | bool snap; | ||||
| float angle_precision = 0.0f; | float angle_precision = 0.0f; | ||||
| const bool has_numInput = hasNumInput(&rc->num_input); | |||||
| bool handled = false; | |||||
| float numValue; | |||||
| /* TODO: fix hardcoded events */ | /* TODO: fix hardcoded events */ | ||||
| snap = event->ctrl != 0; | snap = event->ctrl != 0; | ||||
| switch (event->type) { | /* Modal numinput active, try to handle numeric inputs first... */ | ||||
| case MOUSEMOVE: | if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) { | ||||
| if (rc->slow_mode) { | handled = true; | ||||
| if (rc->subtype == PROP_ANGLE) { | applyNumInput(&rc->num_input, &numValue); | ||||
| float position[2] = {event->x, event->y}; | CLAMP(numValue, rc->min_value, rc->max_value); | ||||
| new_value = numValue; | |||||
| /* calculate the initial angle here first */ | |||||
| delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; | radial_control_set_value(rc, new_value); | ||||
| delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; | rc->current_value = new_value; | ||||
| radial_control_update_header(op, C); | |||||
| /* precision angle gets calculated from dial and gets added later */ | return OPERATOR_RUNNING_MODAL; | ||||
| angle_precision = -0.1f * BLI_dial_angle(rc->dial, position); | } | ||||
| } | else { | ||||
| else { | handled = false; | ||||
| delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; | switch (event->type) { | ||||
| delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; | case ESCKEY: | ||||
| case RIGHTMOUSE: | |||||
| if (rc->zoom_prop) { | /* canceled; restore original value */ | ||||
| RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); | radial_control_set_value(rc, rc->initial_value); | ||||
| delta[0] /= zoom[0]; | ret = OPERATOR_CANCELLED; | ||||
| delta[1] /= zoom[1]; | break; | ||||
| } | |||||
| case LEFTMOUSE: | |||||
| dist = len_v2(delta); | case PADENTER: | ||||
| case RETKEY: | |||||
| delta[0] = event->x - rc->slow_mouse[0]; | /* done; value already set */ | ||||
| delta[1] = event->y - rc->slow_mouse[1]; | RNA_property_update(C, &rc->ptr, rc->prop); | ||||
| ret = OPERATOR_FINISHED; | |||||
| if (rc->zoom_prop) { | break; | ||||
| delta[0] /= zoom[0]; | |||||
| delta[1] /= zoom[1]; | case MOUSEMOVE: | ||||
| } | if (!has_numInput) { | ||||
| if (rc->slow_mode) { | |||||
| dist = dist + 0.1f * (delta[0] + delta[1]); | if (rc->subtype == PROP_ANGLE) { | ||||
| } | float position[2] = {event->x, event->y}; | ||||
| } | |||||
| else { | /* calculate the initial angle here first */ | ||||
| delta[0] = rc->initial_mouse[0] - event->x; | delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; | ||||
| delta[1] = rc->initial_mouse[1] - event->y; | delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; | ||||
| if (rc->zoom_prop) { | /* precision angle gets calculated from dial and gets added later */ | ||||
| RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); | angle_precision = -0.1f * BLI_dial_angle(rc->dial, position); | ||||
| delta[0] /= zoom[0]; | } | ||||
| delta[1] /= zoom[1]; | else { | ||||
| } | delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0]; | ||||
| delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1]; | |||||
| dist = len_v2(delta); | |||||
| } | if (rc->zoom_prop) { | ||||
| RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); | |||||
| /* calculate new value and apply snapping */ | delta[0] /= zoom[0]; | ||||
| switch (rc->subtype) { | delta[1] /= zoom[1]; | ||||
| case PROP_NONE: | } | ||||
| case PROP_DISTANCE: | |||||
| case PROP_PIXEL: | dist = len_v2(delta); | ||||
| new_value = dist; | |||||
| if (snap) new_value = ((int)new_value + 5) / 10 * 10; | delta[0] = event->x - rc->slow_mouse[0]; | ||||
| break; | delta[1] = event->y - rc->slow_mouse[1]; | ||||
| case PROP_FACTOR: | |||||
| new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH; | if (rc->zoom_prop) { | ||||
| if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f; | delta[0] /= zoom[0]; | ||||
| break; | delta[1] /= zoom[1]; | ||||
| case PROP_ANGLE: | } | ||||
| new_value = atan2f(delta[1], delta[0]) + M_PI + angle_precision; | |||||
| new_value = fmod(new_value, 2.0f * (float)M_PI); | dist = dist + 0.1f * (delta[0] + delta[1]); | ||||
| if (new_value < 0.0f) | } | ||||
| new_value += 2.0f * (float)M_PI; | } | ||||
| if (snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10 * 10); | else { | ||||
| break; | delta[0] = rc->initial_mouse[0] - event->x; | ||||
| default: | delta[1] = rc->initial_mouse[1] - event->y; | ||||
| new_value = dist; /* dummy value, should this ever happen? - campbell */ | |||||
| break; | if (rc->zoom_prop) { | ||||
| } | RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); | ||||
| delta[0] /= zoom[0]; | |||||
| /* clamp and update */ | delta[1] /= zoom[1]; | ||||
| CLAMP(new_value, rc->min_value, rc->max_value); | } | ||||
| radial_control_set_value(rc, new_value); | |||||
| rc->current_value = new_value; | dist = len_v2(delta); | ||||
| break; | } | ||||
| case ESCKEY: | /* calculate new value and apply snapping */ | ||||
| case RIGHTMOUSE: | switch (rc->subtype) { | ||||
| /* canceled; restore original value */ | case PROP_NONE: | ||||
| radial_control_set_value(rc, rc->initial_value); | case PROP_DISTANCE: | ||||
| ret = OPERATOR_CANCELLED; | case PROP_PIXEL: | ||||
| break; | new_value = dist; | ||||
| if (snap) new_value = ((int)new_value + 5) / 10 * 10; | |||||
| case LEFTMOUSE: | break; | ||||
| case PADENTER: | case PROP_FACTOR: | ||||
| /* done; value already set */ | new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH; | ||||
| RNA_property_update(C, &rc->ptr, rc->prop); | if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f; | ||||
| ret = OPERATOR_FINISHED; | break; | ||||
| break; | case PROP_ANGLE: | ||||
| new_value = atan2f(delta[1], delta[0]) + M_PI + angle_precision; | |||||
| case LEFTSHIFTKEY: | new_value = fmod(new_value, 2.0f * (float)M_PI); | ||||
| case RIGHTSHIFTKEY: | if (new_value < 0.0f) | ||||
| if (event->val == KM_PRESS) { | new_value += 2.0f * (float)M_PI; | ||||
| rc->slow_mouse[0] = event->x; | if (snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10 * 10); | ||||
| rc->slow_mouse[1] = event->y; | break; | ||||
| rc->slow_mode = true; | default: | ||||
| if (rc->subtype == PROP_ANGLE) { | new_value = dist; /* dummy value, should this ever happen? - campbell */ | ||||
| float initial_position[2] = {UNPACK2(rc->initial_mouse)}; | break; | ||||
| float current_position[2] = {UNPACK2(rc->slow_mouse)}; | } | ||||
| rc->dial = BLI_dial_initialize(initial_position, 0.0f); | /* clamp and update */ | ||||
| /* immediately set the position to get a an initial direction */ | CLAMP(new_value, rc->min_value, rc->max_value); | ||||
| BLI_dial_angle(rc->dial, current_position); | radial_control_set_value(rc, new_value); | ||||
| } | rc->current_value = new_value; | ||||
| } | handled = true; | ||||
| if (event->val == KM_RELEASE) { | break; | ||||
| rc->slow_mode = false; | |||||
| if (rc->dial) { | case LEFTSHIFTKEY: | ||||
| MEM_freeN(rc->dial); | case RIGHTSHIFTKEY: | ||||
| rc->dial = NULL; | if (event->val == KM_PRESS) { | ||||
| } | rc->slow_mouse[0] = event->x; | ||||
Not Done Inline ActionsThis looks redundant. I've seen such code elsewhere (can't remember where off-hand) but I don't think this can ever happen. Have you noticed any case where it is needed? psy-fi: This looks redundant. I've seen such code elsewhere (can't remember where off-hand) but I don't… | |||||
Not Done Inline ActionsWhen radial control is invoked for the first time has_numInput returns false and therefore whole condition on the line 4246 cannot be true. This is workaround for that problem. Same code is also in bevel and inset tools. braffe: When radial control is invoked for the first time //has_numInput// returns false and therefore… | |||||
| } | rc->slow_mouse[1] = event->y; | ||||
| break; | rc->slow_mode = true; | ||||
| } | if (rc->subtype == PROP_ANGLE) { | ||||
| float initial_position[2] = {UNPACK2(rc->initial_mouse)}; | |||||
| ED_region_tag_redraw(CTX_wm_region(C)); | float current_position[2] = {UNPACK2(rc->slow_mouse)}; | ||||
| rc->dial = BLI_dial_initialize(initial_position, 0.0f); | |||||
| if (ret != OPERATOR_RUNNING_MODAL) | /* immediately set the position to get a an initial direction */ | ||||
| radial_control_cancel(C, op); | BLI_dial_angle(rc->dial, current_position); | ||||
| } | |||||
| return ret; | handled = true; | ||||
| } | |||||
| if (event->val == KM_RELEASE) { | |||||
| rc->slow_mode = false; | |||||
| handled = true; | |||||
| if (rc->dial) { | |||||
| MEM_freeN(rc->dial); | |||||
| rc->dial = NULL; | |||||
| } | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* Modal numinput inactive, try to handle numeric inputs last... */ | |||||
| if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) { | |||||
| applyNumInput(&rc->num_input, &numValue); | |||||
| CLAMP(numValue, rc->min_value, rc->max_value); | |||||
| new_value = numValue; | |||||
| radial_control_set_value(rc, new_value); | |||||
| rc->current_value = new_value; | |||||
| radial_control_update_header(op, C); | |||||
| return OPERATOR_RUNNING_MODAL; | |||||
| } | |||||
| } | |||||
| ED_region_tag_redraw(CTX_wm_region(C)); | |||||
| if (ret != OPERATOR_RUNNING_MODAL) | |||||
| radial_control_cancel(C, op); | |||||
| return ret; | |||||
| } | } | ||||
| static void WM_OT_radial_control(wmOperatorType *ot) | static void WM_OT_radial_control(wmOperatorType *ot) | ||||
| Context not available. | |||||
Minor typo here