Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/view2d.c
| Show First 20 Lines • Show All 222 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name View2D Refresh and Validation (Spatial) | /** \name View2D Refresh and Validation (Spatial) | ||||
| * \{ */ | * \{ */ | ||||
| /** | |||||
| * Initialize all relevant View2D data (including view rects if first time) | |||||
| * and/or refresh mask sizes after view resize. | |||||
| * | |||||
| * - For some of these presets, it is expected that the region will have defined some | |||||
| * additional settings necessary for the customization of the 2D viewport to its requirements | |||||
| * - This function should only be called from region init() callbacks, where it is expected that | |||||
| * this is called before #UI_view2d_size_update(), | |||||
| * as this one checks that the rects are properly initialized. | |||||
| */ | |||||
| void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) | void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) | ||||
| { | { | ||||
| bool tot_changed = false, do_init; | bool tot_changed = false, do_init; | ||||
| const uiStyle *style = UI_style_get(); | const uiStyle *style = UI_style_get(); | ||||
| do_init = (v2d->flag & V2D_IS_INIT) == 0; | do_init = (v2d->flag & V2D_IS_INIT) == 0; | ||||
| /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */ | /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */ | ||||
| ▲ Show 20 Lines • Show All 618 Lines • ▼ Show 20 Lines | |||||
| /* ------------------ */ | /* ------------------ */ | ||||
| bool UI_view2d_area_supports_sync(ScrArea *area) | bool UI_view2d_area_supports_sync(ScrArea *area) | ||||
| { | { | ||||
| return ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP, SPACE_GRAPH); | return ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP, SPACE_GRAPH); | ||||
| } | } | ||||
| /* Called by menus to activate it, or by view2d operators | |||||
| * to make sure 'related' views stay in synchrony */ | |||||
| void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag) | void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag) | ||||
| { | { | ||||
| /* don't continue if no view syncing to be done */ | /* don't continue if no view syncing to be done */ | ||||
| if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) { | if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* check if doing within area syncing (i.e. channels/vertical) */ | /* check if doing within area syncing (i.e. channels/vertical) */ | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) { | ||||
| ED_region_tag_redraw_no_rebuild(region); | ED_region_tag_redraw_no_rebuild(region); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot). | |||||
| * This does not take into account if zooming the view on an axis | |||||
| * will improve the view (if allowed). | |||||
| */ | |||||
| void UI_view2d_curRect_reset(View2D *v2d) | void UI_view2d_curRect_reset(View2D *v2d) | ||||
| { | { | ||||
| float width, height; | float width, height; | ||||
| /* assume width and height of 'cur' rect by default, should be same size as mask */ | /* assume width and height of 'cur' rect by default, should be same size as mask */ | ||||
| width = (float)(BLI_rcti_size_x(&v2d->mask) + 1); | width = (float)(BLI_rcti_size_x(&v2d->mask) + 1); | ||||
| height = (float)(BLI_rcti_size_y(&v2d->mask) + 1); | height = (float)(BLI_rcti_size_y(&v2d->mask) + 1); | ||||
| Show All 33 Lines | else { | ||||
| v2d->cur.ymin = -dy; | v2d->cur.ymin = -dy; | ||||
| v2d->cur.ymax = dy; | v2d->cur.ymax = dy; | ||||
| } | } | ||||
| } | } | ||||
| /* ------------------ */ | /* ------------------ */ | ||||
| /* Change the size of the maximum viewable area (i.e. 'tot' rect) */ | |||||
| void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize) | void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize) | ||||
| { | { | ||||
| /* don't do anything if either value is 0 */ | /* don't do anything if either value is 0 */ | ||||
| width = abs(width); | width = abs(width); | ||||
| height = abs(height); | height = abs(height); | ||||
| if (ELEM(0, width, height)) { | if (ELEM(0, width, height)) { | ||||
| if (G.debug & G_DEBUG) { | if (G.debug & G_DEBUG) { | ||||
| ▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | if (sizex > 0.0f && sizey > 0.0f) { | ||||
| } | } | ||||
| if (v2d->mask.ymax + 1 != v2d->winy) { | if (v2d->mask.ymax + 1 != v2d->winy) { | ||||
| r_curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1); | r_curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Set view matrices to use 'cur' rect as viewing frame for View2D drawing */ | |||||
| void UI_view2d_view_ortho(const View2D *v2d) | void UI_view2d_view_ortho(const View2D *v2d) | ||||
| { | { | ||||
| rctf curmasked; | rctf curmasked; | ||||
| const int sizex = BLI_rcti_size_x(&v2d->mask); | const int sizex = BLI_rcti_size_x(&v2d->mask); | ||||
| const int sizey = BLI_rcti_size_y(&v2d->mask); | const int sizey = BLI_rcti_size_y(&v2d->mask); | ||||
| const float eps = 0.001f; | const float eps = 0.001f; | ||||
| float xofs = 0.0f, yofs = 0.0f; | float xofs = 0.0f, yofs = 0.0f; | ||||
| Show All 25 Lines | if (v2d->flag & V2D_PIXELOFS_Y) { | ||||
| curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs); | curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs); | ||||
| curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs); | curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs); | ||||
| } | } | ||||
| /* set matrix on all appropriate axes */ | /* set matrix on all appropriate axes */ | ||||
| wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax); | wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax); | ||||
| } | } | ||||
| /** | |||||
| * Set view matrices to only use one axis of 'cur' only | |||||
| * | |||||
| * \param xaxis: if non-zero, only use cur x-axis, | |||||
| * otherwise use cur-yaxis (mostly this will be used for x). | |||||
| */ | |||||
| void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis) | void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis) | ||||
| { | { | ||||
| rctf curmasked; | rctf curmasked; | ||||
| float xofs, yofs; | float xofs, yofs; | ||||
| /* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1 | /* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1 | ||||
| * correspondence with pixels for smooth UI drawing, | * correspondence with pixels for smooth UI drawing, | ||||
| * but only applied where requested. | * but only applied where requested. | ||||
| Show All 10 Lines | void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis) | ||||
| if (xaxis) { | if (xaxis) { | ||||
| wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, region->winy - yofs); | wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, region->winy - yofs); | ||||
| } | } | ||||
| else { | else { | ||||
| wmOrtho2(-xofs, region->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs); | wmOrtho2(-xofs, region->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs); | ||||
| } | } | ||||
| } | } | ||||
| /* Restore view matrices after drawing */ | |||||
| void UI_view2d_view_restore(const bContext *C) | void UI_view2d_view_restore(const bContext *C) | ||||
| { | { | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| const int width = BLI_rcti_size_x(®ion->winrct) + 1; | const int width = BLI_rcti_size_x(®ion->winrct) + 1; | ||||
| const int height = BLI_rcti_size_y(®ion->winrct) + 1; | const int height = BLI_rcti_size_y(®ion->winrct) + 1; | ||||
| wmOrtho2(0.0f, (float)width, 0.0f, (float)height); | wmOrtho2(0.0f, (float)width, 0.0f, (float)height); | ||||
| GPU_matrix_identity_set(); | GPU_matrix_identity_set(); | ||||
| // ED_region_pixelspace(CTX_wm_region(C)); | // ED_region_pixelspace(CTX_wm_region(C)); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Grid-Line Drawing | /** \name Grid-Line Drawing | ||||
| * \{ */ | * \{ */ | ||||
| /* Draw a multi-level grid in given 2d-region */ | |||||
| void UI_view2d_multi_grid_draw( | void UI_view2d_multi_grid_draw( | ||||
| const View2D *v2d, int colorid, float step, int level_size, int totlevels) | const View2D *v2d, int colorid, float step, int level_size, int totlevels) | ||||
| { | { | ||||
| /* Exit if there is nothing to draw */ | /* Exit if there is nothing to draw */ | ||||
| if (totlevels == 0) { | if (totlevels == 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | static const DotGridLevelInfo level_info[9] = { | ||||
| {0.8f, 0.05f, 0.2f}, | {0.8f, 0.05f, 0.2f}, | ||||
| {0.4f, 0.1f, 0.25f}, | {0.4f, 0.1f, 0.25f}, | ||||
| {0.2f, 0.125f, 0.3f}, | {0.2f, 0.125f, 0.3f}, | ||||
| {0.1f, 0.25f, 0.5f}, | {0.1f, 0.25f, 0.5f}, | ||||
| {0.05f, 0.7f, 0.9f}, | {0.05f, 0.7f, 0.9f}, | ||||
| {0.025f, 0.6f, 0.9f}, | {0.025f, 0.6f, 0.9f}, | ||||
| }; | }; | ||||
| /** | |||||
| * Draw a multi-level grid of dots, with a dynamic number of levels based on the fading. | |||||
| * | |||||
| * \param grid_color_id: The theme color used for the points. Faded dynamically based on zoom. | |||||
| * \param min_step: The base size of the grid. At different zoom levels, the visible grid may have | |||||
| * a larger step size. | |||||
| * \param grid_levels: The maximum grid depth. Larger grid levels will subdivide the grid more. | |||||
| */ | |||||
| void UI_view2d_dot_grid_draw(const View2D *v2d, | void UI_view2d_dot_grid_draw(const View2D *v2d, | ||||
| const int grid_color_id, | const int grid_color_id, | ||||
| const float min_step, | const float min_step, | ||||
| const int grid_levels) | const int grid_levels) | ||||
| { | { | ||||
| BLI_assert(grid_levels >= 0 && grid_levels < 10); | BLI_assert(grid_levels >= 0 && grid_levels < 10); | ||||
| const float zoom_x = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); | const float zoom_x = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); | ||||
| const float zoom_normalized = (zoom_x - v2d->minzoom) / (v2d->maxzoom - v2d->minzoom); | const float zoom_normalized = (zoom_x - v2d->minzoom) / (v2d->maxzoom - v2d->minzoom); | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
| /** | /** | ||||
| * View2DScrollers is typedef'd in UI_view2d.h | * View2DScrollers is typedef'd in UI_view2d.h | ||||
| * | * | ||||
| * \warning The start of this struct must not change, as view2d_ops.c uses this too. | * \warning The start of this struct must not change, as view2d_ops.c uses this too. | ||||
| * For now, we don't need to have a separate (internal) header for structs like this... | * For now, we don't need to have a separate (internal) header for structs like this... | ||||
| */ | */ | ||||
| struct View2DScrollers { | struct View2DScrollers { | ||||
| /* focus bubbles */ | /* focus bubbles */ | ||||
| /* focus bubbles */ | |||||
| /* focus bubbles */ | |||||
| int vert_min, vert_max; /* vertical scrollbar */ | int vert_min, vert_max; /* vertical scrollbar */ | ||||
| int hor_min, hor_max; /* horizontal scrollbar */ | int hor_min, hor_max; /* horizontal scrollbar */ | ||||
| /** Exact size of slider backdrop. */ | /** Exact size of slider backdrop. */ | ||||
| rcti hor, vert; | rcti hor, vert; | ||||
| /* set if sliders are full, we don't draw them */ | /* set if sliders are full, we don't draw them */ | ||||
| /* int horfull, vertfull; */ /* UNUSED */ | /* int horfull, vertfull; */ /* UNUSED */ | ||||
| }; | }; | ||||
| /* Calculate relevant scroller properties */ | |||||
| void UI_view2d_scrollers_calc(View2D *v2d, | void UI_view2d_scrollers_calc(View2D *v2d, | ||||
| const rcti *mask_custom, | const rcti *mask_custom, | ||||
| struct View2DScrollers *r_scrollers) | struct View2DScrollers *r_scrollers) | ||||
| { | { | ||||
| rcti vert, hor; | rcti vert, hor; | ||||
| float fac1, fac2, totsize, scrollsize; | float fac1, fac2, totsize, scrollsize; | ||||
| const int scroll = view2d_scroll_mapped(v2d->scroll); | const int scroll = view2d_scroll_mapped(v2d->scroll); | ||||
| int smaller; | int smaller; | ||||
| ▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | if ((r_scrollers->vert_max - r_scrollers->vert_min) < V2D_SCROLL_THUMB_SIZE_MIN) { | ||||
| r_scrollers->vert_max = r_scrollers->vert_min + V2D_SCROLL_THUMB_SIZE_MIN; | r_scrollers->vert_max = r_scrollers->vert_min + V2D_SCROLL_THUMB_SIZE_MIN; | ||||
| CLAMP(r_scrollers->vert_max, vert.ymin + V2D_SCROLL_THUMB_SIZE_MIN, vert.ymax); | CLAMP(r_scrollers->vert_max, vert.ymin + V2D_SCROLL_THUMB_SIZE_MIN, vert.ymax); | ||||
| CLAMP(r_scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLL_THUMB_SIZE_MIN); | CLAMP(r_scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLL_THUMB_SIZE_MIN); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Draw scrollbars in the given 2d-region */ | |||||
| void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom) | void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom) | ||||
| { | { | ||||
| View2DScrollers scrollers; | View2DScrollers scrollers; | ||||
| UI_view2d_scrollers_calc(v2d, mask_custom, &scrollers); | UI_view2d_scrollers_calc(v2d, mask_custom, &scrollers); | ||||
| bTheme *btheme = UI_GetTheme(); | bTheme *btheme = UI_GetTheme(); | ||||
| rcti vert, hor; | rcti vert, hor; | ||||
| const int scroll = view2d_scroll_mapped(v2d->scroll); | const int scroll = view2d_scroll_mapped(v2d->scroll); | ||||
| const char emboss_alpha = btheme->tui.widget_emboss[3]; | const char emboss_alpha = btheme->tui.widget_emboss[3]; | ||||
| ▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name List View Utilities | /** \name List View Utilities | ||||
| * \{ */ | * \{ */ | ||||
| /** | |||||
| * Get the 'cell' (row, column) that the given 2D-view coordinates | |||||
| * (i.e. in 'tot' rect space) lie in. | |||||
| * | |||||
| * \param columnwidth, rowheight: size of each 'cell' | |||||
| * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from. | |||||
| * This should be (0,0) for most views. However, for those where the starting row was offsetted | |||||
| * (like for Animation Editor channel lists, to make the first entry more visible), these will be | |||||
| * the min-coordinates of the first item. | |||||
| * \param viewx, viewy: 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for | |||||
| * \param r_column, r_row: the 'coordinates' of the relevant 'cell' | |||||
| */ | |||||
| void UI_view2d_listview_view_to_cell(float columnwidth, | void UI_view2d_listview_view_to_cell(float columnwidth, | ||||
| float rowheight, | float rowheight, | ||||
| float startx, | float startx, | ||||
| float starty, | float starty, | ||||
| float viewx, | float viewx, | ||||
| float viewy, | float viewy, | ||||
| int *r_column, | int *r_column, | ||||
| int *r_row) | int *r_row) | ||||
| Show All 31 Lines | return (v2d->cur.xmin + | ||||
| (BLI_rctf_size_x(&v2d->cur) * (x - v2d->mask.xmin) / BLI_rcti_size_x(&v2d->mask))); | (BLI_rctf_size_x(&v2d->cur) * (x - v2d->mask.xmin) / BLI_rcti_size_x(&v2d->mask))); | ||||
| } | } | ||||
| float UI_view2d_region_to_view_y(const struct View2D *v2d, float y) | float UI_view2d_region_to_view_y(const struct View2D *v2d, float y) | ||||
| { | { | ||||
| return (v2d->cur.ymin + | return (v2d->cur.ymin + | ||||
| (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask))); | (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask))); | ||||
| } | } | ||||
| /** | |||||
| * Convert from screen/region space to 2d-View space | |||||
| * | |||||
| * \param x, y: coordinates to convert | |||||
| * \param r_view_x, r_view_y: resultant coordinates | |||||
| */ | |||||
| void UI_view2d_region_to_view( | void UI_view2d_region_to_view( | ||||
| const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) | const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) | ||||
| { | { | ||||
| *r_view_x = UI_view2d_region_to_view_x(v2d, x); | *r_view_x = UI_view2d_region_to_view_x(v2d, x); | ||||
| *r_view_y = UI_view2d_region_to_view_y(v2d, y); | *r_view_y = UI_view2d_region_to_view_y(v2d, y); | ||||
| } | } | ||||
| void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst) | void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst) | ||||
| Show All 17 Lines | return (v2d->mask.xmin + | ||||
| (((x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur)) * BLI_rcti_size_x(&v2d->mask))); | (((x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur)) * BLI_rcti_size_x(&v2d->mask))); | ||||
| } | } | ||||
| float UI_view2d_view_to_region_y(const View2D *v2d, float y) | float UI_view2d_view_to_region_y(const View2D *v2d, float y) | ||||
| { | { | ||||
| return (v2d->mask.ymin + | return (v2d->mask.ymin + | ||||
| (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask))); | (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask))); | ||||
| } | } | ||||
| /** | |||||
| * Convert from 2d-View space to screen/region space | |||||
| * \note Coordinates are clamped to lie within bounds of region | |||||
| * | |||||
| * \param x, y: Coordinates to convert. | |||||
| * \param r_region_x, r_region_y: Resultant coordinates. | |||||
| */ | |||||
| bool UI_view2d_view_to_region_clip( | bool UI_view2d_view_to_region_clip( | ||||
| const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) | const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) | ||||
| { | { | ||||
| /* express given coordinates as proportional values */ | /* express given coordinates as proportional values */ | ||||
| x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); | x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); | ||||
| y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); | y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); | ||||
| /* check if values are within bounds */ | /* check if values are within bounds */ | ||||
| if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) { | if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) { | ||||
| *r_region_x = (int)(v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask))); | *r_region_x = (int)(v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask))); | ||||
| *r_region_y = (int)(v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask))); | *r_region_y = (int)(v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask))); | ||||
| return true; | return true; | ||||
| } | } | ||||
| /* set initial value in case coordinate lies outside of bounds */ | /* set initial value in case coordinate lies outside of bounds */ | ||||
| *r_region_x = *r_region_y = V2D_IS_CLIPPED; | *r_region_x = *r_region_y = V2D_IS_CLIPPED; | ||||
| return false; | return false; | ||||
| } | } | ||||
| /** | |||||
| * Convert from 2d-view space to screen/region space | |||||
| * | |||||
| * \note Coordinates are NOT clamped to lie within bounds of region. | |||||
| * | |||||
| * \param x, y: Coordinates to convert. | |||||
| * \param r_region_x, r_region_y: Resultant coordinates. | |||||
| */ | |||||
| void UI_view2d_view_to_region( | void UI_view2d_view_to_region( | ||||
| const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) | const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) | ||||
| { | { | ||||
| /* Step 1: express given coordinates as proportional values. */ | /* Step 1: express given coordinates as proportional values. */ | ||||
| x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); | x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); | ||||
| y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); | y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); | ||||
| /* Step 2: convert proportional distances to screen coordinates. */ | /* Step 2: convert proportional distances to screen coordinates. */ | ||||
| ▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Utilities | /** \name Utilities | ||||
| * \{ */ | * \{ */ | ||||
| /* View2D data by default resides in region, so get from region stored in context */ | |||||
| View2D *UI_view2d_fromcontext(const bContext *C) | View2D *UI_view2d_fromcontext(const bContext *C) | ||||
| { | { | ||||
| ScrArea *area = CTX_wm_area(C); | ScrArea *area = CTX_wm_area(C); | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| if (area == NULL) { | if (area == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (region == NULL) { | if (region == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| return &(region->v2d); | return &(region->v2d); | ||||
| } | } | ||||
| /* Same as above, but it returns region-window. Utility for pull-downs or buttons. */ | |||||
| View2D *UI_view2d_fromcontext_rwin(const bContext *C) | View2D *UI_view2d_fromcontext_rwin(const bContext *C) | ||||
| { | { | ||||
| ScrArea *area = CTX_wm_area(C); | ScrArea *area = CTX_wm_area(C); | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| if (area == NULL) { | if (area == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (region == NULL) { | if (region == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (region->regiontype != RGN_TYPE_WINDOW) { | if (region->regiontype != RGN_TYPE_WINDOW) { | ||||
| ARegion *region_win = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); | ARegion *region_win = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); | ||||
| return region_win ? &(region_win->v2d) : NULL; | return region_win ? &(region_win->v2d) : NULL; | ||||
| } | } | ||||
| return &(region->v2d); | return &(region->v2d); | ||||
| } | } | ||||
| /* Get scrollbar sizes of the current 2D view. The size will be zero if the view has its scrollbars | |||||
| * disabled. */ | |||||
| void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y) | void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y) | ||||
| { | { | ||||
| const int scroll = view2d_scroll_mapped(v2d->scroll); | const int scroll = view2d_scroll_mapped(v2d->scroll); | ||||
| if (r_x) { | if (r_x) { | ||||
| if (scroll & V2D_SCROLL_VERTICAL) { | if (scroll & V2D_SCROLL_VERTICAL) { | ||||
| *r_x = (scroll & V2D_SCROLL_VERTICAL_HANDLES) ? V2D_SCROLL_HANDLE_WIDTH : V2D_SCROLL_WIDTH; | *r_x = (scroll & V2D_SCROLL_VERTICAL_HANDLES) ? V2D_SCROLL_HANDLE_WIDTH : V2D_SCROLL_WIDTH; | ||||
| } | } | ||||
| else { | else { | ||||
| *r_x = 0; | *r_x = 0; | ||||
| } | } | ||||
| } | } | ||||
| if (r_y) { | if (r_y) { | ||||
| if (scroll & V2D_SCROLL_HORIZONTAL) { | if (scroll & V2D_SCROLL_HORIZONTAL) { | ||||
| *r_y = (scroll & V2D_SCROLL_HORIZONTAL_HANDLES) ? V2D_SCROLL_HANDLE_HEIGHT : | *r_y = (scroll & V2D_SCROLL_HORIZONTAL_HANDLES) ? V2D_SCROLL_HANDLE_HEIGHT : | ||||
| V2D_SCROLL_HEIGHT; | V2D_SCROLL_HEIGHT; | ||||
| } | } | ||||
| else { | else { | ||||
| *r_y = 0; | *r_y = 0; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Calculate the scale per-axis of the drawing-area | |||||
| * | |||||
| * Is used to inverse correct drawing of icons, etc. that need to follow view | |||||
| * but not be affected by scale | |||||
| * | |||||
| * \param r_x, r_y: scale on each axis | |||||
| */ | |||||
| void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y) | void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y) | ||||
| { | { | ||||
| if (r_x) { | if (r_x) { | ||||
| *r_x = UI_view2d_scale_get_x(v2d); | *r_x = UI_view2d_scale_get_x(v2d); | ||||
| } | } | ||||
| if (r_y) { | if (r_y) { | ||||
| *r_y = UI_view2d_scale_get_y(v2d); | *r_y = UI_view2d_scale_get_y(v2d); | ||||
| } | } | ||||
| } | } | ||||
| float UI_view2d_scale_get_x(const View2D *v2d) | float UI_view2d_scale_get_x(const View2D *v2d) | ||||
| { | { | ||||
| return BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur); | return BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur); | ||||
| } | } | ||||
| float UI_view2d_scale_get_y(const View2D *v2d) | float UI_view2d_scale_get_y(const View2D *v2d) | ||||
| { | { | ||||
| return BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur); | return BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur); | ||||
| } | } | ||||
| /** | |||||
| * Same as `UI_view2d_scale_get() - 1.0f / x, y`. | |||||
| */ | |||||
| void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y) | void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y) | ||||
| { | { | ||||
| if (r_x) { | if (r_x) { | ||||
| *r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); | *r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); | ||||
| } | } | ||||
| if (r_y) { | if (r_y) { | ||||
| *r_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); | *r_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Simple functions for consistent center offset access. | |||||
| * Used by node editor to shift view center for each individual node tree. | |||||
| */ | |||||
| void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y) | void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y) | ||||
| { | { | ||||
| /* get center */ | /* get center */ | ||||
| if (r_x) { | if (r_x) { | ||||
| *r_x = BLI_rctf_cent_x(&v2d->cur); | *r_x = BLI_rctf_cent_x(&v2d->cur); | ||||
| } | } | ||||
| if (r_y) { | if (r_y) { | ||||
| *r_y = BLI_rctf_cent_y(&v2d->cur); | *r_y = BLI_rctf_cent_y(&v2d->cur); | ||||
| } | } | ||||
| } | } | ||||
| void UI_view2d_center_set(struct View2D *v2d, float x, float y) | void UI_view2d_center_set(struct View2D *v2d, float x, float y) | ||||
| { | { | ||||
| BLI_rctf_recenter(&v2d->cur, x, y); | BLI_rctf_recenter(&v2d->cur, x, y); | ||||
| /* make sure that 'cur' rect is in a valid state as a result of these changes */ | /* make sure that 'cur' rect is in a valid state as a result of these changes */ | ||||
| UI_view2d_curRect_validate(v2d); | UI_view2d_curRect_validate(v2d); | ||||
| } | } | ||||
| /** | |||||
| * Simple pan function | |||||
| * (0.0, 0.0) bottom left | |||||
| * (0.5, 0.5) center | |||||
| * (1.0, 1.0) top right. | |||||
| */ | |||||
| void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac) | void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac) | ||||
| { | { | ||||
| if (xfac != -1.0f) { | if (xfac != -1.0f) { | ||||
| const float xsize = BLI_rctf_size_x(&v2d->cur); | const float xsize = BLI_rctf_size_x(&v2d->cur); | ||||
| const float xmin = v2d->tot.xmin; | const float xmin = v2d->tot.xmin; | ||||
| const float xmax = v2d->tot.xmax - xsize; | const float xmax = v2d->tot.xmax - xsize; | ||||
| v2d->cur.xmin = (xmin * (1.0f - xfac)) + (xmax * xfac); | v2d->cur.xmin = (xmin * (1.0f - xfac)) + (xmax * xfac); | ||||
| v2d->cur.xmax = v2d->cur.xmin + xsize; | v2d->cur.xmax = v2d->cur.xmin + xsize; | ||||
| } | } | ||||
| if (yfac != -1.0f) { | if (yfac != -1.0f) { | ||||
| const float ysize = BLI_rctf_size_y(&v2d->cur); | const float ysize = BLI_rctf_size_y(&v2d->cur); | ||||
| const float ymin = v2d->tot.ymin; | const float ymin = v2d->tot.ymin; | ||||
| const float ymax = v2d->tot.ymax - ysize; | const float ymax = v2d->tot.ymax - ysize; | ||||
| v2d->cur.ymin = (ymin * (1.0f - yfac)) + (ymax * yfac); | v2d->cur.ymin = (ymin * (1.0f - yfac)) + (ymax * yfac); | ||||
| v2d->cur.ymax = v2d->cur.ymin + ysize; | v2d->cur.ymax = v2d->cur.ymin + ysize; | ||||
| } | } | ||||
| UI_view2d_curRect_validate(v2d); | UI_view2d_curRect_validate(v2d); | ||||
| } | } | ||||
| /** | |||||
| * Check if mouse is within scrollers | |||||
| * | |||||
| * \param x, y: Mouse coordinates in screen (not region) space. | |||||
| * \param r_scroll: Mapped view2d scroll flag. | |||||
| * | |||||
| * \return appropriate code for match. | |||||
| * - 'h' = in horizontal scroller. | |||||
| * - 'v' = in vertical scroller. | |||||
| * - 0 = not in scroller. | |||||
| */ | |||||
| char UI_view2d_mouse_in_scrollers_ex(const ARegion *region, | char UI_view2d_mouse_in_scrollers_ex(const ARegion *region, | ||||
| const View2D *v2d, | const View2D *v2d, | ||||
| const int xy[2], | const int xy[2], | ||||
| int *r_scroll) | int *r_scroll) | ||||
| { | { | ||||
| const int scroll = view2d_scroll_mapped(v2d->scroll); | const int scroll = view2d_scroll_mapped(v2d->scroll); | ||||
| *r_scroll = scroll; | *r_scroll = scroll; | ||||
| ▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | if (UI_view2d_view_to_region_clip(v2d, x, y, &mval[0], &mval[1])) { | ||||
| v2s->mval[0] = mval[0]; | v2s->mval[0] = mval[0]; | ||||
| v2s->mval[1] = mval[1]; | v2s->mval[1] = mval[1]; | ||||
| memcpy(v2s->str, str, alloc_len); | memcpy(v2s->str, str, alloc_len); | ||||
| } | } | ||||
| } | } | ||||
| /* no clip (yet) */ | |||||
| void UI_view2d_text_cache_add_rectf( | void UI_view2d_text_cache_add_rectf( | ||||
| View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4]) | View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4]) | ||||
| { | { | ||||
| rcti rect; | rcti rect; | ||||
| BLI_assert(str_len == strlen(str)); | BLI_assert(str_len == strlen(str)); | ||||
| if (UI_view2d_view_to_region_rcti_clip(v2d, rect_view, &rect)) { | if (UI_view2d_view_to_region_rcti_clip(v2d, rect_view, &rect)) { | ||||
| ▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines | |||||