#import "Basic"; #import "GL"; #import "freetype-2.12.1"; #import "Hash_Table"; #import "Math"; #import "File"; #import "String"; #import "stb_image"; #import "Windows_Utf8"; #import "Windows"; using SDL3 :: #import "SDL3"; #import "kb_text_shape"; #import "stb_rect_pack"; #load "text.jai"; #load "ui.jai"; #load "stb_textedit.jai"; #load "math/colourspace.jai"; #load "math/math.jai"; #load "platform/input.jai"; #load "platform/opengl.jai"; #load "platform/shader.jai"; #load "platform/texture.jai"; window_width :: 1280; window_height :: 720; window : *SDL_Window; gl_context : SDL_GLContext; running : bool = true; dt : float; frame : u64; counter_frequency : u64; ui_font_very_small : Font; ui_font_small : Font; ui_font_normal : Font; ui_font_big : Font; icon_font_small : Font; icon_font_normal : Font; icon_font_big : Font; main :: () { log("Hello, Sailor!"); #if OS == .WINDOWS SetConsoleOutputCP(65001); // CP_UTF8 SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_DEBUG_FLAG, 1); window = SDL_CreateWindow(NAME, window_width, window_height, SDL_WINDOW_OPENGL); gl_context = SDL_GL_CreateContext(window); gl_load(*gl); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); init(); SDL_StartTextInput(window); counter_frequency = SDL_GetPerformanceFrequency(); last_counter : u64 = SDL_GetPerformanceCounter(); while (running) { new_counter : u64 = SDL_GetPerformanceCounter(); dt = cast(float, new_counter - last_counter) / cast(float, counter_frequency); last_counter = new_counter; event : SDL_Event; while SDL_PollEvent(*event) { transition : InputTransition; if event.type == { case SDL_EVENT_QUIT; running = false; case SDL_EVENT_KEY_DOWN; if event.key.key == { case SDLK_ESCAPE; running = false; case SDLK_Z; if event.key.mod == SDL_KMOD_LCTRL | SDL_KMOD_LSHIFT { log("REDO!"); transition.char = STB_TEXTEDIT_K_REDO; } else if event.key.mod == SDL_KMOD_LCTRL { log("UNDO!"); transition.char = STB_TEXTEDIT_K_UNDO; } case SDLK_UP; if event.key.mod == SDL_KMOD_LSHIFT { transition.char = STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT; } else { log("Moving up"); transition.char = STB_TEXTEDIT_K_UP; } case SDLK_DOWN; if event.key.mod == SDL_KMOD_LSHIFT { transition.char = STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT; } else { log("Moving down"); transition.char = STB_TEXTEDIT_K_DOWN; } case SDLK_LEFT; transition.left_arrow_down = true; if event.key.mod == SDL_KMOD_LCTRL { log("Moving word to the left!"); transition.char = STB_TEXTEDIT_K_WORDLEFT; } else if event.key.mod == SDL_KMOD_LSHIFT { transition.char = STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT; } else { log("Moving to the left"); transition.char = STB_TEXTEDIT_K_LEFT; } case SDLK_RIGHT; transition.right_arrow_down = true; if event.key.mod == SDL_KMOD_LCTRL { log("Moving word to the right!"); transition.char = STB_TEXTEDIT_K_WORDRIGHT; } else if event.key.mod == SDL_KMOD_LSHIFT { transition.char = STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT; } else { log("Moving to the right"); transition.char = STB_TEXTEDIT_K_RIGHT; } case SDLK_BACKSPACE; transition.backspace = true; if event.key.mod == SDL_KMOD_LSHIFT { transition.char = STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT; } else { transition.char = STB_TEXTEDIT_K_BACKSPACE; } case SDLK_LSHIFT; transition.shift_down = true; case SDLK_LCTRL; transition.control_down = true; case SDLK_RETURN; transition.char = STB_TEXTEDIT_NEWLINE; } case SDL_EVENT_MOUSE_MOTION; transition.motion_delta = .{event.motion.xrel, event.motion.yrel}; case SDL_EVENT_MOUSE_WHEEL; transition.mouse_wheel = xx event.wheel.y; case SDL_EVENT_MOUSE_BUTTON_DOWN; if event.button.button == SDL_BUTTON_LEFT { transition.left_down = true; input_state.left_mouse = true; } if event.button.button == SDL_BUTTON_RIGHT { transition.right_down = true; input_state.right_mouse = true; } case SDL_EVENT_MOUSE_BUTTON_UP; if event.button.button == SDL_BUTTON_LEFT { transition.left_up = true; input_state.left_mouse = false; } if event.button.button == SDL_BUTTON_RIGHT { transition.right_up = true; input_state.right_mouse = false; } case SDL_EVENT_TEXT_INPUT; //input_state.last_char = xx it.utf32; text : string = to_string(event.text.text); log("%", text); StringAt : u64; while StringAt < xx text.count { Decode : kbts_decode = kbts_DecodeUtf8(text.data + StringAt, xx text.count - StringAt); StringAt += Decode.SourceCharactersConsumed; if Decode.Valid { transition.char = xx Decode.Codepoint; } } } array_add(*input_transitions, transition); } glClearColor(0.5, 0.1, 0.5, 0.0); glClear(GL_COLOR_BUFFER_BIT); ui_new_frame(); ui_context.anchor = .TOP_LEFT; ui_context.layout = .TTB; ui_context.sizing_x = .GROW; ui_context.sizing_y = .GROW; ui_context.colours.normal = Vector4.{0.13, 0.16, 0.22, 1}; ui_context.colours.hover = Vector4.{0.23, 0.26, 0.32, 1}; ui_context.colours.active = Vector4.{0.13, 0.16, 0.22, 1}; ui_context.colours.background = Vector4.{0.07, 0.09, 0.16, 1}; ui_context.font = *ui_font_normal; ui_begin("Dashboard"); { ui_context.layout = .LTR; ui_context.colours.background = .{0.07, 0.09, 0.16, 1}; ui_context.colours.background = .{0.11, 0.25, 0.26, 1}; ui_context.sizing_x = .FIT; ui_context.sizing_y = .FIT; //ui_label("Hello, World! How's it going?"); //ui_label("Hello, World!"); ui_text_input("Name"); // ui_begin_container("Picture-Name-Settings"); // { // ui_icon("Icon", *dog, v2(128)); // ui_context.layout = .TTB; // ui_context.sizing_x = .FIT; // ui_begin_container("Name-Ready-Score"); // { // ui_context.layout = .LTR; // ui_begin_container("Name-Ready"); // { // ui_label("John Dog"); // ui_context.font = *ui_font_very_small; // ui_context.offaxis_layout = .MIDDLE; // ui_context.colours.background = .{0.11, 0.25, 0.26, 1}; // ui_label("Ready to Train", .{0.25, 0.78, 0.6, 1}); // ui_context.offaxis_layout = .NONE; // ui_context.colours.background = .{0.07, 0.09, 0.16, 1}; // } // ui_end_container(); // ui_context.layout = .LTR; // ui_begin_container("asd"); // { // ui_context.offaxis_layout = .MIDDLE; // ui_font_icon(*icon_font_normal, "battery-three-quarters", .{48, 48}, .{0.25, 0.78, 0.6, 1}); // ui_label("Recovery Score: 85%"); // } // ui_end_container(); // } // ui_end_container(); // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.offaxis_layout = .MIDDLE; // if ui_button("Settings") { // log("Settings!"); // } // ui_context.offaxis_layout = .NONE; // } // ui_end_container(); // ui_context.layout = .TTB; // ui_begin_container("Scroll", flags = .SCROLL); // { // ui_context.sizing_x = .GROW; // ui_context.colours.background = .{1.0, 0.0, 0.0, 1.0}; // ui_begin_container("HR&Strain", max_y = 200, flags = .SCROLL); // { // ui_context.layout = .TTB; // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_begin_container("HR"); // { // ui_context.layout = .LTR; // ui_context.font = *ui_font_small; // ui_begin_container("HR-icon"); // { // ui_font_icon(*icon_font_normal, "heart-pulse", .{48, 48}, .{0.89, 0.44, 0.43, 1}); // ui_context.offaxis_layout = .MIDDLE; // ui_label("HR"); // ui_context.offaxis_layout = .NONE; // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.font = *ui_font_very_small; // ui_context.offaxis_layout = .MIDDLE; // ui_label("Live"); // ui_context.offaxis_layout = .NONE; // } // ui_end_container(); // ui_context.font = *ui_font_big; // ui_label("67bpm"); // ui_context.font = *ui_font_small; // ui_label("+12% from baseline"); // } // ui_end_container(); // ui_context.layout = .TTB; // ui_begin_container("Strain"); // { // ui_context.layout = .LTR; // ui_begin_container("Strain-Today"); // { // ui_context.font = *ui_font_small; // ui_font_icon(*icon_font_normal, "bolt", .{48, 48}, .{0.96, 0.73, 0.15, 1}); // ui_context.offaxis_layout = .MIDDLE; // ui_label("Strain"); // ui_context.offaxis_layout = .NONE; // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.offaxis_layout = .MIDDLE; // ui_label("Today"); // ui_context.offaxis_layout = .NONE; // } // ui_end_container(); // ui_context.font = *ui_font_big; // ui_label("14.2"); // } // ui_end_container(); // } // ui_end_container(); // ui_context.colours.normal = Vector4.{1, 1, 0, 1}; // ui_text_input("Name"); // ui_context.colours.background = Vector4.{0.07, 0.09, 0.16, 1}; // ui_begin_container("!Padding"); // { // ui_context.font = *ui_font_normal; // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_context.layout = .TTB; // ui_begin_container("CurrentSession"); // { // ui_context.sizing_x = .GROW; // ui_context.layout = .LTR; // ui_begin_container("Session-Live"); // { // ui_label("Current Session"); // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.font = *ui_font_small; // ui_context.offaxis_layout = .MIDDLE; // ui_label("Live"); // ui_context.offaxis_layout = .NONE; // } // ui_end_container(); // ui_context.layout = .LTR; // ui_context.sizing_x = .GROW; // ui_begin_container("CurrentWork"); // { // ui_context.sizing_x = .FIT; // ui_begin_container("Icon-Exercise-Set"); // { // ui_context.colours.background = .{0.26, 0.23, 0.45, 1}; // ui_begin_container("Icon-Container"); // { // ui_font_icon(*icon_font_small, "dumbbell", .{48, 48}, .{0.64, 0.55, 0.97, 1}); // } // ui_end_container(); // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_context.layout = .TTB; // ui_begin_container("Exercise-Set"); // { // ui_label("Bench Press"); // ui_context.font = *ui_font_small; // ui_label("Set 3 of 4"); // } // ui_end_container(); // } // ui_end_container(); // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.sizing_x = .FIT; // ui_begin_container("Weight-Reps"); // { // ui_context.font = *ui_font_normal; // ui_label("225 lbs"); // ui_begin_container("padding-reps"); // { // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.font = *ui_font_small; // ui_label("8 reps", colour = .{0.23, 0.79, 0.62, 1}); // } // ui_end_container(); // } // ui_end_container(); // } // ui_end_container(); // } // ui_end_container(); // } // ui_end_container(); // ui_context.colours.background = Vector4.{0.07, 0.09, 0.16, 1}; // ui_begin_container("Padding2"); // { // ui_context.layout = .LTR; // ui_context.colours.background = .{0.07, 0.09, 0.16, 1}; // ui_context.sizing_x = .GROW; // ui_begin_container("Activation-Refresh"); // { // ui_label("Muscle Activation"); // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_font_icon(*icon_font_small, "arrows-rotate", .{48, 48}); // } // ui_end_container(); // } // ui_end_container(); // ui_context.colours.background = .{0.07, 0.09, 0.16, 1}; // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_context.layout = .TTB; // ui_begin_container("Padding3"); // { // ui_context.layout = .LTR; // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_begin_container("Chest"); // { // ui_context.font = *ui_font_small; // ui_label("Chest"); // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.colours.background = .{0.3, 0.21, 0.25, 1}; // ui_context.font = *ui_font_small; // ui_label("High Strain", colour = .{0.96, 0.44, 0.44, 1}); // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_label("92%", colour = .{0.96, 0.44, 0.44, 1}); // } // ui_end_container(); // ui_progress_bar("chest-progress", 0.92, .{1800, 20}, .{0.22, 0.25, 0.32, 1}, .{0.96, 0.45, 0.45, 1}); // } // ui_end_container(); // ui_context.colours.background = Vector4.{0.07, 0.09, 0.16, 1}; // ui_context.layout = .TTB; // ui_begin_container("Padding4"); // { // ui_context.layout = .LTR; // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_begin_container("Triceps"); // { // ui_context.font = *ui_font_small; // ui_label("Triceps"); // ui_context.sizing_x = .GROW; // ui_spacing("padding"); // ui_context.font = *ui_font_small; // ui_context.colours.background = .{0.29, 0.27, 0.23, 1}; // ui_label("Moderate", colour = .{0.98, 0.75, 0.15, 1}); // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_label("67%", colour = .{0.98, 0.75, 0.15, 1}); // } // ui_end_container(); // } // ui_end_container(); // ui_context.colours.background = Vector4.{0.07, 0.09, 0.16, 1}; // ui_context.layout = .TTB; // ui_begin_container("Padding5"); // { // ui_context.layout = .TTB; // ui_context.font = *ui_font_small; // ui_context.colours.background = .{0.13, 0.16, 0.22, 1}; // ui_begin_container("AI", true, .{0.16, 0.15, 0.31, 1}, .{0.09, 0.18, 0.31, 1}); // { // ui_context.sizing_x = .FIT; // ui_context.sizing_y = .FIT; // ui_context.layout = .LTR; // ui_context.colours.background = .{}; // ui_begin_container("Icon-AI-Form"); // { // ui_context.colours.background = .{0.26, 0.23, 0.45, 1}; // ui_begin_container("Icon-Container"); // { // ui_font_icon(*icon_font_small, "robot", .{48, 48}, .{0.64, 0.54, 0.97, 1}); // } // ui_end_container(); // ui_context.colours.background = .{}; // ui_context.layout = .TTB; // ui_begin_container("AI-Form"); // { // ui_context.font = *ui_font_normal; // ui_label("AI Feedback"); // ui_context.font = *ui_font_small; // ui_label("Form Analysis"); // } // ui_end_container(); // } // ui_end_container(); // ui_label("Reduce weight by 5 lbs for optimal form. Bar path showing slight right deviation."); // ui_context.layout = .LTR; // ui_context.sizing_x = .GROW; // ui_begin_container("buttons"); // { // ui_context.colours.normal = .{0.25, 0.22, 0.45, 1}; // ui_button("Adjust Weight", font_colour = .{0.64, 0.55, 0.97, 1}); // ui_spacing("padding"); // ui_context.colours.normal = .{0.22, 0.25, 0.32, 1}; // ui_button("View Details", font_colour = .{0.6, 0.64, 0.69, 1}); // } // ui_end_container(); // } // ui_end_container(); // } // ui_end_container(); // } // ui_end_container(); } ui_end(); // ui_context.anchor = .BOTTOM_LEFT; // ui_context.layout = .LTR; // ui_context.sizing_x = .GROW; // ui_context.sizing_y = .FIT; // ui_context.colours.background = Vector4.{0.13, 0.16, 0.22, 1}; // ui_context.colours.normal = Vector4.{0.1, 0.14, 0.21, 1}; // ui_context.font = *ui_font_very_small; // ui_begin("Menu"); // { // if ui_button("Dashboard") { // log("Dashboard!"); // } // if ui_button("Workout") { // log("Workout!"); // } // if ui_button("Recovery") { // log("Recovery!"); // } // if ui_button("Profile") { // log("Profile!"); // } // if ui_button("Exit") { // break; // } // } // ui_end(); ui_end_frame(); ui_render(); SDL_GL_SwapWindow(window); } SDL_StopTextInput(window); SDL_GL_DestroyContext(gl_context); SDL_DestroyWindow(window); SDL_Quit(); } init :: () { window_proj = orthographic_gl(0.0, xx window_width, 0.0, xx window_height, -1.0, 1.0); init_shaders(); init_texture(*normal_frame, "panel-border-000.png"); init_texture(*hot_frame, "panel-transparent-center-000.png"); init_texture(*active_frame, "panel-000.png"); init_texture(*dog, "dog.png"); FT_Init_FreeType(*ftlib); init_font(*ui_font_very_small, "./JetBrainsMono-Regular.ttf", 18); init_font(*ui_font_small, "./JetBrainsMono-Regular.ttf", 32); init_font(*ui_font_normal, "./JetBrainsMono-Regular.ttf", 48); init_font(*ui_font_big, "./JetBrainsMono-Regular.ttf", 54); init_font(*icon_font_small, "./Font Awesome 6 Free-Solid-900.otf", 32); init_font(*icon_font_normal, "./Font Awesome 6 Free-Solid-900.otf", 48); init_font(*icon_font_big, "./Font Awesome 6 Free-Solid-900.otf", 54); } offset_of :: ($T: Type, ident: Code) -> s64 #expand { t: T = ---; return cast(*void) (*t.#insert ident) - cast(*void) *t; } glDebugOutput :: (source: GLenum, type: GLenum, id: u32, severity: GLenum, length: u64, message: *u8, userParam: *void) { // ignore non-significant error/warning codes if id == 131169 || id == 131185 || id == 131218 || id == 131204 return; log("---------------"); log("Debug message (%): %", id, message); if source == { case GL_DEBUG_SOURCE_API; log("Source: API"); case GL_DEBUG_SOURCE_WINDOW_SYSTEM; log("Source: Window System"); case GL_DEBUG_SOURCE_SHADER_COMPILER; log("Source: Shader Compiler"); case GL_DEBUG_SOURCE_THIRD_PARTY; log("Source: Third Party"); case GL_DEBUG_SOURCE_APPLICATION; log("Source: Application"); case GL_DEBUG_SOURCE_OTHER; log("Source: Other"); } if type == { case GL_DEBUG_TYPE_ERROR; log("Type: Error"); case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR; log("Type: Deprecated Behaviour"); case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR; log("Type: Undefined Behaviour"); case GL_DEBUG_TYPE_PORTABILITY; log("Type: Portability"); case GL_DEBUG_TYPE_PERFORMANCE; log("Type: Performance"); case GL_DEBUG_TYPE_MARKER; log("Type: Marker"); case GL_DEBUG_TYPE_PUSH_GROUP; log("Type: Push Group"); case GL_DEBUG_TYPE_POP_GROUP; log("Type: Pop Group"); case GL_DEBUG_TYPE_OTHER; log("Type: Other"); } if severity == { case GL_DEBUG_SEVERITY_HIGH; log("Severity: high"); case GL_DEBUG_SEVERITY_MEDIUM; log("Severity: medium"); case GL_DEBUG_SEVERITY_LOW; log("Severity: low"); case GL_DEBUG_SEVERITY_NOTIFICATION; log("Severity: notification"); } log(""); }