GCC Code Coverage Report


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

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