Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <mail@jlucke.com>2019-05-02 13:00:12 +0300
committerJacques Lucke <mail@jlucke.com>2019-05-02 13:00:12 +0300
commit667af6cf411918ba181afc1a7d6bcb474f9fadb8 (patch)
treed9d8831caff733df9293db42d87fbc9733ba1415 /source/blender/editors/interface/view2d.c
parent5b14b5654231a50874fd9103d2adb306f62aec8d (diff)
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
Diffstat (limited to 'source/blender/editors/interface/view2d.c')
-rw-r--r--source/blender/editors/interface/view2d.c466
1 files changed, 4 insertions, 462 deletions
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 072497dbb74..58d26c4a840 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -31,12 +31,14 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
+#include "BLI_array.h"
#include "BLI_utildefines.h"
#include "BLI_link_utils.h"
#include "BLI_rect.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_timecode.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -1117,7 +1119,7 @@ void UI_view2d_zoom_cache_reset(void)
/* View Matrix Setup */
/* mapping function to ensure 'cur' draws extended over the area where sliders are */
-static void view2d_map_cur_using_mask(View2D *v2d, rctf *r_curmasked)
+static void view2d_map_cur_using_mask(const View2D *v2d, rctf *r_curmasked)
{
*r_curmasked = v2d->cur;
@@ -1149,7 +1151,7 @@ static void view2d_map_cur_using_mask(View2D *v2d, rctf *r_curmasked)
}
/* Set view matrices to use 'cur' rect as viewing frame for View2D drawing */
-void UI_view2d_view_ortho(View2D *v2d)
+void UI_view2d_view_ortho(const View2D *v2d)
{
rctf curmasked;
const int sizex = BLI_rcti_size_x(&v2d->mask);
@@ -1238,337 +1240,6 @@ void UI_view2d_view_restore(const bContext *C)
/* *********************************************************************** */
/* Gridlines */
-/* View2DGrid is typedef'd in UI_view2d.h */
-struct View2DGrid {
- float dx, dy; /* stepsize (in pixels) between gridlines */
- float startx, starty; /* initial coordinates to start drawing grid from */
- int powerx, powery; /* step as power of 10 */
-};
-
-/* --------------- */
-
-/* try to write step as a power of 10 */
-static void step_to_grid(float *step, const int unit, int *r_power)
-{
- const float loga = (float)log10(*step);
- float rem;
-
- int power = (int)(loga);
-
- rem = loga - power;
- rem = (float)pow(10.0, rem);
-
- if (loga < 0.0f) {
- if (rem < 0.2f) {
- rem = 0.2f;
- }
- else if (rem < 0.5f) {
- rem = 0.5f;
- }
- else {
- rem = 1.0f;
- }
-
- *step = rem * (float)pow(10.0, power);
-
- /* for frames, we want 1.0 frame intervals only */
- if (unit == V2D_UNIT_FRAMES) {
- rem = 1.0f;
- /* use 2 since there are grid lines drawn in between,
- * this way to get 1 line per frame */
- *step = 2.0f;
- }
-
- /* prevents printing 1.0 2.0 3.0 etc */
- if (rem == 1.0f) {
- power++;
- }
- }
- else {
- if (rem < 2.0f) {
- rem = 2.0f;
- }
- else if (rem < 5.0f) {
- rem = 5.0f;
- }
- else {
- rem = 10.0f;
- }
-
- *step = rem * (float)pow(10.0, power);
-
- power++;
- /* prevents printing 1.0, 2.0, 3.0, etc. */
- if (rem == 10.0f) {
- power++;
- }
- }
-
- *r_power = power;
-}
-
-/**
- * Initialize settings necessary for drawing gridlines in a 2d-view
- *
- * - Currently, will return pointer to View2DGrid struct that needs to
- * be freed with UI_view2d_grid_free()
- * - Units + clamping args will be checked, to make sure they are valid values that can be used
- * so it is very possible that we won't return grid at all!
- *
- * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames
- * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals
- * - winx = width of region we're drawing to, note: not used but keeping for completeness.
- * - winy = height of region we're drawing into
- */
-View2DGrid *UI_view2d_grid_calc(Scene *scene,
- View2D *v2d,
- short xunits,
- short xclamp,
- short yunits,
- short yclamp,
- int UNUSED(winx),
- int winy)
-{
-
- View2DGrid *grid;
- float space, seconddiv;
-
- /* check that there are at least some workable args */
- if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) && ELEM(V2D_ARG_DUMMY, yunits, yclamp)) {
- return NULL;
- }
-
- /* grid here is allocated... */
- grid = MEM_callocN(sizeof(View2DGrid), "View2DGrid");
-
- /* rule: gridstep is minimal GRIDSTEP pixels */
- if (xunits == V2D_UNIT_SECONDS) {
- seconddiv = (float)(0.01 * FPS);
- }
- else {
- seconddiv = 1.0f;
- }
-
- /* calculate x-axis grid scale (only if both args are valid) */
- if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
- space = BLI_rctf_size_x(&v2d->cur);
-
- if (space != 0.0f) {
- const float pixels = (float)BLI_rcti_size_x(&v2d->mask);
- if (pixels != 0.0f) {
- grid->dx = (U.v2d_min_gridsize * UI_DPI_FAC * space) / (seconddiv * pixels);
- step_to_grid(&grid->dx, xunits, &grid->powerx);
- grid->dx *= seconddiv;
- }
- }
-
- if (xclamp == V2D_GRID_CLAMP) {
- CLAMP_MIN(grid->dx, 0.1f);
- CLAMP_MIN(grid->powerx, 0);
- grid->powerx -= 2;
- }
- }
-
- /* calculate y-axis grid scale (only if both args are valid) */
- if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
- space = BLI_rctf_size_y(&v2d->cur);
- if (space != 0.0f) {
- const float pixels = (float)winy;
- if (pixels != 0.0f) {
- grid->dy = U.v2d_min_gridsize * UI_DPI_FAC * space / pixels;
- step_to_grid(&grid->dy, yunits, &grid->powery);
- }
- }
-
- if (yclamp == V2D_GRID_CLAMP) {
- CLAMP_MIN(grid->dy, 1.0f);
- CLAMP_MIN(grid->powery, 1);
- }
- }
-
- /* calculate start position */
- if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
- grid->startx = seconddiv * (v2d->cur.xmin / seconddiv -
- (float)fmod(v2d->cur.xmin / seconddiv, grid->dx / seconddiv));
- if (v2d->cur.xmin < 0.0f) {
- grid->startx -= grid->dx;
- }
- }
- else {
- grid->startx = v2d->cur.xmin;
- }
-
- if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
- grid->starty = (v2d->cur.ymin - (float)fmod(v2d->cur.ymin, grid->dy));
- if (v2d->cur.ymin < 0.0f) {
- grid->starty -= grid->dy;
- }
- }
- else {
- grid->starty = v2d->cur.ymin;
- }
-
- return grid;
-}
-
-/* Draw gridlines in the given 2d-region */
-void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
-{
- float vec1[2], vec2[2];
- int a, step;
- int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
- int horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) /
- (U.v2d_min_gridsize * UI_DPI_FAC);
- uchar grid_line_color[3];
-
- /* check for grid first, as it may not exist */
- if (grid == NULL) {
- return;
- }
-
- /* Count the needed vertices for the gridlines */
- unsigned vertex_count = 0;
- if (flag & V2D_VERTICAL_LINES) {
- /* vertical lines */
- vertex_count += 2 * vertical_minor_step; /* minor gridlines */
- vertex_count += 2 * (vertical_minor_step + 2); /* major gridlines */
- }
- if (flag & V2D_HORIZONTAL_LINES) {
- /* horizontal lines */
- vertex_count += 2 * (horizontal_major_step + 1); /* major gridlines */
-
- /* fine lines */
- if (flag & V2D_HORIZONTAL_FINELINES) {
- vertex_count += 2 * (horizontal_major_step + 1);
- }
- }
- /* axes */
- if (flag & V2D_HORIZONTAL_AXIS) {
- vertex_count += 2;
- }
- if (flag & V2D_VERTICAL_AXIS) {
- vertex_count += 2;
- }
-
- /* If there is nothing to render, exit early */
- if (vertex_count == 0) {
- return;
- }
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint color = GPU_vertformat_attr_add(
- format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GPU_PRIM_LINES, vertex_count);
-
- /* vertical lines */
- if (flag & V2D_VERTICAL_LINES) {
- /* initialize initial settings */
- vec1[0] = vec2[0] = grid->startx;
- vec1[1] = grid->starty;
- vec2[1] = v2d->cur.ymax;
-
- /* minor gridlines */
- step = vertical_minor_step;
- if (step != 0) {
- UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
-
- for (a = 0; a < step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[0] = vec1[0] += grid->dx;
- }
- }
-
- /* major gridlines */
- vec2[0] = vec1[0] -= 0.5f * grid->dx;
-
- UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
-
- step++;
- for (a = 0; a <= step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[0] = vec1[0] -= grid->dx;
- }
- }
-
- /* horizontal lines */
- if (flag & V2D_HORIZONTAL_LINES) {
- /* only major gridlines */
- vec1[1] = vec2[1] = grid->starty;
- vec1[0] = grid->startx;
- vec2[0] = v2d->cur.xmax;
-
- step = horizontal_major_step;
-
- UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
-
- for (a = 0; a <= step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[1] = vec1[1] += grid->dy;
- }
-
- /* fine grid lines */
- vec2[1] = vec1[1] -= 0.5f * grid->dy;
- step++;
-
- if (flag & V2D_HORIZONTAL_FINELINES) {
- UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
- for (a = 0; a < step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[1] = vec1[1] -= grid->dy;
- }
- }
- }
-
- /* Axes are drawn as darker lines */
- UI_GetThemeColorShade3ubv(TH_GRID, -50, grid_line_color);
-
- /* horizontal axis */
- if (flag & V2D_HORIZONTAL_AXIS) {
- vec1[0] = v2d->cur.xmin;
- vec2[0] = v2d->cur.xmax;
- vec1[1] = vec2[1] = 0.0f;
-
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
- }
-
- /* vertical axis */
- if (flag & V2D_VERTICAL_AXIS) {
- vec1[1] = v2d->cur.ymin;
- vec2[1] = v2d->cur.ymax;
- vec1[0] = vec2[0] = 0.0f;
-
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
- }
-
- immEnd();
- immUnbindProgram();
-}
-
/* Draw a constant grid in given 2d-region */
void UI_view2d_constant_grid_draw(View2D *v2d, float step)
{
@@ -1726,135 +1397,6 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s
immUnbindProgram();
}
-static void get_scale_indicator_text(
- const Scene *scene, float value, int brevity_level, short unit, uint max_length, char *r_str)
-{
- if (unit == V2D_UNIT_SECONDS) {
- BLI_timecode_string_from_time(
- r_str, max_length, brevity_level, value / (float)FPS, FPS, U.timecode_style);
- }
- else {
- BLI_timecode_string_from_time_seconds(r_str, max_length, brevity_level, value);
- }
-}
-
-void UI_view2d_grid_draw_numbers_horizontal(const Scene *scene,
- const View2D *v2d,
- const View2DGrid *grid,
- const rcti *rect,
- int unit,
- bool whole_numbers_only)
-{
- BLI_assert(grid);
- float xstep = grid->dx * UI_view2d_scale_get_x(v2d);
- if (xstep <= 0.0f) {
- return;
- }
-
- float initial_xpos = UI_view2d_view_to_region_x(v2d, grid->startx);
- float ypos = (float)rect->ymin + 4 * UI_DPI_FAC;
- float initial_value = grid->startx;
- float value_step = grid->dx;
- int brevity_level = grid->powerx;
-
- /* Make sure that the value_step is >= 1 when only whole numbers are displayed.
- * Otherwise the same number could be displayed more than once. */
- if (whole_numbers_only) {
- while (value_step < 0.9999f) {
- xstep *= 2.0f;
- value_step *= 2.0f;
- }
- }
-
- /* Skip first few steps if they don't intersect
- * the rectangle that will contain the numbers. */
- while (initial_xpos < rect->xmin) {
- initial_xpos += xstep;
- initial_value += value_step;
- }
-
- if (unit == V2D_UNIT_FRAMES) {
- brevity_level = 1;
- }
-
- const int font_id = BLF_default();
- UI_FontThemeColor(font_id, TH_TEXT);
-
- BLF_batch_draw_begin();
-
- for (float xpos = initial_xpos, value = initial_value; xpos < rect->xmax;
- xpos += xstep, value += value_step) {
- char text[32];
- get_scale_indicator_text(scene, value, brevity_level, unit, sizeof(text), text);
- float text_width = BLF_width(font_id, text, strlen(text));
- BLF_draw_default_ascii(xpos - text_width / 2.0f, ypos, 0.0f, text, sizeof(text));
- }
-
- BLF_batch_draw_end();
-}
-
-void UI_view2d_grid_draw_numbers_vertical(const Scene *scene,
- const View2D *v2d,
- const View2DGrid *grid,
- const rcti *rect,
- int unit,
- float text_offset)
-{
- BLI_assert(grid);
- float ystep = grid->dy * UI_view2d_scale_get_y(v2d);
- if (ystep <= 0.0f) {
- return;
- }
-
- const int font_id = BLF_default();
- UI_FontThemeColor(font_id, TH_TEXT);
-
- BLF_enable(font_id, BLF_ROTATION);
- BLF_rotation(font_id, M_PI_2);
-
- float initial_value = grid->starty;
- float value_step = grid->dy;
- float xpos = rect->xmax - 2.0f * UI_DPI_FAC;
- float initial_ypos = UI_view2d_view_to_region_y(v2d, grid->starty);
-
- /* Currently only used by the sequencer to display
- * channel numbers in the center. */
- initial_ypos += text_offset * ystep;
-
- /* Skip first few steps if they don't intersect
- * the rectangle that will contain the numbers. */
- while (initial_ypos < rect->ymin) {
- initial_ypos += ystep;
- initial_value += value_step;
- }
-
- for (float ypos = initial_ypos, value = initial_value; ypos < rect->ymax;
- ypos += ystep, value += value_step) {
- char text[32];
- get_scale_indicator_text(scene, value, grid->powery, unit, sizeof(text), text);
- float text_width = BLF_width(font_id, text, sizeof(text));
- BLF_draw_default_ascii(xpos, ypos - text_width / 2.0f, 0.0f, text, sizeof(text));
- }
-
- BLF_disable(font_id, BLF_ROTATION);
-}
-
-/* the price we pay for not exposting structs :( */
-void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy)
-{
- *r_dx = grid->dx;
- *r_dy = grid->dy;
-}
-
-/* free temporary memory used for drawing grid */
-void UI_view2d_grid_free(View2DGrid *grid)
-{
- /* only free if there's a grid */
- if (grid) {
- MEM_freeN(grid);
- }
-}
-
/* *********************************************************************** */
/* Scrollers */