2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2008 Blender Foundation. All rights reserved. */
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup edinterface
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
#include <cfloat>
|
|
|
|
|
#include <climits>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <cstring>
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
|
2008-10-08 18:07:56 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2009-07-02 18:12:46 +00:00
|
|
|
#include "DNA_userdef_types.h"
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
|
Refactor grid and scale indicator text drawing
This affects the timeline, dopesheet, graph editor, sequencer,
clip editor and nla editor.
Removed structs and enums: `V2D_ARG_DUMMY`, `eView2D_Units`,
`eView2D_Clamp`, `eView2D_Gridlines`, `View2DGrid`.
A main goal of this refactor is to get rid of the very generic
`View2DGrid` struct. The drawing code became very complex
because there were many different combinations of settings.
This refactor implements a different approach.
Instead of one very generic API, there are many slighly
different functions that do exactly, what we need in the
different editors. Only very little code is duplicated,
because the API functions compose some shared low level code.
This structure makes the code much easier to debug and change,
because every function has much fewer responsibilities.
Additionally, this refactor fixes some long standing bugs.
E.g. when `Show Seconds` is enabled, you zoom in and pan the view.
Or that the step size between displayed frame numbers was
always `>= 2`, no matter how close you zoom in.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D4776
2019-05-02 12:00:12 +02:00
|
|
|
#include "BLI_array.h"
|
2021-10-25 21:46:39 -05:00
|
|
|
#include "BLI_easing.h"
|
2014-04-17 15:14:07 +10:00
|
|
|
#include "BLI_link_utils.h"
|
2020-04-03 17:38:58 +02:00
|
|
|
#include "BLI_listbase.h"
|
2014-04-17 15:14:07 +10:00
|
|
|
#include "BLI_math.h"
|
|
|
|
|
#include "BLI_memarena.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_rect.h"
|
Refactor grid and scale indicator text drawing
This affects the timeline, dopesheet, graph editor, sequencer,
clip editor and nla editor.
Removed structs and enums: `V2D_ARG_DUMMY`, `eView2D_Units`,
`eView2D_Clamp`, `eView2D_Gridlines`, `View2DGrid`.
A main goal of this refactor is to get rid of the very generic
`View2DGrid` struct. The drawing code became very complex
because there were many different combinations of settings.
This refactor implements a different approach.
Instead of one very generic API, there are many slighly
different functions that do exactly, what we need in the
different editors. Only very little code is duplicated,
because the API functions compose some shared low level code.
This structure makes the code much easier to debug and change,
because every function has much fewer responsibilities.
Additionally, this refactor fixes some long standing bugs.
E.g. when `Show Seconds` is enabled, you zoom in and pan the view.
Or that the step size between displayed frame numbers was
always `>= 2`, no matter how close you zoom in.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D4776
2019-05-02 12:00:12 +02:00
|
|
|
#include "BLI_string.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_timecode.h"
|
|
|
|
|
#include "BLI_utildefines.h"
|
2008-12-12 16:29:33 +00:00
|
|
|
|
2008-12-18 02:56:48 +00:00
|
|
|
#include "BKE_context.h"
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
#include "BKE_global.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_screen.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2016-11-15 18:56:52 -05:00
|
|
|
#include "GPU_immediate.h"
|
2017-03-21 17:49:21 -04:00
|
|
|
#include "GPU_matrix.h"
|
2018-06-27 19:07:23 -06:00
|
|
|
#include "GPU_state.h"
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
|
|
2009-05-06 00:18:06 +00:00
|
|
|
#include "BLF_api.h"
|
|
|
|
|
|
2008-12-03 22:35:38 +00:00
|
|
|
#include "ED_screen.h"
|
|
|
|
|
|
2009-04-10 16:30:28 +00:00
|
|
|
#include "UI_interface.h"
|
Port of part of the Interface code to 2.50.
This is based on the current trunk version, so these files should not need
merges. There's two things (clipboard and intptr_t) that are missing in 2.50
and commented out with XXX 2.48, these can be enabled again once trunk is
merged into this branch.
Further this is not all interface code, there are many parts commented out:
* interface.c: nearly all button types, missing: links, chartab, keyevent.
* interface_draw.c: almost all code, with some small exceptions.
* interface_ops.c: this replaces ui_do_but and uiDoBlocks with two operators,
making it non-blocking.
* interface_regions: this is a part of interface.c, split off, contains code to
create regions for tooltips, menus, pupmenu (that one is crashing currently),
color chooser, basically regions with buttons which is fairly independent of
core interface code.
* interface_panel.c and interface_icons.c: not ported over, so no panels and
icons yet. Panels should probably become (free floating) regions?
* text.c: (formerly language.c) for drawing text and translation. this works
but is using bad globals still and could be cleaned up.
Header Files:
* ED_datafiles.h now has declarations for datatoc_ files, so those extern
declarations can be #included instead of repeated.
* The user interface code is in UI_interface.h and other UI_* files.
Core:
* The API for creating blocks, buttons, etc is nearly the same still. Blocks
are now created per region instead of per area.
* The code was made non-blocking, which means that any changes and redraws
should be possible while editing a button. That means though that we need
some sort of persistence even though the blender model is to recreate buttons
for each redraw. So when a new block is created, some matching happens to
find out which buttons correspond to buttons in the previously created block,
and for activated buttons some data is then copied over to the new button.
* Added UI_init/UI_init_userdef/UI_exit functions that should initialize code
in this module, instead of multiple function calls in the windowmanager.
* Removed most static/globals from interface.c.
* Removed UIafterfunc_ I don't think it's needed anymore, and not sure how it
would integrate here?
* Currently only full window redraws are used, this should become per region
and maybe per button later.
Operators:
* Events are currently handled through two operators: button activate and menu
handle. Operators may not be the best way to implement this, since there are
currently some issues with events being missed, but they can become a special
handler type instead, this should not be a big change.
* The button activate operator runs as long as a button is active, and will
handle all interaction with that button until the button is not activated
anymore. This means clicking, text editing, number dragging, opening menu
blocks, etc.
* Since this operator has to be non-blocking, the ui_do_but code needed to made
non-blocking. That means variables that were previously on the stack, now
need to be stored away in a struct such that they can be accessed again when
the operator receives more events.
* Additionally the place in the ui_do_but code indicated the state, now that
needs to be set explicit in order to handle the right events in the right
state. So an activated button can be in one of these states: init, highlight,
wait_flash, wait_release, wait_key_event, num_editing, text_editing,
text_selecting, block_open, exit.
* For each button type an ui_apply_but_* function has also been separated out
from ui_do_but. This makes it possible to continuously apply the button as
text is being typed for example, and there is an option in the code to enable
this. Since the code non-blocking and can deal with the button being deleted
even, it should be safe to do this.
* When editing text, dragging numbers, etc, the actual data (but->poin) is not
being edited, since that would mean data is being edited without correct
updates happening, while some other part of blender may be accessing that
data in the meantime. So data values, strings, vectors are written to a
temporary location and only flush in the apply function.
Regions:
* Menus, color chooser, tooltips etc all create screen level regions. Such menu
blocks give a handle to the button that creates it, which will contain the
results of the menu block once a MESSAGE event is received from that menu
block.
* For this type of menu block the coordinates used to be in window space. They
are still created that way and ui_positionblock still works with window
coordinates, but after that the block and buttons are brought back to region
coordinates since these are now contained in a region.
* The flush/overdraw frontbuffer drawing code was removed, the windowmanager
should have enough information with these screen level regions to have full
control over what gets drawn when and to then do correct compositing.
Testing:
* The header in the time space currently has some buttons to test the UI code.
2008-11-11 18:31:32 +00:00
|
|
|
#include "UI_view2d.h"
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
|
2008-12-26 13:11:04 +00:00
|
|
|
#include "interface_intern.h"
|
2008-12-12 11:41:05 +00:00
|
|
|
|
2020-04-16 20:42:56 +02:00
|
|
|
static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize);
|
2012-12-26 13:05:39 +00:00
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Internal Utilities
|
|
|
|
|
* \{ */
|
2009-01-28 18:26:47 +00:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
BLI_INLINE int clamp_float_to_int(const float f)
|
|
|
|
|
{
|
2020-03-27 11:16:17 +11:00
|
|
|
const float min = (float)INT_MIN;
|
|
|
|
|
const float max = (float)INT_MAX;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
if (UNLIKELY(f < min)) {
|
|
|
|
|
return min;
|
|
|
|
|
}
|
2020-07-03 14:20:10 +02:00
|
|
|
if (UNLIKELY(f > max)) {
|
2018-05-07 14:28:22 +02:00
|
|
|
return (int)max;
|
2014-04-21 16:47:16 +10:00
|
|
|
}
|
2020-07-03 14:20:10 +02:00
|
|
|
return (int)f;
|
2014-04-21 16:47:16 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* use instead of #BLI_rcti_rctf_copy so we have consistent behavior
|
|
|
|
|
* with users of #clamp_float_to_int.
|
|
|
|
|
*/
|
|
|
|
|
BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src)
|
|
|
|
|
{
|
|
|
|
|
dst->xmin = clamp_float_to_int(src->xmin);
|
|
|
|
|
dst->xmax = clamp_float_to_int(src->xmax);
|
|
|
|
|
dst->ymin = clamp_float_to_int(src->ymin);
|
|
|
|
|
dst->ymax = clamp_float_to_int(src->ymax);
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-29 17:10:46 +00:00
|
|
|
/* XXX still unresolved: scrolls hide/unhide vs region mask handling */
|
|
|
|
|
/* XXX there's V2D_SCROLL_HORIZONTAL_HIDE and V2D_SCROLL_HORIZONTAL_FULLR ... */
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Internal Scroll & Mask Utilities
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2015-05-05 03:13:47 +10:00
|
|
|
/**
|
|
|
|
|
* helper to allow scrollbars to dynamically hide
|
|
|
|
|
* - returns a copy of the scrollbar settings with the flags to display
|
|
|
|
|
* horizontal/vertical scrollbars removed
|
|
|
|
|
* - input scroll value is the v2d->scroll var
|
|
|
|
|
* - hide flags are set per region at drawtime
|
2010-01-31 11:13:31 +00:00
|
|
|
*/
|
2009-01-28 18:26:47 +00:00
|
|
|
static int view2d_scroll_mapped(int scroll)
|
|
|
|
|
{
|
2019-03-25 10:15:20 +11:00
|
|
|
if (scroll & V2D_SCROLL_HORIZONTAL_FULLR) {
|
2020-06-18 12:21:38 +10:00
|
|
|
scroll &= ~V2D_SCROLL_HORIZONTAL;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
if (scroll & V2D_SCROLL_VERTICAL_FULLR) {
|
2020-06-18 12:21:38 +10:00
|
|
|
scroll &= ~V2D_SCROLL_VERTICAL;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2009-01-28 18:26:47 +00:00
|
|
|
return scroll;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-22 16:41:18 +11:00
|
|
|
void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
|
|
|
|
|
{
|
|
|
|
|
r_mask->xmin = 0;
|
|
|
|
|
r_mask->ymin = 0;
|
|
|
|
|
r_mask->xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
|
|
|
|
|
r_mask->ymax = v2d->winy - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called each time #View2D.cur changes, to dynamically update masks.
|
|
|
|
|
*
|
|
|
|
|
* \param mask_scroll: Optionally clamp scrollbars by this region.
|
|
|
|
|
*/
|
2020-04-16 20:42:56 +02:00
|
|
|
static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
|
2009-01-28 18:26:47 +00:00
|
|
|
{
|
|
|
|
|
int scroll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-01-28 18:26:47 +00:00
|
|
|
/* mask - view frame */
|
2018-10-22 16:41:18 +11:00
|
|
|
UI_view2d_mask_from_win(v2d, &v2d->mask);
|
2022-04-03 00:00:42 -05:00
|
|
|
if (mask_scroll == nullptr) {
|
2018-10-22 16:41:18 +11:00
|
|
|
mask_scroll = &v2d->mask;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-16 20:42:56 +02:00
|
|
|
/* check size if hiding flag is set: */
|
|
|
|
|
if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
|
|
|
|
|
if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
|
|
|
|
|
if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
|
|
|
|
|
v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
|
2012-12-26 13:05:39 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-04-16 20:42:56 +02:00
|
|
|
}
|
|
|
|
|
if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
|
|
|
|
|
if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
|
|
|
|
|
if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
|
|
|
|
|
v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
|
2012-12-26 13:05:39 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-06-27 06:45:49 -07:00
|
|
|
/* Do not use mapped scroll here because we want to update scroller rects
|
|
|
|
|
* even if they are not displayed. For init purposes. See T75003.*/
|
|
|
|
|
scroll = v2d->scroll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-10-26 22:24:56 +11:00
|
|
|
/* Scrollers are based off region-size:
|
2018-11-14 12:53:15 +11:00
|
|
|
* - they can only be on one to two edges of the region they define
|
|
|
|
|
* - if they overlap, they must not occupy the corners (which are reserved for other widgets)
|
2009-02-09 04:39:25 +00:00
|
|
|
*/
|
2009-01-28 18:26:47 +00:00
|
|
|
if (scroll) {
|
2019-12-04 16:00:03 +01:00
|
|
|
float scroll_width, scroll_height;
|
|
|
|
|
|
2022-06-27 06:45:49 -07:00
|
|
|
UI_view2d_scroller_size_get(v2d, false, &scroll_width, &scroll_height);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-01-28 18:26:47 +00:00
|
|
|
/* vertical scroller */
|
|
|
|
|
if (scroll & V2D_SCROLL_LEFT) {
|
|
|
|
|
/* on left-hand edge of region */
|
2018-10-22 16:41:18 +11:00
|
|
|
v2d->vert = *mask_scroll;
|
2018-04-26 15:25:59 +02:00
|
|
|
v2d->vert.xmax = scroll_width;
|
2009-01-28 18:26:47 +00:00
|
|
|
}
|
|
|
|
|
else if (scroll & V2D_SCROLL_RIGHT) {
|
|
|
|
|
/* on right-hand edge of region */
|
2018-10-22 16:41:18 +11:00
|
|
|
v2d->vert = *mask_scroll;
|
2009-02-09 04:39:25 +00:00
|
|
|
v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
|
2018-04-26 15:25:59 +02:00
|
|
|
v2d->vert.xmin = v2d->vert.xmax - scroll_width;
|
2009-01-28 18:26:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-08 15:09:02 +02:00
|
|
|
/* Currently, all regions that have vertical scale handles,
|
2019-05-07 15:09:14 +02:00
|
|
|
* also have the scrubbing area at the top.
|
|
|
|
|
* So the scrollbar has to move down a bit. */
|
2019-05-08 15:09:02 +02:00
|
|
|
if (scroll & V2D_SCROLL_VERTICAL_HANDLES) {
|
2019-05-28 16:17:15 +10:00
|
|
|
v2d->vert.ymax -= UI_TIME_SCRUB_MARGIN_Y;
|
2019-05-07 15:09:14 +02:00
|
|
|
}
|
|
|
|
|
|
2009-01-28 18:26:47 +00:00
|
|
|
/* horizontal scroller */
|
2020-06-18 12:21:38 +10:00
|
|
|
if (scroll & V2D_SCROLL_BOTTOM) {
|
2012-12-26 13:05:39 +00:00
|
|
|
/* on bottom edge of region */
|
2018-10-22 16:41:18 +11:00
|
|
|
v2d->hor = *mask_scroll;
|
2018-04-26 15:25:59 +02:00
|
|
|
v2d->hor.ymax = scroll_height;
|
2009-01-28 18:26:47 +00:00
|
|
|
}
|
|
|
|
|
else if (scroll & V2D_SCROLL_TOP) {
|
|
|
|
|
/* on upper edge of region */
|
2018-10-22 16:41:18 +11:00
|
|
|
v2d->hor = *mask_scroll;
|
2018-04-26 15:25:59 +02:00
|
|
|
v2d->hor.ymin = v2d->hor.ymax - scroll_height;
|
2009-01-28 18:26:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name View2D Refresh and Validation (Spatial)
|
|
|
|
|
* \{ */
|
2008-12-01 00:20:19 +00:00
|
|
|
|
2008-12-16 11:24:24 +00:00
|
|
|
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
|
2008-12-15 11:58:57 +00:00
|
|
|
{
|
2013-11-26 06:39:14 +11:00
|
|
|
bool tot_changed = false, do_init;
|
2020-03-15 17:32:25 +11:00
|
|
|
const uiStyle *style = UI_style_get();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-01 13:02:21 +10:00
|
|
|
do_init = (v2d->flag & V2D_IS_INIT) == 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
|
|
|
|
|
switch (type) {
|
|
|
|
|
/* 'standard view' - optimum setup for 'standard' view behavior,
|
2018-09-02 18:28:27 +10:00
|
|
|
* that should be used new views as basis for their
|
|
|
|
|
* own unique View2D settings, which should be used instead of this in most cases...
|
2012-12-26 13:05:39 +00:00
|
|
|
*/
|
|
|
|
|
case V2D_COMMONVIEW_STANDARD: {
|
2019-01-15 23:24:20 +11:00
|
|
|
/* for now, aspect ratio should be maintained,
|
|
|
|
|
* and zoom is clamped within sane default limits */
|
2012-12-26 13:05:39 +00:00
|
|
|
v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
|
|
|
|
|
v2d->minzoom = 0.01f;
|
|
|
|
|
v2d->maxzoom = 1000.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-17 08:44:38 +02:00
|
|
|
/* View2D tot rect and cur should be same size,
|
|
|
|
|
* and aligned using 'standard' OpenGL coordinates for now:
|
2018-09-02 18:28:27 +10:00
|
|
|
* - region can resize 'tot' later to fit other data
|
|
|
|
|
* - keeptot is only within bounds, as strict locking is not that critical
|
|
|
|
|
* - view is aligned for (0,0) -> (winx-1, winy-1) setup
|
2008-12-17 10:25:02 +00:00
|
|
|
*/
|
2012-12-26 13:05:39 +00:00
|
|
|
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
|
|
|
|
|
v2d->keeptot = V2D_KEEPTOT_BOUNDS;
|
|
|
|
|
if (do_init) {
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.xmin = v2d->tot.ymin = 0.0f;
|
|
|
|
|
v2d->tot.xmax = (float)(winx - 1);
|
|
|
|
|
v2d->tot.ymax = (float)(winy - 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
v2d->cur = v2d->tot;
|
2008-12-17 10:25:02 +00:00
|
|
|
}
|
2012-12-26 13:05:39 +00:00
|
|
|
/* scrollers - should we have these by default? */
|
|
|
|
|
/* XXX for now, we don't override this, or set it either! */
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2012-12-26 13:05:39 +00:00
|
|
|
}
|
|
|
|
|
/* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
|
|
|
|
|
case V2D_COMMONVIEW_LIST: {
|
|
|
|
|
/* zoom + aspect ratio are locked */
|
|
|
|
|
v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
|
|
|
|
|
v2d->minzoom = v2d->maxzoom = 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
|
|
|
|
|
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
|
|
|
|
|
v2d->keeptot = V2D_KEEPTOT_STRICT;
|
2022-06-27 06:45:49 -07:00
|
|
|
v2d->keepofs = (V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
|
2012-12-26 13:05:39 +00:00
|
|
|
tot_changed = do_init;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* scroller settings are currently not set here... that is left for regions... */
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2012-12-26 13:05:39 +00:00
|
|
|
}
|
2019-04-17 08:44:38 +02:00
|
|
|
/* '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. */
|
2012-12-26 13:05:39 +00:00
|
|
|
case V2D_COMMONVIEW_STACK: {
|
|
|
|
|
/* zoom + aspect ratio are locked */
|
|
|
|
|
v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
|
|
|
|
|
v2d->minzoom = v2d->maxzoom = 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
|
|
|
|
|
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
|
|
|
|
|
v2d->keeptot = V2D_KEEPTOT_STRICT;
|
2022-06-27 06:45:49 -07:00
|
|
|
v2d->keepofs = (V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
|
2012-12-26 13:05:39 +00:00
|
|
|
tot_changed = do_init;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* scroller settings are currently not set here... that is left for regions... */
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2012-12-26 13:05:39 +00:00
|
|
|
}
|
2019-01-15 23:24:20 +11:00
|
|
|
/* 'header' regions - zoom, aspect ratio,
|
|
|
|
|
* alignment, and panning restrictions are set here */
|
2012-12-26 13:05:39 +00:00
|
|
|
case V2D_COMMONVIEW_HEADER: {
|
|
|
|
|
/* zoom + aspect ratio are locked */
|
|
|
|
|
v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
|
|
|
|
|
v2d->minzoom = v2d->maxzoom = 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
if (do_init) {
|
|
|
|
|
v2d->tot.xmin = 0.0f;
|
|
|
|
|
v2d->tot.xmax = winx;
|
|
|
|
|
v2d->tot.ymin = 0.0f;
|
|
|
|
|
v2d->tot.ymax = winy;
|
|
|
|
|
v2d->cur = v2d->tot;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
v2d->min[0] = v2d->max[0] = (float)(winx - 1);
|
|
|
|
|
v2d->min[1] = v2d->max[1] = (float)(winy - 1);
|
2008-12-17 10:25:02 +00:00
|
|
|
}
|
2012-12-26 13:05:39 +00:00
|
|
|
/* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
|
|
|
|
|
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
|
|
|
|
|
v2d->keeptot = V2D_KEEPTOT_STRICT;
|
|
|
|
|
tot_changed = do_init;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* panning in y-axis is prohibited */
|
|
|
|
|
v2d->keepofs = V2D_LOCKOFS_Y;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* absolutely no scrollers allowed */
|
|
|
|
|
v2d->scroll = 0;
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2012-12-26 13:05:39 +00:00
|
|
|
}
|
|
|
|
|
/* panels view, with horizontal/vertical align */
|
|
|
|
|
case V2D_COMMONVIEW_PANELS_UI: {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* for now, aspect ratio should be maintained,
|
|
|
|
|
* and zoom is clamped within sane default limits */
|
2012-12-26 13:05:39 +00:00
|
|
|
v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
|
|
|
|
|
v2d->minzoom = 0.5f;
|
|
|
|
|
v2d->maxzoom = 2.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
|
|
|
|
|
v2d->keeptot = V2D_KEEPTOT_BOUNDS;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: scroll is being flipped in #ED_region_panels() drawing. */
|
2016-01-25 08:33:22 +11:00
|
|
|
v2d->scroll |= (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
if (do_init) {
|
2020-08-26 10:11:13 +10:00
|
|
|
const float panelzoom = (style) ? style->panelzoom : 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.xmin = 0.0f;
|
2016-01-09 05:42:37 +11:00
|
|
|
v2d->tot.xmax = winx;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.ymax = 0.0f;
|
|
|
|
|
v2d->tot.ymin = -winy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.xmin = 0.0f;
|
2016-01-09 05:42:37 +11:00
|
|
|
v2d->cur.xmax = (winx)*panelzoom;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.ymax = 0.0f;
|
2012-03-30 01:51:25 +00:00
|
|
|
v2d->cur.ymin = (-winy) * panelzoom;
|
2009-02-10 15:38:00 +00:00
|
|
|
}
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2008-12-17 10:25:02 +00:00
|
|
|
}
|
2012-12-26 13:05:39 +00:00
|
|
|
/* other view types are completely defined using their own settings already */
|
|
|
|
|
default:
|
2019-01-15 23:24:20 +11:00
|
|
|
/* we don't do anything here,
|
|
|
|
|
* as settings should be fine, but just make sure that rect */
|
2012-12-26 13:05:39 +00:00
|
|
|
break;
|
2008-12-17 10:25:02 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-01 13:18:47 +10:00
|
|
|
/* set initialized flag so that View2D doesn't get reinitialized next time again */
|
2020-08-01 13:02:21 +10:00
|
|
|
v2d->flag |= V2D_IS_INIT;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-16 11:24:24 +00:00
|
|
|
/* store view size */
|
2012-03-30 01:51:25 +00:00
|
|
|
v2d->winx = winx;
|
|
|
|
|
v2d->winy = winy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
view2d_masks(v2d, nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-07 01:31:18 +02:00
|
|
|
if (do_init) {
|
|
|
|
|
/* Visible by default. */
|
|
|
|
|
v2d->alpha_hor = v2d->alpha_vert = 255;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-16 11:24:24 +00:00
|
|
|
/* set 'tot' rect before setting cur? */
|
2020-04-16 20:42:56 +02:00
|
|
|
/* XXX confusing stuff here still */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (tot_changed) {
|
2012-12-26 13:05:39 +00:00
|
|
|
UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2020-04-16 20:42:56 +02:00
|
|
|
ui_view2d_curRect_validate_resize(v2d, !do_init);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
Port of part of the Interface code to 2.50.
This is based on the current trunk version, so these files should not need
merges. There's two things (clipboard and intptr_t) that are missing in 2.50
and commented out with XXX 2.48, these can be enabled again once trunk is
merged into this branch.
Further this is not all interface code, there are many parts commented out:
* interface.c: nearly all button types, missing: links, chartab, keyevent.
* interface_draw.c: almost all code, with some small exceptions.
* interface_ops.c: this replaces ui_do_but and uiDoBlocks with two operators,
making it non-blocking.
* interface_regions: this is a part of interface.c, split off, contains code to
create regions for tooltips, menus, pupmenu (that one is crashing currently),
color chooser, basically regions with buttons which is fairly independent of
core interface code.
* interface_panel.c and interface_icons.c: not ported over, so no panels and
icons yet. Panels should probably become (free floating) regions?
* text.c: (formerly language.c) for drawing text and translation. this works
but is using bad globals still and could be cleaned up.
Header Files:
* ED_datafiles.h now has declarations for datatoc_ files, so those extern
declarations can be #included instead of repeated.
* The user interface code is in UI_interface.h and other UI_* files.
Core:
* The API for creating blocks, buttons, etc is nearly the same still. Blocks
are now created per region instead of per area.
* The code was made non-blocking, which means that any changes and redraws
should be possible while editing a button. That means though that we need
some sort of persistence even though the blender model is to recreate buttons
for each redraw. So when a new block is created, some matching happens to
find out which buttons correspond to buttons in the previously created block,
and for activated buttons some data is then copied over to the new button.
* Added UI_init/UI_init_userdef/UI_exit functions that should initialize code
in this module, instead of multiple function calls in the windowmanager.
* Removed most static/globals from interface.c.
* Removed UIafterfunc_ I don't think it's needed anymore, and not sure how it
would integrate here?
* Currently only full window redraws are used, this should become per region
and maybe per button later.
Operators:
* Events are currently handled through two operators: button activate and menu
handle. Operators may not be the best way to implement this, since there are
currently some issues with events being missed, but they can become a special
handler type instead, this should not be a big change.
* The button activate operator runs as long as a button is active, and will
handle all interaction with that button until the button is not activated
anymore. This means clicking, text editing, number dragging, opening menu
blocks, etc.
* Since this operator has to be non-blocking, the ui_do_but code needed to made
non-blocking. That means variables that were previously on the stack, now
need to be stored away in a struct such that they can be accessed again when
the operator receives more events.
* Additionally the place in the ui_do_but code indicated the state, now that
needs to be set explicit in order to handle the right events in the right
state. So an activated button can be in one of these states: init, highlight,
wait_flash, wait_release, wait_key_event, num_editing, text_editing,
text_selecting, block_open, exit.
* For each button type an ui_apply_but_* function has also been separated out
from ui_do_but. This makes it possible to continuously apply the button as
text is being typed for example, and there is an option in the code to enable
this. Since the code non-blocking and can deal with the button being deleted
even, it should be safe to do this.
* When editing text, dragging numbers, etc, the actual data (but->poin) is not
being edited, since that would mean data is being edited without correct
updates happening, while some other part of blender may be accessing that
data in the meantime. So data values, strings, vectors are written to a
temporary location and only flush in the apply function.
Regions:
* Menus, color chooser, tooltips etc all create screen level regions. Such menu
blocks give a handle to the button that creates it, which will contain the
results of the menu block once a MESSAGE event is received from that menu
block.
* For this type of menu block the coordinates used to be in window space. They
are still created that way and ui_positionblock still works with window
coordinates, but after that the block and buttons are brought back to region
coordinates since these are now contained in a region.
* The flush/overdraw frontbuffer drawing code was removed, the windowmanager
should have enough information with these screen level regions to have full
control over what gets drawn when and to then do correct compositing.
Testing:
* The header in the time space currently has some buttons to test the UI code.
2008-11-11 18:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
2015-05-31 14:20:03 +10:00
|
|
|
/**
|
|
|
|
|
* Ensure View2D rects remain in a viable configuration
|
|
|
|
|
* 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot'
|
2008-11-30 06:15:33 +00:00
|
|
|
*/
|
|
|
|
|
/* XXX pre2.5 -> this used to be called test_view2d() */
|
2020-04-16 20:42:56 +02:00
|
|
|
static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
|
2008-11-30 06:15:33 +00:00
|
|
|
{
|
2008-12-06 09:25:42 +00:00
|
|
|
float totwidth, totheight, curwidth, curheight, width, height;
|
2008-12-10 09:07:15 +00:00
|
|
|
float winx, winy;
|
2008-11-30 06:15:33 +00:00
|
|
|
rctf *cur, *tot;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-08 22:33:58 +01:00
|
|
|
/* use mask as size of region that View2D resides in, as it takes into account
|
|
|
|
|
* scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
|
2012-09-15 11:48:20 +00:00
|
|
|
winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
|
|
|
|
|
winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* get pointers to rcts for less typing */
|
2012-03-30 01:51:25 +00:00
|
|
|
cur = &v2d->cur;
|
|
|
|
|
tot = &v2d->tot;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* we must satisfy the following constraints (in decreasing order of importance):
|
2018-11-14 12:53:15 +11:00
|
|
|
* - alignment restrictions are respected
|
|
|
|
|
* - cur must not fall outside of tot
|
|
|
|
|
* - axis locks (zoom and offset) must be maintained
|
|
|
|
|
* - zoom must not be excessive (check either sizes or zoom values)
|
|
|
|
|
* - aspect ratio should be respected (NOTE: this is quite closely related to zoom too)
|
2008-12-06 09:25:42 +00:00
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* Step 1: if keepzoom, adjust the sizes of the rects only
|
2018-11-14 12:53:15 +11:00
|
|
|
* - firstly, we calculate the sizes of the rects
|
|
|
|
|
* - curwidth and curheight are saved as reference... modify width and height values here
|
2008-12-06 09:25:42 +00:00
|
|
|
*/
|
2012-09-15 11:48:20 +00:00
|
|
|
totwidth = BLI_rctf_size_x(tot);
|
|
|
|
|
totheight = BLI_rctf_size_y(tot);
|
2015-02-08 22:33:58 +01:00
|
|
|
/* keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
|
2012-09-15 11:48:20 +00:00
|
|
|
curwidth = width = BLI_rctf_size_x(cur);
|
|
|
|
|
curheight = height = BLI_rctf_size_y(cur);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* if zoom is locked, size on the appropriate axis is reset to mask size */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (v2d->keepzoom & V2D_LOCKZOOM_X) {
|
2012-03-30 01:51:25 +00:00
|
|
|
width = winx;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
if (v2d->keepzoom & V2D_LOCKZOOM_Y) {
|
2012-03-30 01:51:25 +00:00
|
|
|
height = winy;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-23 10:47:12 +02:00
|
|
|
/* values used to divide, so make it safe
|
2010-01-25 11:06:55 +00:00
|
|
|
* NOTE: width and height must use FLT_MIN instead of 1, otherwise it is impossible to
|
2012-03-30 01:51:25 +00:00
|
|
|
* get enough resolution in Graph Editor for editing some curves
|
2010-01-25 11:06:55 +00:00
|
|
|
*/
|
2019-03-25 10:15:20 +11:00
|
|
|
if (width < FLT_MIN) {
|
|
|
|
|
width = 1;
|
|
|
|
|
}
|
|
|
|
|
if (height < FLT_MIN) {
|
|
|
|
|
height = 1;
|
|
|
|
|
}
|
|
|
|
|
if (winx < 1) {
|
|
|
|
|
winx = 1;
|
|
|
|
|
}
|
|
|
|
|
if (winy < 1) {
|
|
|
|
|
winy = 1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-07-29 22:57:53 +00:00
|
|
|
/* V2D_LIMITZOOM indicates that zoom level should be preserved when the window size changes */
|
|
|
|
|
if (resize && (v2d->keepzoom & V2D_KEEPZOOM)) {
|
|
|
|
|
float zoom, oldzoom;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
|
|
|
|
|
zoom = winx / width;
|
|
|
|
|
oldzoom = v2d->oldwinx / curwidth;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-25 10:15:20 +11:00
|
|
|
if (oldzoom != zoom) {
|
2012-03-30 01:51:25 +00:00
|
|
|
width *= zoom / oldzoom;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2009-07-29 22:57:53 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
|
|
|
|
|
zoom = winy / height;
|
|
|
|
|
oldzoom = v2d->oldwiny / curheight;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-25 10:15:20 +11:00
|
|
|
if (oldzoom != zoom) {
|
2012-03-30 01:51:25 +00:00
|
|
|
height *= zoom / oldzoom;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2009-07-29 22:57:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-05-23 10:47:12 +02:00
|
|
|
/* keepzoom (V2D_LIMITZOOM set), indicates that zoom level on each axis must not exceed limits
|
2008-12-06 09:25:42 +00:00
|
|
|
* NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
|
|
|
|
|
*/
|
2009-07-29 22:57:53 +00:00
|
|
|
else if (v2d->keepzoom & V2D_LIMITZOOM) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* check if excessive zoom on x-axis */
|
2012-03-30 01:51:25 +00:00
|
|
|
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
|
2014-01-15 10:03:56 +11:00
|
|
|
const float zoom = winx / width;
|
|
|
|
|
if (zoom < v2d->minzoom) {
|
|
|
|
|
width = winx / v2d->minzoom;
|
|
|
|
|
}
|
|
|
|
|
else if (zoom > v2d->maxzoom) {
|
|
|
|
|
width = winx / v2d->maxzoom;
|
2008-12-11 03:50:50 +00:00
|
|
|
}
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* check if excessive zoom on y-axis */
|
2012-03-30 01:51:25 +00:00
|
|
|
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
|
2014-01-15 10:03:56 +11:00
|
|
|
const float zoom = winy / height;
|
|
|
|
|
if (zoom < v2d->minzoom) {
|
|
|
|
|
height = winy / v2d->minzoom;
|
|
|
|
|
}
|
|
|
|
|
else if (zoom > v2d->maxzoom) {
|
|
|
|
|
height = winy / v2d->maxzoom;
|
2008-12-11 03:50:50 +00:00
|
|
|
}
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2019-01-15 23:24:20 +11:00
|
|
|
/* make sure sizes don't exceed that of the min/max sizes
|
|
|
|
|
* (even though we're not doing zoom clamping) */
|
2008-12-06 09:25:42 +00:00
|
|
|
CLAMP(width, v2d->min[0], v2d->max[0]);
|
|
|
|
|
CLAMP(height, v2d->min[1], v2d->max[1]);
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* check if we should restore aspect ratio (if view size changed) */
|
2022-06-27 06:45:49 -07:00
|
|
|
if (v2d->keepzoom & V2D_KEEPASPECT && !(v2d->keeptot == V2D_KEEPTOT_STRICT)) {
|
|
|
|
|
bool do_x = false, do_y = false, do_cur;
|
2015-10-17 02:01:41 +11:00
|
|
|
float curRatio, winRatio;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-11-30 06:15:33 +00:00
|
|
|
/* when a window edge changes, the aspect ratio can't be used to
|
2018-09-27 15:35:22 +02:00
|
|
|
* find which is the best new 'cur' rect. that's why it stores 'old'
|
2008-11-30 06:15:33 +00:00
|
|
|
*/
|
2019-03-25 10:15:20 +11:00
|
|
|
if (winx != v2d->oldwinx) {
|
|
|
|
|
do_x = true;
|
|
|
|
|
}
|
|
|
|
|
if (winy != v2d->oldwiny) {
|
|
|
|
|
do_y = true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-17 02:01:41 +11:00
|
|
|
curRatio = height / width;
|
2012-03-30 01:51:25 +00:00
|
|
|
winRatio = winy / winx;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Both sizes change (area/region maximized). */
|
2008-11-30 06:15:33 +00:00
|
|
|
if (do_x == do_y) {
|
2008-12-06 09:25:42 +00:00
|
|
|
if (do_x && do_y) {
|
|
|
|
|
/* here is 1,1 case, so all others must be 0,0 */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (fabsf(winx - v2d->oldwinx) > fabsf(winy - v2d->oldwiny)) {
|
|
|
|
|
do_y = false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
do_x = false;
|
|
|
|
|
}
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2015-10-17 02:01:41 +11:00
|
|
|
else if (winRatio > curRatio) {
|
2014-01-04 17:16:19 +11:00
|
|
|
do_x = false;
|
2013-03-09 03:46:30 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2014-01-04 17:16:19 +11:00
|
|
|
do_x = true;
|
2013-03-09 03:46:30 +00:00
|
|
|
}
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2012-03-30 01:51:25 +00:00
|
|
|
do_cur = do_x;
|
2012-05-27 19:40:36 +00:00
|
|
|
/* do_win = do_y; */ /* UNUSED */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
if (do_cur) {
|
2022-06-27 06:45:49 -07:00
|
|
|
/* portrait window: correct for x */
|
|
|
|
|
width = height / winRatio;
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2022-06-27 06:45:49 -07:00
|
|
|
/* landscape window: correct for y */
|
|
|
|
|
height = width * winRatio;
|
2008-12-18 09:20:29 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-11-30 06:15:33 +00:00
|
|
|
/* store region size for next time */
|
2012-03-30 01:51:25 +00:00
|
|
|
v2d->oldwinx = (short)winx;
|
|
|
|
|
v2d->oldwiny = (short)winy;
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* Step 2: apply new sizes to cur rect,
|
|
|
|
|
* but need to take into account alignment settings here... */
|
2008-12-06 09:25:42 +00:00
|
|
|
if ((width != curwidth) || (height != curheight)) {
|
|
|
|
|
float temp, dh;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-13 17:44:51 +11:00
|
|
|
/* Resize from center-point, unless otherwise specified. */
|
2008-12-06 09:25:42 +00:00
|
|
|
if (width != curwidth) {
|
2009-05-19 17:13:33 +00:00
|
|
|
if (v2d->keepofs & V2D_LOCKOFS_X) {
|
2012-09-15 11:48:20 +00:00
|
|
|
cur->xmax += width - BLI_rctf_size_x(cur);
|
2009-05-19 17:13:33 +00:00
|
|
|
}
|
2009-07-29 22:57:53 +00:00
|
|
|
else if (v2d->keepofs & V2D_KEEPOFS_X) {
|
2019-03-25 10:15:20 +11:00
|
|
|
if (v2d->align & V2D_ALIGN_NO_POS_X) {
|
2012-09-15 11:48:20 +00:00
|
|
|
cur->xmin -= width - BLI_rctf_size_x(cur);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2012-09-15 11:48:20 +00:00
|
|
|
cur->xmax += width - BLI_rctf_size_x(cur);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2009-05-19 17:13:33 +00:00
|
|
|
else {
|
2012-09-15 11:48:20 +00:00
|
|
|
temp = BLI_rctf_cent_x(cur);
|
2012-03-30 01:51:25 +00:00
|
|
|
dh = width * 0.5f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-05-19 17:13:33 +00:00
|
|
|
cur->xmin = temp - dh;
|
|
|
|
|
cur->xmax = temp + dh;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2009-05-19 17:13:33 +00:00
|
|
|
}
|
2008-12-06 09:25:42 +00:00
|
|
|
if (height != curheight) {
|
2009-05-19 17:13:33 +00:00
|
|
|
if (v2d->keepofs & V2D_LOCKOFS_Y) {
|
2012-09-15 11:48:20 +00:00
|
|
|
cur->ymax += height - BLI_rctf_size_y(cur);
|
2009-05-19 17:13:33 +00:00
|
|
|
}
|
2009-07-29 22:57:53 +00:00
|
|
|
else if (v2d->keepofs & V2D_KEEPOFS_Y) {
|
2019-03-25 10:15:20 +11:00
|
|
|
if (v2d->align & V2D_ALIGN_NO_POS_Y) {
|
2012-09-15 11:48:20 +00:00
|
|
|
cur->ymin -= height - BLI_rctf_size_y(cur);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2012-09-15 11:48:20 +00:00
|
|
|
cur->ymax += height - BLI_rctf_size_y(cur);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2009-05-19 17:13:33 +00:00
|
|
|
else {
|
2012-09-15 11:48:20 +00:00
|
|
|
temp = BLI_rctf_cent_y(cur);
|
2012-03-30 01:51:25 +00:00
|
|
|
dh = height * 0.5f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-05-19 17:13:33 +00:00
|
|
|
cur->ymin = temp - dh;
|
|
|
|
|
cur->ymax = temp + dh;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2009-05-19 17:13:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 00:11:33 +00:00
|
|
|
/* Step 3: adjust so that it doesn't fall outside of bounds of 'tot' */
|
2008-11-30 06:15:33 +00:00
|
|
|
if (v2d->keeptot) {
|
2008-12-11 03:50:50 +00:00
|
|
|
float temp, diff;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* recalculate extents of cur */
|
2012-09-15 11:48:20 +00:00
|
|
|
curwidth = BLI_rctf_size_x(cur);
|
|
|
|
|
curheight = BLI_rctf_size_y(cur);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* width */
|
2012-09-09 00:00:21 +00:00
|
|
|
if ((curwidth > totwidth) &&
|
|
|
|
|
!(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_X | V2D_LIMITZOOM))) {
|
2008-12-06 09:25:42 +00:00
|
|
|
/* if zoom doesn't have to be maintained, just clamp edges */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (cur->xmin < tot->xmin) {
|
|
|
|
|
cur->xmin = tot->xmin;
|
|
|
|
|
}
|
|
|
|
|
if (cur->xmax > tot->xmax) {
|
|
|
|
|
cur->xmax = tot->xmax;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2008-12-16 11:24:24 +00:00
|
|
|
else if (v2d->keeptot == V2D_KEEPTOT_STRICT) {
|
2018-05-23 10:47:12 +02:00
|
|
|
/* This is an exception for the outliner (and later channel-lists, headers)
|
2018-11-14 12:53:15 +11:00
|
|
|
* - must clamp within tot rect (absolutely no excuses)
|
|
|
|
|
* --> therefore, cur->xmin must not be less than tot->xmin
|
2008-12-06 09:25:42 +00:00
|
|
|
*/
|
|
|
|
|
if (cur->xmin < tot->xmin) {
|
|
|
|
|
/* move cur across so that it sits at minimum of tot */
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = tot->xmin - cur->xmin;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
cur->xmin += temp;
|
|
|
|
|
cur->xmax += temp;
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2008-12-06 09:25:42 +00:00
|
|
|
else if (cur->xmax > tot->xmax) {
|
2018-05-23 10:47:12 +02:00
|
|
|
/* - only offset by difference of cur-xmax and tot-xmax if that would not move
|
2018-09-02 18:28:27 +10:00
|
|
|
* cur-xmin to lie past tot-xmin
|
2008-12-06 09:25:42 +00:00
|
|
|
* - otherwise, simply shift to tot-xmin???
|
|
|
|
|
*/
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = cur->xmax - tot->xmax;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
if ((cur->xmin - temp) < tot->xmin) {
|
2008-12-10 09:07:15 +00:00
|
|
|
/* only offset by difference from cur-min and tot-min */
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = cur->xmin - tot->xmin;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
cur->xmin -= temp;
|
|
|
|
|
cur->xmax -= temp;
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2008-12-06 09:25:42 +00:00
|
|
|
else {
|
|
|
|
|
cur->xmin -= temp;
|
|
|
|
|
cur->xmax -= temp;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2008-12-06 09:25:42 +00:00
|
|
|
/* This here occurs when:
|
2018-11-14 12:53:15 +11:00
|
|
|
* - width too big, but maintaining zoom (i.e. widths cannot be changed)
|
|
|
|
|
* - width is OK, but need to check if outside of boundaries
|
2018-05-23 10:47:12 +02:00
|
|
|
*
|
2008-12-06 09:25:42 +00:00
|
|
|
* So, resolution is to just shift view by the gap between the extremities.
|
2020-02-10 10:33:00 +11:00
|
|
|
* We favor moving the 'minimum' across, as that's origin for most things.
|
2021-07-03 23:08:40 +10:00
|
|
|
* (XXX: in the past, max was favored... if there are bugs, swap!)
|
2008-12-06 09:25:42 +00:00
|
|
|
*/
|
2009-07-29 22:57:53 +00:00
|
|
|
if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
|
2019-01-15 23:24:20 +11:00
|
|
|
/* outside boundaries on both sides,
|
|
|
|
|
* so take middle-point of tot, and place in balanced way */
|
2012-09-15 11:48:20 +00:00
|
|
|
temp = BLI_rctf_cent_x(tot);
|
2012-10-30 15:33:03 +00:00
|
|
|
diff = curwidth * 0.5f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
cur->xmin = temp - diff;
|
|
|
|
|
cur->xmax = temp + diff;
|
2008-12-11 03:50:50 +00:00
|
|
|
}
|
2008-12-14 08:32:21 +00:00
|
|
|
else if (cur->xmin < tot->xmin) {
|
|
|
|
|
/* move cur across so that it sits at minimum of tot */
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = tot->xmin - cur->xmin;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
cur->xmin += temp;
|
|
|
|
|
cur->xmax += temp;
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
2008-12-14 08:32:21 +00:00
|
|
|
else if (cur->xmax > tot->xmax) {
|
2018-05-23 10:47:12 +02:00
|
|
|
/* - only offset by difference of cur-xmax and tot-xmax if that would not move
|
2018-09-02 18:28:27 +10:00
|
|
|
* cur-xmin to lie past tot-xmin
|
2008-12-14 08:32:21 +00:00
|
|
|
* - otherwise, simply shift to tot-xmin???
|
|
|
|
|
*/
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = cur->xmax - tot->xmax;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-14 08:32:21 +00:00
|
|
|
if ((cur->xmin - temp) < tot->xmin) {
|
|
|
|
|
/* only offset by difference from cur-min and tot-min */
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = cur->xmin - tot->xmin;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-14 08:32:21 +00:00
|
|
|
cur->xmin -= temp;
|
|
|
|
|
cur->xmax -= temp;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cur->xmin -= temp;
|
|
|
|
|
cur->xmax -= temp;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2008-12-14 08:32:21 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
/* height */
|
2012-09-09 00:00:21 +00:00
|
|
|
if ((curheight > totheight) &&
|
|
|
|
|
!(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_Y | V2D_LIMITZOOM))) {
|
2008-12-06 09:25:42 +00:00
|
|
|
/* if zoom doesn't have to be maintained, just clamp edges */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (cur->ymin < tot->ymin) {
|
|
|
|
|
cur->ymin = tot->ymin;
|
|
|
|
|
}
|
|
|
|
|
if (cur->ymax > tot->ymax) {
|
|
|
|
|
cur->ymax = tot->ymax;
|
|
|
|
|
}
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2008-12-06 09:25:42 +00:00
|
|
|
/* This here occurs when:
|
2018-11-14 12:53:15 +11:00
|
|
|
* - height too big, but maintaining zoom (i.e. heights cannot be changed)
|
|
|
|
|
* - height is OK, but need to check if outside of boundaries
|
2018-05-23 10:47:12 +02:00
|
|
|
*
|
2008-12-06 09:25:42 +00:00
|
|
|
* So, resolution is to just shift view by the gap between the extremities.
|
2020-02-10 10:33:00 +11:00
|
|
|
* We favor moving the 'minimum' across, as that's origin for most things.
|
2008-12-06 09:25:42 +00:00
|
|
|
*/
|
2008-12-11 03:50:50 +00:00
|
|
|
if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
|
2019-01-15 23:24:20 +11:00
|
|
|
/* outside boundaries on both sides,
|
|
|
|
|
* so take middle-point of tot, and place in balanced way */
|
2012-09-15 11:48:20 +00:00
|
|
|
temp = BLI_rctf_cent_y(tot);
|
2012-03-30 01:51:25 +00:00
|
|
|
diff = curheight * 0.5f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
cur->ymin = temp - diff;
|
|
|
|
|
cur->ymax = temp + diff;
|
2008-12-11 03:50:50 +00:00
|
|
|
}
|
|
|
|
|
else if (cur->ymin < tot->ymin) {
|
2008-12-06 09:25:42 +00:00
|
|
|
/* there's still space remaining, so shift up */
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = tot->ymin - cur->ymin;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
cur->ymin += temp;
|
|
|
|
|
cur->ymax += temp;
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
|
|
|
|
else if (cur->ymax > tot->ymax) {
|
2008-12-10 09:07:15 +00:00
|
|
|
/* there's still space remaining, so shift down */
|
2012-03-30 01:51:25 +00:00
|
|
|
temp = cur->ymax - tot->ymax;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-06 09:25:42 +00:00
|
|
|
cur->ymin -= temp;
|
|
|
|
|
cur->ymax -= temp;
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 00:11:33 +00:00
|
|
|
/* Step 4: Make sure alignment restrictions are respected */
|
|
|
|
|
if (v2d->align) {
|
|
|
|
|
/* If alignment flags are set (but keeptot is not), they must still be respected, as although
|
2018-05-23 10:47:12 +02:00
|
|
|
* they don't specify any particular bounds to stay within, they do define ranges which are
|
2008-12-22 00:11:33 +00:00
|
|
|
* invalid.
|
|
|
|
|
*
|
2018-05-23 10:47:12 +02:00
|
|
|
* Here, we only check to make sure that on each axis, the 'cur' rect doesn't stray into these
|
2008-12-22 00:11:33 +00:00
|
|
|
* invalid zones, otherwise we offset.
|
|
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 00:11:33 +00:00
|
|
|
/* 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 */
|
|
|
|
|
if (v2d->cur.xmax > 0) {
|
|
|
|
|
v2d->cur.xmin -= v2d->cur.xmax;
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.xmax = 0.0f;
|
2008-12-22 00:11:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
|
|
|
|
|
/* width is in positive-x half */
|
|
|
|
|
if (v2d->cur.xmin < 0) {
|
|
|
|
|
v2d->cur.xmax -= v2d->cur.xmin;
|
|
|
|
|
v2d->cur.xmin = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 00:11:33 +00:00
|
|
|
/* 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 */
|
|
|
|
|
if (v2d->cur.ymax > 0) {
|
|
|
|
|
v2d->cur.ymin -= v2d->cur.ymax;
|
|
|
|
|
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 */
|
|
|
|
|
if (v2d->cur.ymin < 0) {
|
|
|
|
|
v2d->cur.ymax -= v2d->cur.ymin;
|
|
|
|
|
v2d->cur.ymin = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-01-28 18:26:47 +00:00
|
|
|
/* set masks */
|
2022-04-03 00:00:42 -05:00
|
|
|
view2d_masks(v2d, nullptr);
|
2008-11-30 06:15:33 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-29 22:57:53 +00:00
|
|
|
void UI_view2d_curRect_validate(View2D *v2d)
|
|
|
|
|
{
|
2020-04-16 20:42:56 +02:00
|
|
|
ui_view2d_curRect_validate_resize(v2d, false);
|
2009-07-29 22:57:53 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-12 12:12:29 +02:00
|
|
|
void UI_view2d_curRect_changed(const bContext *C, View2D *v2d)
|
2020-08-12 12:36:19 +02:00
|
|
|
{
|
|
|
|
|
UI_view2d_curRect_validate(v2d);
|
2020-08-12 12:12:29 +02:00
|
|
|
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
|
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
if (region->type->on_view2d_changed != nullptr) {
|
2020-08-12 12:12:29 +02:00
|
|
|
region->type->on_view2d_changed(C, region);
|
|
|
|
|
}
|
2020-08-12 12:36:19 +02:00
|
|
|
}
|
|
|
|
|
|
2008-12-05 02:03:37 +00:00
|
|
|
/* ------------------ */
|
|
|
|
|
|
2021-09-16 12:40:22 +02:00
|
|
|
bool UI_view2d_area_supports_sync(ScrArea *area)
|
|
|
|
|
{
|
|
|
|
|
return ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP, SPACE_GRAPH);
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-21 11:56:42 +00:00
|
|
|
void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
|
|
|
|
|
{
|
|
|
|
|
/* don't continue if no view syncing to be done */
|
2019-03-25 10:15:20 +11:00
|
|
|
if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) {
|
2008-12-21 11:56:42 +00:00
|
|
|
return;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-21 11:56:42 +00:00
|
|
|
/* check if doing within area syncing (i.e. channels/vertical) */
|
2008-12-22 22:59:48 +00:00
|
|
|
if ((v2dcur->flag & V2D_VIEWSYNC_AREA_VERTICAL) && (area)) {
|
2020-08-18 21:46:29 -04:00
|
|
|
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
2008-12-21 11:56:42 +00:00
|
|
|
/* don't operate on self */
|
2020-03-06 16:56:42 +01:00
|
|
|
if (v2dcur != ®ion->v2d) {
|
2008-12-21 11:56:42 +00:00
|
|
|
/* only if view has vertical locks enabled */
|
2020-03-06 16:56:42 +01:00
|
|
|
if (region->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
|
2008-12-21 11:56:42 +00:00
|
|
|
if (flag == V2D_LOCK_COPY) {
|
|
|
|
|
/* other views with locks on must copy active */
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.cur.ymin = v2dcur->cur.ymin;
|
|
|
|
|
region->v2d.cur.ymax = v2dcur->cur.ymax;
|
2008-12-21 11:56:42 +00:00
|
|
|
}
|
|
|
|
|
else { /* V2D_LOCK_SET */
|
2012-03-30 01:51:25 +00:00
|
|
|
/* active must copy others */
|
2020-03-06 16:56:42 +01:00
|
|
|
v2dcur->cur.ymin = region->v2d.cur.ymin;
|
|
|
|
|
v2dcur->cur.ymax = region->v2d.cur.ymax;
|
2008-12-21 11:56:42 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-21 11:56:42 +00:00
|
|
|
/* region possibly changed, so refresh */
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw_no_rebuild(region);
|
2008-12-21 11:56:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-21 11:56:42 +00:00
|
|
|
/* check if doing whole screen syncing (i.e. time/horizontal) */
|
2008-12-22 22:59:48 +00:00
|
|
|
if ((v2dcur->flag & V2D_VIEWSYNC_SCREEN_TIME) && (screen)) {
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
|
2021-09-16 12:40:22 +02:00
|
|
|
if (!UI_view2d_area_supports_sync(area_iter)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-08-18 21:46:29 -04:00
|
|
|
LISTBASE_FOREACH (ARegion *, region, &area_iter->regionbase) {
|
2008-12-21 11:56:42 +00:00
|
|
|
/* don't operate on self */
|
2020-03-06 16:56:42 +01:00
|
|
|
if (v2dcur != ®ion->v2d) {
|
2008-12-21 11:56:42 +00:00
|
|
|
/* only if view has horizontal locks enabled */
|
2020-03-06 16:56:42 +01:00
|
|
|
if (region->v2d.flag & V2D_VIEWSYNC_SCREEN_TIME) {
|
2008-12-21 11:56:42 +00:00
|
|
|
if (flag == V2D_LOCK_COPY) {
|
|
|
|
|
/* other views with locks on must copy active */
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.cur.xmin = v2dcur->cur.xmin;
|
|
|
|
|
region->v2d.cur.xmax = v2dcur->cur.xmax;
|
2008-12-21 11:56:42 +00:00
|
|
|
}
|
|
|
|
|
else { /* V2D_LOCK_SET */
|
2012-03-30 01:51:25 +00:00
|
|
|
/* active must copy others */
|
2020-03-06 16:56:42 +01:00
|
|
|
v2dcur->cur.xmin = region->v2d.cur.xmin;
|
|
|
|
|
v2dcur->cur.xmax = region->v2d.cur.xmax;
|
2008-12-21 11:56:42 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-21 11:56:42 +00:00
|
|
|
/* region possibly changed, so refresh */
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw_no_rebuild(region);
|
2008-12-21 11:56:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
void UI_view2d_curRect_reset(View2D *v2d)
|
2008-12-05 02:03:37 +00:00
|
|
|
{
|
2008-12-10 09:07:15 +00:00
|
|
|
float width, height;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-10 09:07:15 +00:00
|
|
|
/* assume width and height of 'cur' rect by default, should be same size as mask */
|
2012-09-15 11:48:20 +00:00
|
|
|
width = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
|
|
|
|
|
height = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-05 02:03:37 +00:00
|
|
|
/* 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 */
|
2014-01-16 19:15:53 +11:00
|
|
|
v2d->cur.xmin = -width;
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.xmax = 0.0f;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
|
|
|
|
|
/* width is in positive-x half */
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.xmin = 0.0f;
|
2014-01-16 19:15:53 +11:00
|
|
|
v2d->cur.xmax = width;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-27 19:40:36 +00:00
|
|
|
/* width is centered around (x == 0) */
|
2014-01-16 19:15:53 +11:00
|
|
|
const float dx = width / 2.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.xmin = -dx;
|
|
|
|
|
v2d->cur.xmax = dx;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-05 02:03:37 +00:00
|
|
|
/* 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 */
|
2014-01-16 19:15:53 +11:00
|
|
|
v2d->cur.ymin = -height;
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.ymax = 0.0f;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
|
|
|
|
|
/* height is in positive-y half */
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.ymin = 0.0f;
|
2014-01-16 19:15:53 +11:00
|
|
|
v2d->cur.ymax = height;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-27 19:40:36 +00:00
|
|
|
/* height is centered around (y == 0) */
|
2014-01-16 19:15:53 +11:00
|
|
|
const float dy = height / 2.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->cur.ymin = -dy;
|
|
|
|
|
v2d->cur.ymax = dy;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-12 23:25:54 +00:00
|
|
|
/* ------------------ */
|
|
|
|
|
|
2015-10-17 01:01:57 +11:00
|
|
|
void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize)
|
2008-12-05 02:03:37 +00:00
|
|
|
{
|
2008-12-10 09:07:15 +00:00
|
|
|
/* don't do anything if either value is 0 */
|
2012-03-30 01:51:25 +00:00
|
|
|
width = abs(width);
|
|
|
|
|
height = abs(height);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-09-15 07:31:17 +00:00
|
|
|
if (ELEM(0, width, height)) {
|
2019-03-25 10:15:20 +11:00
|
|
|
if (G.debug & G_DEBUG) {
|
2021-06-23 12:05:40 +10:00
|
|
|
/* XXX: temp debug info. */
|
2012-03-31 00:59:17 +00:00
|
|
|
printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n",
|
|
|
|
|
(void *)v2d,
|
|
|
|
|
width,
|
2021-06-23 12:05:40 +10:00
|
|
|
height);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2008-12-10 09:07:15 +00:00
|
|
|
return;
|
2.5 - Outliner/RNA Viewer View2d Fixes (Part 1)
Cleaned up the View2D setup stuff here, by removing all the hacky manual setting of tot and cur rects. Now the Outliner and RNA are scrollable again.
However, in the process, I uncovered a few rather nasty bugs that must've been around for ages.
1) The width-calculation code depends on te->xend for calculating the max-extents, but that is not set until drawing of channels commences. This is far too late, as it is needed for the setting of the 'tot' rect's extents, so that we can have horizontal scrolling, and an accurate horizontal scroller! I noticed that RNA version of this currently hacks around this by using constant width of 100, but that's not a great final solution.
2) There's some minor pixel offset twitching going on with the restriction columns when the view is resized. Also, for RNA, the buttons sometimes cause a few drawing artifacts. Will check on this in part 2.
2009-01-04 04:21:32 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-05 02:03:37 +00:00
|
|
|
/* 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 */
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.xmin = (float)-width;
|
|
|
|
|
v2d->tot.xmax = 0.0f;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
|
|
|
|
|
/* width is in positive-x half */
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.xmin = 0.0f;
|
|
|
|
|
v2d->tot.xmax = (float)width;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-27 19:40:36 +00:00
|
|
|
/* width is centered around (x == 0) */
|
2012-03-30 01:51:25 +00:00
|
|
|
const float dx = (float)width / 2.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.xmin = -dx;
|
|
|
|
|
v2d->tot.xmax = dx;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-05 02:03:37 +00:00
|
|
|
/* 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 */
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.ymin = (float)-height;
|
|
|
|
|
v2d->tot.ymax = 0.0f;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
|
|
|
|
|
/* height is in positive-y half */
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.ymin = 0.0f;
|
|
|
|
|
v2d->tot.ymax = (float)height;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-27 19:40:36 +00:00
|
|
|
/* height is centered around (y == 0) */
|
2012-03-30 01:51:25 +00:00
|
|
|
const float dy = (float)height / 2.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 02:51:46 +00:00
|
|
|
v2d->tot.ymin = -dy;
|
|
|
|
|
v2d->tot.ymax = dy;
|
2008-12-05 02:03:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-10 09:07:15 +00:00
|
|
|
/* make sure that 'cur' rect is in a valid state as a result of these changes */
|
2020-04-16 20:42:56 +02:00
|
|
|
ui_view2d_curRect_validate_resize(v2d, resize);
|
2009-07-29 22:57:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
|
|
|
|
|
{
|
2020-04-16 20:42:56 +02:00
|
|
|
UI_view2d_totRect_set_resize(v2d, width, height, false);
|
2009-07-29 22:57:53 +00:00
|
|
|
}
|
|
|
|
|
|
2014-01-20 12:43:56 +11:00
|
|
|
void UI_view2d_zoom_cache_reset(void)
|
|
|
|
|
{
|
2019-01-25 11:04:00 +11:00
|
|
|
/* TODO(sergey): This way we avoid threading conflict with sequencer rendering
|
2018-02-01 16:24:25 +01:00
|
|
|
* text strip. But ideally we want to make glyph cache to be fully safe
|
|
|
|
|
* for threading.
|
|
|
|
|
*/
|
|
|
|
|
if (G.is_rendering) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-01-20 12:43:56 +11:00
|
|
|
/* While scaling we can accumulate fonts at many sizes (~20 or so).
|
2020-09-30 20:09:02 +10:00
|
|
|
* Not an issue with embedded font, but can use over 500Mb with i18n ones! See T38244. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: only some views draw text, we could check for this case to avoid cleaning cache. */
|
2014-01-20 12:43:56 +11:00
|
|
|
BLF_cache_clear();
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name View2D Matrix Setup
|
|
|
|
|
* \{ */
|
2008-12-02 09:43:23 +00:00
|
|
|
|
2008-12-12 23:25:54 +00:00
|
|
|
/* mapping function to ensure 'cur' draws extended over the area where sliders are */
|
Refactor grid and scale indicator text drawing
This affects the timeline, dopesheet, graph editor, sequencer,
clip editor and nla editor.
Removed structs and enums: `V2D_ARG_DUMMY`, `eView2D_Units`,
`eView2D_Clamp`, `eView2D_Gridlines`, `View2DGrid`.
A main goal of this refactor is to get rid of the very generic
`View2DGrid` struct. The drawing code became very complex
because there were many different combinations of settings.
This refactor implements a different approach.
Instead of one very generic API, there are many slighly
different functions that do exactly, what we need in the
different editors. Only very little code is duplicated,
because the API functions compose some shared low level code.
This structure makes the code much easier to debug and change,
because every function has much fewer responsibilities.
Additionally, this refactor fixes some long standing bugs.
E.g. when `Show Seconds` is enabled, you zoom in and pan the view.
Or that the step size between displayed frame numbers was
always `>= 2`, no matter how close you zoom in.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D4776
2019-05-02 12:00:12 +02:00
|
|
|
static void view2d_map_cur_using_mask(const View2D *v2d, rctf *r_curmasked)
|
2008-12-12 16:29:33 +00:00
|
|
|
{
|
2019-03-25 12:19:55 +11:00
|
|
|
*r_curmasked = v2d->cur;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-01-28 18:26:47 +00:00
|
|
|
if (view2d_scroll_mapped(v2d->scroll)) {
|
2020-08-26 10:11:13 +10:00
|
|
|
const float sizex = BLI_rcti_size_x(&v2d->mask);
|
|
|
|
|
const float sizey = BLI_rcti_size_y(&v2d->mask);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* prevent tiny or narrow regions to get
|
|
|
|
|
* invalid coordinates - mask can get negative even... */
|
2013-04-18 10:10:58 +00:00
|
|
|
if (sizex > 0.0f && sizey > 0.0f) {
|
2020-08-26 10:11:13 +10:00
|
|
|
const float dx = BLI_rctf_size_x(&v2d->cur) / (sizex + 1);
|
|
|
|
|
const float dy = BLI_rctf_size_y(&v2d->cur) / (sizey + 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-25 10:15:20 +11:00
|
|
|
if (v2d->mask.xmin != 0) {
|
2019-03-25 12:19:55 +11:00
|
|
|
r_curmasked->xmin -= dx * (float)v2d->mask.xmin;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
if (v2d->mask.xmax + 1 != v2d->winx) {
|
2019-03-25 12:19:55 +11:00
|
|
|
r_curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-25 10:15:20 +11:00
|
|
|
if (v2d->mask.ymin != 0) {
|
2019-03-25 12:19:55 +11:00
|
|
|
r_curmasked->ymin -= dy * (float)v2d->mask.ymin;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
if (v2d->mask.ymax + 1 != v2d->winy) {
|
2019-03-25 12:19:55 +11:00
|
|
|
r_curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2013-04-18 10:10:58 +00:00
|
|
|
}
|
2008-12-12 16:29:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Refactor grid and scale indicator text drawing
This affects the timeline, dopesheet, graph editor, sequencer,
clip editor and nla editor.
Removed structs and enums: `V2D_ARG_DUMMY`, `eView2D_Units`,
`eView2D_Clamp`, `eView2D_Gridlines`, `View2DGrid`.
A main goal of this refactor is to get rid of the very generic
`View2DGrid` struct. The drawing code became very complex
because there were many different combinations of settings.
This refactor implements a different approach.
Instead of one very generic API, there are many slighly
different functions that do exactly, what we need in the
different editors. Only very little code is duplicated,
because the API functions compose some shared low level code.
This structure makes the code much easier to debug and change,
because every function has much fewer responsibilities.
Additionally, this refactor fixes some long standing bugs.
E.g. when `Show Seconds` is enabled, you zoom in and pan the view.
Or that the step size between displayed frame numbers was
always `>= 2`, no matter how close you zoom in.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D4776
2019-05-02 12:00:12 +02:00
|
|
|
void UI_view2d_view_ortho(const View2D *v2d)
|
2008-12-02 09:43:23 +00:00
|
|
|
{
|
2008-12-12 16:29:33 +00:00
|
|
|
rctf curmasked;
|
2014-01-15 10:41:13 +11:00
|
|
|
const int sizex = BLI_rcti_size_x(&v2d->mask);
|
|
|
|
|
const int sizey = BLI_rcti_size_y(&v2d->mask);
|
|
|
|
|
const float eps = 0.001f;
|
2013-04-18 10:22:42 +00:00
|
|
|
float xofs = 0.0f, yofs = 0.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-17 08:44:38 +02:00
|
|
|
/* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1
|
|
|
|
|
* correspondence with pixels for smooth UI drawing,
|
|
|
|
|
* but only applied where requested.
|
2008-12-02 09:43:23 +00:00
|
|
|
*/
|
2009-05-19 17:13:33 +00:00
|
|
|
/* XXX brecht: instead of zero at least use a tiny offset, otherwise
|
|
|
|
|
* pixel rounding is effectively random due to float inaccuracy */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (sizex > 0) {
|
2014-01-15 10:41:13 +11:00
|
|
|
xofs = eps * BLI_rctf_size_x(&v2d->cur) / sizex;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
if (sizey > 0) {
|
2014-01-15 10:41:13 +11:00
|
|
|
yofs = eps * BLI_rctf_size_y(&v2d->cur) / sizey;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* apply mask-based adjustments to cur rect (due to scrollers),
|
|
|
|
|
* to eliminate scaling artifacts */
|
2008-12-12 16:29:33 +00:00
|
|
|
view2d_map_cur_using_mask(v2d, &curmasked);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-09-16 23:40:03 +00:00
|
|
|
BLI_rctf_translate(&curmasked, -xofs, -yofs);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-01-26 12:26:44 +00:00
|
|
|
/* XXX ton: this flag set by outliner, for icons */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (v2d->flag & V2D_PIXELOFS_X) {
|
2014-01-15 10:41:13 +11:00
|
|
|
curmasked.xmin = floorf(curmasked.xmin) - (eps + xofs);
|
|
|
|
|
curmasked.xmax = floorf(curmasked.xmax) - (eps + xofs);
|
2011-01-26 12:26:44 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
if (v2d->flag & V2D_PIXELOFS_Y) {
|
2014-01-15 10:41:13 +11:00
|
|
|
curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs);
|
|
|
|
|
curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs);
|
2011-01-26 12:26:44 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-18 09:20:29 +00:00
|
|
|
/* set matrix on all appropriate axes */
|
2013-02-02 14:11:58 +00:00
|
|
|
wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
|
2008-12-02 09:43:23 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis)
|
2008-12-02 09:43:23 +00:00
|
|
|
{
|
2008-12-12 16:29:33 +00:00
|
|
|
rctf curmasked;
|
2008-12-18 09:20:29 +00:00
|
|
|
float xofs, yofs;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-17 08:44:38 +02:00
|
|
|
/* Pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1
|
|
|
|
|
* correspondence with pixels for smooth UI drawing,
|
|
|
|
|
* but only applied where requested.
|
2008-12-02 09:43:23 +00:00
|
|
|
*/
|
2021-07-03 23:08:40 +10:00
|
|
|
/* XXX(ton): temp. */
|
2012-08-05 17:27:52 +00:00
|
|
|
xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f;
|
|
|
|
|
yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* apply mask-based adjustments to cur rect (due to scrollers),
|
|
|
|
|
* to eliminate scaling artifacts */
|
2008-12-12 16:29:33 +00:00
|
|
|
view2d_map_cur_using_mask(v2d, &curmasked);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-18 09:20:29 +00:00
|
|
|
/* only set matrix with 'cur' coordinates on relevant axes */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (xaxis) {
|
2020-03-06 16:56:42 +01:00
|
|
|
wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, region->winy - yofs);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2020-03-06 16:56:42 +01:00
|
|
|
wmOrtho2(-xofs, region->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2018-05-23 10:47:12 +02:00
|
|
|
}
|
2008-12-02 09:43:23 +00:00
|
|
|
|
|
|
|
|
void UI_view2d_view_restore(const bContext *C)
|
|
|
|
|
{
|
2020-03-06 16:56:42 +01:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2020-08-26 10:11:13 +10:00
|
|
|
const int width = BLI_rcti_size_x(®ion->winrct) + 1;
|
|
|
|
|
const int height = BLI_rcti_size_y(®ion->winrct) + 1;
|
2018-05-23 10:47:12 +02:00
|
|
|
|
2009-07-02 18:12:46 +00:00
|
|
|
wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
|
2018-07-15 15:27:15 +02:00
|
|
|
GPU_matrix_identity_set();
|
2018-05-23 10:47:12 +02:00
|
|
|
|
2009-07-02 18:12:46 +00:00
|
|
|
// ED_region_pixelspace(CTX_wm_region(C));
|
2008-12-02 09:43:23 +00:00
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2019-09-19 13:18:52 +10:00
|
|
|
/** \name Grid-Line Drawing
|
2019-09-06 16:12:47 +10:00
|
|
|
* \{ */
|
2008-10-08 18:07:56 +00:00
|
|
|
|
2020-05-04 19:32:59 +10:00
|
|
|
void UI_view2d_multi_grid_draw(
|
|
|
|
|
const View2D *v2d, int colorid, float step, int level_size, int totlevels)
|
2012-06-28 08:47:22 +00:00
|
|
|
{
|
2016-11-28 20:07:56 -05:00
|
|
|
/* Exit if there is nothing to draw */
|
2019-03-25 10:15:20 +11:00
|
|
|
if (totlevels == 0) {
|
2016-11-28 20:07:56 -05:00
|
|
|
return;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-28 08:47:22 +00:00
|
|
|
int offset = -10;
|
|
|
|
|
float lstep = step;
|
2019-01-04 11:05:53 +11:00
|
|
|
uchar grid_line_color[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-28 20:07:56 -05:00
|
|
|
/* Make an estimate of at least how many vertices will be needed */
|
2020-02-08 01:02:18 +11:00
|
|
|
uint vertex_count = 4;
|
2016-11-28 20:07:56 -05:00
|
|
|
vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
|
|
|
|
|
vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
GPUVertFormat *format = immVertexFormat();
|
2020-08-26 10:11:13 +10:00
|
|
|
const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
2018-07-18 00:12:21 +02:00
|
|
|
uint color = GPU_vertformat_attr_add(
|
|
|
|
|
format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-27 19:07:23 -06:00
|
|
|
GPU_line_width(1.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-28 20:07:56 -05:00
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
|
2018-07-18 00:12:21 +02:00
|
|
|
immBeginAtMost(GPU_PRIM_LINES, vertex_count);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int level = 0; level < totlevels; level++) {
|
2020-09-15 18:42:38 -05:00
|
|
|
/* Blend the background color (colorid) with the grid color, to avoid either too low contrast
|
|
|
|
|
* or high contrast grid lines. This only has an effect if colorid != TH_GRID. */
|
|
|
|
|
UI_GetThemeColorBlendShade3ubv(colorid, TH_GRID, 0.25f, offset, grid_line_color);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-28 20:07:56 -05:00
|
|
|
int i = (int)(v2d->cur.xmin / lstep);
|
2019-03-25 10:15:20 +11:00
|
|
|
if (v2d->cur.xmin > 0.0f) {
|
2016-11-28 20:07:56 -05:00
|
|
|
i++;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2016-11-28 20:07:56 -05:00
|
|
|
float start = i * lstep;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (; start < v2d->cur.xmax; start += lstep, i++) {
|
2019-03-25 10:15:20 +11:00
|
|
|
if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
|
2012-06-28 08:47:22 +00:00
|
|
|
continue;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttrSkip(color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, start, v2d->cur.ymin);
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttr3ubv(color, grid_line_color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, start, v2d->cur.ymax);
|
2012-06-28 08:47:22 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-28 20:07:56 -05:00
|
|
|
i = (int)(v2d->cur.ymin / lstep);
|
2019-03-25 10:15:20 +11:00
|
|
|
if (v2d->cur.ymin > 0.0f) {
|
2016-11-28 20:07:56 -05:00
|
|
|
i++;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2012-06-28 08:47:22 +00:00
|
|
|
start = i * lstep;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (; start < v2d->cur.ymax; start += lstep, i++) {
|
2019-03-25 10:15:20 +11:00
|
|
|
if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
|
2012-06-28 08:47:22 +00:00
|
|
|
continue;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttrSkip(color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, v2d->cur.xmin, start);
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttr3ubv(color, grid_line_color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, v2d->cur.xmax, start);
|
2012-06-28 08:47:22 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-28 08:47:22 +00:00
|
|
|
lstep *= level_size;
|
|
|
|
|
offset -= 6;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-28 20:07:56 -05:00
|
|
|
/* X and Y axis */
|
2020-09-15 18:42:38 -05:00
|
|
|
UI_GetThemeColorBlendShade3ubv(
|
|
|
|
|
colorid, TH_GRID, 0.5f, -18 + ((totlevels - 1) * -6), grid_line_color);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttrSkip(color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, 0.0f, v2d->cur.ymin);
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttr3ubv(color, grid_line_color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, 0.0f, v2d->cur.ymax);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttrSkip(color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, v2d->cur.xmin, 0.0f);
|
2018-10-09 11:01:50 +11:00
|
|
|
immAttr3ubv(color, grid_line_color);
|
2016-11-28 20:07:56 -05:00
|
|
|
immVertex2f(pos, v2d->cur.xmax, 0.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-28 20:07:56 -05:00
|
|
|
immEnd();
|
|
|
|
|
immUnbindProgram();
|
2012-06-28 08:47:22 +00:00
|
|
|
}
|
|
|
|
|
|
2021-10-25 21:46:39 -05:00
|
|
|
static void grid_axis_start_and_count(
|
|
|
|
|
const float step, const float min, const float max, float *r_start, int *r_count)
|
|
|
|
|
{
|
|
|
|
|
*r_start = min;
|
|
|
|
|
if (*r_start < 0.0f) {
|
|
|
|
|
*r_start += -(float)fmod(min, step);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_start += step - (float)fabs(fmod(min, step));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*r_start > max) {
|
|
|
|
|
*r_count = 0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_count = (max - *r_start) / step + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UI_view2d_dot_grid_draw(const View2D *v2d,
|
|
|
|
|
const int grid_color_id,
|
|
|
|
|
const float min_step,
|
2022-03-30 21:21:57 +02:00
|
|
|
const int grid_subdivisions)
|
2021-10-25 21:46:39 -05:00
|
|
|
{
|
2022-03-30 21:21:57 +02:00
|
|
|
BLI_assert(grid_subdivisions >= 0 && grid_subdivisions < 4);
|
|
|
|
|
if (grid_subdivisions == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-25 21:46:39 -05:00
|
|
|
const float zoom_x = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
|
|
|
|
|
|
|
|
|
|
GPUVertFormat *format = immVertexFormat();
|
|
|
|
|
const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
|
|
|
|
|
|
2022-03-30 21:21:57 +02:00
|
|
|
/* Scaling the dots fully with the zoom looks too busy, but a bit of size variation is nice. */
|
|
|
|
|
const float min_point_size = 2.0f * UI_DPI_FAC;
|
|
|
|
|
const float point_size_factor = 1.5f;
|
|
|
|
|
const float max_point_size = point_size_factor * min_point_size;
|
2021-10-25 21:46:39 -05:00
|
|
|
|
2022-03-30 21:21:57 +02:00
|
|
|
/* Each consecutive grid level is five times larger than the previous. */
|
|
|
|
|
const int subdivision_scale = 5;
|
2021-10-25 21:46:39 -05:00
|
|
|
|
2022-03-30 21:21:57 +02:00
|
|
|
const float view_level = logf(min_step / zoom_x) / logf(subdivision_scale);
|
|
|
|
|
const int largest_visible_level = (int)view_level;
|
|
|
|
|
|
|
|
|
|
for (int level_offset = 0; level_offset <= grid_subdivisions; level_offset++) {
|
|
|
|
|
const int level = largest_visible_level - level_offset;
|
|
|
|
|
|
|
|
|
|
if (level < 0) {
|
2021-10-25 21:46:39 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-30 21:21:57 +02:00
|
|
|
const float level_scale = powf(subdivision_scale, level);
|
|
|
|
|
const float point_size_precise = min_point_size * level_scale * zoom_x;
|
|
|
|
|
const float point_size_draw = ceilf(
|
|
|
|
|
clamp_f(point_size_precise, min_point_size, max_point_size));
|
|
|
|
|
|
|
|
|
|
/* To compensate the for the clamped point_size we adjust the alpha to make the overall
|
|
|
|
|
* brightness of the grid background more consistent. */
|
|
|
|
|
const float alpha = pow2f(point_size_precise / point_size_draw);
|
|
|
|
|
|
|
|
|
|
/* Make sure we don't draw points once the alpha gets too low. */
|
|
|
|
|
const float alpha_cutoff = 0.01f;
|
|
|
|
|
if (alpha < alpha_cutoff) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
const float alpha_clamped = clamp_f((1.0f + alpha_cutoff) * alpha - alpha_cutoff, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
/* If we have don't draw enough subdivision levels so they fade out naturally, we apply an
|
|
|
|
|
* additional fade to the last level to avoid pop in. */
|
|
|
|
|
const bool last_level = level_offset == grid_subdivisions;
|
|
|
|
|
const float subdivision_fade = last_level ? (1.0f - fractf(view_level)) : 1.0f;
|
|
|
|
|
|
|
|
|
|
float color[4];
|
|
|
|
|
UI_GetThemeColor3fv(grid_color_id, color);
|
|
|
|
|
color[3] = alpha_clamped * subdivision_fade;
|
|
|
|
|
|
|
|
|
|
const float step = min_step * level_scale;
|
2021-10-25 21:46:39 -05:00
|
|
|
int count_x;
|
|
|
|
|
float start_x;
|
|
|
|
|
grid_axis_start_and_count(step, v2d->cur.xmin, v2d->cur.xmax, &start_x, &count_x);
|
|
|
|
|
int count_y;
|
|
|
|
|
float start_y;
|
|
|
|
|
grid_axis_start_and_count(step, v2d->cur.ymin, v2d->cur.ymax, &start_y, &count_y);
|
|
|
|
|
if (count_x == 0 || count_y == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-30 21:21:57 +02:00
|
|
|
GPU_point_size(point_size_draw);
|
2021-10-25 21:46:39 -05:00
|
|
|
immBegin(GPU_PRIM_POINTS, count_x * count_y);
|
|
|
|
|
|
|
|
|
|
/* Theoretically drawing on top of lower grid levels could be avoided, but it would also
|
|
|
|
|
* increase the complexity of this loop, which isn't worth the time at the moment. */
|
|
|
|
|
for (int i_y = 0; i_y < count_y; i_y++) {
|
|
|
|
|
const float y = start_y + step * i_y;
|
|
|
|
|
for (int i_x = 0; i_x < count_x; i_x++) {
|
|
|
|
|
const float x = start_x + step * i_x;
|
|
|
|
|
immAttr4fv(color_id, color);
|
|
|
|
|
immVertex2f(pos, x, y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
immEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
immUnbindProgram();
|
|
|
|
|
}
|
2021-12-14 15:49:31 +11:00
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Scrollers
|
|
|
|
|
* \{ */
|
2008-11-30 06:15:33 +00:00
|
|
|
|
2015-05-05 03:13:47 +10:00
|
|
|
/**
|
|
|
|
|
* View2DScrollers is typedef'd in UI_view2d.h
|
|
|
|
|
*
|
|
|
|
|
* \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...
|
2008-12-07 12:15:04 +00:00
|
|
|
*/
|
2009-07-02 18:12:46 +00:00
|
|
|
struct View2DScrollers {
|
2021-12-09 00:55:11 +11:00
|
|
|
/* focus bubbles */
|
|
|
|
|
/* focus bubbles */
|
2012-03-30 01:51:25 +00:00
|
|
|
/* focus bubbles */
|
|
|
|
|
int vert_min, vert_max; /* vertical scrollbar */
|
|
|
|
|
int hor_min, hor_max; /* horizontal scrollbar */
|
2018-05-23 10:47:12 +02:00
|
|
|
|
2020-06-23 15:21:30 +10:00
|
|
|
/** Exact size of slider backdrop. */
|
|
|
|
|
rcti hor, vert;
|
|
|
|
|
/* set if sliders are full, we don't draw them */
|
|
|
|
|
/* int horfull, vertfull; */ /* UNUSED */
|
2008-12-01 00:20:19 +00:00
|
|
|
};
|
2008-11-30 06:15:33 +00:00
|
|
|
|
2020-06-22 21:44:18 +02:00
|
|
|
void UI_view2d_scrollers_calc(View2D *v2d,
|
|
|
|
|
const rcti *mask_custom,
|
|
|
|
|
struct View2DScrollers *r_scrollers)
|
2008-12-01 00:20:19 +00:00
|
|
|
{
|
2008-12-01 11:37:05 +00:00
|
|
|
rcti vert, hor;
|
2009-07-02 18:12:46 +00:00
|
|
|
float fac1, fac2, totsize, scrollsize;
|
2020-08-26 10:11:13 +10:00
|
|
|
const int scroll = view2d_scroll_mapped(v2d->scroll);
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
int smaller;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-07 01:31:18 +02:00
|
|
|
/* Always update before drawing (for dynamically sized scrollers). */
|
2020-04-16 20:42:56 +02:00
|
|
|
view2d_masks(v2d, mask_custom);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
vert = v2d->vert;
|
|
|
|
|
hor = v2d->hor;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-04 15:11:51 +01:00
|
|
|
/* slider rects need to be smaller than region and not interfere with splitter areas */
|
|
|
|
|
hor.xmin += UI_HEADER_OFFSET;
|
|
|
|
|
hor.xmax -= UI_HEADER_OFFSET;
|
|
|
|
|
vert.ymin += UI_HEADER_OFFSET;
|
|
|
|
|
vert.ymax -= UI_HEADER_OFFSET;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-04 15:11:51 +01:00
|
|
|
/* width of sliders */
|
2018-04-27 00:49:00 +02:00
|
|
|
smaller = (int)(0.1f * U.widget_unit);
|
2019-03-25 10:15:20 +11:00
|
|
|
if (scroll & V2D_SCROLL_BOTTOM) {
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
hor.ymin += smaller;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
hor.ymax -= smaller;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-25 10:15:20 +11:00
|
|
|
if (scroll & V2D_SCROLL_LEFT) {
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
vert.xmin += smaller;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
vert.xmax -= smaller;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-24 14:29:29 +10:00
|
|
|
CLAMP_MAX(vert.ymin, vert.ymax - V2D_SCROLL_HANDLE_SIZE_HOTSPOT);
|
|
|
|
|
CLAMP_MAX(hor.xmin, hor.xmax - V2D_SCROLL_HANDLE_SIZE_HOTSPOT);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-07-02 18:12:46 +00:00
|
|
|
/* store in scrollers, used for drawing */
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->vert = vert;
|
|
|
|
|
r_scrollers->hor = hor;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-03 09:06:30 +00:00
|
|
|
/* scroller 'buttons':
|
2018-11-14 12:53:15 +11:00
|
|
|
* - These should always remain within the visible region of the scrollbar
|
|
|
|
|
* - They represent the region of 'tot' that is visible in 'cur'
|
2008-12-01 11:37:05 +00:00
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-03 09:06:30 +00:00
|
|
|
/* horizontal scrollers */
|
2009-01-28 18:26:47 +00:00
|
|
|
if (scroll & V2D_SCROLL_HORIZONTAL) {
|
2008-12-07 06:21:06 +00:00
|
|
|
/* scroller 'button' extents */
|
2012-09-15 11:48:20 +00:00
|
|
|
totsize = BLI_rctf_size_x(&v2d->tot);
|
|
|
|
|
scrollsize = (float)BLI_rcti_size_x(&hor);
|
2019-03-25 10:15:20 +11:00
|
|
|
if (totsize == 0.0f) {
|
|
|
|
|
totsize = 1.0f; /* avoid divide by zero */
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
fac1 = (v2d->cur.xmin - v2d->tot.xmin) / totsize;
|
2019-03-25 10:15:20 +11:00
|
|
|
if (fac1 <= 0.0f) {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->hor_min = hor.xmin;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->hor_min = (int)(hor.xmin + (fac1 * scrollsize));
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
fac2 = (v2d->cur.xmax - v2d->tot.xmin) / totsize;
|
2019-03-25 10:15:20 +11:00
|
|
|
if (fac2 >= 1.0f) {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->hor_max = hor.xmax;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->hor_max = (int)(hor.xmin + (fac2 * scrollsize));
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-09-23 11:49:12 +00:00
|
|
|
/* prevent inverted sliders */
|
2020-06-22 21:44:18 +02:00
|
|
|
if (r_scrollers->hor_min > r_scrollers->hor_max) {
|
|
|
|
|
r_scrollers->hor_min = r_scrollers->hor_max;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-06-03 18:13:52 +02:00
|
|
|
/* prevent sliders from being too small to grab */
|
2020-06-22 21:44:18 +02:00
|
|
|
if ((r_scrollers->hor_max - r_scrollers->hor_min) < V2D_SCROLL_THUMB_SIZE_MIN) {
|
|
|
|
|
r_scrollers->hor_max = r_scrollers->hor_min + V2D_SCROLL_THUMB_SIZE_MIN;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-22 21:44:18 +02:00
|
|
|
CLAMP(r_scrollers->hor_max, hor.xmin + V2D_SCROLL_THUMB_SIZE_MIN, hor.xmax);
|
|
|
|
|
CLAMP(r_scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLL_THUMB_SIZE_MIN);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2009-09-28 12:10:23 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-03 09:06:30 +00:00
|
|
|
/* vertical scrollers */
|
2009-01-28 18:26:47 +00:00
|
|
|
if (scroll & V2D_SCROLL_VERTICAL) {
|
2008-12-07 06:21:06 +00:00
|
|
|
/* scroller 'button' extents */
|
2012-09-15 11:48:20 +00:00
|
|
|
totsize = BLI_rctf_size_y(&v2d->tot);
|
|
|
|
|
scrollsize = (float)BLI_rcti_size_y(&vert);
|
2019-03-25 10:15:20 +11:00
|
|
|
if (totsize == 0.0f) {
|
|
|
|
|
totsize = 1.0f; /* avoid divide by zero */
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
fac1 = (v2d->cur.ymin - v2d->tot.ymin) / totsize;
|
2019-03-25 10:15:20 +11:00
|
|
|
if (fac1 <= 0.0f) {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->vert_min = vert.ymin;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->vert_min = (int)(vert.ymin + (fac1 * scrollsize));
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
fac2 = (v2d->cur.ymax - v2d->tot.ymin) / totsize;
|
2019-03-25 10:15:20 +11:00
|
|
|
if (fac2 >= 1.0f) {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->vert_max = vert.ymax;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2020-06-22 21:44:18 +02:00
|
|
|
r_scrollers->vert_max = (int)(vert.ymin + (fac2 * scrollsize));
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-09-23 11:49:12 +00:00
|
|
|
/* prevent inverted sliders */
|
2020-06-22 21:44:18 +02:00
|
|
|
if (r_scrollers->vert_min > r_scrollers->vert_max) {
|
|
|
|
|
r_scrollers->vert_min = r_scrollers->vert_max;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-06-03 18:13:52 +02:00
|
|
|
/* prevent sliders from being too small to grab */
|
2020-06-22 21:44:18 +02:00
|
|
|
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;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-22 21:44:18 +02:00
|
|
|
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);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2009-09-28 12:10:23 +00:00
|
|
|
}
|
2008-12-01 00:20:19 +00:00
|
|
|
}
|
|
|
|
|
|
2022-06-27 06:45:49 -07:00
|
|
|
void UI_view2d_scrollers_draw_ex(View2D *v2d, const rcti *mask_custom, bool use_full_hide)
|
2008-12-01 00:20:19 +00:00
|
|
|
{
|
2020-06-22 21:44:18 +02:00
|
|
|
View2DScrollers scrollers;
|
|
|
|
|
UI_view2d_scrollers_calc(v2d, mask_custom, &scrollers);
|
2018-05-07 01:31:18 +02:00
|
|
|
bTheme *btheme = UI_GetTheme();
|
2009-07-02 18:12:46 +00:00
|
|
|
rcti vert, hor;
|
2018-05-07 01:31:18 +02:00
|
|
|
const int scroll = view2d_scroll_mapped(v2d->scroll);
|
|
|
|
|
const char emboss_alpha = btheme->tui.widget_emboss[3];
|
2022-06-27 06:45:49 -07:00
|
|
|
const float alpha_min = use_full_hide ? 0.0f : V2D_SCROLL_MIN_ALPHA;
|
|
|
|
|
|
2019-01-04 11:05:53 +11:00
|
|
|
uchar scrollers_back_color[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-28 20:12:33 -05:00
|
|
|
/* Color for scrollbar backs */
|
|
|
|
|
UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-12 11:41:05 +00:00
|
|
|
/* make copies of rects for less typing */
|
2020-06-22 21:44:18 +02:00
|
|
|
vert = scrollers.vert;
|
|
|
|
|
hor = scrollers.hor;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-01 00:20:19 +00:00
|
|
|
/* horizontal scrollbar */
|
2009-01-28 18:26:47 +00:00
|
|
|
if (scroll & V2D_SCROLL_HORIZONTAL) {
|
2012-12-26 13:05:39 +00:00
|
|
|
uiWidgetColors wcol = btheme->tui.wcol_scroll;
|
2022-06-27 06:45:49 -07:00
|
|
|
/* 0..255 -> min...1 */
|
|
|
|
|
const float alpha_fac = ((v2d->alpha_hor / 255.0f) * (1.0f - alpha_min)) + alpha_min;
|
2012-12-26 13:05:39 +00:00
|
|
|
rcti slider;
|
2022-05-12 15:53:12 +02:00
|
|
|
int state;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-22 21:44:18 +02:00
|
|
|
slider.xmin = scrollers.hor_min;
|
|
|
|
|
slider.xmax = scrollers.hor_max;
|
2012-12-26 13:05:39 +00:00
|
|
|
slider.ymin = hor.ymin;
|
|
|
|
|
slider.ymax = hor.ymax;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-07 01:31:18 +02:00
|
|
|
wcol.inner[3] *= alpha_fac;
|
|
|
|
|
wcol.item[3] *= alpha_fac;
|
2022-06-27 06:45:49 -07:00
|
|
|
wcol.outline[3] = 0;
|
|
|
|
|
btheme->tui.widget_emboss[3] = 0; /* will be reset later */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* show zoom handles if:
|
2018-11-14 12:53:15 +11:00
|
|
|
* - zooming on x-axis is allowed (no scroll otherwise)
|
|
|
|
|
* - slider bubble is large enough (no overdraw confusion)
|
|
|
|
|
* - scale is shown on the scroller
|
|
|
|
|
* (workaround to make sure that button windows don't show these,
|
2020-02-26 15:21:32 +11:00
|
|
|
* and only the time-grids with their zoom-ability can do so).
|
2012-12-26 13:05:39 +00:00
|
|
|
*/
|
2019-05-08 15:09:02 +02:00
|
|
|
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) &&
|
2019-06-04 10:53:12 +10:00
|
|
|
(BLI_rcti_size_x(&slider) > V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) {
|
2012-12-26 13:05:39 +00:00
|
|
|
state |= UI_SCROLL_ARROWS;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-11-09 21:20:40 +01:00
|
|
|
UI_draw_widget_scroll(&wcol, &hor, &slider, state);
|
2008-12-01 00:20:19 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-01 00:20:19 +00:00
|
|
|
/* vertical scrollbar */
|
2009-01-28 18:26:47 +00:00
|
|
|
if (scroll & V2D_SCROLL_VERTICAL) {
|
2012-12-26 13:05:39 +00:00
|
|
|
uiWidgetColors wcol = btheme->tui.wcol_scroll;
|
|
|
|
|
rcti slider;
|
2022-06-27 06:45:49 -07:00
|
|
|
/* 0..255 -> min...1 */
|
|
|
|
|
const float alpha_fac = ((v2d->alpha_vert / 255.0f) * (1.0f - alpha_min)) + alpha_min;
|
2022-05-12 15:53:12 +02:00
|
|
|
int state;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
slider.xmin = vert.xmin;
|
|
|
|
|
slider.xmax = vert.xmax;
|
2020-06-22 21:44:18 +02:00
|
|
|
slider.ymin = scrollers.vert_min;
|
|
|
|
|
slider.ymax = scrollers.vert_max;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-07 01:31:18 +02:00
|
|
|
wcol.inner[3] *= alpha_fac;
|
|
|
|
|
wcol.item[3] *= alpha_fac;
|
2022-06-27 06:45:49 -07:00
|
|
|
wcol.outline[3] = 0;
|
|
|
|
|
btheme->tui.widget_emboss[3] = 0; /* will be reset later */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-26 13:05:39 +00:00
|
|
|
/* show zoom handles if:
|
2018-11-14 12:53:15 +11:00
|
|
|
* - zooming on y-axis is allowed (no scroll otherwise)
|
|
|
|
|
* - slider bubble is large enough (no overdraw confusion)
|
|
|
|
|
* - scale is shown on the scroller
|
|
|
|
|
* (workaround to make sure that button windows don't show these,
|
|
|
|
|
* and only the time-grids with their zoomability can do so)
|
2012-12-26 13:05:39 +00:00
|
|
|
*/
|
2019-05-08 15:09:02 +02:00
|
|
|
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) &&
|
2019-06-04 10:53:12 +10:00
|
|
|
(BLI_rcti_size_y(&slider) > V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) {
|
2012-12-26 13:05:39 +00:00
|
|
|
state |= UI_SCROLL_ARROWS;
|
2008-12-12 11:41:05 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-11-09 21:20:40 +01:00
|
|
|
UI_draw_widget_scroll(&wcol, &vert, &slider, state);
|
2008-12-01 00:20:19 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-07 01:31:18 +02:00
|
|
|
/* Was changed above, so reset. */
|
|
|
|
|
btheme->tui.widget_emboss[3] = emboss_alpha;
|
2008-12-01 00:20:19 +00:00
|
|
|
}
|
|
|
|
|
|
2022-06-27 06:45:49 -07:00
|
|
|
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
|
|
|
|
|
{
|
|
|
|
|
UI_view2d_scrollers_draw_ex(v2d, mask_custom, false);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name List View Utilities
|
|
|
|
|
* \{ */
|
2008-12-31 10:44:00 +00:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
void UI_view2d_listview_view_to_cell(float columnwidth,
|
2015-05-05 03:13:47 +10:00
|
|
|
float rowheight,
|
|
|
|
|
float startx,
|
|
|
|
|
float starty,
|
2019-03-25 12:19:55 +11:00
|
|
|
float viewx,
|
|
|
|
|
float viewy,
|
|
|
|
|
int *r_column,
|
|
|
|
|
int *r_row)
|
2008-12-31 10:44:00 +00:00
|
|
|
{
|
2019-05-03 13:00:18 +02:00
|
|
|
if (r_column) {
|
|
|
|
|
if (columnwidth > 0) {
|
|
|
|
|
/* Columns go from left to right (x increases). */
|
|
|
|
|
*r_column = floorf((viewx - startx) / columnwidth);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-05-03 13:00:18 +02:00
|
|
|
else {
|
|
|
|
|
*r_column = 0;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
if (r_row) {
|
|
|
|
|
if (rowheight > 0) {
|
|
|
|
|
/* Rows got from top to bottom (y decreases). */
|
|
|
|
|
*r_row = floorf((starty - viewy) / rowheight);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_row = 0;
|
|
|
|
|
}
|
2008-12-31 10:44:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Coordinate Conversions
|
|
|
|
|
* \{ */
|
2008-10-08 18:07:56 +00:00
|
|
|
|
2018-11-13 13:28:43 +11:00
|
|
|
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
|
2014-04-21 16:47:16 +10:00
|
|
|
{
|
|
|
|
|
return (v2d->cur.xmin +
|
|
|
|
|
(BLI_rctf_size_x(&v2d->cur) * (x - v2d->mask.xmin) / BLI_rcti_size_x(&v2d->mask)));
|
|
|
|
|
}
|
2018-11-13 13:28:43 +11:00
|
|
|
float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
|
2014-04-21 16:47:16 +10:00
|
|
|
{
|
|
|
|
|
return (v2d->cur.ymin +
|
|
|
|
|
(BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask)));
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-13 13:28:43 +11:00
|
|
|
void UI_view2d_region_to_view(
|
|
|
|
|
const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
{
|
2014-04-21 16:47:16 +10:00
|
|
|
*r_view_x = UI_view2d_region_to_view_x(v2d, x);
|
|
|
|
|
*r_view_y = UI_view2d_region_to_view_y(v2d, y);
|
|
|
|
|
}
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
|
2018-11-13 13:28:43 +11:00
|
|
|
void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst)
|
2014-04-21 16:47:16 +10:00
|
|
|
{
|
|
|
|
|
const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
|
2022-04-03 00:00:42 -05:00
|
|
|
const float mask_size[2] = {(float)BLI_rcti_size_x(&v2d->mask),
|
|
|
|
|
(float)BLI_rcti_size_y(&v2d->mask)};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
rect_dst->xmin = (v2d->cur.xmin +
|
|
|
|
|
(cur_size[0] * (rect_src->xmin - v2d->mask.xmin) / mask_size[0]));
|
|
|
|
|
rect_dst->xmax = (v2d->cur.xmin +
|
|
|
|
|
(cur_size[0] * (rect_src->xmax - v2d->mask.xmin) / mask_size[0]));
|
|
|
|
|
rect_dst->ymin = (v2d->cur.ymin +
|
|
|
|
|
(cur_size[1] * (rect_src->ymin - v2d->mask.ymin) / mask_size[1]));
|
|
|
|
|
rect_dst->ymax = (v2d->cur.ymin +
|
|
|
|
|
(cur_size[1] * (rect_src->ymax - v2d->mask.ymin) / mask_size[1]));
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-13 13:28:43 +11:00
|
|
|
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
|
2014-04-21 16:47:16 +10:00
|
|
|
{
|
|
|
|
|
return (v2d->mask.xmin +
|
|
|
|
|
(((x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur)) * BLI_rcti_size_x(&v2d->mask)));
|
|
|
|
|
}
|
2018-11-13 13:28:43 +11:00
|
|
|
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
|
2014-04-21 16:47:16 +10:00
|
|
|
{
|
|
|
|
|
return (v2d->mask.ymin +
|
|
|
|
|
(((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask)));
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
2018-11-13 13:28:43 +11:00
|
|
|
bool UI_view2d_view_to_region_clip(
|
|
|
|
|
const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
{
|
2008-11-28 04:01:35 +00:00
|
|
|
/* express given coordinates as proportional values */
|
2012-09-15 11:48:20 +00:00
|
|
|
x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
|
|
|
|
|
y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-11-28 04:01:35 +00:00
|
|
|
/* check if values are within bounds */
|
2012-03-30 01:51:25 +00:00
|
|
|
if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) {
|
2014-04-21 16:47:16 +10:00
|
|
|
*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)));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
return true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-03 14:20:10 +02:00
|
|
|
/* set initial value in case coordinate lies outside of bounds */
|
|
|
|
|
*r_region_x = *r_region_y = V2D_IS_CLIPPED;
|
|
|
|
|
|
|
|
|
|
return false;
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 19:32:59 +10:00
|
|
|
void UI_view2d_view_to_region(
|
|
|
|
|
const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
{
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Step 1: express given coordinates as proportional values. */
|
2012-09-15 11:48:20 +00:00
|
|
|
x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
|
|
|
|
|
y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
|
2014-04-21 16:47:16 +10:00
|
|
|
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Step 2: convert proportional distances to screen coordinates. */
|
2014-04-21 16:47:16 +10:00
|
|
|
x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
|
|
|
|
|
y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
|
|
|
|
|
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Although we don't clamp to lie within region bounds, we must avoid exceeding size of ints. */
|
2014-04-21 16:47:16 +10:00
|
|
|
*r_region_x = clamp_float_to_int(x);
|
|
|
|
|
*r_region_y = clamp_float_to_int(y);
|
2.5 Branch
==========
* Changed wmOperatorType, removing init/exit callbacks and adding cancel
callback, removed default storage in favor of properties. Defined return
values for exec/invoke/modal/cancel.
* Don't allocate operator on the stack, and removed operator copy for
handlers. Now it frees based on return values from callbacks, and just
keeps a wmOperator on the heap. Also it now registers after the operator
is fully finished, to get the correct final properties.
* Changed OP_get_* functions to return 1 if the property is found and 0
otherwise, gives more readable code in my opinion. Added OP_verify_*
functions to quickly check if the property is available and set if it's
not, that's common for exec/invoke.
* Removed WM_operatortypelist_append in favor of WM_operatortype_append
which takes a function pointer instead of a list, avoids macro's and
duplicating code.
* Fix a crash where the handler would still be used while it was freed by
the operator.
* Spacetypes now have operatortypes() and keymap() callbacks to abstract
them a bit more.
* Renamed C->curarea to C->area for consistency. Removed View3D/View2D/
SpaceIpo from bContext, seems bad to keep these.
* Set context variables like window/screen/area/region to NULL again when
leaving that context, instead of leaving the pointers there.
* Added if(G.f & G_DEBUG) for many of the prints, makes output a bit
cleaner and easier to debug.
* Fixed priority of the editors/interface module in scons, would otherwise
give link errors.
* Added start of generic view2d api.
* Added space_time with some basic drawing and a single operator to change
the frame.
2008-06-11 10:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
void UI_view2d_view_to_region_fl(
|
2020-05-04 19:32:59 +10:00
|
|
|
const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
|
2013-08-26 20:23:26 +00:00
|
|
|
{
|
|
|
|
|
/* express given coordinates as proportional values */
|
2014-04-21 14:30:13 +10:00
|
|
|
x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
|
|
|
|
|
y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
|
2013-08-26 20:23:26 +00:00
|
|
|
|
|
|
|
|
/* convert proportional distances to screen coordinates */
|
2014-04-21 16:47:16 +10:00
|
|
|
*r_region_x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
|
|
|
|
|
*r_region_y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-12 19:39:57 +10:00
|
|
|
bool UI_view2d_view_to_region_segment_clip(const View2D *v2d,
|
|
|
|
|
const float xy_a[2],
|
|
|
|
|
const float xy_b[2],
|
|
|
|
|
int r_region_a[2],
|
|
|
|
|
int r_region_b[2])
|
|
|
|
|
{
|
|
|
|
|
rctf rect_unit;
|
|
|
|
|
rect_unit.xmin = rect_unit.ymin = 0.0f;
|
|
|
|
|
rect_unit.xmax = rect_unit.ymax = 1.0f;
|
|
|
|
|
|
|
|
|
|
/* Express given coordinates as proportional values. */
|
|
|
|
|
const float s_a[2] = {
|
|
|
|
|
(xy_a[0] - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur),
|
|
|
|
|
(xy_a[1] - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur),
|
|
|
|
|
};
|
|
|
|
|
const float s_b[2] = {
|
|
|
|
|
(xy_b[0] - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur),
|
|
|
|
|
(xy_b[1] - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Set initial value in case coordinates lie outside bounds. */
|
|
|
|
|
r_region_a[0] = r_region_b[0] = r_region_a[1] = r_region_b[1] = V2D_IS_CLIPPED;
|
|
|
|
|
|
|
|
|
|
if (BLI_rctf_isect_segment(&rect_unit, s_a, s_b)) {
|
|
|
|
|
r_region_a[0] = (int)(v2d->mask.xmin + (s_a[0] * BLI_rcti_size_x(&v2d->mask)));
|
|
|
|
|
r_region_a[1] = (int)(v2d->mask.ymin + (s_a[1] * BLI_rcti_size_y(&v2d->mask)));
|
|
|
|
|
r_region_b[0] = (int)(v2d->mask.xmin + (s_b[0] * BLI_rcti_size_x(&v2d->mask)));
|
|
|
|
|
r_region_b[1] = (int)(v2d->mask.ymin + (s_b[1] * BLI_rcti_size_y(&v2d->mask)));
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 19:32:59 +10:00
|
|
|
void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
|
2014-04-21 16:47:16 +10:00
|
|
|
{
|
|
|
|
|
const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
|
2022-04-03 00:00:42 -05:00
|
|
|
const float mask_size[2] = {(float)BLI_rcti_size_x(&v2d->mask),
|
|
|
|
|
(float)BLI_rcti_size_y(&v2d->mask)};
|
2014-04-21 16:47:16 +10:00
|
|
|
rctf rect_tmp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Step 1: express given coordinates as proportional values. */
|
2014-04-21 16:47:16 +10:00
|
|
|
rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
|
|
|
|
|
rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
|
|
|
|
|
rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
|
|
|
|
|
rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Step 2: convert proportional distances to screen coordinates. */
|
2014-04-21 16:47:16 +10:00
|
|
|
rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
|
|
|
|
|
rect_tmp.xmax = v2d->mask.xmin + (rect_tmp.xmax * mask_size[0]);
|
|
|
|
|
rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
|
|
|
|
|
rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
clamp_rctf_to_rcti(rect_dst, &rect_tmp);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 19:32:59 +10:00
|
|
|
void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4])
|
2017-08-29 19:36:06 +10:00
|
|
|
{
|
|
|
|
|
rctf mask;
|
|
|
|
|
unit_m4(matrix);
|
|
|
|
|
BLI_rctf_rcti_copy(&mask, &v2d->mask);
|
|
|
|
|
BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &mask, matrix);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 19:32:59 +10:00
|
|
|
bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
|
2014-04-21 16:47:16 +10:00
|
|
|
{
|
|
|
|
|
const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
|
2022-04-03 00:00:42 -05:00
|
|
|
const float mask_size[2] = {(float)BLI_rcti_size_x(&v2d->mask),
|
|
|
|
|
(float)BLI_rcti_size_y(&v2d->mask)};
|
2014-04-21 16:47:16 +10:00
|
|
|
rctf rect_tmp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
BLI_assert(rect_src->xmin <= rect_src->xmax && rect_src->ymin <= rect_src->ymax);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Step 1: express given coordinates as proportional values. */
|
2014-04-21 16:47:16 +10:00
|
|
|
rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
|
|
|
|
|
rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
|
|
|
|
|
rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
|
|
|
|
|
rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
if (((rect_tmp.xmax < 0.0f) || (rect_tmp.xmin > 1.0f) || (rect_tmp.ymax < 0.0f) ||
|
|
|
|
|
(rect_tmp.ymin > 1.0f)) == 0) {
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Step 2: convert proportional distances to screen coordinates. */
|
2014-04-21 16:47:16 +10:00
|
|
|
rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
|
|
|
|
|
rect_tmp.xmax = v2d->mask.ymin + (rect_tmp.xmax * mask_size[0]);
|
|
|
|
|
rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
|
|
|
|
|
rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
clamp_rctf_to_rcti(rect_dst, &rect_tmp);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
return true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-03 14:20:10 +02:00
|
|
|
rect_dst->xmin = rect_dst->xmax = rect_dst->ymin = rect_dst->ymax = V2D_IS_CLIPPED;
|
|
|
|
|
return false;
|
2013-08-26 20:23:26 +00:00
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Utilities
|
|
|
|
|
* \{ */
|
2008-11-28 04:01:35 +00:00
|
|
|
|
2008-12-02 09:43:23 +00:00
|
|
|
View2D *UI_view2d_fromcontext(const bContext *C)
|
|
|
|
|
{
|
2012-03-30 01:51:25 +00:00
|
|
|
ScrArea *area = CTX_wm_area(C);
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
if (area == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2022-04-03 00:00:42 -05:00
|
|
|
if (region == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2008-12-18 02:56:48 +00:00
|
|
|
return &(region->v2d);
|
2008-12-02 09:43:23 +00:00
|
|
|
}
|
|
|
|
|
|
2008-12-11 15:38:16 +00:00
|
|
|
View2D *UI_view2d_fromcontext_rwin(const bContext *C)
|
|
|
|
|
{
|
2020-04-03 13:25:03 +02:00
|
|
|
ScrArea *area = CTX_wm_area(C);
|
2012-03-30 01:51:25 +00:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
if (area == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2022-04-03 00:00:42 -05:00
|
|
|
if (region == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2012-03-30 01:51:25 +00:00
|
|
|
if (region->regiontype != RGN_TYPE_WINDOW) {
|
2020-04-03 13:25:03 +02:00
|
|
|
ARegion *region_win = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
|
2022-04-03 00:00:42 -05:00
|
|
|
return region_win ? &(region_win->v2d) : nullptr;
|
2008-12-11 15:38:16 +00:00
|
|
|
}
|
2008-12-18 02:56:48 +00:00
|
|
|
return &(region->v2d);
|
2008-12-11 15:38:16 +00:00
|
|
|
}
|
|
|
|
|
|
2022-06-27 06:45:49 -07:00
|
|
|
void UI_view2d_scroller_size_get(const View2D *v2d, bool mapped, float *r_x, float *r_y)
|
2019-12-04 16:00:03 +01:00
|
|
|
{
|
2022-06-27 06:45:49 -07:00
|
|
|
const int scroll = (mapped) ? view2d_scroll_mapped(v2d->scroll) : v2d->scroll;
|
2019-12-04 16:00:03 +01:00
|
|
|
|
|
|
|
|
if (r_x) {
|
|
|
|
|
if (scroll & V2D_SCROLL_VERTICAL) {
|
|
|
|
|
*r_x = (scroll & V2D_SCROLL_VERTICAL_HANDLES) ? V2D_SCROLL_HANDLE_WIDTH : V2D_SCROLL_WIDTH;
|
2022-06-27 06:45:49 -07:00
|
|
|
*r_x = ((*r_x - V2D_SCROLL_MIN_WIDTH) * (v2d->alpha_vert / 255.0f)) + V2D_SCROLL_MIN_WIDTH;
|
2019-12-04 16:00:03 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_x = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (r_y) {
|
|
|
|
|
if (scroll & V2D_SCROLL_HORIZONTAL) {
|
|
|
|
|
*r_y = (scroll & V2D_SCROLL_HORIZONTAL_HANDLES) ? V2D_SCROLL_HANDLE_HEIGHT :
|
|
|
|
|
V2D_SCROLL_HEIGHT;
|
2022-06-27 06:45:49 -07:00
|
|
|
*r_y = ((*r_y - V2D_SCROLL_MIN_WIDTH) * (v2d->alpha_hor / 255.0f)) + V2D_SCROLL_MIN_WIDTH;
|
2019-12-04 16:00:03 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_y = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y)
|
2008-11-24 18:59:59 +00:00
|
|
|
{
|
2019-03-25 12:19:55 +11:00
|
|
|
if (r_x) {
|
2019-04-16 14:15:49 +02:00
|
|
|
*r_x = UI_view2d_scale_get_x(v2d);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-03-25 12:19:55 +11:00
|
|
|
if (r_y) {
|
2019-04-16 14:15:49 +02:00
|
|
|
*r_y = UI_view2d_scale_get_y(v2d);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2008-11-24 18:59:59 +00:00
|
|
|
}
|
2019-04-16 14:15:49 +02:00
|
|
|
float UI_view2d_scale_get_x(const View2D *v2d)
|
|
|
|
|
{
|
|
|
|
|
return BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
|
|
|
|
|
}
|
|
|
|
|
float UI_view2d_scale_get_y(const View2D *v2d)
|
|
|
|
|
{
|
|
|
|
|
return BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
|
|
|
|
|
}
|
2020-05-04 19:32:59 +10:00
|
|
|
void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y)
|
2012-12-14 16:51:02 +00:00
|
|
|
{
|
2019-03-25 12:19:55 +11:00
|
|
|
if (r_x) {
|
|
|
|
|
*r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-03-25 12:19:55 +11:00
|
|
|
if (r_y) {
|
|
|
|
|
*r_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2012-12-14 16:51:02 +00:00
|
|
|
}
|
2008-12-15 18:09:55 +00:00
|
|
|
|
2020-05-04 19:32:59 +10:00
|
|
|
void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
/* get center */
|
2019-03-25 12:19:55 +11:00
|
|
|
if (r_x) {
|
|
|
|
|
*r_x = BLI_rctf_cent_x(&v2d->cur);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-03-25 12:19:55 +11:00
|
|
|
if (r_y) {
|
|
|
|
|
*r_y = BLI_rctf_cent_y(&v2d->cur);
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2014-04-21 18:46:52 +10:00
|
|
|
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2013-03-19 10:54:52 +00:00
|
|
|
BLI_rctf_recenter(&v2d->cur, x, y);
|
2013-03-18 18:25:05 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* make sure that 'cur' rect is in a valid state as a result of these changes */
|
|
|
|
|
UI_view2d_curRect_validate(v2d);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-22 13:07:02 +11:00
|
|
|
void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
|
|
|
|
|
{
|
|
|
|
|
if (xfac != -1.0f) {
|
|
|
|
|
const float xsize = BLI_rctf_size_x(&v2d->cur);
|
|
|
|
|
const float xmin = v2d->tot.xmin;
|
|
|
|
|
const float xmax = v2d->tot.xmax - xsize;
|
|
|
|
|
|
|
|
|
|
v2d->cur.xmin = (xmin * (1.0f - xfac)) + (xmax * xfac);
|
|
|
|
|
v2d->cur.xmax = v2d->cur.xmin + xsize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (yfac != -1.0f) {
|
|
|
|
|
const float ysize = BLI_rctf_size_y(&v2d->cur);
|
|
|
|
|
const float ymin = v2d->tot.ymin;
|
|
|
|
|
const float ymax = v2d->tot.ymax - ysize;
|
|
|
|
|
|
|
|
|
|
v2d->cur.ymin = (ymin * (1.0f - yfac)) + (ymax * yfac);
|
|
|
|
|
v2d->cur.ymax = v2d->cur.ymin + ysize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UI_view2d_curRect_validate(v2d);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 20:49:02 -03:00
|
|
|
char UI_view2d_mouse_in_scrollers_ex(const ARegion *region,
|
|
|
|
|
const View2D *v2d,
|
|
|
|
|
const int xy[2],
|
|
|
|
|
int *r_scroll)
|
2008-12-23 11:02:39 +00:00
|
|
|
{
|
2019-04-23 16:43:50 +10:00
|
|
|
const int scroll = view2d_scroll_mapped(v2d->scroll);
|
2018-11-07 18:14:21 +11:00
|
|
|
*r_scroll = scroll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-23 17:12:09 +10:00
|
|
|
if (scroll) {
|
|
|
|
|
/* Move to region-coordinates. */
|
|
|
|
|
const int co[2] = {
|
2021-10-20 20:49:02 -03:00
|
|
|
xy[0] - region->winrct.xmin,
|
|
|
|
|
xy[1] - region->winrct.ymin,
|
2019-04-23 17:12:09 +10:00
|
|
|
};
|
|
|
|
|
if (scroll & V2D_SCROLL_HORIZONTAL) {
|
|
|
|
|
if (IN_2D_HORIZ_SCROLL(v2d, co)) {
|
|
|
|
|
return 'h';
|
|
|
|
|
}
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2019-04-23 17:12:09 +10:00
|
|
|
if (scroll & V2D_SCROLL_VERTICAL) {
|
|
|
|
|
if (IN_2D_VERT_SCROLL(v2d, co)) {
|
|
|
|
|
return 'v';
|
|
|
|
|
}
|
2019-03-25 10:15:20 +11:00
|
|
|
}
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-23 11:02:39 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
char UI_view2d_rect_in_scrollers_ex(const ARegion *region,
|
2019-04-23 16:43:50 +10:00
|
|
|
const View2D *v2d,
|
|
|
|
|
const rcti *rect,
|
|
|
|
|
int *r_scroll)
|
|
|
|
|
{
|
|
|
|
|
const int scroll = view2d_scroll_mapped(v2d->scroll);
|
|
|
|
|
*r_scroll = scroll;
|
|
|
|
|
|
2019-04-23 17:12:09 +10:00
|
|
|
if (scroll) {
|
|
|
|
|
/* Move to region-coordinates. */
|
|
|
|
|
rcti rect_region = *rect;
|
2020-03-06 16:56:42 +01:00
|
|
|
BLI_rcti_translate(&rect_region, -region->winrct.xmin, region->winrct.ymin);
|
2019-04-23 17:12:09 +10:00
|
|
|
if (scroll & V2D_SCROLL_HORIZONTAL) {
|
|
|
|
|
if (IN_2D_HORIZ_SCROLL_RECT(v2d, &rect_region)) {
|
|
|
|
|
return 'h';
|
|
|
|
|
}
|
2019-04-23 16:43:50 +10:00
|
|
|
}
|
2019-04-23 17:12:09 +10:00
|
|
|
if (scroll & V2D_SCROLL_VERTICAL) {
|
|
|
|
|
if (IN_2D_VERT_SCROLL_RECT(v2d, &rect_region)) {
|
|
|
|
|
return 'v';
|
|
|
|
|
}
|
2019-04-23 16:43:50 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 20:49:02 -03:00
|
|
|
char UI_view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, const int xy[2])
|
2018-11-07 18:14:21 +11:00
|
|
|
{
|
|
|
|
|
int scroll_dummy = 0;
|
2021-10-20 20:49:02 -03:00
|
|
|
return UI_view2d_mouse_in_scrollers_ex(region, v2d, xy, &scroll_dummy);
|
2018-11-07 18:14:21 +11:00
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
char UI_view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect)
|
2019-04-23 16:43:50 +10:00
|
|
|
{
|
|
|
|
|
int scroll_dummy = 0;
|
2020-03-06 16:56:42 +01:00
|
|
|
return UI_view2d_rect_in_scrollers_ex(region, v2d, rect, &scroll_dummy);
|
2019-04-23 16:43:50 +10:00
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name View2D Text Drawing Cache
|
|
|
|
|
* \{ */
|
2009-06-01 16:22:53 +00:00
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
struct View2DString {
|
2014-04-17 15:14:07 +10:00
|
|
|
struct View2DString *next;
|
2010-12-20 03:59:22 +00:00
|
|
|
union {
|
2019-01-04 11:05:53 +11:00
|
|
|
uchar ub[4];
|
2010-12-20 03:59:22 +00:00
|
|
|
int pack;
|
|
|
|
|
} col;
|
2009-06-01 17:21:03 +00:00
|
|
|
rcti rect;
|
2014-04-17 15:14:07 +10:00
|
|
|
int mval[2];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-06-15 04:06:44 +10:00
|
|
|
/* str is allocated past the end */
|
|
|
|
|
char str[0];
|
2022-04-03 00:00:42 -05:00
|
|
|
};
|
2009-06-01 16:22:53 +00:00
|
|
|
|
2014-04-17 15:14:07 +10:00
|
|
|
/* assumes caches are used correctly, so for time being no local storage in v2d */
|
2022-04-03 00:00:42 -05:00
|
|
|
static MemArena *g_v2d_strings_arena = nullptr;
|
|
|
|
|
static View2DString *g_v2d_strings = nullptr;
|
2009-06-01 16:22:53 +00:00
|
|
|
|
2015-05-05 03:13:47 +10:00
|
|
|
void UI_view2d_text_cache_add(
|
2020-03-16 11:53:08 +11:00
|
|
|
View2D *v2d, float x, float y, const char *str, size_t str_len, const uchar col[4])
|
2009-06-01 16:22:53 +00:00
|
|
|
{
|
|
|
|
|
int mval[2];
|
2018-05-23 10:47:12 +02:00
|
|
|
|
2014-04-17 15:14:07 +10:00
|
|
|
BLI_assert(str_len == strlen(str));
|
|
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
if (UI_view2d_view_to_region_clip(v2d, x, y, &mval[0], &mval[1])) {
|
2020-08-26 10:11:13 +10:00
|
|
|
const int alloc_len = str_len + 1;
|
2014-04-17 15:14:07 +10:00
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
if (g_v2d_strings_arena == nullptr) {
|
2014-04-17 15:14:07 +10:00
|
|
|
g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
View2DString *v2s = static_cast<View2DString *>(
|
|
|
|
|
BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len));
|
2014-04-17 15:14:07 +10:00
|
|
|
|
|
|
|
|
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
|
2010-12-07 07:02:47 +00:00
|
|
|
|
2015-01-01 23:26:03 +11:00
|
|
|
v2s->col.pack = *((const int *)col);
|
2014-04-17 15:14:07 +10:00
|
|
|
|
|
|
|
|
memset(&v2s->rect, 0, sizeof(v2s->rect));
|
|
|
|
|
|
2012-03-30 01:51:25 +00:00
|
|
|
v2s->mval[0] = mval[0];
|
|
|
|
|
v2s->mval[1] = mval[1];
|
2014-04-17 15:14:07 +10:00
|
|
|
|
2014-06-15 04:06:44 +10:00
|
|
|
memcpy(v2s->str, str, alloc_len);
|
2009-06-01 16:22:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-05 03:13:47 +10:00
|
|
|
void UI_view2d_text_cache_add_rectf(
|
2020-03-16 11:53:08 +11:00
|
|
|
View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4])
|
2009-06-01 17:21:03 +00:00
|
|
|
{
|
2014-04-21 16:47:16 +10:00
|
|
|
rcti rect;
|
2014-04-17 15:14:07 +10:00
|
|
|
|
|
|
|
|
BLI_assert(str_len == strlen(str));
|
|
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
if (UI_view2d_view_to_region_rcti_clip(v2d, rect_view, &rect)) {
|
2020-08-26 10:11:13 +10:00
|
|
|
const int alloc_len = str_len + 1;
|
2014-04-21 16:47:16 +10:00
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
if (g_v2d_strings_arena == nullptr) {
|
2014-04-21 16:47:16 +10:00
|
|
|
g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
|
|
|
|
|
}
|
2014-04-17 15:14:07 +10:00
|
|
|
|
2022-04-03 00:00:42 -05:00
|
|
|
View2DString *v2s = static_cast<View2DString *>(
|
|
|
|
|
BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len));
|
2014-04-17 15:14:07 +10:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
|
2014-04-17 15:14:07 +10:00
|
|
|
|
2015-01-01 23:26:03 +11:00
|
|
|
v2s->col.pack = *((const int *)col);
|
2010-12-07 07:02:47 +00:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
v2s->rect = rect;
|
2010-12-07 07:02:47 +00:00
|
|
|
|
2014-04-21 16:47:16 +10:00
|
|
|
v2s->mval[0] = v2s->rect.xmin;
|
|
|
|
|
v2s->mval[1] = v2s->rect.ymin;
|
2010-12-07 07:02:47 +00:00
|
|
|
|
2014-06-15 04:06:44 +10:00
|
|
|
memcpy(v2s->str, str, alloc_len);
|
2014-04-21 16:47:16 +10:00
|
|
|
}
|
2009-06-01 17:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
void UI_view2d_text_cache_draw(ARegion *region)
|
2009-06-01 16:22:53 +00:00
|
|
|
{
|
|
|
|
|
View2DString *v2s;
|
2012-03-30 01:51:25 +00:00
|
|
|
int col_pack_prev = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-20 19:23:12 +00:00
|
|
|
/* investigate using BLF_ascender() */
|
2017-02-05 00:54:21 -05:00
|
|
|
const int font_id = BLF_default();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-23 11:37:24 -08:00
|
|
|
BLF_set_default();
|
2017-02-05 00:54:21 -05:00
|
|
|
const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
wmOrtho2_region_pixelspace(region);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-17 15:14:07 +10:00
|
|
|
for (v2s = g_v2d_strings; v2s; v2s = v2s->next) {
|
2012-03-30 01:51:25 +00:00
|
|
|
int xofs = 0, yofs;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-09-15 11:48:20 +00:00
|
|
|
yofs = ceil(0.5f * (BLI_rcti_size_y(&v2s->rect) - default_height));
|
2019-03-25 10:15:20 +11:00
|
|
|
if (yofs < 1) {
|
|
|
|
|
yofs = 1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (col_pack_prev != v2s->col.pack) {
|
2017-02-05 00:54:21 -05:00
|
|
|
BLF_color3ubv(font_id, v2s->col.ub);
|
2012-03-30 01:51:25 +00:00
|
|
|
col_pack_prev = v2s->col.pack;
|
2010-12-20 03:59:22 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-05-27 11:24:03 +02:00
|
|
|
BLF_enable(font_id, BLF_CLIPPING);
|
|
|
|
|
BLF_clipping(
|
|
|
|
|
font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
|
|
|
|
|
BLF_draw_default(
|
|
|
|
|
v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX);
|
|
|
|
|
BLF_disable(font_id, BLF_CLIPPING);
|
2009-06-01 16:22:53 +00:00
|
|
|
}
|
2022-04-03 00:00:42 -05:00
|
|
|
g_v2d_strings = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-17 15:14:07 +10:00
|
|
|
if (g_v2d_strings_arena) {
|
|
|
|
|
BLI_memarena_free(g_v2d_strings_arena);
|
2022-04-03 00:00:42 -05:00
|
|
|
g_v2d_strings_arena = nullptr;
|
2014-04-17 15:14:07 +10:00
|
|
|
}
|
2009-06-01 16:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
2019-09-06 16:12:47 +10:00
|
|
|
/** \} */
|