Fix visual bug when scrolling

This commit is contained in:
Krzosa Karol
2024-06-28 10:37:47 +02:00
parent ffe1ca643e
commit b8cdb49ea5
2 changed files with 66 additions and 46 deletions

View File

@@ -20,6 +20,7 @@ struct Window {
float font_spacing;
Rect2 rect;
bool mouse_selecting;
Vec2 scroll; // window_world_to_window_units
Cursor main_cursor_begin_frame;
Array<Cursor> cursors;
@@ -132,3 +133,28 @@ Tuple<LayoutRow *, LayoutColumn *> GetRowCol(Window &window, int64_t pos) {
return result;
}
Range CalculateVisibleLineRange(Window &window) {
Vec2 s = GetSize(window.rect);
float line_offset = window.font_size;
float _line_min_y = (window.scroll.y) / line_offset;
float _line_max_y = (s.y + window.scroll.y) / line_offset;
int64_t line_min_y = (int64_t)floorf(_line_min_y);
int64_t line_max_y = (int64_t)ceilf(_line_max_y);
Range result = {line_min_y, line_max_y};
return result;
}
Array<LayoutColumn> CalculateVisibleColumns(Arena *arena, Window &window) {
Range visible_line_range = CalculateVisibleLineRange(window);
Array<LayoutColumn> r = {*arena};
for (int64_t line = visible_line_range.min; line < visible_line_range.max && line >= 0 && line < window.layout.rows.len; line += 1) {
LayoutRow &row = window.layout.rows[line];
For(row.columns) {
if (CheckCollisionRecs(ToRectangle(it.rect - window.scroll), ToRectangle(window.rect))) {
r.add(it);
}
}
}
return r;
}

View File

@@ -455,42 +455,59 @@ int main() {
Rectangle rectangle_in_render_units = ToRectangle(window.rect);
DrawRectangleRec(rectangle_in_render_units, WHITE);
// Figure out which lines to draw
Vec2 s = GetSize(window.rect);
float line_offset = font_size;
float _line_min_y = (window.scroll.y) / line_offset;
float _line_max_y = (s.y + window.scroll.y) / line_offset;
int64_t line_min_y = (int64_t)floorf(_line_min_y);
int64_t line_max_y = (int64_t)ceilf(_line_max_y);
int64_t visible_lines = line_max_y - line_min_y;
Array<LayoutColumn> visible_columns = CalculateVisibleColumns(&FrameArena, window);
// Mouse selection
// @todo: multicursor
{
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
Vec2 mouse = GetMousePosition();
Vec2 mouse_lookup = Vector2Add(mouse, window.scroll);
Array<LayoutColumn> visible_columns = {FrameArena};
for (int64_t line = line_min_y; line < line_max_y && line >= 0 && line < window.layout.rows.len; line += 1) {
LayoutRow &row = window.layout.rows[line];
For(row.columns) {
if (CheckCollisionRecs(ToRectangle(it.rect - window.scroll), ToRectangle(window.rect))) {
visible_columns.add(it);
Tuple<LayoutRow *, LayoutColumn *> rowcol = GetRowCol(window, mouse_lookup);
if (rowcol.b) {
Rect2 col_rect = rowcol.b->rect - window.scroll;
Rectangle col_rectangle = ToRectangle(col_rect);
if (CheckCollisionPointRec(mouse, col_rectangle)) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
window.cursors.clear();
window.cursors.add({rowcol.b->pos, rowcol.b->pos});
window.mouse_selecting = true;
}
if (!window.mouse_selecting) {
SetMouseCursor(MOUSE_CURSOR_IBEAM);
}
}
if (window.mouse_selecting) {
SetMouseCursor(MOUSE_CURSOR_RESIZE_ALL);
if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
window.mouse_selecting = false;
}
Cursor *cursor = window.cursors.last();
cursor[0] = ChangeBack(*cursor, rowcol.b->pos);
}
}
}
// Update the scroll based on first cursor
// @todo: needs a rewrite
// @todo: needs a rewrite, make sure we also handle scrolling for mouse
if (!AreEqual(window.main_cursor_begin_frame, window.cursors[0])) {
Range visible_line_range = CalculateVisibleLineRange(window);
Vec2 rect_size = GetSize(window.rect);
float visible_cells_in_render_units = font_size * (float)visible_lines;
float visible_cells_in_render_units = font_size * (float)GetRangeSize(visible_line_range);
float cut_off_in_render_units = visible_cells_in_render_units - rect_size.y;
Cursor cursor = window.cursors[0];
int64_t front = GetFront(cursor);
int64_t front = GetBack(cursor);
Line line = FindLine(window.buffer, front);
// Scroll Y
if (line.number < (line_min_y + 1)) {
if (line.number < (visible_line_range.min)) {
window.scroll.y = line.number * font_size;
} else if (line.number >= (line_max_y - 1)) {
int64_t diff = line.number - line_max_y;
window.scroll.y = (line_min_y + diff) * font_size + cut_off_in_render_units;
} else if (line.number >= (visible_line_range.max)) {
int64_t diff = line.number - visible_line_range.max;
window.scroll.y = (visible_line_range.min + diff) * font_size + cut_off_in_render_units;
}
// Scroll X
@@ -513,36 +530,13 @@ int main() {
}
}
// Mouse selection @todo
{
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
Vec2 mouse = GetMousePosition();
Vec2 mouse_lookup = Vector2Add(mouse, window.scroll);
Tuple<LayoutRow *, LayoutColumn *> rowcol = GetRowCol(window, mouse_lookup);
if (rowcol.b) {
Rect2 col_rect = rowcol.b->rect - window.scroll;
Rectangle col_rectangle = ToRectangle(col_rect);
if (CheckCollisionPointRec(mouse, col_rectangle)) {
// DrawRectangleRec(col_rectangle, {0, 0, 255, 40});
SetMouseCursor(MOUSE_CURSOR_IBEAM);
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
window.cursors.clear();
window.cursors.add({rowcol.b->pos, rowcol.b->pos});
} else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
Cursor *cursor = window.cursors.last();
cursor[0] = ChangeBack(*cursor, rowcol.b->pos);
}
}
}
}
Range visible_line_range = CalculateVisibleLineRange(window);
// Draw the glyphs
Vec2 window_rect_size = GetSize(window.rect);
BeginScissorMode((int)window.rect.min.x, (int)window.rect.min.y, (int)window_rect_size.x, (int)window_rect_size.y);
for (int64_t line = line_min_y; line < line_max_y; line += 1) {
for (int64_t line = visible_line_range.min; line < visible_line_range.max; line += 1) {
if (line < 0 || line >= window.layout.rows.len) continue;
LayoutRow &row = window.layout.rows[line];