- View2D provides a system of manipulating view matrices to allow panning and/or zooming of the data presented by the region where it's used. This is similar to a 'Scrolled Window' or 'Scrolled Panel' in other GUI toolkits.
- Tools and an API are provided to facilitate manipulations of the rects used to achieve this, with settings/flags stored per View2D data-block providing constraints on the manipulations possible
- Visualisation and manipulation of current view through 'scrollers' (which are effectively scrollbars, though they also double up as scale indicators for grids)
- Provide grid-drawing system for use in 2d-views where it is appropriate
- A set of 'preset' view settings that can be used as a base for quickly and easily setting up a viewport for 2D presentation of data
These settings are defined and saved to file in
View2D structs. This struct, and all of these settings, can be found in
- Firstly, the view rects responsible for the panning + zooming capabilities:
- tot - this appears to be the 'entire canvas' that all the keyframes, etc. get drawn on (visualise it as a map drawn on a piece of paper)
- cur - this is the 'viewable region' of the entire canvas, or what gets manipulated when we adjust the viewport
- Now, to support this, there are some additional rects (in screenspace):
- mask - this area-space/screen-region that we see the contents of cur region in
- hor - current region of horizontal scrollbar
- vert - current region of vertical scrollbar
- Settings used to define the behaviour of the 'cur' rect
- keepzoom - holds settings relevant to zoom/scale of view
- V2D_KEEPZOOM - zoom is clamped to lie within minzoom/maxzoom bounds
- V2D_LOCKZOOM_X - zooming is not allowed on x-axis
- V2D_LOCKZOOM_Y - zooming is not allowed on y-axis
- V2D_KEEPASPECT - aspect ratio is maintained after view size changes. View will either be zoomed to maintain this ratio or moved to keep contents in view if zooming is locked.
- keeptot - should the extents of 'tot' rect be respected?
- V2D_KEEPTOT_FREE - extents of 'tot' rect are not respected
- V2D_KEEPTOT_BOUNDS - some of the extents of 'tot' rect are respected, but not all will be satisfied
- V2D_KEEPTOT_STRICT - the 'minimum' bounds of the 'tot' rect are always respected (particularly in x-axis). If view is resized and V2D_KEEPASPECT is set, view contents are moved.
- keepofs - hold settings for view panning restrictions
- V2D_LOCKOFS_X - no panning allowed on x-axis
- V2D_LOCKOFS_Y - no panning allowed on y-axis
- scroll - holds settings for what scrollers are visible, and how they should be presented
- V2D_SCROLL_LEFT - vertical scrollbar on left side of region (is favoured over V2D_SCROLL_RIGHT when both are set)
- V2D_SCROLL_RIGHT - vertical scrollbar on right side of region
- V2D_SCROLL_VERTICAL - convenience define for checking if a vertical scroller is enabled
- V2D_SCROLL_BOTTOM - horizontal scrollbar on bottom edge of region (is favoured over V2D_SCROLL_TOP when both are set)
- V2D_SCROLL_BOTTOM_O - same as V2D_SCROLL_BOTTOM, but is used for Outliner only, as older Blenders would hang due to an old bug in the scale-markings code
- V2D_SCROLL_TOP - horizontal scrollbar on top edge of region
- V2D_SCROLL_HORIZONTAL - convenience define for checking if a horizontal scroller is enabled
- V2D_SCROLL_SCALE_VERTICAL - show scale markings on vertical scroller (only if visible)
- V2D_SCROLL_SCALE_HORIZONTAL - show scale markings on horizontal scroller (only if visible)
- align - holds settings for which 'quadrants' the 'tot' rect occupies, with flags using the shading-out convention
- V2D_ALIGN_FREE - tot is centered around (0,0) in what is assumed to be a 'balanced' way
- V2D_ALIGN_NO_POS_X - 'tot' can only occur in negative x half (this is mutually exclusive to V2D_ALIGN_NO_NEG_X as they cancel each other out)
- V2D_ALIGN_NO_NEG_X - 'tot' can only occur in positive x half
- V2D_ALIGN_NO_POS_Y - 'tot' can only occur in negative y half (this is mutually exlusive to V2D_ALIGN_NO_NEG_Y as they cancel each other out)
- V2D_ALIGN_NO_NEG_Y - 'tot' can only occur in positive y half
- Size/zoom constraints (values):
- min/maxzoom - these define the minimum and maximum zoom factors to clamp within (when V2D_KEEPZOOM is set)
- min/max - these define the minimum and maximum sizes of the 'cur' rect on x and y axes independently, which are used when V2D_KEEPZOOM is NOT set
- Also defined in the View2D data, are some settings related to transform pivots, etc. which can be used by the region if there is such a need
- around - pivot to transform around (uses the same defines as are used for 3D-View)
- cursor - coordinates for 2D-cursor
See http://aligorith.googlepages.com/v2d_chart.xls (FIXME: move this to wiki server...) for settings used by each of the old spacetypes for their 'main' scrollable area...
API - What you need to know when using View2D
Setting Up 2D views in Regions
View2D data is stored per ARegion as a direct member, allowing each region to have its own 2D viewport. Regions (typically) define 3 callback methods for handling their drawing and interaction with users:
init, main, free.
Of these three,
init is the most relevant for setting up the viewport or making sure that the viewport is still valid after the region has been resized/reloaded. Typically, a call to
UI_view2d_region_reinit() is made here. This call serves 2 purposes:
- 1) It ensures that the necessary settings for the viewport have been set (as necessary for the View2D preset specified as the second argument).
- 2) Whenever the region is resized, etc. the view extents are adjusted so that the viewport is in the most suitable (and valid) configuration as a result of these changes.
The presets provide a set of commonly used configurations for View2D viewports, allowing appropriate viewports to be set up with less effort.
Presets are not saved in SDNA or stored for later access, and are mainly used as the second argument to
UI_view2d_region_reinit(). A list of the defines can be found in
UI_view2d.h alongside the API, and is also presented here for completeness.
- V2D_COMMONVIEW_CUSTOM - custom view type - Use this preset when the region has defined all necessary settings already in the
spacetype_new()code when creating the region-data needed for the editor.
- V2D_COMMONVIEW_STANDARD - standard View2D configuration - Use this preset when setting up a new view, as a sensible base for most settings)
- V2D_COMMONVIEW_LIST - list view - Use this preset for a vertical list of items (such as the Outliner, or the Channel List regions for the Animation Editors) that can get arbitrarily long, with items being added to the end, and the possibility to expand/collapse items as necessary.
- V2D_COMMONVIEW_STACK - stack view - This preset should be used when a list where new items are added at the top instead of at the bottom of the list.
- V2D_COMMONVIEW_HEADER - Header regions
- V2D_COMMONVIEW_PANELS_UI - UI region containing panels
Guidelines for the use of presets:
- In general, it is recommended that if there are similar types of viewports, a preset defining the characteristics required for all of them should be used/created.
- When only a single viewport uses a particular combination of settings that differ significantly from an existing preset
Drawing and View2D Viewports
Design Rationale Information (only for the curious and/or historical archiving purposes)
Relationship to Regions
- Most regions provide a 2D-view of some data (the 3D-View region in 3D-View Area/Spacetype is exception). Therefore, most will require the services provided by the View2D system, to extend (or provide tools to improve) view of data.
- View2D data is stored as a direct member of ARegion struct, so that it will be accessable to all.
- Panels (floating, etc.), channel lists, buttons views, etc. are Regions, so will get their own View2D data
- Listeners/notifiers used to communicate relevant view changes inter-regionally and also inter-area as necessary to satisfy view-syncing requirements
- Scrollers are scrollbars which also show scale markings for animation editors (in particular), and also regions where precision is an issue.
- Manipulations done over the scrollbars alter the view too in a way that is consistent with expectations that they are widgets that operate in same way as seen elsewhere
- i.e. non-uniform scale using grabbers on ends of 'bubble'
- Scrollers are not separate regions themselves, and they are also not UI-widgets. While this may sound controversial to some, there are reasons why:
- A scroller is only really relevant to the region that it affects (Note: each region can have own 'context' and own 'state' with regiondata. Sliders belong to this single context/state that they represent/modify)
- Scrollers are relatively simple 2D-manipulators, compared to the more complex region views. However, they are a bit too complex to be full-blown UI-widget, given that they exhibit multiple behaviours and show information which is strictly dependent on the View2D data they affect/belong to.
- Regions should become "dockable" or "collapsed", in which case we would most likely want some form of tab widget to allow regions to be collapsed and expanded. It would be inappropriate to have such tab widgets for a scroller purely on the basis that the scroller was region, so needed one of them.
- Scrollers are implemented using three main components: extra rects in the View2D data for defining where they exist in the region,