Move to integer based rendering, fix Big line
This commit is contained in:
@@ -4,6 +4,12 @@ void LoadBigText(Buffer *buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
void LoadBigLine(Buffer *buffer) {
|
||||
for (int i = 0; i < 5000000; i += 1) {
|
||||
ReplaceText(buffer, GetEndAsRange(*buffer), L"Line number and another meme or something of the sort which is here or there frankly somewhere");
|
||||
}
|
||||
}
|
||||
|
||||
void LoadTextA(Buffer *buffer) {
|
||||
Scratch scratch;
|
||||
for (int i = 0; i < 1000; i += 1) {
|
||||
|
||||
@@ -3,37 +3,23 @@ struct Vec2 {
|
||||
float y;
|
||||
};
|
||||
|
||||
struct Vec2I {
|
||||
Int x;
|
||||
Int y;
|
||||
};
|
||||
|
||||
struct Rect2 {
|
||||
Vec2 min;
|
||||
Vec2 max;
|
||||
};
|
||||
|
||||
struct Rect2I {
|
||||
Vec2I min;
|
||||
Vec2I max;
|
||||
};
|
||||
|
||||
Vec2 GetSize(Rect2 r) {
|
||||
Vec2 result = {r.max.x - r.min.x, r.max.y - r.min.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2I GetSize(Rect2I r) {
|
||||
Vec2I result = {(r.max.x - r.min.x), (r.max.y - r.min.y)};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2 GetSizeF(Rect2I r) {
|
||||
Vec2 result = {(float)(r.max.x - r.min.x), (float)(r.max.y - r.min.y)};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2 ToVec2(Vec2I v) { return {(float)v.x, (float)v.y}; }
|
||||
Vec2 ToVec2(Vec2I v) { return {(float)v.x, (float)v.y}; }
|
||||
Vec2I ToVec2I(Vec2 v) { return {(Int)v.x, (Int)v.y}; }
|
||||
|
||||
// clang-format off
|
||||
Rect2 operator-(Rect2 r, Rect2 value) { return { r.min.x - value.min.x, r.min.y - value.min.y, r.max.x - value.max.x, r.max.y - value.max.y }; }
|
||||
@@ -155,4 +141,4 @@ float SafeDivide(float a, float b) {
|
||||
return 0.f;
|
||||
}
|
||||
return a / b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,18 +3,23 @@ Rectangle ToRectangle(Rect2 r) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Rect2 GetScreenRect() {
|
||||
Rect2 result = {0, 0, (float)GetRenderWidth(), (float)GetRenderHeight()};
|
||||
Rectangle ToRectangle(Rect2I r) {
|
||||
Rectangle result = {(float)r.min.x, (float)r.min.y, (float)(r.max.x - r.min.x), (float)(r.max.y - r.min.y)};
|
||||
return result;
|
||||
}
|
||||
|
||||
float GetCharSpacing(Font font, float font_size, float spacing) {
|
||||
Rect2I GetScreenRect() {
|
||||
Rect2I result = {0, 0, GetRenderWidth(), GetRenderHeight()};
|
||||
return result;
|
||||
}
|
||||
|
||||
Int GetCharSpacing(Font font, Int font_size, Int spacing) {
|
||||
int index = GetGlyphIndex(font, '_');
|
||||
|
||||
float textOffsetX = 0;
|
||||
float scaleFactor = font_size / font.baseSize; // Character quad scaling factor
|
||||
if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width * scaleFactor + spacing);
|
||||
else textOffsetX += ((float)font.glyphs[index].advanceX * scaleFactor + spacing);
|
||||
Int textOffsetX = 0;
|
||||
Int scaleFactor = font_size / font.baseSize; // Character quad scaling factor
|
||||
if (font.glyphs[index].advanceX == 0) textOffsetX += ((Int)font.recs[index].width * scaleFactor + spacing);
|
||||
else textOffsetX += ((Int)font.glyphs[index].advanceX * scaleFactor + spacing);
|
||||
return textOffsetX;
|
||||
}
|
||||
|
||||
@@ -25,7 +30,7 @@ void DrawString(Font font, String16 text, Vector2 position, float fontSize, floa
|
||||
|
||||
float scaleFactor = fontSize / font.baseSize; // Character quad scaling factor
|
||||
|
||||
for (int i = 0; i < text.len; i += 1) {
|
||||
for (Int i = 0; i < text.len; i += 1) {
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
int codepoint = text[i];
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "new_basic.cpp"
|
||||
#include "string16.cpp"
|
||||
#include <math.h>
|
||||
#include "math_int.cpp"
|
||||
#include "math.cpp"
|
||||
|
||||
#include "../profiler/profiler.cpp"
|
||||
@@ -20,6 +21,8 @@
|
||||
#include "view_draw.cpp"
|
||||
|
||||
/*
|
||||
- when no new line at the end - END button sets cursor before last char
|
||||
|
||||
- Ctrl + Z, Ctrl + C - Undo redo history
|
||||
- Ctrl + D - create new cursor at next occurence of word
|
||||
- Ctrl + X, Ctrl + C, Ctrl + V - Copy paste
|
||||
@@ -33,6 +36,8 @@
|
||||
- Line numbers
|
||||
- Colored strings
|
||||
|
||||
- file dock on left side
|
||||
- file info bar at bottom
|
||||
- multiple windows
|
||||
- multiple views per window
|
||||
*/
|
||||
@@ -60,10 +65,10 @@ int main(void) {
|
||||
|
||||
View view = {};
|
||||
{
|
||||
float font_size = 32;
|
||||
float font_spacing = 1;
|
||||
float line_spacing = font_size;
|
||||
Font font = LoadFontEx("c:\\Windows\\Fonts\\consola.ttf", (int)font_size, NULL, 250);
|
||||
Int font_size = 32;
|
||||
Int font_spacing = 1;
|
||||
Int line_spacing = font_size;
|
||||
Font font = LoadFontEx("c:\\Windows\\Fonts\\consola.ttf", (int)font_size, NULL, 250);
|
||||
|
||||
view.font = font;
|
||||
view.font_size = font_size;
|
||||
@@ -72,6 +77,7 @@ int main(void) {
|
||||
view.char_spacing = GetCharSpacing(font, font_size, font_spacing);
|
||||
Add(&view.carets, {0, 0});
|
||||
view.buffer = CreateBuffer(Perm);
|
||||
// LoadBigLine(view.buffer);
|
||||
LoadTextA(view.buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
struct View {
|
||||
Font font;
|
||||
float font_size;
|
||||
float font_spacing;
|
||||
float line_spacing;
|
||||
float char_spacing;
|
||||
Font font;
|
||||
Int font_size;
|
||||
Int font_spacing;
|
||||
Int line_spacing;
|
||||
Int char_spacing;
|
||||
|
||||
bool mouse_selecting;
|
||||
|
||||
Vec2 scroll;
|
||||
Vec2I scroll;
|
||||
Buffer *buffer;
|
||||
Array<Caret> carets;
|
||||
Rect2 rect;
|
||||
Rect2I rect;
|
||||
};
|
||||
|
||||
Rect2I GetVisibleCells(const View &view);
|
||||
@@ -161,13 +161,17 @@ void HandleKeybindings(View *_view) {
|
||||
Caret main_caret_on_begin_frame = view.carets[0];
|
||||
|
||||
if (IsKeyDown(KEY_F1)) {
|
||||
view.scroll.x -= GetMouseWheelMove() * 48;
|
||||
view.scroll.x -= (Int)(GetMouseWheelMove() * 48);
|
||||
} else {
|
||||
view.scroll.y -= GetMouseWheelMove() * 48;
|
||||
view.scroll.y -= (Int)(GetMouseWheelMove() * 48);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_F2)) {
|
||||
LoadBigText(view.buffer);
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL)) {
|
||||
LoadBigLine(view.buffer);
|
||||
} else {
|
||||
LoadBigText(view.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -242,13 +246,14 @@ void HandleKeybindings(View *_view) {
|
||||
|
||||
{
|
||||
ProfileScope(mouse);
|
||||
Vec2 mouse = GetMousePosition();
|
||||
bool mouse_in_view = CheckCollisionPointRec(mouse, ToRectangle(view.rect));
|
||||
Vec2 _mouse = GetMousePosition();
|
||||
bool mouse_in_view = CheckCollisionPointRec(_mouse, ToRectangle(view.rect));
|
||||
Vec2I mouse = ToVec2I(_mouse);
|
||||
|
||||
Vec2 mworld = mouse - view.rect.min + view.scroll;
|
||||
Vec2 pos = mworld / Vec2{view.char_spacing, view.line_spacing};
|
||||
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
||||
Int p = XYToPosWithoutNL(buf, xy);
|
||||
Vec2I mworld = mouse - view.rect.min + view.scroll;
|
||||
Vec2I pos = mworld / Vec2I{view.char_spacing, view.line_spacing};
|
||||
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
||||
Int p = XYToPosWithoutNL(buf, xy);
|
||||
|
||||
if (mouse_in_view && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
||||
@@ -275,20 +280,19 @@ void HandleKeybindings(View *_view) {
|
||||
// which is exactly the thing which shows the view, will need
|
||||
// to think about this later
|
||||
if (!AreEqual(main_caret_on_begin_frame, view.carets[0])) {
|
||||
|
||||
Caret c = view.carets[0];
|
||||
Int front = GetFront(c);
|
||||
XY xy = PosToXY(buf, front);
|
||||
|
||||
Rect2I visible = GetVisibleCells(view);
|
||||
Vec2I visible_cells = GetSize(visible);
|
||||
Vec2 visible_size = ToVec2(visible_cells) * Vec2{view.char_spacing, view.line_spacing};
|
||||
Vec2 rect_size = GetSize(view.rect);
|
||||
Vec2I visible_size = visible_cells * Vec2I{view.char_spacing, view.line_spacing};
|
||||
Vec2I rect_size = GetSize(view.rect);
|
||||
|
||||
if (xy.line > visible.max.y - 3) {
|
||||
Int set_view_at_line = xy.line - (visible_cells.y - 1);
|
||||
float cut_off_y = Max(0.f, visible_size.y - rect_size.y);
|
||||
view.scroll.y = ((float)set_view_at_line * view.line_spacing) + cut_off_y;
|
||||
if (xy.line > visible.max.y - 2) {
|
||||
Int set_view_at_line = xy.line - (visible_cells.y - 1);
|
||||
Int cut_off_y = Max((Int)0, visible_size.y - rect_size.y);
|
||||
view.scroll.y = (set_view_at_line * view.line_spacing) + cut_off_y;
|
||||
}
|
||||
|
||||
if (xy.line < visible.min.y + 1) {
|
||||
@@ -296,9 +300,9 @@ void HandleKeybindings(View *_view) {
|
||||
}
|
||||
|
||||
if (xy.col >= visible.max.x - 1) {
|
||||
Int set_view_at_line = xy.col - (visible_cells.x - 1);
|
||||
float cut_off_x = Max(0.f, visible_size.x - rect_size.x);
|
||||
view.scroll.x = ((float)set_view_at_line * view.char_spacing) + cut_off_x;
|
||||
Int set_view_at_line = xy.col - (visible_cells.x - 1);
|
||||
Int cut_off_x = Max((Int)0, visible_size.x - rect_size.x);
|
||||
view.scroll.x = (set_view_at_line * view.char_spacing) + cut_off_x;
|
||||
}
|
||||
|
||||
if (xy.col <= visible.min.x) {
|
||||
@@ -310,12 +314,12 @@ void HandleKeybindings(View *_view) {
|
||||
{
|
||||
ProfileScope(clip_scroll);
|
||||
Int last_line = LastLine(view.buffer[0]);
|
||||
view.scroll.y = Clamp(view.scroll.y, 0.f, Max(0.f, (last_line - 1) * view.line_spacing));
|
||||
view.scroll.y = Clamp(view.scroll.y, (Int)0, Max((Int)0, (last_line - 1) * view.line_spacing));
|
||||
|
||||
// @note:
|
||||
// GetCharCountOfLongestLine is a bottleneck, there is probably an algorithm for
|
||||
// calculating this value incrementally but do we even need X scrollbar or x clipping?
|
||||
view.scroll.x = ClampBottom(view.scroll.x, 0.f);
|
||||
view.scroll.x = ClampBottom(view.scroll.x, (Int)0);
|
||||
// Int line_chars = GetCharCountOfLongestLine(view.buffer[0]);
|
||||
// view.scroll.x = Clamp(view.scroll.x, 0.f, Max(0.f, (line_chars - 2) * view.char_spacing));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
Vec2I GetCellSize(const View &view) {
|
||||
Vec2I result = {(Int)view.char_spacing, (Int)view.line_spacing};
|
||||
return result;
|
||||
}
|
||||
|
||||
Rect2I GetVisibleCells(const View &view) {
|
||||
ProfileFunction();
|
||||
Vec2 size = GetSize(view.rect);
|
||||
float _cx = size.x / view.char_spacing;
|
||||
float _cy = size.y / view.line_spacing;
|
||||
int cx = (int)ceilf(_cx) + 1;
|
||||
int cy = (int)ceilf(_cy) + 1;
|
||||
Vec2I size = GetSize(view.rect);
|
||||
|
||||
Vec2 pos = {SafeDivide(view.scroll.x, view.char_spacing), SafeDivide(view.scroll.y, view.line_spacing)};
|
||||
int x = (int)floorf(pos.x);
|
||||
int y = (int)floorf(pos.y);
|
||||
Int _cx = size.x / view.char_spacing;
|
||||
Int _cy = size.y / view.line_spacing;
|
||||
Int cx = _cx + 1;
|
||||
Int cy = _cy + 1;
|
||||
|
||||
Vec2I pos = {SafeDivide(view.scroll.x, view.char_spacing), SafeDivide(view.scroll.y, view.line_spacing)};
|
||||
Int x = pos.x;
|
||||
Int y = pos.y;
|
||||
Rect2I result = {x, y, x + cx, y + cy};
|
||||
return result;
|
||||
}
|
||||
@@ -22,40 +28,35 @@ void DrawVisibleCells(const View &view) {
|
||||
line_string = Skip(line_string, visible.min.x);
|
||||
line_string = GetPrefix(line_string, visible.max.x - visible.min.x);
|
||||
|
||||
Vec2 pos = {visible.min.x * view.char_spacing, line_index * view.line_spacing};
|
||||
Vec2I pos = {visible.min.x * (Int)view.char_spacing, line_index * (Int)view.line_spacing};
|
||||
pos -= view.scroll;
|
||||
DrawString(view.font, line_string, pos, view.font_size, view.font_spacing, BLACK);
|
||||
DrawString(view.font, line_string, ToVec2(pos), (float)view.font_size, (float)view.font_spacing, BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
Vec2 GetCellSize(const View &view) {
|
||||
Vec2 result = {view.char_spacing, view.line_spacing};
|
||||
Vec2I XYToWorldPos(const View &view, XY xy) {
|
||||
Vec2I result = {xy.col * (Int)view.char_spacing, xy.line * (Int)view.line_spacing};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2 XYToWorldPos(const View &view, XY xy) {
|
||||
Vec2 result = {(float)xy.col * view.char_spacing, (float)xy.line * view.line_spacing};
|
||||
return result;
|
||||
}
|
||||
|
||||
Rect2 XYToRect(const View &view, XY xy) {
|
||||
Rect2 result = Rect2FromSize(XYToWorldPos(view, xy), GetCellSize(view));
|
||||
Rect2I XYToRect(const View &view, XY xy) {
|
||||
Rect2I result = Rect2IFromSize(XYToWorldPos(view, xy), GetCellSize(view));
|
||||
return result;
|
||||
}
|
||||
|
||||
void DrawCaret(const View &view, XY xy, float size, Color color) {
|
||||
Rect2 _rect = XYToRect(view, xy);
|
||||
Rect2 rect = CutLeft(&_rect, size * view.char_spacing);
|
||||
Rect2I _rect = XYToRect(view, xy);
|
||||
Rect2I rect = CutLeft(&_rect, (Int)(size * (float)view.char_spacing));
|
||||
rect -= view.scroll;
|
||||
DrawRectangleRec(ToRectangle(rect), color);
|
||||
}
|
||||
|
||||
void DrawLineHighlight(const View &view, XY fxy, Color color) {
|
||||
Vec2 w = XYToWorldPos(view, XYLine(fxy.line));
|
||||
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
|
||||
w -= view.scroll;
|
||||
Range range = GetLineRange(*view.buffer, fxy.line);
|
||||
float xsize = view.char_spacing * (float)GetSize(range);
|
||||
Rect2 rect = Rect2FromSize(w, {xsize, view.line_spacing});
|
||||
Range range = GetLineRange(*view.buffer, fxy.line);
|
||||
Int xsize = (Int)view.char_spacing * GetSize(range);
|
||||
Rect2I rect = Rect2IFromSize(w, {xsize, view.line_spacing});
|
||||
DrawRectangleRec(ToRectangle(rect), color);
|
||||
}
|
||||
|
||||
@@ -95,9 +96,9 @@ void DrawCaret(const View &view, Caret &it) {
|
||||
bool d = min.line == max.line && line == max.line && col >= min.col && col < max.col;
|
||||
|
||||
if (a || b || c || d) {
|
||||
Vec2 pos = {col * view.char_spacing, line * view.line_spacing};
|
||||
Vec2I pos = {col * view.char_spacing, line * view.line_spacing};
|
||||
pos -= view.scroll;
|
||||
Rectangle rectangle = {pos.x, pos.y, view.char_spacing, view.line_spacing};
|
||||
Rectangle rectangle = {(float)pos.x, (float)pos.y, (float)view.char_spacing, (float)view.line_spacing};
|
||||
DrawRectangleRec(rectangle, {0, 50, 150, 20});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user