Transitioning text editor to SDL
This commit is contained in:
@@ -116,8 +116,9 @@ int CompileTextEditor() {
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
Array<Library> libs = {};
|
Array<Library> libs = {};
|
||||||
libs.add(PrepareRaylib());
|
libs.add(PrepareSDLDynamic());
|
||||||
libs.add(PrepareLua());
|
libs.add(PrepareLua());
|
||||||
|
libs.add(PrepareGlad());
|
||||||
|
|
||||||
Array<S8_String> cmd = {};
|
Array<S8_String> cmd = {};
|
||||||
cmd.add("cl.exe");
|
cmd.add("cl.exe");
|
||||||
@@ -127,7 +128,7 @@ int CompileTextEditor() {
|
|||||||
AddCommonFlags(&cmd);
|
AddCommonFlags(&cmd);
|
||||||
For2(lib, libs) For(lib.defines) cmd.add(it);
|
For2(lib, libs) For(lib.defines) cmd.add(it);
|
||||||
|
|
||||||
cmd.add("../src/text_editor/text_editor.cpp");
|
cmd.add("../src/text_editor/new_text_editor.cpp");
|
||||||
cmd.add("../src/basic/win32.cpp");
|
cmd.add("../src/basic/win32.cpp");
|
||||||
|
|
||||||
For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it)));
|
For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it)));
|
||||||
@@ -135,7 +136,8 @@ int CompileTextEditor() {
|
|||||||
cmd.add("/link");
|
cmd.add("/link");
|
||||||
cmd.add("/incremental:no");
|
cmd.add("/incremental:no");
|
||||||
// cmd.add("/SUBSYSTEM:WINDOWS");
|
// cmd.add("/SUBSYSTEM:WINDOWS");
|
||||||
cmd.add("opengl32.lib gdi32.lib winmm.lib shell32.lib user32.lib msvcrt.lib /NODEFAULTLIB:LIBCMT");
|
// cmd.add("opengl32.lib gdi32.lib winmm.lib shell32.lib user32.lib msvcrt.lib /NODEFAULTLIB:LIBCMT");
|
||||||
|
For2(lib, libs) For(lib.link) cmd.add(it);
|
||||||
For(libs) For2(o, it.objects) cmd.add(o);
|
For(libs) For2(o, it.objects) cmd.add(o);
|
||||||
|
|
||||||
OS_DeleteFile("te.pdb");
|
OS_DeleteFile("te.pdb");
|
||||||
@@ -161,7 +163,7 @@ int CompileNewPlatform() {
|
|||||||
AddCommonFlags(&cmd);
|
AddCommonFlags(&cmd);
|
||||||
For2(lib, libs) For(lib.defines) cmd.add(it);
|
For2(lib, libs) For(lib.defines) cmd.add(it);
|
||||||
|
|
||||||
cmd.add("../src/new_platform/new_platform.cpp");
|
cmd.add("../src/platform/platform.cpp");
|
||||||
cmd.add("../src/basic/win32.cpp");
|
cmd.add("../src/basic/win32.cpp");
|
||||||
|
|
||||||
For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it)));
|
For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it)));
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ Vec2 GetSizeF(Rect2I r) {
|
|||||||
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}; }
|
Vec2I ToVec2I(Vec2 v) { return {(Int)v.x, (Int)v.y}; }
|
||||||
Rect2I ToRect2I(Rect2 r) { return {ToVec2I(r.min), ToVec2I(r.max)}; }
|
Rect2I ToRect2I(Rect2 r) { return {ToVec2I(r.min), ToVec2I(r.max)}; }
|
||||||
|
Rect2 ToRect2(Rect2I r) { return {ToVec2(r.min), ToVec2(r.max)}; }
|
||||||
|
|
||||||
// clang-format off
|
// 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 }; }
|
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 }; }
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ struct Rect2I {
|
|||||||
Vec2I max;
|
Vec2I max;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Color {
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t a;
|
||||||
|
};
|
||||||
|
|
||||||
Vec2I GetSize(Rect2I r) {
|
Vec2I GetSize(Rect2I r) {
|
||||||
Vec2I result = {r.max.x - r.min.x, r.max.y - r.min.y};
|
Vec2I result = {r.max.x - r.min.x, r.max.y - r.min.y};
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
struct Glyph {
|
|
||||||
Vec2 size;
|
|
||||||
Vec2 offset;
|
|
||||||
float xadvance;
|
|
||||||
float left_side_bearing;
|
|
||||||
Rect2 atlas_bounding_box;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Font {
|
|
||||||
Array<Glyph> glyphs;
|
|
||||||
uint32_t first_char, last_char;
|
|
||||||
uint32_t texture_id;
|
|
||||||
|
|
||||||
float size;
|
|
||||||
float descent;
|
|
||||||
float ascent;
|
|
||||||
float line_gap;
|
|
||||||
|
|
||||||
Rect2 white_texture_bounding_box;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Atlas {
|
|
||||||
uint8_t *bitmap;
|
|
||||||
Vec2I size;
|
|
||||||
Vec2 inverse_size;
|
|
||||||
int xcursor;
|
|
||||||
int ycursor;
|
|
||||||
|
|
||||||
int32_t biggest_height;
|
|
||||||
Rect2 white_texture_bounding_box;
|
|
||||||
uint32_t texture_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
Atlas CreateAtlas(Allocator allocator, Vec2I size) {
|
|
||||||
Atlas result = {};
|
|
||||||
result.size = size;
|
|
||||||
result.inverse_size.x = 1.f / (float)result.size.x;
|
|
||||||
result.inverse_size.y = 1.f / (float)result.size.y;
|
|
||||||
result.bitmap = AllocArray(allocator, uint8_t, size.x * size.y);
|
|
||||||
|
|
||||||
// Add a whitebox first for rectangle rendering
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
uint8_t *dst = result.bitmap + x + y * result.size.x;
|
|
||||||
*dst = 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.white_texture_bounding_box = {2.f * result.inverse_size.x, 2.f / (float)result.size.y, 14.f * result.inverse_size.x, 14.f / (float)result.size.y};
|
|
||||||
result.xcursor += 16;
|
|
||||||
result.biggest_height += 16;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect2 PackBitmap(Atlas *atlas, uint8_t *bitmap, int width, int height) {
|
|
||||||
// Packing into a texture atlas
|
|
||||||
// @Inefficient The algorithm is a simplest thing I had in mind, first we advance
|
|
||||||
// through the atlas in X packing consecutive glyphs. After we get to the end of the row
|
|
||||||
// we advance to the next row by the Y size of the biggest packed glyph. If we get to the
|
|
||||||
// end of atlas and fail to pack everything the app panics.
|
|
||||||
|
|
||||||
int spacing = 4;
|
|
||||||
if (atlas->xcursor + width > atlas->size.x) {
|
|
||||||
if (atlas->ycursor + height < atlas->size.y) {
|
|
||||||
atlas->xcursor = 0;
|
|
||||||
atlas->ycursor += atlas->biggest_height + spacing;
|
|
||||||
} else {
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Font loading error!", "Error while packing a font into atlas. Atlas size for this font scale is a bit too small", NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *src = bitmap;
|
|
||||||
for (int y = atlas->ycursor; y < atlas->ycursor + height; y += 1) {
|
|
||||||
for (int x = atlas->xcursor; x < atlas->xcursor + width; x += 1) {
|
|
||||||
uint8_t *dst = atlas->bitmap + x + y * atlas->size.x;
|
|
||||||
*dst = *src++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2 size = {(float)width * atlas->inverse_size.x, (float)height * atlas->inverse_size.y};
|
|
||||||
Vec2 pos = {(float)atlas->xcursor * atlas->inverse_size.x, (float)atlas->ycursor * atlas->inverse_size.y};
|
|
||||||
Rect2 result = {pos.x, pos.y, pos.x + size.x, pos.y + size.y};
|
|
||||||
|
|
||||||
atlas->xcursor += width + spacing;
|
|
||||||
if (height > atlas->biggest_height) {
|
|
||||||
atlas->biggest_height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Font CreateFont(Atlas *atlas, int32_t size, String path) {
|
|
||||||
Scratch scratch;
|
|
||||||
Font result = {};
|
|
||||||
|
|
||||||
String file = ReadFile(scratch, path);
|
|
||||||
if (file.len == 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
stbtt_fontinfo stb_font;
|
|
||||||
int success = stbtt_InitFont(&stb_font, (const unsigned char *)file.data, 0);
|
|
||||||
if (!success) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
float scale = stbtt_ScaleForPixelHeight(&stb_font, (float)size);
|
|
||||||
float em_scale = stbtt_ScaleForMappingEmToPixels(&stb_font, (float)size);
|
|
||||||
|
|
||||||
int ascent, descent, line_gap;
|
|
||||||
stbtt_GetFontVMetrics(&stb_font, &ascent, &descent, &line_gap);
|
|
||||||
result.ascent = (float)ascent * scale;
|
|
||||||
result.descent = (float)descent * scale;
|
|
||||||
result.line_gap = (float)line_gap * scale;
|
|
||||||
result.size = (float)size;
|
|
||||||
result.first_char = ' ';
|
|
||||||
result.last_char = '~';
|
|
||||||
result.white_texture_bounding_box = atlas->white_texture_bounding_box;
|
|
||||||
|
|
||||||
for (uint32_t ascii_symbol = result.first_char; ascii_symbol <= result.last_char; ascii_symbol++) {
|
|
||||||
int width, height, xoff, yoff;
|
|
||||||
uint8_t *bitmap = (uint8_t *)stbtt_GetCodepointBitmap(&stb_font, 0, scale, ascii_symbol, &width, &height, &xoff, &yoff);
|
|
||||||
defer { stbtt_FreeBitmap(bitmap, 0); };
|
|
||||||
|
|
||||||
int xadvance, left_side_bearing;
|
|
||||||
stbtt_GetCodepointHMetrics(&stb_font, ascii_symbol, &xadvance, &left_side_bearing);
|
|
||||||
|
|
||||||
Glyph glyph = {};
|
|
||||||
glyph.atlas_bounding_box = PackBitmap(atlas, bitmap, width, height);
|
|
||||||
glyph.size = {(float)width, (float)height};
|
|
||||||
glyph.offset = {(float)xoff, (float)yoff};
|
|
||||||
glyph.xadvance = (float)xadvance * scale;
|
|
||||||
glyph.left_side_bearing = (float)left_side_bearing * scale;
|
|
||||||
Add(&result.glyphs, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Glyph *GetGlyph(Font *font, uint32_t codepoint) {
|
|
||||||
bool is_in_range = codepoint >= font->first_char && codepoint <= font->last_char;
|
|
||||||
if (is_in_range) {
|
|
||||||
uint32_t index = codepoint - font->first_char;
|
|
||||||
return &font->glyphs[index];
|
|
||||||
} else {
|
|
||||||
uint32_t index = '?' - font->first_char;
|
|
||||||
return &font->glyphs[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
#define BASIC_IMPL
|
|
||||||
#include "basic/basic.h"
|
|
||||||
#include "basic/filesystem.h"
|
|
||||||
|
|
||||||
#include "SDL3/SDL.h"
|
|
||||||
#include "external/glad/glad.h"
|
|
||||||
#include "external/stb_truetype.h"
|
|
||||||
#include "external/stb_truetype.c"
|
|
||||||
|
|
||||||
#include "basic/math_int.cpp"
|
|
||||||
#include "basic/math.cpp"
|
|
||||||
#include "font.cpp"
|
|
||||||
#include "render_opengl.cpp"
|
|
||||||
|
|
||||||
bool AppIsRunning = true;
|
|
||||||
|
|
||||||
void ProcessSDLEvent(SDL_Event *event) {
|
|
||||||
switch (event->type) {
|
|
||||||
case SDL_EVENT_QUIT: AppIsRunning = false; return;
|
|
||||||
case SDL_EVENT_KEY_DOWN: {
|
|
||||||
SDL_KeyboardEvent &key = event->key;
|
|
||||||
bool shift = key.mod & SDL_KMOD_SHIFT;
|
|
||||||
bool ctrl = key.mod & SDL_KMOD_CTRL;
|
|
||||||
bool alt = key.mod & SDL_KMOD_ALT;
|
|
||||||
bool super = key.mod & SDL_KMOD_GUI;
|
|
||||||
|
|
||||||
if (key.key == SDLK_F5) {
|
|
||||||
AppIsRunning = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case SDL_EVENT_KEY_UP: {
|
|
||||||
SDL_KeyboardEvent &key = event->key;
|
|
||||||
bool shift = key.mod & SDL_KMOD_SHIFT;
|
|
||||||
bool ctrl = key.mod & SDL_KMOD_CTRL;
|
|
||||||
bool alt = key.mod & SDL_KMOD_ALT;
|
|
||||||
bool super = key.mod & SDL_KMOD_GUI;
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case SDL_EVENT_TEXT_INPUT: {
|
|
||||||
} break;
|
|
||||||
case SDL_EVENT_MOUSE_MOTION: {
|
|
||||||
} break;
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
|
||||||
} break;
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
|
||||||
} break;
|
|
||||||
case SDL_EVENT_MOUSE_WHEEL: {
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *user) {
|
|
||||||
printf("%s", message);
|
|
||||||
if (severity == GL_DEBUG_SEVERITY_HIGH || severity == GL_DEBUG_SEVERITY_MEDIUM) {
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "OpenGL error", message, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
int WinMain(void *hInstance, void *hPrevInstance, const char *lpCmdLine, int nShowCmd)
|
|
||||||
#else
|
|
||||||
int main()
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
InitScratch();
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) == -1) {
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *glsl_version = "#version 450";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
|
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
|
||||||
Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
|
|
||||||
SDL_Window *window = SDL_CreateWindow("Text editor", 640, 480, window_flags);
|
|
||||||
if (window == NULL) {
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window!", SDL_GetError(), NULL);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
|
|
||||||
SDL_GL_MakeCurrent(window, gl_context);
|
|
||||||
SDL_GL_SetSwapInterval(1); // Enable vsync
|
|
||||||
SDL_ShowWindow(window);
|
|
||||||
|
|
||||||
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load opengl!", SDL_GetError(), NULL);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GL_SetSwapInterval(1); // vsync
|
|
||||||
glDebugMessageCallback(&GLDebugCallback, NULL);
|
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
|
||||||
|
|
||||||
{
|
|
||||||
Scratch scratch;
|
|
||||||
Atlas atlas = CreateAtlas(scratch, {1024, 1024});
|
|
||||||
MainFont = CreateFont(&atlas, 16, "C:\\Windows\\Fonts\\consola.ttf");
|
|
||||||
{
|
|
||||||
glCreateTextures(GL_TEXTURE_2D, 1, &atlas.texture_id);
|
|
||||||
glTextureParameteri(atlas.texture_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTextureParameteri(atlas.texture_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTextureParameteri(atlas.texture_id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTextureParameteri(atlas.texture_id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTextureStorage2D(atlas.texture_id, 1, GL_R8, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y);
|
|
||||||
glTextureSubImage2D(atlas.texture_id, 0, 0, 0, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y, GL_RED, GL_UNSIGNED_BYTE, atlas.bitmap);
|
|
||||||
}
|
|
||||||
MainFont.texture_id = atlas.texture_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitRender();
|
|
||||||
|
|
||||||
while (AppIsRunning) {
|
|
||||||
int window_x, window_y;
|
|
||||||
SDL_GetWindowSize(window, &window_x, &window_y);
|
|
||||||
Vec2 window_size = {(float)window_x, (float)window_y};
|
|
||||||
|
|
||||||
SDL_Event event;
|
|
||||||
SDL_WaitEvent(&event);
|
|
||||||
ProcessSDLEvent(&event);
|
|
||||||
|
|
||||||
BeginFrameRender(window_size);
|
|
||||||
DrawString(&MainFont, L"Testing", {0, 0}, {255, 0, 0, 255});
|
|
||||||
EndFrameRender({0, 0, 0, 1});
|
|
||||||
SDL_GL_SwapWindow(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
SDL_Quit();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
struct Shader {
|
|
||||||
uint32_t pipeline;
|
|
||||||
uint32_t fshader;
|
|
||||||
uint32_t vshader;
|
|
||||||
};
|
|
||||||
Shader CreateShader(char *glsl_vshader, char *glsl_fshader);
|
|
||||||
|
|
||||||
struct Color {
|
|
||||||
uint8_t r;
|
|
||||||
uint8_t g;
|
|
||||||
uint8_t b;
|
|
||||||
uint8_t a;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Vertex2D {
|
|
||||||
Vec2 pos;
|
|
||||||
Vec2 tex;
|
|
||||||
Color color;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VertexNode2D {
|
|
||||||
VertexNode2D *next;
|
|
||||||
int count;
|
|
||||||
Vertex2D vertices[1024 * 64];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VertexList2D {
|
|
||||||
VertexNode2D *first;
|
|
||||||
VertexNode2D *last;
|
|
||||||
};
|
|
||||||
|
|
||||||
VertexList2D Vertices;
|
|
||||||
int64_t TotalVertexCount;
|
|
||||||
|
|
||||||
unsigned VBO, VAO;
|
|
||||||
Shader Shader2D;
|
|
||||||
Arena RenderArena;
|
|
||||||
Font MainFont;
|
|
||||||
Vec2 WindowSize;
|
|
||||||
|
|
||||||
void BeginFrameRender(Vec2 window_size) {
|
|
||||||
Clear(&RenderArena);
|
|
||||||
TotalVertexCount = 0;
|
|
||||||
Vertices.first = NULL;
|
|
||||||
Vertices.last = NULL;
|
|
||||||
WindowSize = window_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndFrameRender(Vec4 color) {
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
glViewport(0, 0, (GLsizei)WindowSize.x, (GLsizei)WindowSize.y);
|
|
||||||
glClearColor(color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a * 255.f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
||||||
|
|
||||||
// Default draw using the font texture
|
|
||||||
glBindProgramPipeline(Shader2D.pipeline);
|
|
||||||
float xinverse = 1.f / (WindowSize.x / 2.f);
|
|
||||||
float yinverse = 1.f / (WindowSize.y / 2.f);
|
|
||||||
glProgramUniform2f(Shader2D.vshader, 0, xinverse, yinverse);
|
|
||||||
for (VertexNode2D *it = Vertices.first; it; it = it->next) {
|
|
||||||
glNamedBufferSubData(VBO, 0, it->count * sizeof(Vertex2D), it->vertices);
|
|
||||||
glBindVertexArray(VAO);
|
|
||||||
GLint s_texture = 0; // texture unit that sampler2D will use in GLSL code
|
|
||||||
glBindTextureUnit(s_texture, MainFont.texture_id);
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, it->count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitRender() {
|
|
||||||
InitArena(&RenderArena);
|
|
||||||
|
|
||||||
glCreateBuffers(1, &VBO);
|
|
||||||
glNamedBufferStorage(VBO, Lengthof(VertexNode2D::vertices) * sizeof(Vertex2D), 0, GL_DYNAMIC_STORAGE_BIT);
|
|
||||||
|
|
||||||
glCreateVertexArrays(1, &VAO);
|
|
||||||
|
|
||||||
GLint vbuf_index = 0;
|
|
||||||
glVertexArrayVertexBuffer(VAO, vbuf_index, VBO, 0, sizeof(struct Vertex2D));
|
|
||||||
|
|
||||||
GLint a_pos = 0;
|
|
||||||
glVertexArrayAttribFormat(VAO, a_pos, 2, GL_FLOAT, GL_FALSE, offsetof(struct Vertex2D, pos));
|
|
||||||
glVertexArrayAttribBinding(VAO, a_pos, vbuf_index);
|
|
||||||
glEnableVertexArrayAttrib(VAO, a_pos);
|
|
||||||
|
|
||||||
GLint a_tex = 1;
|
|
||||||
glVertexArrayAttribFormat(VAO, a_tex, 2, GL_FLOAT, GL_FALSE, offsetof(struct Vertex2D, tex));
|
|
||||||
glVertexArrayAttribBinding(VAO, a_tex, vbuf_index);
|
|
||||||
glEnableVertexArrayAttrib(VAO, a_tex);
|
|
||||||
|
|
||||||
GLint a_color = 2;
|
|
||||||
glVertexArrayAttribFormat(VAO, a_color, 4, GL_UNSIGNED_BYTE, GL_FALSE, offsetof(struct Vertex2D, color));
|
|
||||||
glVertexArrayAttribBinding(VAO, a_color, vbuf_index);
|
|
||||||
glEnableVertexArrayAttrib(VAO, a_color);
|
|
||||||
|
|
||||||
char *glsl_vshader = R"==(
|
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(location=0) uniform vec2 U_InvHalfScreenSize;
|
|
||||||
layout(location=0) in vec2 VPos;
|
|
||||||
layout(location=1) in vec2 VTex;
|
|
||||||
layout(location=2) in vec4 VColor;
|
|
||||||
|
|
||||||
out gl_PerVertex { vec4 gl_Position; }; // required because of ARB_separate_shader_objects
|
|
||||||
out vec2 FUV;
|
|
||||||
out vec4 FColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec2 pos = VPos * U_InvHalfScreenSize;
|
|
||||||
pos.y = 2 - pos.y; // invert y axis
|
|
||||||
pos -= vec2(1, 1); // convert to 0,1 range
|
|
||||||
|
|
||||||
gl_Position = vec4(pos, 0, 1);
|
|
||||||
FUV = VTex;
|
|
||||||
|
|
||||||
FColor = VColor / 255.0;
|
|
||||||
}
|
|
||||||
)==";
|
|
||||||
|
|
||||||
char *glsl_fshader = R"==(
|
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
in vec2 FUV;
|
|
||||||
in vec4 FColor;
|
|
||||||
|
|
||||||
layout (binding=0) uniform sampler2D S_Texture;
|
|
||||||
layout (location=0) out vec4 OutColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 c = FColor;
|
|
||||||
c.a *= texture(S_Texture, FUV).r;
|
|
||||||
OutColor = c;
|
|
||||||
}
|
|
||||||
)==";
|
|
||||||
|
|
||||||
Shader2D = CreateShader(glsl_vshader, glsl_fshader);
|
|
||||||
}
|
|
||||||
|
|
||||||
Shader CreateShader(char *glsl_vshader, char *glsl_fshader) {
|
|
||||||
Shader result = {};
|
|
||||||
result.vshader = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vshader);
|
|
||||||
result.fshader = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fshader);
|
|
||||||
|
|
||||||
GLint linked;
|
|
||||||
glGetProgramiv(result.vshader, GL_LINK_STATUS, &linked);
|
|
||||||
if (!linked) {
|
|
||||||
char message[1024];
|
|
||||||
glGetProgramInfoLog(result.vshader, sizeof(message), NULL, message);
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Failed to create vertex shader!", message, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
glGetProgramiv(result.fshader, GL_LINK_STATUS, &linked);
|
|
||||||
if (!linked) {
|
|
||||||
char message[1024];
|
|
||||||
glGetProgramInfoLog(result.fshader, sizeof(message), NULL, message);
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Failed to create fragment shader!", message, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenProgramPipelines(1, &result.pipeline);
|
|
||||||
glUseProgramStages(result.pipeline, GL_VERTEX_SHADER_BIT, result.vshader);
|
|
||||||
glUseProgramStages(result.pipeline, GL_FRAGMENT_SHADER_BIT, result.fshader);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SLL_QUEUE_ADD_MOD(f, l, n, next) \
|
|
||||||
do { \
|
|
||||||
(n)->next = 0; \
|
|
||||||
if ((f) == 0) { \
|
|
||||||
(f) = (l) = (n); \
|
|
||||||
} else { \
|
|
||||||
(l) = (l)->next = (n); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define SLL_QUEUE_ADD(f, l, n) SLL_QUEUE_ADD_MOD(f, l, n, next)
|
|
||||||
|
|
||||||
Vertex2D *AllocVertex2D(Allocator allocator, VertexList2D *list, int count) {
|
|
||||||
VertexNode2D *node = list->last;
|
|
||||||
if (node == 0 || node->count + count > Lengthof(node->vertices)) {
|
|
||||||
node = AllocType(allocator, VertexNode2D);
|
|
||||||
SLL_QUEUE_ADD(list->first, list->last, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
TotalVertexCount += count;
|
|
||||||
Vertex2D *result = node->vertices + node->count;
|
|
||||||
node->count += count;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushVertex2D(Allocator allocator, VertexList2D *list, Vertex2D *vertices, int count) {
|
|
||||||
Vertex2D *result = AllocVertex2D(allocator, list, count);
|
|
||||||
for (int i = 0; i < count; i += 1) result[i] = vertices[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushQuad2D(Allocator arena, VertexList2D *list, Rect2 rect, Rect2 tex, Color color, float rotation = 0.f, Vec2 rotation_point = {}) {
|
|
||||||
Vertex2D *v = AllocVertex2D(arena, list, 6);
|
|
||||||
v[0] = {
|
|
||||||
{rect.min.x, rect.max.y},
|
|
||||||
{ tex.min.x, tex.max.y},
|
|
||||||
color
|
|
||||||
};
|
|
||||||
v[1] = {
|
|
||||||
{rect.max.x, rect.max.y},
|
|
||||||
{ tex.max.x, tex.max.y},
|
|
||||||
color
|
|
||||||
};
|
|
||||||
v[2] = {
|
|
||||||
{rect.min.x, rect.min.y},
|
|
||||||
{ tex.min.x, tex.min.y},
|
|
||||||
color
|
|
||||||
};
|
|
||||||
v[3] = {
|
|
||||||
{rect.min.x, rect.min.y},
|
|
||||||
{ tex.min.x, tex.min.y},
|
|
||||||
color
|
|
||||||
};
|
|
||||||
v[4] = {
|
|
||||||
{rect.max.x, rect.max.y},
|
|
||||||
{ tex.max.x, tex.max.y},
|
|
||||||
color
|
|
||||||
};
|
|
||||||
v[5] = {
|
|
||||||
{rect.max.x, rect.min.y},
|
|
||||||
{ tex.max.x, tex.min.y},
|
|
||||||
color
|
|
||||||
};
|
|
||||||
if (rotation != 0.f) {
|
|
||||||
float s = sinf(rotation);
|
|
||||||
float c = cosf(rotation);
|
|
||||||
for (int i = 0; i < 6; i += 1) {
|
|
||||||
v[i].pos -= rotation_point;
|
|
||||||
v[i].pos = {v[i].pos.x * c + v[i].pos.y * (-s), v[i].pos.x * s + v[i].pos.y * c};
|
|
||||||
v[i].pos += rotation_point;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawRect(Rect2 rect, Color color) {
|
|
||||||
PushQuad2D(RenderArena, &Vertices, rect, MainFont.white_texture_bounding_box, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2 DrawString(Font *font, String16 string, Vec2 pos, Color color, bool draw = true) {
|
|
||||||
pos.y += font->ascent;
|
|
||||||
Vec2 original_pos = pos;
|
|
||||||
For(string) {
|
|
||||||
Glyph *g = GetGlyph(font, it);
|
|
||||||
Rect2 rect = Rect2FromSize(pos + g->offset, g->size);
|
|
||||||
if (draw && it != '\n' && it != ' ' && it != '\t') {
|
|
||||||
PushQuad2D(RenderArena, &Vertices, rect, g->atlas_bounding_box, color);
|
|
||||||
}
|
|
||||||
pos.x += g->xadvance;
|
|
||||||
}
|
|
||||||
Vec2 result = {pos.x - original_pos.x, font->size};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2 GetStringSize(Font *font, String16 string, Vec2 pos, Color color) {
|
|
||||||
return DrawString(font, string, pos, color, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Int GetCharSpacing(Font *font) {
|
|
||||||
Glyph *g = GetGlyph(font, '_');
|
|
||||||
if (g->xadvance) return (Int)g->xadvance;
|
|
||||||
return (Int)g->size.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BeginScissor(Rect2 rect) {
|
|
||||||
glScissor((GLint)rect.min.x, (GLint)rect.min.y, (GLsizei)(rect.max.x - rect.min.x), (GLsizei)(rect.max.y - rect.min.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndScissor() {
|
|
||||||
glScissor(0, 0, (GLsizei)WindowSize.x, (GLsizei)WindowSize.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect2 GetScreenRectF() {
|
|
||||||
Rect2 result = {0, 0, WindowSize.x, WindowSize.y};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect2I GetScreenRectI() {
|
|
||||||
Rect2I result = {0, 0, (Int)WindowSize.x, (Int)WindowSize.y};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
void Test() {
|
|
||||||
{
|
|
||||||
Array<int> array = {};
|
|
||||||
for (int i = 0; i < 64; i += 1) {
|
|
||||||
Add(&array, i);
|
|
||||||
}
|
|
||||||
Assert(array.len == 64);
|
|
||||||
int i = 0;
|
|
||||||
For(array) {
|
|
||||||
Assert(it == i++);
|
|
||||||
}
|
|
||||||
Assert(Contains(array, 5));
|
|
||||||
Assert(!Contains(array, 70));
|
|
||||||
|
|
||||||
int a[] = {64, 65, 66, 67};
|
|
||||||
InsertArray(&array, a, 4, 62);
|
|
||||||
Assert(array.len == 68);
|
|
||||||
Assert(array[61] == 61);
|
|
||||||
Assert(array[62] == 64);
|
|
||||||
Assert(array[63] == 65);
|
|
||||||
Assert(array[64] == 66);
|
|
||||||
Assert(array[65] == 67);
|
|
||||||
Assert(array[66] == 62);
|
|
||||||
|
|
||||||
Assert(Get(array, 90, 0) == 0);
|
|
||||||
Assert(Get(array, 4, 0) == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Array<int> arr = {};
|
|
||||||
for (int i = 0; i < 32; i += 1) {
|
|
||||||
Add(&arr, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 31;
|
|
||||||
For(IterateInReverse(&arr)) {
|
|
||||||
Assert(i == it);
|
|
||||||
i -= 1;
|
|
||||||
}
|
|
||||||
Assert(i == -1);
|
|
||||||
GetSlice(arr, 4, 7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
#define BASIC_IMPL
|
#define BASIC_IMPL
|
||||||
#include "basic/basic.h"
|
#include "basic/basic.h"
|
||||||
#include "basic/filesystem.h"
|
#include "basic/filesystem.h"
|
||||||
#include "basic/string16.cpp"
|
#include "basic/string16.cpp"
|
||||||
#include "basic/math_int.cpp"
|
#include "basic/math_int.cpp"
|
||||||
#include "basic/math.cpp"
|
#include "basic/math.cpp"
|
||||||
#include "profiler/profiler.cpp"
|
|
||||||
#include "new_basic.cpp"
|
|
||||||
#include <math.h>
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "colors.cpp"
|
#include "colors.cpp"
|
||||||
#include "raylib_utils.cpp"
|
#include "raylib_utils.cpp"
|
||||||
|
|
||||||
|
#include "profiler/profiler.cpp"
|
||||||
#include "text_editor.h"
|
#include "text_editor.h"
|
||||||
|
|
||||||
#include "buffer_helpers.cpp"
|
#include "buffer_helpers.cpp"
|
||||||
@@ -30,26 +31,8 @@
|
|||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
#include "lua_api.cpp"
|
#include "lua_api.cpp"
|
||||||
|
|
||||||
/*
|
|
||||||
- Save file (utf16->utf8)
|
|
||||||
- resize windows
|
|
||||||
- file dock on left side
|
|
||||||
- We can actually combine this with command window and lua, it's just going to be a buffer of
|
|
||||||
- open "asd/asd/asd/asd"
|
|
||||||
- Ctrl + F
|
|
||||||
|
|
||||||
- word completion
|
|
||||||
- Colored strings
|
|
||||||
|
|
||||||
- move off raylib
|
|
||||||
- Adjust text position a little bit down?
|
|
||||||
- proper double click that works on laptop
|
|
||||||
- font cache and on demand unicode loads
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
InitScratch();
|
InitScratch();
|
||||||
Test();
|
|
||||||
BeginProfiler();
|
BeginProfiler();
|
||||||
BeginProfileScope("main");
|
BeginProfileScope("main");
|
||||||
|
|
||||||
|
|||||||
@@ -86,17 +86,9 @@ struct Scroller {
|
|||||||
Int line_count;
|
Int line_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
float MenuFontSize;
|
|
||||||
Font MenuFont;
|
|
||||||
|
|
||||||
Font MainFont;
|
|
||||||
Int FontSize;
|
|
||||||
Int FontSpacing;
|
|
||||||
Int FontLineSpacing;
|
|
||||||
Int FontCharSpacing;
|
|
||||||
|
|
||||||
Int FrameID;
|
Int FrameID;
|
||||||
String WorkingDir;
|
String WorkingDir;
|
||||||
|
Arena Perm;
|
||||||
|
|
||||||
String16 EvalString(Allocator allocator, String16 string16);
|
String16 EvalString(Allocator allocator, String16 string16);
|
||||||
Rect2I GetVisibleCells(Window &window);
|
Rect2I GetVisibleCells(Window &window);
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
void SetMouseCursor() {
|
void SetMouseCursor() {
|
||||||
Window *w = GetActiveWindow();
|
// Window *w = GetActiveWindow();
|
||||||
Vec2 mouse = GetMousePosition();
|
// Vec2 mouse = GetMousePosition();
|
||||||
|
|
||||||
bool mouse_in_document = CheckCollisionPointRec(mouse, ToRectangle(w->document_rect));
|
// bool mouse_in_document = CheckCollisionPointRec(mouse, ToRectangle(w->document_rect));
|
||||||
bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(w->scrollbar_rect));
|
// bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(w->scrollbar_rect));
|
||||||
bool mouse_in_total = CheckCollisionPointRec(mouse, ToRectangle(w->total_rect));
|
// bool mouse_in_total = CheckCollisionPointRec(mouse, ToRectangle(w->total_rect));
|
||||||
|
|
||||||
if (w->mouse_selecting || mouse_in_document) {
|
// if (w->mouse_selecting || mouse_in_document) {
|
||||||
SetMouseCursor(MOUSE_CURSOR_IBEAM);
|
// SetMouseCursor(MOUSE_CURSOR_IBEAM);
|
||||||
} else if (mouse_in_scrollbar || w->mouse_selecting_scrollbar) {
|
// } else if (mouse_in_scrollbar || w->mouse_selecting_scrollbar) {
|
||||||
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
|
// SetMouseCursor(MOUSE_CURSOR_DEFAULT);
|
||||||
} else {
|
// } else {
|
||||||
SetMouseCursor(MOUSE_CURSOR_POINTING_HAND);
|
// SetMouseCursor(MOUSE_CURSOR_POINTING_HAND);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Array<Int> GetWindowZOrder(Allocator allocator) {
|
Array<Int> GetWindowZOrder(Allocator allocator) {
|
||||||
|
|||||||
@@ -51,23 +51,27 @@ void DrawVisibleText(Window &window) {
|
|||||||
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
||||||
pos -= view.scroll;
|
pos -= view.scroll;
|
||||||
pos += window.document_rect.min;
|
pos += window.document_rect.min;
|
||||||
// pos.y += (Int)(0.3 * (double)FontSize); // @todo: descent
|
|
||||||
|
|
||||||
float text_offset_x = 0;
|
float text_offset_x = 0;
|
||||||
for (Int col_index = visible.min.x; col_index < visible.max.x && col_index >= 0 && col_index < line_string.len; col_index += 1) {
|
for (Int col_index = visible.min.x; col_index < visible.max.x && col_index >= 0 && col_index < line_string.len; col_index += 1) {
|
||||||
int codepoint = line_string[col_index];
|
int codepoint = line_string[col_index];
|
||||||
int index = GetGlyphIndex(MainFont, codepoint);
|
Glyph *g = GetGlyph(&MainFont, codepoint);
|
||||||
|
Vec2 p = ToVec2(pos);
|
||||||
|
p.y += MainFont.ascent;
|
||||||
|
p.x += text_offset_x;
|
||||||
|
Rect2 rect = Rect2FromSize(p + g->offset, g->size);
|
||||||
|
|
||||||
if (codepoint == '\n' || codepoint == '\r') {
|
if (codepoint == '\n' || codepoint == '\r') {
|
||||||
// DrawCircle((int)pos.x + (int)text_offset_x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, tint);
|
// DrawCircle((int)pos.x + (int)text_offset_x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, tint);
|
||||||
} else if (codepoint == ' ') {
|
} else if (codepoint == ' ') {
|
||||||
// DrawCircle((int)pos.x + (int)text_offset_x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, space_color);
|
// DrawCircle((int)pos.x + (int)text_offset_x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, space_color);
|
||||||
} else if (codepoint != '\t') {
|
} else if (codepoint != '\t') {
|
||||||
DrawTextCodepoint(MainFont, codepoint, {(float)pos.x + text_offset_x, (float)pos.y}, (float)FontSize, tint);
|
PushQuad2D(RenderArena, &Vertices, rect, g->atlas_bounding_box, tint);
|
||||||
|
// DrawTextCodepoint(MainFont, codepoint, {(float)pos.x + text_offset_x, (float)pos.y}, (float)FontSize, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MainFont.glyphs[index].advanceX == 0) text_offset_x += ((float)MainFont.recs[index].width + FontSpacing);
|
if (g->xadvance == 0) text_offset_x += g->size.x;
|
||||||
else text_offset_x += ((float)MainFont.glyphs[index].advanceX + FontSpacing);
|
else text_offset_x += g->xadvance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,16 +92,16 @@ void DrawCaret(Window &window, XY xy, float size, Color color) {
|
|||||||
Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing));
|
Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing));
|
||||||
rect -= view.scroll;
|
rect -= view.scroll;
|
||||||
rect += window.document_rect.min;
|
rect += window.document_rect.min;
|
||||||
DrawRectangleRec(ToRectangle(rect), color);
|
DrawRect(ToRect2(rect), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawWindow(Window &window) {
|
void DrawWindow(Window &window) {
|
||||||
View &view = *GetActiveView(&window);
|
View &view = *GetActiveView(&window);
|
||||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||||
DrawRectangleRec(ToRectangle(window.total_rect), ColorBackground);
|
DrawRect(ToRect2(window.total_rect), ColorBackground);
|
||||||
bool is_active = IsActive(&window) || window.id.id == GetLastActiveWindow().id;
|
bool is_active = IsActive(&window) || window.id.id == GetLastActiveWindow().id;
|
||||||
|
|
||||||
BeginScissorMode((int)window.document_rect.min.x, (int)window.document_rect.min.y, (int)window.document_rect.max.x - (int)window.document_rect.min.x, (int)window.document_rect.max.y - (int)window.document_rect.min.y);
|
BeginScissor(window.document_rect);
|
||||||
BeginProfileScope(draw_caret_selection);
|
BeginProfileScope(draw_caret_selection);
|
||||||
Rect2I visible = GetVisibleCells(window);
|
Rect2I visible = GetVisibleCells(window);
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
@@ -122,15 +126,15 @@ void DrawWindow(Window &window) {
|
|||||||
Vec2I pos = {col * FontCharSpacing, line * FontLineSpacing};
|
Vec2I pos = {col * FontCharSpacing, line * FontLineSpacing};
|
||||||
pos -= view.scroll;
|
pos -= view.scroll;
|
||||||
pos += window.document_rect.min;
|
pos += window.document_rect.min;
|
||||||
Rectangle rectangle = {(float)pos.x, (float)pos.y, (float)FontCharSpacing, (float)FontLineSpacing};
|
Rect2 rect = Rect2FromSize({(float)pos.x, (float)pos.y}, {(float)FontCharSpacing, (float)FontLineSpacing});
|
||||||
DrawRectangleRec(rectangle, ColorSelection);
|
DrawRect(rect, ColorSelection);
|
||||||
|
|
||||||
if (line_string[col] == ' ' || line_string[col] == '\t') {
|
if (line_string[col] == ' ' || line_string[col] == '\t') {
|
||||||
DrawCircle((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, ColorWhitespaceDuringSelection);
|
// DrawCircle((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)MainFont.size / 10.f, ColorWhitespaceDuringSelection);
|
||||||
} else if (line_string[col] == '\n') {
|
} else if (line_string[col] == '\n') {
|
||||||
DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 4.f, (float)FontSize / 15.f, ColorWhitespaceDuringSelection);
|
// DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)MainFont.size / 4.f, (float)MainFont.size / 15.f, ColorWhitespaceDuringSelection);
|
||||||
} else if (line_string[col] == '\r') {
|
} else if (line_string[col] == '\r') {
|
||||||
DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)FontSize / 10.f, (float)FontSize / 4.f, ColorWhitespaceDuringSelection);
|
// DrawEllipse((int)pos.x + (int)FontCharSpacing / 2, (int)pos.y + (int)FontLineSpacing / 2, (float)MainFont.size / 10.f, (float)MainFont.size / 4.f, ColorWhitespaceDuringSelection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,11 +146,11 @@ void DrawWindow(Window &window) {
|
|||||||
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
|
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
|
||||||
w -= view.scroll;
|
w -= view.scroll;
|
||||||
w += window.document_rect.min;
|
w += window.document_rect.min;
|
||||||
Rect2I rect = {
|
Rect2 rect = {
|
||||||
{ 0, w.y},
|
{ 0.f, (float)w.y},
|
||||||
{GetRenderWidth(), w.y + FontLineSpacing}
|
{WindowSize.x, (float)w.y + (float)FontLineSpacing}
|
||||||
};
|
};
|
||||||
DrawRectangleRec(ToRectangle(rect), ColorLineHighlight);
|
DrawRect(rect, ColorLineHighlight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EndProfileScope();
|
EndProfileScope();
|
||||||
@@ -163,28 +167,28 @@ void DrawWindow(Window &window) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EndProfileScope();
|
EndProfileScope();
|
||||||
EndScissorMode();
|
EndScissor();
|
||||||
|
|
||||||
// Draw scrollbar
|
// Draw scrollbar
|
||||||
if (window.draw_scrollbar) {
|
if (window.draw_scrollbar) {
|
||||||
Vec2 mouse = GetMousePosition();
|
// Vec2 mouse = GetMousePosition();
|
||||||
bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(window.scrollbar_rect));
|
// bool mouse_in_scrollbar = CheckCollisionPointRec(mouse, ToRectangle(window.scrollbar_rect));
|
||||||
|
|
||||||
DrawRectangleRec(ToRectangle(window.scrollbar_rect), ColorScrollbarBackground);
|
DrawRect(ToRect2(window.scrollbar_rect), ColorScrollbarBackground);
|
||||||
Scroller scroller = ComputeScrollerRect(window);
|
Scroller scroller = ComputeScrollerRect(window);
|
||||||
Rect2 rect = Shrink(scroller.rect, 2);
|
Rect2 rect = Shrink(scroller.rect, 2);
|
||||||
Color color = ColorScrollbarScroller;
|
Color color = ColorScrollbarScroller;
|
||||||
if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) {
|
// if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) {
|
||||||
if (is_active) color = ColorScrollbarScrollerSelected;
|
// if (is_active) color = ColorScrollbarScrollerSelected;
|
||||||
}
|
// }
|
||||||
DrawRectangleRec(ToRectangle(rect), color);
|
DrawRect(rect, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw line numbers
|
// Draw line numbers
|
||||||
if (window.draw_line_numbers) {
|
if (window.draw_line_numbers) {
|
||||||
Rect2I r = window.line_numbers_rect;
|
Rect2I r = window.line_numbers_rect;
|
||||||
DrawRectangleRec(ToRectangle(r), ColorBackground);
|
DrawRect(ToRect2(r), ColorBackground);
|
||||||
BeginScissorMode((int)r.min.x, (int)r.min.y, (int)r.max.x - (int)r.min.x, (int)r.max.y - (int)r.min.y);
|
BeginScissor(r);
|
||||||
|
|
||||||
Rect2I vlines = GetVisibleCells(window);
|
Rect2I vlines = GetVisibleCells(window);
|
||||||
for (Int line = vlines.min.y; line <= vlines.max.y; line += 1) {
|
for (Int line = vlines.min.y; line <= vlines.max.y; line += 1) {
|
||||||
@@ -194,18 +198,18 @@ void DrawWindow(Window &window) {
|
|||||||
pos += r.min;
|
pos += r.min;
|
||||||
String s = Format(scratch, "%lld", (long long)line);
|
String s = Format(scratch, "%lld", (long long)line);
|
||||||
String16 string = ToString16(scratch, s);
|
String16 string = ToString16(scratch, s);
|
||||||
float x = MeasureTextEx(MainFont, s.data, (float)FontSize, (float)FontSpacing).x;
|
float x = GetStringSize(&MainFont, string).x;
|
||||||
Vec2 p = ToVec2(pos);
|
Vec2 p = ToVec2(pos);
|
||||||
float rectx = (float)GetSize(r).x;
|
float rectx = (float)GetSize(r).x;
|
||||||
p.x += (rectx - x) / 2.f;
|
p.x += (rectx - x) / 2.f;
|
||||||
if (x > rectx) p.x = (float)r.min.x;
|
if (x > rectx) p.x = (float)r.min.x;
|
||||||
DrawString(MainFont, string, p, (float)FontSize, (float)FontSpacing, ColorTextLineNumbers);
|
DrawString(&MainFont, string, p, ColorTextLineNumbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScissorMode();
|
EndScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_active) {
|
if (!is_active) {
|
||||||
DrawRectangleRec(ToRectangle(window.total_rect), {0, 0, 0, 30});
|
DrawRect(ToRect2(window.total_rect), {0, 0, 0, 30});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user