GCC Code Coverage Report


./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 of 119, 0 excluded
0.0%
Functions:
0 of 2, 0 excluded
0.0%
Branches:
0 of 266, 0 excluded
0.0%

libs/mrgui/examples/main.cc
Line Branch Exec Source
1 // todo(Gustav): look into glad support
2 #define SDL_FUNCTION_POINTER_IS_VOID_POINTER
3
4 #include "SDL.h"
5 #include "SDL_timer.h"
6
7 #include <cassert>
8 #include <optional>
9 #include <vector>
10 #include <unordered_map>
11 #include <string>
12 #include <algorithm>
13 #include <cstdint>
14
15 #include "dependency_glad.h"
16 #include "OpenSans-Regular.ttf.h"
17 #include "uv-texture.png.h"
18 #include "spritesheet.png.h"
19
20 #include "eu/log/log.h"
21 #include "eu/base/memorychunk.h"
22
23 #include "eu/render/canvas.h"
24 #include "eu/render/state.h"
25 #include "eu/render/font.h"
26 #include "eu/render/opengl_utils.h"
27 #include "eu/render/texture.io.h"
28 #include "eu/render/enable_high_performance_graphics.h"
29
30 #include "data/spritesheet.h"
31
32 #include "eu/mrgui/widgets.h"
33
34 using namespace eu::mrgui;
35
36 ENABLE_HIGH_PERFORMANCE_GRAPHICS
37
38 static eu::MemoryChunk chunk_from_embed(const embedded_binary& binary)
39 {
40 return
41 {
42 .bytes = reinterpret_cast<const char*>(binary.data),
43 .size = binary.size
44 };
45 }
46
47 int main(int, char**)
48 {
49 int window_width = 1280;
50 int window_height = 720;
51
52 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == false) {
53 LOG_ERR("Error initializing SDL: {}", SDL_GetError());
54 return -1;
55 }
56
57
58 #ifdef __APPLE__
59 // GL 3.2 Core + GLSL 150
60 const char* glsl_version = "#version 150";
61 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
62 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
63 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
64 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
65 #else
66 // GL 3.0 + GLSL 130
67 // const char* glsl_version = "#version 130";
68 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
69 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
70 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
71 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); // was 0 in dear imgui example??
72 #endif
73
74 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
75 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
76
77 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
78 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
79
80 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
81 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
82 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
83 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
84
85 SDL_Window* window = SDL_CreateWindow("mrgui sample",
86 window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_RESIZABLE);
87 if (window == nullptr) {
88 LOG_ERR("Error creating window: {}", SDL_GetError());
89 return -1;
90 }
91
92 auto* gl_context = SDL_GL_CreateContext(window);
93 SDL_GetWindowSize(window, &window_width, &window_height);
94 if (gl_context == nullptr) {
95 LOG_ERR("Error creating gl context: {}", SDL_GetError());
96 return -1;
97 }
98
99 /* OpenGL setup */
100 const int glad_result = gladLoadGLLoader(SDL_GL_GetProcAddress);
101 if (glad_result == 0)
102 {
103 LOG_ERR("Failed to init glad, error: {0}", glad_result);
104 return -1;
105 }
106
107 {
108 const std::string gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
109 const std::string gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
110 const std::string gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
111 const std::string gl_shading_language_version = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
112
113 LOG_INFO("Vendor: {0}", gl_vendor);
114 LOG_INFO("Renderer: {0}", gl_renderer);
115 LOG_INFO("Version OpenGL: {0}", gl_version);
116 LOG_INFO("Version GLSL: {0}", gl_shading_language_version);
117 }
118
119 eu::render::State states;
120 eu::render::Render2 render{ &states };
121
122 UiState uistate;
123 const IdStack idstack;
124 eu::render::DrawableFont font{chunk_from_embed(OPENSANS_REGULAR_TTF)};
125
126 const auto sample_texture = eu::render::load_image_from_embedded(SEND_DEBUG_LABEL_MANY("uv-texture.png") UV_TEXTURE_PNG,
127 eu::render::TextureEdge::clamp, eu::render::TextureRenderStyle::linear, eu::render::Transparency::exclude, eu::render::ColorData::color_data);
128
129 const auto spritesheet = eu::render::load_image_from_embedded(SEND_DEBUG_LABEL_MANY("spritesheet.png") SPRITESHEET_PNG,
130 eu::render::TextureEdge::repeat, eu::render::TextureRenderStyle::linear, eu::render::Transparency::include, eu::render::ColorData::color_data);
131
132 bool running = true;
133 std::string editable_text = "Editable text";
134
135 LOG_INFO("Mrgui sample started");
136 while (running)
137 {
138 // events
139 SDL_Event e;
140 while (SDL_PollEvent(&e))
141 {
142 switch (e.type)
143 {
144 case SDL_EVENT_MOUSE_MOTION:
145 uistate.mouse = { e.motion.x, static_cast<float>(window_height) - e.motion.y };
146 break;
147 case SDL_EVENT_MOUSE_BUTTON_DOWN:
148 if (e.button.button == 1)
149 {
150 uistate.mousedown = true;
151 }
152 break;
153 case SDL_EVENT_MOUSE_BUTTON_UP:
154 if (e.button.button == 1)
155 {
156 uistate.mousedown = false;
157 }
158 break;
159 case SDL_EVENT_WINDOW_RESIZED:
160 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
161 LOG_INFO("Resized");
162 SDL_GetWindowSize(window, &window_width, &window_height);
163 break;
164 case SDL_EVENT_KEY_DOWN:
165 uistate.key = KeyboardInput {.key = e.key.key, .mod = e.key.mod };
166 break;
167 case SDL_EVENT_TEXT_INPUT:
168 {
169 // todo(Gustav): handle unicode
170 const char first_char = e.text.text[0];
171 if ((first_char & 0xFF80) == 0)
172 {
173 uistate.keychar = static_cast<char>(first_char & 0x7f);
174 }
175 }
176 break;
177 case SDL_EVENT_QUIT: running = false; break;
178 default:
179 // ignore other events
180 break;
181 }
182 }
183
184 // render
185 {
186 const eu::render::RenderCommand cmd {.states = &states, .render = &render, .size = {.width = window_width, .height = window_height} };
187
188 // todo(Gustav): provide a pixel layout
189 const auto screen = eu::render::LayoutData{ .style = eu::render::ViewportStyle::extended,
190 .requested_width = static_cast<float>(window_width), .requested_height = static_cast<float>(window_height) };
191
192 cmd.clear(eu::colors::blue_sky, screen);
193
194 auto layer = eu::render::with_layer2(cmd, screen);
195 eu::render::Quad{ .tint = eu::colors::green_bluish }.draw(layer.batch, layer.viewport_aabb_in_worldspace.get_bottom(50));
196
197 static eu::An rotation = eu::no_rotation;
198 static float slider_a = 0.5f;
199 static float slider_b = 0.5f;
200
201 eu::render::Quad{
202 .texture = &sample_texture,
203 // select bottom right of the texture, assuming it is split in 4 smaller rects
204 .texturecoord = eu::Rect::from_bottom_left_size({0.5f, 0}, {0.5f, 0.5f}),
205 .rotation = eu::render::RotateQuad{.angle = rotation, .center = {slider_a, slider_b} }
206 }.draw(layer.batch, eu::Rect::from_bottom_left_size({ 300, 300 }, { 300, 300 }));
207
208 const auto button_size = eu::v2{ 64, 64 };
209
210 uistate.begin();
211 if (basic_button(idstack.get("a"), eu::Rect::from_bottom_left_size({ 100, 100 }, button_size), uistate, layer.batch))
212 {
213 rotation -= eu::An::from_degrees(15.0f);
214 }
215 if (basic_button(idstack.get("b"), eu::Rect::from_bottom_left_size({ 200, 100 }, button_size), uistate, layer.batch))
216 {
217 rotation += eu::An::from_degrees(15.0f);
218 }
219 if (basic_button(idstack.get("c"), eu::Rect::from_bottom_left_size({ 300, 100 }, button_size), uistate, layer.batch))
220 {
221 rotation = eu::no_rotation;
222 }
223 button_texture(idstack.get("d"), eu::Rect::from_bottom_left_size({ 400, 100 }, button_size), uistate, layer.batch, &spritesheet,
224 ::spritesheet::button_square_flat,
225 ::spritesheet::button_square_depth_flat,
226 ::spritesheet::button_square_depth_gradient
227 );
228
229 const auto slider_size = eu::v2{ 256, 25 };
230 slider(idstack.get("slider_a"), &slider_a, eu::Rect::from_bottom_left_size({ 100, 200 }, slider_size), uistate, layer.batch);
231 slider(idstack.get("slider_b"), &slider_b, eu::Rect::from_bottom_left_size({ 100, 250 }, slider_size), uistate, layer.batch);
232 textfield(idstack.get("textfield"), &editable_text, &font, 20, {100, 300}, uistate, layer.batch);
233 uistate.end();
234
235 draw_text(layer.batch, &font, "Hello world", 60, {200, 400 + 200}, eu::colors::black);
236 }
237 SDL_GL_SwapWindow(window);
238 }
239
240 LOG_INFO("Shutting down");
241 SDL_GL_DestroyContext(gl_context);
242 SDL_DestroyWindow(window);
243 SDL_Quit();
244
245 return 0;
246 }
247