diff options
Diffstat (limited to 'source/blender/editors/interface/interface_handlers.c')
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 335 |
1 files changed, 333 insertions, 2 deletions
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 806b5789df1..673e4c1a8da 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -32,7 +32,7 @@ #include "MEM_guardedalloc.h" #include "DNA_brush_types.h" - +#include "DNA_curveprofile_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -57,6 +57,7 @@ #include "BKE_tracking.h" #include "BKE_unit.h" #include "BKE_paint.h" +#include "BKE_curveprofile.h" #include "IMB_colormanagement.h" @@ -442,6 +443,8 @@ static uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut static ColorBand but_copypaste_coba = {0}; static CurveMapping but_copypaste_curve = {0}; static bool but_copypaste_curve_alive = false; +static CurveProfile but_copypaste_profile = {0}; +static bool but_copypaste_profile_alive = false; /** \} */ @@ -1080,6 +1083,13 @@ static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data data->applied = true; } +static void ui_apply_but_CURVEPROFILE(bContext *C, uiBut *but, uiHandleButtonData *data) +{ + ui_apply_but_func(C, but); + data->retval = but->retval; + data->applied = true; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1979,6 +1989,7 @@ static void ui_apply_but( float *editvec; ColorBand *editcoba; CurveMapping *editcumap; + CurveProfile *editprofile; data->retval = 0; @@ -2036,11 +2047,13 @@ static void ui_apply_but( editvec = but->editvec; editcoba = but->editcoba; editcumap = but->editcumap; + editprofile = but->editprofile; but->editstr = NULL; but->editval = NULL; but->editvec = NULL; but->editcoba = NULL; but->editcumap = NULL; + but->editprofile = NULL; /* handle different types */ switch (but->type) { @@ -2100,6 +2113,9 @@ static void ui_apply_but( case UI_BTYPE_CURVE: ui_apply_but_CURVE(C, but, data); break; + case UI_BTYPE_CURVEPROFILE: + ui_apply_but_CURVEPROFILE(C, but, data); + break; case UI_BTYPE_KEY_EVENT: case UI_BTYPE_HOTKEY_EVENT: ui_apply_but_BUT(C, but, data); @@ -2147,6 +2163,7 @@ static void ui_apply_but( but->editvec = editvec; but->editcoba = editcoba; but->editcumap = editcumap; + but->editprofile = editprofile; } /** \} */ @@ -2446,6 +2463,29 @@ static void ui_but_paste_curvemapping(bContext *C, uiBut *but) } } +static void ui_but_copy_CurveProfile(uiBut *but) +{ + if (but->poin != NULL) { + but_copypaste_profile_alive = true; + BKE_curveprofile_free_data(&but_copypaste_profile); + BKE_curveprofile_copy_data(&but_copypaste_profile, (CurveProfile *)but->poin); + } +} + +static void ui_but_paste_CurveProfile(bContext *C, uiBut *but) +{ + if (but_copypaste_profile_alive) { + if (!but->poin) { + but->poin = MEM_callocN(sizeof(CurveProfile), "CurveProfile"); + } + + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + BKE_curveprofile_free_data((CurveProfile *)but->poin); + BKE_curveprofile_copy_data((CurveProfile *)but->poin, &but_copypaste_profile); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } +} + static void ui_but_copy_operator(bContext *C, uiBut *but, char *output, int output_len_max) { PointerRNA *opptr; @@ -2540,6 +2580,10 @@ static void ui_but_copy(bContext *C, uiBut *but, const bool copy_array) ui_but_copy_curvemapping(but); break; + case UI_BTYPE_CURVEPROFILE: + ui_but_copy_CurveProfile(but); + break; + case UI_BTYPE_BUT: if (!but->optype) { break; @@ -2623,6 +2667,10 @@ static void ui_but_paste(bContext *C, uiBut *but, uiHandleButtonData *data, cons ui_but_paste_curvemapping(C, but); break; + case UI_BTYPE_CURVEPROFILE: + ui_but_paste_CurveProfile(C, but); + break; + default: break; } @@ -2633,6 +2681,7 @@ static void ui_but_paste(bContext *C, uiBut *but, uiHandleButtonData *data, cons void ui_but_clipboard_free(void) { BKE_curvemapping_free_data(&but_copypaste_curve); + BKE_curveprofile_free_data(&but_copypaste_profile); } /** \} */ @@ -3757,6 +3806,9 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data) if (but->type == UI_BTYPE_CURVE) { but->editcumap = (CurveMapping *)but->poin; } + if (but->type == UI_BTYPE_CURVEPROFILE) { + but->editprofile = (CurveProfile *)but->poin; + } else if (but->type == UI_BTYPE_COLORBAND) { data->coba = (ColorBand *)but->poin; but->editcoba = data->coba; @@ -3847,6 +3899,7 @@ static void ui_numedit_end(uiBut *but, uiHandleButtonData *data) but->editvec = NULL; but->editcoba = NULL; but->editcumap = NULL; + but->editprofile = NULL; data->dragstartx = 0; data->draglastx = 0; @@ -6803,6 +6856,281 @@ static int ui_do_but_CURVE( return WM_UI_HANDLER_CONTINUE; } +/* Same as ui_numedit_but_CURVE with some smaller changes. */ +static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, + uiBut *but, + uiHandleButtonData *data, + int evtx, + int evty, + bool snap, + const bool shift) +{ + CurveProfile *profile = (CurveProfile *)but->poin; + CurveProfilePoint *pts = profile->path; + float fx, fy, zoomx, zoomy; + int mx, my, dragx, dragy; + int a; + bool changed = false; + + /* evtx evty and drag coords are absolute mousecoords, + * prevents errors when editing when layout changes */ + mx = evtx; + my = evty; + ui_window_to_block(data->region, block, &mx, &my); + dragx = data->draglastx; + dragy = data->draglasty; + ui_window_to_block(data->region, block, &dragx, &dragy); + + zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&profile->view_rect); + zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&profile->view_rect); + + if (snap) { + float d[2]; + + d[0] = mx - data->dragstartx; + d[1] = my - data->dragstarty; + + if (len_squared_v2(d) < (3.0f * 3.0f)) { + snap = false; + } + } + + fx = (mx - dragx) / zoomx; + fy = (my - dragy) / zoomy; + + if (data->dragsel != -1) { + CurveProfilePoint *point_last = NULL; + const float mval_factor = ui_mouse_scale_warp_factor(shift); + bool moved_point = false; /* for ctrl grid, can't use orig coords because of sorting */ + + fx *= mval_factor; + fy *= mval_factor; + + /* Move all the points that aren't the last or the first */ + for (a = 1; a < profile->path_len - 1; a++) { + if (pts[a].flag & PROF_SELECT) { + float origx = pts[a].x, origy = pts[a].y; + pts[a].x += fx; + pts[a].y += fy; + if (snap) { + pts[a].x = 0.125f * roundf(8.0f * pts[a].x); + pts[a].y = 0.125f * roundf(8.0f * pts[a].y); + } + if (!moved_point && (pts[a].x != origx || pts[a].y != origy)) { + moved_point = true; + } + + point_last = &pts[a]; + } + } + + BKE_curveprofile_update(profile, false); + + if (moved_point) { + data->draglastx = evtx; + data->draglasty = evty; + changed = true; +#ifdef USE_CONT_MOUSE_CORRECT + /* note: using 'cmp_last' is weak since there may be multiple points selected, + * but in practice this isnt really an issue */ + if (ui_but_is_cursor_warp(but)) { + /* OK but can go outside bounds */ + data->ungrab_mval[0] = but->rect.xmin + ((point_last->x - profile->view_rect.xmin) * zoomx); + data->ungrab_mval[1] = but->rect.ymin + ((point_last->y - profile->view_rect.ymin) * zoomy); + BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval); + } +#endif + } + data->dragchange = true; /* mark for selection */ + } + else { + /* clamp for clip */ + if (profile->flag & PROF_USE_CLIP) { + if (profile->view_rect.xmin - fx < profile->clip_rect.xmin) { + fx = profile->view_rect.xmin - profile->clip_rect.xmin; + } + else if (profile->view_rect.xmax - fx > profile->clip_rect.xmax) { + fx = profile->view_rect.xmax - profile->clip_rect.xmax; + } + if (profile->view_rect.ymin - fy < profile->clip_rect.ymin) { + fy = profile->view_rect.ymin - profile->clip_rect.ymin; + } + else if (profile->view_rect.ymax - fy > profile->clip_rect.ymax) { + fy = profile->view_rect.ymax - profile->clip_rect.ymax; + } + } + + profile->view_rect.xmin -= fx; + profile->view_rect.ymin -= fy; + profile->view_rect.xmax -= fx; + profile->view_rect.ymax -= fy; + + data->draglastx = evtx; + data->draglasty = evty; + + changed = true; + } + + return changed; +} + +/** Interaction for curve profile widget. + * \note Uses hardcoded keys rather than the keymap. */ +static int ui_do_but_CURVEPROFILE( + bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +{ + int mx, my, i; + + mx = event->x; + my = event->y; + ui_window_to_block(data->region, block, &mx, &my); + + /* Move selected control points. */ + if (event->type == GKEY && event->val == KM_RELEASE) { + data->dragstartx = mx; + data->dragstarty = my; + data->draglastx = mx; + data->draglasty = my; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + return WM_UI_HANDLER_BREAK; + } + + CurveProfile *profile = (CurveProfile *)but->poin; + + /* Delete selected control points. */ + if (event->type == XKEY && event->val == KM_RELEASE) { + BKE_curveprofile_remove_by_flag(profile, PROF_SELECT); + BKE_curveprofile_update(profile, false); + button_activate_state(C, but, BUTTON_STATE_EXIT); + return WM_UI_HANDLER_BREAK; + } + + /* Selecting, adding, and starting point movements. */ + if (data->state == BUTTON_STATE_HIGHLIGHT) { + if (event->type == LEFTMOUSE && event->val == KM_PRESS) { + CurveProfilePoint *pts; /* Path or table. */ + const float m_xy[2] = {mx, my}; + float dist_min_sq; + int i_selected = -1; + + if (event->ctrl) { + float f_xy[2]; + BLI_rctf_transform_pt_v(&profile->view_rect, &but->rect, f_xy, m_xy); + + BKE_curveprofile_insert(profile, f_xy[0], f_xy[1]); + BKE_curveprofile_update(profile, false); + } + + /* Check for selecting of a point by finding closest point in radius. */ + dist_min_sq = SQUARE(U.dpi_fac * 14.0f); /* 14 pixels radius for selecting points. */ + pts = profile->path; + for (i = 0; i < profile->path_len; i++) { + float f_xy[2]; + BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &pts[i].x); + const float dist_sq = len_squared_v2v2(m_xy, f_xy); + if (dist_sq < dist_min_sq) { + i_selected = i; + dist_min_sq = dist_sq; + } + } + + /* Add a point if the click was close to the path but not a control point. */ + if (i_selected == -1) { /* No control point selected. */ + float f_xy[2], f_xy_prev[2]; + pts = profile->table; + BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &pts[0].x); + + dist_min_sq = SQUARE(U.dpi_fac * 8.0f); /* 8 pixel radius from each table point. */ + + /* Loop through the path's high resolution table and find what's near the click. */ + for (i = 1; i <= PROF_N_TABLE(profile->path_len); i++) { + copy_v2_v2(f_xy_prev, f_xy); + BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &pts[i].x); + + if (dist_squared_to_line_segment_v2(m_xy, f_xy_prev, f_xy) < dist_min_sq) { + BLI_rctf_transform_pt_v(&profile->view_rect, &but->rect, f_xy, m_xy); + + CurveProfilePoint *new_pt = BKE_curveprofile_insert(profile, f_xy[0], f_xy[1]); + BKE_curveprofile_update(profile, false); + + /* reset pts back to the control points. */ + pts = profile->path; + + /* Get the index of the newly added point. */ + for (i = 0; i < profile->path_len; i++) { + if (&pts[i] == new_pt) { + i_selected = i; + } + } + break; + } + } + } + + /* Change the flag for the point(s) if one was selected. */ + if (i_selected != -1) { + /* Deselect all if this one is deselected, except if we hold shift. */ + if (!event->shift) { + for (i = 0; i < profile->path_len; i++) { + pts[i].flag &= ~PROF_SELECT; + } + pts[i_selected].flag |= PROF_SELECT; + } + else { + pts[i_selected].flag ^= PROF_SELECT; + } + } + else { + /* Move the view. */ + data->cancel = true; + } + + data->dragsel = i_selected; + + data->dragstartx = mx; + data->dragstarty = my; + data->draglastx = mx; + data->draglasty = my; + + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + return WM_UI_HANDLER_BREAK; + } + } + else if (data->state == BUTTON_STATE_NUM_EDITING) { /* Do control point movement. */ + if (event->type == MOUSEMOVE) { + if (mx != data->draglastx || my != data->draglasty) { + if (ui_numedit_but_CURVEPROFILE( + block, but, data, mx, my, event->ctrl != 0, event->shift != 0)) { + ui_numedit_apply(C, block, but, data); + } + } + } + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + /* Finish move. */ + if (data->dragsel != -1) { + CurveProfilePoint *pts = profile->path; + + if (data->dragchange == false) { + /* Deselect all, select one. */ + if (!event->shift) { + for (i = 0; i < profile->path_len; i++) { + pts[i].flag &= ~PROF_SELECT; + } + pts[data->dragsel].flag |= PROF_SELECT; + } + } + else { + BKE_curveprofile_update(profile, true); /* Remove doubles after move. */ + } + } + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + return WM_UI_HANDLER_BREAK; + } + + return WM_UI_HANDLER_CONTINUE; +} + static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx, int my) { Histogram *hist = (Histogram *)but->poin; @@ -7208,6 +7536,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case UI_BTYPE_CURVE: retval = ui_do_but_CURVE(C, block, but, data, event); break; + case UI_BTYPE_CURVEPROFILE: + retval = ui_do_but_CURVEPROFILE(C, block, but, data, event); + break; case UI_BTYPE_HSVCUBE: retval = ui_do_but_HSVCUBE(C, block, but, data, event); break; @@ -7599,7 +7930,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA copy_v2_fl(data->ungrab_mval, FLT_MAX); #endif - if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU)) { + if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_CURVEPROFILE, UI_BTYPE_SEARCH_MENU)) { /* XXX curve is temp */ } else { |