*/
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
{
- short tot_changed = 0, do_init;
+ bool tot_changed = false, do_init;
uiStyle *style = UI_GetStyle();
do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
}
/* scrollers - should we have these by default? */
/* XXX for now, we don't override this, or set it either! */
+ break;
}
- break;
-
/* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
case V2D_COMMONVIEW_LIST:
{
tot_changed = do_init;
/* scroller settings are currently not set here... that is left for regions... */
+ break;
}
- break;
-
/* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
* zoom, aspect ratio, and alignment restrictions are set here */
case V2D_COMMONVIEW_STACK:
tot_changed = do_init;
/* scroller settings are currently not set here... that is left for regions... */
+ break;
}
- break;
-
/* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
case V2D_COMMONVIEW_HEADER:
{
/* absolutely no scrollers allowed */
v2d->scroll = 0;
-
+ break;
}
- break;
-
/* panels view, with horizontal/vertical align */
case V2D_COMMONVIEW_PANELS_UI:
{
v2d->cur.ymax = 0.0f;
v2d->cur.ymin = (-winy) * panelzoom;
}
+ break;
}
- break;
-
/* other view types are completely defined using their own settings already */
default:
/* we don't do anything here, as settings should be fine, but just make sure that rect */
* NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
*/
else if (v2d->keepzoom & V2D_LIMITZOOM) {
- float zoom, fac;
/* check if excessive zoom on x-axis */
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- zoom = winx / width;
- if ((zoom < v2d->minzoom) || (zoom > v2d->maxzoom)) {
- fac = (zoom < v2d->minzoom) ? (zoom / v2d->minzoom) : (zoom / v2d->maxzoom);
- width *= fac;
+ const float zoom = winx / width;
+ if (zoom < v2d->minzoom) {
+ width = winx / v2d->minzoom;
+ }
+ else if (zoom > v2d->maxzoom) {
+ width = winx / v2d->maxzoom;
}
}
/* check if excessive zoom on y-axis */
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- zoom = winy / height;
- if ((zoom < v2d->minzoom) || (zoom > v2d->maxzoom)) {
- fac = (zoom < v2d->minzoom) ? (zoom / v2d->minzoom) : (zoom / v2d->maxzoom);
- height *= fac;
+ const float zoom = winy / height;
+ if (zoom < v2d->minzoom) {
+ height = winy / v2d->minzoom;
+ }
+ else if (zoom > v2d->maxzoom) {
+ height = winy / v2d->maxzoom;
}
}
}
/* check if we should restore aspect ratio (if view size changed) */
if (v2d->keepzoom & V2D_KEEPASPECT) {
- short do_x = FALSE, do_y = FALSE, do_cur /* , do_win */ /* UNUSED */;
+ bool do_x = false, do_y = false, do_cur /* , do_win */ /* UNUSED */;
float /* curRatio, */ /* UNUSED */ winRatio;
/* when a window edge changes, the aspect ratio can't be used to
* find which is the best new 'cur' rect. thats why it stores 'old'
*/
- if (winx != v2d->oldwinx) do_x = TRUE;
- if (winy != v2d->oldwiny) do_y = TRUE;
+ if (winx != v2d->oldwinx) do_x = true;
+ if (winy != v2d->oldwiny) do_y = true;
/* curRatio = height / width; */ /* UNUSED */
winRatio = winy / winx;
if (do_x == do_y) {
if (do_x && do_y) {
/* here is 1,1 case, so all others must be 0,0 */
- if (ABS(winx - v2d->oldwinx) > ABS(winy - v2d->oldwiny)) do_y = FALSE;
- else do_x = FALSE;
+ if (fabsf(winx - v2d->oldwinx) > fabsf(winy - v2d->oldwiny)) do_y = false;
+ else do_x = false;
}
else if (winRatio > 1.0f) {
- do_x = FALSE;
+ do_x = false;
}
else {
- do_x = TRUE;
+ do_x = true;
}
}
do_cur = do_x;
/* handle width - posx and negx flags are mutually exclusive, so watch out */
if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
/* width is in negative-x half */
- v2d->cur.xmin = (float)-width;
+ v2d->cur.xmin = -width;
v2d->cur.xmax = 0.0f;
}
else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
/* width is in positive-x half */
v2d->cur.xmin = 0.0f;
- v2d->cur.xmax = (float)width;
+ v2d->cur.xmax = width;
}
else {
/* width is centered around (x == 0) */
- const float dx = (float)width / 2.0f;
+ const float dx = width / 2.0f;
v2d->cur.xmin = -dx;
v2d->cur.xmax = dx;
/* handle height - posx and negx flags are mutually exclusive, so watch out */
if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
/* height is in negative-y half */
- v2d->cur.ymin = (float)-height;
+ v2d->cur.ymin = -height;
v2d->cur.ymax = 0.0f;
}
else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
/* height is in positive-y half */
v2d->cur.ymin = 0.0f;
- v2d->cur.ymax = (float)height;
+ v2d->cur.ymax = height;
}
else {
/* height is centered around (y == 0) */
- const float dy = (float)height / 2.0f;
+ const float dy = height / 2.0f;
v2d->cur.ymin = -dy;
v2d->cur.ymax = dy;
}
-int UI_view2d_tab_set(View2D *v2d, int tab)
+bool UI_view2d_tab_set(View2D *v2d, int tab)
{
float default_offset[2] = {0.0f, 0.0f};
float *offset, *new_offset;
- int changed = 0;
+ bool changed = false;
/* if tab changed, change offset */
if (tab != v2d->tab_cur && v2d->tab_offset) {
/* validation should happen in subsequent totRect_set */
- changed = 1;
+ changed = true;
}
/* resize array if needed */
return changed;
}
+void UI_view2d_zoom_cache_reset(void)
+{
+ /* While scaling we can accumulate fonts at many sizes (~20 or so).
+ * Not an issue with embedded font, but can use over 500Mb with i18n ones! See [#38244]. */
+
+ /* note: only some views draw text, we could check for this case to avoid clearning cache */
+ BLF_cache_clear();
+}
+
/* *********************************************************************** */
/* View Matrix Setup */
*curmasked = v2d->cur;
if (view2d_scroll_mapped(v2d->scroll)) {
- float dx = BLI_rctf_size_x(&v2d->cur) / ((float)(BLI_rcti_size_x(&v2d->mask) + 1));
- float dy = BLI_rctf_size_y(&v2d->cur) / ((float)(BLI_rcti_size_y(&v2d->mask) + 1));
-
- if (v2d->mask.xmin != 0)
- curmasked->xmin -= dx * (float)v2d->mask.xmin;
- if (v2d->mask.xmax + 1 != v2d->winx)
- curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
-
- if (v2d->mask.ymin != 0)
- curmasked->ymin -= dy * (float)v2d->mask.ymin;
- if (v2d->mask.ymax + 1 != v2d->winy)
- curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1);
+ float sizex = BLI_rcti_size_x(&v2d->mask);
+ float sizey = BLI_rcti_size_y(&v2d->mask);
+ /* prevent tiny or narrow regions to get invalid coordinates - mask can get negative even... */
+ if (sizex > 0.0f && sizey > 0.0f) {
+ float dx = BLI_rctf_size_x(&v2d->cur) / (sizex + 1);
+ float dy = BLI_rctf_size_y(&v2d->cur) / (sizey + 1);
+
+ if (v2d->mask.xmin != 0)
+ curmasked->xmin -= dx * (float)v2d->mask.xmin;
+ if (v2d->mask.xmax + 1 != v2d->winx)
+ curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
+
+ if (v2d->mask.ymin != 0)
+ curmasked->ymin -= dy * (float)v2d->mask.ymin;
+ if (v2d->mask.ymax + 1 != v2d->winy)
+ curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1);
+ }
}
}
void UI_view2d_view_ortho(View2D *v2d)
{
rctf curmasked;
- float xofs, yofs;
+ const int sizex = BLI_rcti_size_x(&v2d->mask);
+ const int sizey = BLI_rcti_size_y(&v2d->mask);
+ const float eps = 0.001f;
+ float xofs = 0.0f, yofs = 0.0f;
/* pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1 correspondence with pixels for smooth UI drawing,
* but only applied where requested
*/
/* XXX brecht: instead of zero at least use a tiny offset, otherwise
* pixel rounding is effectively random due to float inaccuracy */
- xofs = 0.001f * BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
- yofs = 0.001f * BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
+ if (sizex > 0)
+ xofs = eps * BLI_rctf_size_x(&v2d->cur) / sizex;
+ if (sizey > 0)
+ yofs = eps * BLI_rctf_size_y(&v2d->cur) / sizey;
/* apply mask-based adjustments to cur rect (due to scrollers), to eliminate scaling artifacts */
view2d_map_cur_using_mask(v2d, &curmasked);
/* XXX ton: this flag set by outliner, for icons */
if (v2d->flag & V2D_PIXELOFS_X) {
- curmasked.xmin = floorf(curmasked.xmin) - (0.001f + xofs);
- curmasked.xmax = floorf(curmasked.xmax) - (0.001f + xofs);
+ curmasked.xmin = floorf(curmasked.xmin) - (eps + xofs);
+ curmasked.xmax = floorf(curmasked.xmax) - (eps + xofs);
}
if (v2d->flag & V2D_PIXELOFS_Y) {
- curmasked.ymin = floorf(curmasked.ymin) - (0.001f + yofs);
- curmasked.ymax = floorf(curmasked.ymax) - (0.001f + yofs);
+ curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs);
+ curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs);
}
/* set matrix on all appropriate axes */
* and only the time-grids with their zoomability can do so)
*/
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
- (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
+ (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
{
state |= UI_SCROLL_ARROWS;
}
fac2 = fac2 - time;
scroll_printstr(scene, fac, h, time + (float)FPS * fac2 / 100.0f, grid->powerx, V2D_UNIT_SECONDSSEQ, 'h');
+ break;
}
- break;
-
case V2D_UNIT_DEGREES: /* Graph Editor for rotation Drivers */
/* HACK: although we're drawing horizontal, we make this draw as 'vertical', just to get degree signs */
scroll_printstr(scene, fac, h, val, grid->powerx, V2D_UNIT_DEGREES, 'v');
* and only the time-grids with their zoomability can do so)
*/
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
- (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
+ (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
{
state |= UI_SCROLL_ARROWS;
}
* - column, row = the 2d-coordinates (in 2D-view / 'tot' rect space) the cell exists at
* - rect = coordinates of the cell (passed as single var instead of 4 separate, as it's more useful this way)
*/
-void UI_view2d_listview_cell_to_view(View2D *v2d, short columnwidth, short rowheight,
+void UI_view2d_listview_cell_to_view(View2D *v2d, float columnwidth, float rowheight,
float startx, float starty,
int column, int row, rctf *rect)
{
* - viewx, viewy = 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for
* - column, row = the 'coordinates' of the relevant 'cell'
*/
-void UI_view2d_listview_view_to_cell(View2D *v2d, short columnwidth, short rowheight, float startx, float starty,
+void UI_view2d_listview_view_to_cell(View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
float viewx, float viewy, int *column, int *row)
{
/* adjust view coordinates to be all positive ints, corrected for the start offset */
* - startx, starty = coordinates that the list starts from, which should be (0,0) for most views
* - column/row_min/max = the starting and ending column/row indices
*/
-void UI_view2d_listview_visible_cells(View2D *v2d, short columnwidth, short rowheight, float startx, float starty,
+void UI_view2d_listview_visible_cells(View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
int *column_min, int *column_max, int *row_min, int *row_max)
{
/* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */
* - x,y = coordinates to convert
* - viewx,viewy = resultant coordinates
*/
-void UI_view2d_region_to_view(View2D *v2d, int x, int y, float *r_viewx, float *r_viewy)
+void UI_view2d_region_to_view(View2D *v2d, float x, float y, float *r_viewx, float *r_viewy)
{
float div, ofs;
}
}
+void UI_view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
+{
+ /* express given coordinates as proportional values */
+ x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur);
+ y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur);
+
+ /* convert proportional distances to screen coordinates */
+ *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
+ *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
+}
+
/* *********************************************************************** */
/* Utilities */
}
/* no clip (yet) */
-void UI_view2d_text_cache_rectf(View2D *v2d, rctf *rect, const char *str, const char col[4])
+void UI_view2d_text_cache_rectf(View2D *v2d, const rctf *rect, const char *str, const char col[4])
{
int len = strlen(str) + 1;
View2DString *v2s = MEM_callocN(sizeof(View2DString) + len, "View2DString");
int col_pack_prev = 0;
/* investigate using BLF_ascender() */
- const float default_height = strings.first ? BLF_height_default("28") : 0.0f;
+ const float default_height = strings.first ? BLF_height_default("28", 3) : 0.0f;
// glMatrixMode(GL_PROJECTION);
// glPushMatrix();