GCC Code Coverage Report


./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 of 277, 0 excluded
0.0%
Functions:
0 of 12, 0 excluded
0.0%
Branches:
0 of 472, 0 excluded
0.0%

apps/editor/src/editor/main.cc
Line Branch Exec Source
1 #include "SDL.h"
2 #include "SDL_timer.h"
3
4 #include <cassert>
5 #include "dependency_glad.h"
6 #include "OpenSans-Regular.ttf.h"
7 #include "uv-texture.png.h"
8
9 #include "log/log.h"
10 #include "base/memorychunk.h"
11
12 #include "render/canvas.h"
13 #include "render/opengl_states.h"
14 #include "render/font.h"
15 #include "render/opengl_utils.h"
16 #include "render/texture.io.h"
17 #include "render/enable_high_performance_graphics.h"
18
19 ENABLE_HIGH_PERFORMANCE_GRAPHICS
20
21 #if 1
22
23 /// djb2 initial hash
24 constexpr eu::u32 initial_hash = 5381;
25
26 /// djb2 hash function
27 eu::u32 hash(unsigned char *str, std::size_t length, eu::u32 seed)
28 {
29 eu::u32 hash = seed;
30
31 for(std::size_t index = 0; index < length; index += 1)
32 {
33 auto c = str[index];
34 hash = ((hash << 5) + hash) + c;
35 }
36
37 return hash;
38 }
39
40 struct IdStack
41 {
42 [[nodiscard]] eu::u32 get(const std::string& str) const
43 {
44 return hash(reinterpret_cast<unsigned char*>(const_cast<char*>(str.data())), str.size(), last_id());
45 }
46
47 [[nodiscard]] eu::u32 get(int id) const
48 {
49 return hash(reinterpret_cast<unsigned char*>(&id), sizeof(int), last_id());
50 }
51 void push(const std::string& str)
52 {
53 stack.push_back(get(str));
54 }
55 void push(int id)
56 {
57 stack.push_back(get(id));
58 }
59 void pop()
60 {
61 stack.pop_back();
62 }
63 [[nodiscard]] eu::u32 last_id() const
64 {
65 return stack.empty() ? initial_hash : *stack.rbegin();
66 }
67 std::vector<eu::u32> stack;
68 };
69
70 struct KeyboardInput
71 {
72 SDL_Keycode key;
73 eu::u16 mod;
74 };
75
76 struct UiState
77 {
78 eu::v2 mouse = {0,0};
79 bool mousedown = false;
80 std::optional<eu::u32> hot_item = std::nullopt;
81 std::optional<eu::u32> active_item = std::nullopt;
82 bool active_item_locked = false;
83
84 std::optional<eu::u32> kbd_item = std::nullopt;
85 std::optional<eu::u32> last_widget = std::nullopt;
86 std::optional<KeyboardInput> key = std::nullopt; // todo(Gustav): change to a vector
87 std::optional<char> keychar = std::nullopt; // todo(Gustav): change to a vector
88
89 void begin()
90 {
91 hot_item = std::nullopt;
92 }
93
94 void end()
95 {
96 if (mousedown)
97 {
98 if (active_item == std::nullopt)
99 {
100 active_item = std::nullopt;
101 active_item_locked = true;
102 }
103 }
104 else
105 {
106 active_item = std::nullopt;
107 active_item_locked = false;
108 }
109
110 if (key && key->key == SDLK_TAB)
111 {
112 kbd_item = std::nullopt;
113 }
114 key = std::nullopt;
115 keychar = std::nullopt;
116 }
117
118 [[nodiscard]] bool is_active_free() const
119 {
120 return active_item_locked == false && active_item.has_value() == false;
121 }
122 };
123
124 // Simple button IMGUI widget
125 bool button(eu::u32 id, const eu::Rect& rect, UiState& uistate, eu::render::SpriteBatch* batch)
126 {
127 if (eu::is_within(uistate.mouse, rect))
128 {
129 uistate.hot_item = id;
130 if (uistate.is_active_free() && uistate.mousedown)
131 {
132 uistate.active_item = id;
133 }
134 }
135
136 if (uistate.kbd_item == std::nullopt)
137 {
138 uistate.kbd_item = id;
139 }
140
141 if (uistate.kbd_item == id)
142 {
143 eu::render::Quad{
144 .tint = eu::colors::red_vermillion
145 }.draw(batch, rect.with_inset(eu::Lrtb{ -4 }).with_offset({8, -8}));
146 }
147
148 // shadow
149 eu::render::Quad{
150 .tint = eu::colors::black
151 }.draw(batch, rect.with_offset({8.0f, -8.0f}));
152
153 if (uistate.hot_item == id)
154 {
155 if (uistate.active_item == id)
156 {
157 // Button is both 'hot' and 'active'
158 eu::render::Quad{.tint = eu::colors::white}.draw(batch, rect.with_offset({ 2.0f, -2.0f }));
159 }
160 else
161 {
162 // Button is merely 'hot'
163 eu::render::Quad{ .tint = eu::colors::white }.draw(batch, rect);
164 }
165 }
166 else
167 {
168 // button is not hot, but it may be active
169 eu::render::Quad{ .tint = eu::colors::orange }.draw(batch, rect);
170 // todo(Gustav): add grays
171 }
172
173 // keyboard interaction
174 if (uistate.kbd_item == id)
175 {
176 if(uistate.key.has_value())
177 {
178 const auto k = *uistate.key;
179 uistate.key = std::nullopt;
180 switch (k.key)
181 {
182 case SDLK_TAB:
183 uistate.kbd_item = std::nullopt;
184 if (k.mod & KMOD_SHIFT)
185 uistate.kbd_item = uistate.last_widget;
186 break;
187 case SDLK_RETURN:
188 return true;
189 }
190 }
191 }
192
193 uistate.last_widget = id;
194
195 // If button is hot and active, but mouse button is not
196 // down, the user must have clicked the button.
197 if (uistate.mousedown == false &&
198 uistate.hot_item == id &&
199 uistate.active_item == id)
200 {
201 return true;
202 }
203
204 // Otherwise, no clicky.
205 return false;
206 }
207
208 bool slider(eu::u32 id, float* val, const eu::Rect& rect, UiState& uistate, eu::render::SpriteBatch* batch)
209 {
210 const auto grab_size = 16.0f;
211 const auto inner = rect.with_inset(eu::Lrtb{ 3.0f });
212 const auto avail = inner.get_size().x - grab_size;
213 const auto pos = avail * *val;
214
215 const auto grabber_rect = eu::Rect::from_size({ grab_size, inner.get_size().y }).with_bottom_left_at({ inner.left + pos, inner.bottom });
216
217 if (eu::is_within(uistate.mouse, inner))
218 {
219 uistate.hot_item = id;
220 if (uistate.is_active_free() && uistate.mousedown)
221 {
222 uistate.active_item = id;
223 }
224 }
225
226 if (uistate.kbd_item == std::nullopt)
227 {
228 uistate.kbd_item = id;
229 }
230
231 if (uistate.kbd_item == id)
232 {
233 eu::render::Quad{ .tint = eu::colors::red_vermillion }.draw(batch, rect.with_inset(eu::Lrtb{ -6 }));
234 }
235
236 eu::render::Quad{ .tint = eu::colors::orange }.draw(batch, rect);
237 eu::render::Quad{ .tint = uistate.active_item == id && uistate.hot_item == id ? eu::colors::white : eu::colors::green_bluish }.draw(batch, grabber_rect);
238 if (uistate.kbd_item == id)
239 {
240 if (uistate.key.has_value())
241 {
242 const auto k = *uistate.key;
243 uistate.key = std::nullopt;
244 constexpr float change = 0.1f;
245
246 switch (k.key)
247 {
248 case SDLK_TAB:
249 uistate.kbd_item = std::nullopt;
250 if (k.mod & KMOD_SHIFT)
251 {
252 uistate.kbd_item = uistate.last_widget;
253 }
254 break;
255 case SDLK_LEFT:
256 if (*val > 0)
257 {
258 *val = std::max(0.0f, *val - change);
259 return true;
260 }
261 break;
262 case SDLK_RIGHT:
263 if (*val < 1)
264 {
265 *val = std::min(1.0f, *val + change);
266 return true;
267 }
268 break;
269 }
270 }
271 }
272
273 uistate.last_widget = id;
274
275 if (uistate.active_item == id)
276 {
277 const auto new_range = eu::to_01(inner, uistate.mouse);
278 const auto new_value = eu::keep_within01(new_range.x);
279 if (*val != new_value)
280 {
281 *val = new_value;
282 return true;
283 }
284 }
285
286 return false;
287 }
288
289
290 void draw_text(eu::render::SpriteBatch* batch, eu::render::DrawableFont* font, const std::string& str, float size, const eu::v2& pos, const eu::Rgb& color)
291 {
292 eu::render::DrawableText text{ font };
293 text.set_text(str);
294 text.set_size(size);
295 text.compile();
296 text.draw(batch, pos, color, color);
297 }
298
299 bool textfield(eu::u32 id, std::string* val, eu::render::DrawableFont* font, float size, const eu::v2& pos, UiState& uistate, eu::render::SpriteBatch* batch)
300 {
301 // todo(Gustav): update to use stb textinput?
302
303 const auto len = val->length();
304 bool changed = false;
305
306 eu::render::DrawableText text{ font };
307 text.set_text(*val);
308 text.set_size(size);
309 text.compile();
310
311 const auto rect = text.get_extents().with_offset(pos).with_inset(eu::Lrtb{-6});
312
313 if (eu::is_within(uistate.mouse, rect))
314 {
315 uistate.hot_item = id;
316 if (uistate.active_item == std::nullopt && uistate.mousedown)
317 uistate.active_item = id;
318 }
319
320 if (uistate.kbd_item == std::nullopt)
321 uistate.kbd_item = id;
322
323 if (uistate.kbd_item == id)
324 {
325 eu::render::Quad{ .tint = eu::colors::red_vermillion }.draw(batch, rect.with_inset(eu::Lrtb{ -6 }));
326 }
327
328 if (uistate.active_item == id || uistate.hot_item == id)
329 {
330 eu::render::Quad{ .tint = eu::colors::white }.draw(batch, rect.with_inset(eu::Lrtb{ -6 }));
331 }
332 else
333 {
334 eu::render::Quad{ .tint = eu::colors::green_bluish }.draw(batch, rect.with_inset(eu::Lrtb{ -6 }));
335 }
336
337 text.draw(batch, pos, eu::colors::black, eu::colors::black);
338
339 const auto is_cursor_blink_visible = (SDL_GetTicks() >> 8) & 1;
340 if (uistate.kbd_item == id && is_cursor_blink_visible)
341 {
342 const auto cursor = eu::v2{ rect.right, pos.y };
343 draw_text(batch, font, "_", size, cursor, eu::colors::black);
344 }
345
346 if (uistate.kbd_item == id && uistate.key.has_value())
347 {
348 switch (uistate.key->key)
349 {
350 case SDLK_TAB:
351 uistate.kbd_item = std::nullopt;
352 if (uistate.key->mod & KMOD_SHIFT)
353 uistate.kbd_item = uistate.last_widget;
354 uistate.key = std::nullopt;
355 break;
356 case SDLK_BACKSPACE:
357 if (len > 0)
358 {
359 val->pop_back();
360 changed = true;
361 }
362 break;
363 }
364 if (uistate.keychar >= 32 && uistate.keychar < 127 && len < 30)
365 {
366 val->push_back(*uistate.keychar);
367 changed = true;
368 }
369 }
370
371 if (uistate.mousedown == false &&
372 uistate.hot_item == id &&
373 uistate.active_item == id)
374 uistate.kbd_item = id;
375
376 uistate.last_widget = id;
377
378 return changed;
379 }
380
381 eu::MemoryChunk chunk_from_embed(const embedded_binary& binary)
382 {
383 return { .bytes = reinterpret_cast<const char*>(binary.data), .size = binary.size };
384 }
385
386 int main(int, char**)
387 {
388 int window_width = 1280;
389 int window_height = 720;
390
391 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) < 0) {
392 LOG_ERR("Error initializing SDL: {}", SDL_GetError());
393 return -1;
394 }
395
396 #if 0
397 SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
398 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
399 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
400 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
401 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
402 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
403 #else
404 #if defined(__APPLE__)
405 // GL 3.2 Core + GLSL 150
406 const char* glsl_version = "#version 150";
407 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
408 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
409 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
410 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
411 #else
412 // GL 3.0 + GLSL 130
413 // const char* glsl_version = "#version 130";
414 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
415 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
416 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
417 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); // was 0 in dear imgui example??
418 #endif
419
420 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
421 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
422
423 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
424 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
425
426 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
427 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
428 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
429 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
430 #endif
431
432 SDL_Window* window = SDL_CreateWindow("Euphoria", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
433 window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE);
434 if (!window) {
435 LOG_ERR("Error creating window: {}", SDL_GetError());
436 return -1;
437 }
438
439 auto* glContext = SDL_GL_CreateContext(window);
440 SDL_GetWindowSize(window, &window_width, &window_height);
441 if (!glContext) {
442 LOG_ERR("Error creating gl context: {}", SDL_GetError());
443 return -1;
444 }
445
446 /* OpenGL setup */
447 const int glad_result = gladLoadGLLoader(SDL_GL_GetProcAddress);
448 if (glad_result == 0)
449 {
450 LOG_ERR("Failed to init glad, error: {0}", glad_result);
451 return -1;
452 }
453
454 {
455 const std::string gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
456 const std::string gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
457 const std::string gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
458 const std::string gl_shading_language_version = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
459
460 LOG_INFO("Vendor: {0}", gl_vendor);
461 LOG_INFO("Renderer: {0}", gl_renderer);
462 LOG_INFO("Version OpenGL: {0}", gl_version);
463 LOG_INFO("Version GLSL: {0}", gl_shading_language_version);
464 }
465
466 eu::render::OpenglStates states;
467 eu::render::Render2 render{ &states };
468
469 UiState uistate;
470 IdStack idstack;
471 eu::render::DrawableFont font{chunk_from_embed(OPENSANS_REGULAR_TTF)};
472
473 const auto sample_texture = eu::render::load_image_from_embedded(SEND_DEBUG_LABEL_MANY("uv-texture.png") UV_TEXTURE_PNG,
474 eu::render::TextureEdge::clamp, eu::render::TextureRenderStyle::linear, eu::render::Transparency::exclude, eu::render::ColorData::color_data);
475
476 bool running = true;
477 std::string editable_text = "Editable text";
478
479 LOG_INFO("Editor started");
480 while (running)
481 {
482 // events
483 SDL_Event e;
484 while (SDL_PollEvent(&e) != 0)
485 {
486 switch (e.type)
487 {
488 case SDL_MOUSEMOTION:
489 uistate.mouse = { static_cast<float>(e.motion.x), static_cast<float>(window_height - e.motion.y) };
490 break;
491 case SDL_MOUSEBUTTONDOWN:
492 if (e.button.button == 1)
493 {
494 uistate.mousedown = true;
495 }
496 break;
497 case SDL_MOUSEBUTTONUP:
498 if (e.button.button == 1)
499 {
500 uistate.mousedown = false;
501 }
502 break;
503 case SDL_WINDOWEVENT:
504 if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
505 {
506 LOG_INFO("Resized");
507 SDL_GetWindowSize(window, &window_width, &window_height);
508 }
509 break;
510 case SDL_KEYDOWN:
511 uistate.key = KeyboardInput {.key = e.key.keysym.sym, .mod = e.key.keysym.mod };
512 break;
513 case SDL_TEXTINPUT:
514 {
515 // todo(Gustav): handle unicode
516 char c = e.text.text[0];
517 if ((c & 0xFF80) == 0)
518 uistate.keychar = static_cast<char>(c & 0x7f);
519 }
520 break;
521 case SDL_QUIT: running = false; break;
522 default:
523 // ignore other events
524 break;
525 }
526 }
527
528 // render
529 {
530 eu::render::RenderCommand cmd {.states = &states, .render = &render, .size = {.width = window_width, .height = window_height} };
531
532 // todo(Gustav): provide a pixel layout
533 const auto screen = eu::render::LayoutData{ .style = eu::render::ViewportStyle::extended,
534 .requested_width = static_cast<float>(window_width), .requested_height = static_cast<float>(window_height) };
535
536 cmd.clear(eu::colors::blue_sky, screen);
537
538 auto layer = eu::render::with_layer2(cmd, screen);
539 eu::render::Quad{ .tint = eu::colors::green_bluish }.draw(layer.batch, layer.viewport_aabb_in_worldspace.get_bottom(50));
540
541 static eu::An rotation = eu::no_rotation;
542 static float slider_a = 0.5f;
543 static float slider_b = 0.5f;
544
545 eu::render::Quad{
546 .texture = &sample_texture,
547 // select bottom right of the texture, assuming it is split in 4 smaller rects
548 .texturecoord = eu::Rect::from_bottom_left_size({0.5f, 0}, {0.5f, 0.5f}),
549 .rotation = eu::render::RotateQuad{.angle = rotation, .center = {slider_a, slider_b} }
550 }.draw(layer.batch, eu::Rect::from_bottom_left_size({ 300, 300 }, { 300, 300 }));
551
552 const auto button_size = eu::v2{ 64, 64 };
553
554 uistate.begin();
555 if (button(idstack.get("a"), eu::Rect::from_bottom_left_size({ 100, 100 }, button_size), uistate, layer.batch))
556 {
557 rotation -= eu::An::from_degrees(15.0f);
558 }
559 if (button(idstack.get("b"), eu::Rect::from_bottom_left_size({ 200, 100 }, button_size), uistate, layer.batch))
560 {
561 rotation += eu::An::from_degrees(15.0f);
562 }
563 if (button(idstack.get("c"), eu::Rect::from_bottom_left_size({ 300, 100 }, button_size), uistate, layer.batch))
564 {
565 rotation = eu::no_rotation;
566 }
567 button(idstack.get("d"), eu::Rect::from_bottom_left_size({ 400, 100 }, button_size), uistate, layer.batch);
568
569 const auto slider_size = eu::v2{ 256, 25 };
570 slider(idstack.get("slider_a"), &slider_a, eu::Rect::from_bottom_left_size({ 100, 200 }, slider_size), uistate, layer.batch);
571 slider(idstack.get("slider_b"), &slider_b, eu::Rect::from_bottom_left_size({ 100, 250 }, slider_size), uistate, layer.batch);
572 textfield(idstack.get("textfield"), &editable_text, &font, 20, {100, 300}, uistate, layer.batch);
573 uistate.end();
574
575 draw_text(layer.batch, &font, "Hello world", 60, {200, 400 + 200}, eu::colors::black);
576 }
577 SDL_GL_SwapWindow(window);
578 }
579
580 LOG_INFO("Shutting down");
581 SDL_GL_DeleteContext(glContext);
582 SDL_DestroyWindow(window);
583 SDL_Quit();
584
585 return 0;
586 }
587
588 #else
589
590 #include "dependency_nuklear.h"
591 #include "dependency_nuklear_impl.h"
592
593
594 constexpr int MAX_VERTEX_MEMORY = 512 * 1024;
595 constexpr int MAX_ELEMENT_MEMORY = 128 * 1024;
596
597 /* This are some code examples to provide a small overview of what can be
598 * done with this library. To try out an example uncomment the defines */
599 #define INCLUDE_ALL
600 // #define INCLUDE_STYLE
601 // #define INCLUDE_CALCULATOR
602 // #define INCLUDE_CANVAS
603 #define INCLUDE_OVERVIEW
604 // #define INCLUDE_CONFIGURATOR
605 // #define INCLUDE_NODE_EDITOR
606
607 #ifdef INCLUDE_ALL
608 #define INCLUDE_STYLE
609 #define INCLUDE_CALCULATOR
610 #define INCLUDE_CANVAS
611 #define INCLUDE_OVERVIEW
612 #define INCLUDE_CONFIGURATOR
613 #define INCLUDE_NODE_EDITOR
614 #endif
615
616 #define NK_ASSERT(expr) assert(expr)
617 constexpr nk_color nk_white = { 255,255,255,255 };
618
619 #define LEN(a) (sizeof(a)/sizeof(a)[0])
620
621 #define NK_COLOR_MAP(NK_COLOR)\
622 NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
623 NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
624 NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
625 NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
626 NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
627 NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
628 NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
629 NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
630 NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
631 NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
632 NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
633 NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
634 NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
635 NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
636 NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
637 NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
638 NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
639 NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
640 NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
641 NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
642 NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
643 NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
644 NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \
645 NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
646 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
647 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \
648 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \
649 NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) \
650 NK_COLOR(NK_COLOR_KNOB, 38, 38, 38, 255) \
651 NK_COLOR(NK_COLOR_KNOB_CURSOR, 100,100,100,255) \
652 NK_COLOR(NK_COLOR_KNOB_CURSOR_HOVER, 120,120,120,255) \
653 NK_COLOR(NK_COLOR_KNOB_CURSOR_ACTIVE, 150,150,150,255)
654
655 NK_GLOBAL const struct nk_color
656 nk_default_color_style[NK_COLOR_COUNT] = {
657 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
658 NK_COLOR_MAP(NK_COLOR)
659 #undef NK_COLOR
660 };
661
662 #ifdef INCLUDE_STYLE
663 #include "demo/style.c"
664 #endif
665 #ifdef INCLUDE_CALCULATOR
666 #include "demo/calculator.c"
667 #endif
668 #ifdef INCLUDE_CANVAS
669 #include "demo/canvas.c"
670 #endif
671 #ifdef INCLUDE_OVERVIEW
672 #include "demo/overview.c"
673 #endif
674 #ifdef INCLUDE_CONFIGURATOR
675 #include "demo/style_configurator.c"
676 #endif
677 #ifdef INCLUDE_NODE_EDITOR
678 #include "demo/node_editor.c"
679 #endif
680
681 struct media {
682 GLint skin;
683 struct nk_image menu;
684 struct nk_image check;
685 struct nk_image check_cursor;
686 struct nk_image option;
687 struct nk_image option_cursor;
688 struct nk_image header;
689 struct nk_image window;
690 struct nk_image scrollbar_inc_button;
691 struct nk_image scrollbar_inc_button_hover;
692 struct nk_image scrollbar_dec_button;
693 struct nk_image scrollbar_dec_button_hover;
694 struct nk_image button;
695 struct nk_image button_hover;
696 struct nk_image button_active;
697 struct nk_image tab_minimize;
698 struct nk_image tab_maximize;
699 struct nk_image slider;
700 struct nk_image slider_hover;
701 struct nk_image slider_active;
702 };
703
704
705 static GLuint
706 image_load(const char* filename)
707 {
708 int x, y, n;
709 GLuint tex;
710 unsigned char* data = stbi_load(filename, &x, &y, &n, 0);
711 if (!data)
712 {
713 LOG_ERR("failed to load image: {}", filename);
714 std::exit(-1);
715 }
716
717 glGenTextures(1, &tex);
718 glBindTexture(GL_TEXTURE_2D, tex);
719 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
720 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
721 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
722 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
723 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
724 glGenerateMipmap(GL_TEXTURE_2D);
725 stbi_image_free(data);
726 return tex;
727 }
728
729 /* ===============================================================
730 *
731 * DEMO
732 *
733 * ===============================================================*/
734 int main(int, char **)
735 {
736 int window_width = 1280;
737 int window_height = 720;
738
739 SDL_Window *win;
740 SDL_GLContext glContext;
741 int win_width, win_height;
742 bool running = true;
743
744 /* GUI */
745 struct nk_context *ctx;
746 struct nk_colorf bg;
747 struct media media;
748
749 #ifdef INCLUDE_CONFIGURATOR
750 static struct nk_color color_table[NK_COLOR_COUNT];
751 memcpy(color_table, nk_default_color_style, sizeof(color_table));
752 #endif
753
754 /* SDL setup */
755 SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
756 SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS);
757 SDL_GL_SetAttribute (SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
758 SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
759 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
760 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
761 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
762 win = SDL_CreateWindow("Demo",
763 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
764 window_width, window_height, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI);
765 glContext = SDL_GL_CreateContext(win);
766 SDL_GetWindowSize(win, &win_width, &win_height);
767
768 /* OpenGL setup */
769 const int glad_result = gladLoadGLLoader(SDL_GL_GetProcAddress);
770 if (glad_result == 0)
771 {
772 LOG_ERR("Failed to init glad, error: {0}", glad_result);
773 return -1;
774 }
775
776 {
777 const std::string gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
778 const std::string gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
779 const std::string gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
780 const std::string gl_shading_language_version = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
781
782 LOG_INFO("Vendor: {0}", gl_vendor);
783 LOG_INFO("Renderer: {0}", gl_renderer);
784 LOG_INFO("Version OpenGL: {0}", gl_version);
785 LOG_INFO("Version GLSL: {0}", gl_shading_language_version);
786 }
787 glViewport(0, 0, window_width, window_height);
788
789 ctx = nk_sdl_init(win);
790 /* Load Fonts: if none of these are loaded a default font will be used */
791 /* Load Cursor: if you uncomment cursor loading please hide the cursor */
792 {struct nk_font_atlas *atlas;
793 nk_sdl_font_stash_begin(&atlas);
794 /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/
795 /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 16, 0);*/
796 /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/
797 /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/
798 /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/
799 /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/
800 nk_sdl_font_stash_end();
801 /*nk_style_load_all_cursors(ctx, atlas->cursors);*/
802 /*nk_style_set_font(ctx, &roboto->handle);*/}
803
804 /* style.c */
805 #ifdef INCLUDE_STYLE
806 /* ease regression testing during Nuklear release process; not needed for anything else */
807 #ifdef STYLE_WHITE
808 set_style(ctx, THEME_WHITE);
809 #elif defined(STYLE_RED)
810 set_style(ctx, THEME_RED);
811 #elif defined(STYLE_BLUE)
812 set_style(ctx, THEME_BLUE);
813 #elif defined(STYLE_DARK)
814 set_style(ctx, THEME_DARK);
815 #endif
816 #endif
817
818 bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
819
820 { /* skin */
821 glEnable(GL_TEXTURE_2D);
822 media.skin = image_load("../skins/gwen.png");
823 media.check = nk_subimage_id(media.skin, 512, 512, nk_rect(464, 32, 15, 15));
824 media.check_cursor = nk_subimage_id(media.skin, 512, 512, nk_rect(450, 34, 11, 11));
825 media.option = nk_subimage_id(media.skin, 512, 512, nk_rect(464, 64, 15, 15));
826 media.option_cursor = nk_subimage_id(media.skin, 512, 512, nk_rect(451, 67, 9, 9));
827 media.header = nk_subimage_id(media.skin, 512, 512, nk_rect(128, 0, 127, 24));
828 media.window = nk_subimage_id(media.skin, 512, 512, nk_rect(128, 23, 127, 104));
829 media.scrollbar_inc_button = nk_subimage_id(media.skin, 512, 512, nk_rect(464, 256, 15, 15));
830 media.scrollbar_inc_button_hover = nk_subimage_id(media.skin, 512, 512, nk_rect(464, 320, 15, 15));
831 media.scrollbar_dec_button = nk_subimage_id(media.skin, 512, 512, nk_rect(464, 224, 15, 15));
832 media.scrollbar_dec_button_hover = nk_subimage_id(media.skin, 512, 512, nk_rect(464, 288, 15, 15));
833 media.button = nk_subimage_id(media.skin, 512, 512, nk_rect(384, 336, 127, 31));
834 media.button_hover = nk_subimage_id(media.skin, 512, 512, nk_rect(384, 368, 127, 31));
835 media.button_active = nk_subimage_id(media.skin, 512, 512, nk_rect(384, 400, 127, 31));
836 media.tab_minimize = nk_subimage_id(media.skin, 512, 512, nk_rect(451, 99, 9, 9));
837 media.tab_maximize = nk_subimage_id(media.skin, 512, 512, nk_rect(467, 99, 9, 9));
838 media.slider = nk_subimage_id(media.skin, 512, 512, nk_rect(418, 33, 11, 14));
839 media.slider_hover = nk_subimage_id(media.skin, 512, 512, nk_rect(418, 49, 11, 14));
840 media.slider_active = nk_subimage_id(media.skin, 512, 512, nk_rect(418, 64, 11, 14));
841
842 /* window */
843 ctx->style.window.background = nk_rgb(204, 204, 204);
844 ctx->style.window.fixed_background = nk_style_item_image(media.window);
845 ctx->style.window.border_color = nk_rgb(67, 67, 67);
846 ctx->style.window.combo_border_color = nk_rgb(67, 67, 67);
847 ctx->style.window.contextual_border_color = nk_rgb(67, 67, 67);
848 ctx->style.window.menu_border_color = nk_rgb(67, 67, 67);
849 ctx->style.window.group_border_color = nk_rgb(67, 67, 67);
850 ctx->style.window.tooltip_border_color = nk_rgb(67, 67, 67);
851 ctx->style.window.scrollbar_size = nk_vec2(16, 16);
852 ctx->style.window.border_color = nk_rgba(0, 0, 0, 0);
853 ctx->style.window.padding = nk_vec2(8, 4);
854 ctx->style.window.border = 3;
855
856 /* window header */
857 ctx->style.window.header.normal = nk_style_item_image(media.header);
858 ctx->style.window.header.hover = nk_style_item_image(media.header);
859 ctx->style.window.header.active = nk_style_item_image(media.header);
860 ctx->style.window.header.label_normal = nk_rgb(95, 95, 95);
861 ctx->style.window.header.label_hover = nk_rgb(95, 95, 95);
862 ctx->style.window.header.label_active = nk_rgb(95, 95, 95);
863
864 /* scrollbar */
865 ctx->style.scrollv.normal = nk_style_item_color(nk_rgb(184, 184, 184));
866 ctx->style.scrollv.hover = nk_style_item_color(nk_rgb(184, 184, 184));
867 ctx->style.scrollv.active = nk_style_item_color(nk_rgb(184, 184, 184));
868 ctx->style.scrollv.cursor_normal = nk_style_item_color(nk_rgb(220, 220, 220));
869 ctx->style.scrollv.cursor_hover = nk_style_item_color(nk_rgb(235, 235, 235));
870 ctx->style.scrollv.cursor_active = nk_style_item_color(nk_rgb(99, 202, 255));
871 ctx->style.scrollv.dec_symbol = NK_SYMBOL_NONE;
872 ctx->style.scrollv.inc_symbol = NK_SYMBOL_NONE;
873 ctx->style.scrollv.show_buttons = nk_true;
874 ctx->style.scrollv.border_color = nk_rgb(81, 81, 81);
875 ctx->style.scrollv.cursor_border_color = nk_rgb(81, 81, 81);
876 ctx->style.scrollv.border = 1;
877 ctx->style.scrollv.rounding = 0;
878 ctx->style.scrollv.border_cursor = 1;
879 ctx->style.scrollv.rounding_cursor = 2;
880
881 /* scrollbar buttons */
882 ctx->style.scrollv.inc_button.normal = nk_style_item_image(media.scrollbar_inc_button);
883 ctx->style.scrollv.inc_button.hover = nk_style_item_image(media.scrollbar_inc_button_hover);
884 ctx->style.scrollv.inc_button.active = nk_style_item_image(media.scrollbar_inc_button_hover);
885 ctx->style.scrollv.inc_button.border_color = nk_rgba(0, 0, 0, 0);
886 ctx->style.scrollv.inc_button.text_background = nk_rgba(0, 0, 0, 0);
887 ctx->style.scrollv.inc_button.text_normal = nk_rgba(0, 0, 0, 0);
888 ctx->style.scrollv.inc_button.text_hover = nk_rgba(0, 0, 0, 0);
889 ctx->style.scrollv.inc_button.text_active = nk_rgba(0, 0, 0, 0);
890 ctx->style.scrollv.inc_button.border = 0.0f;
891
892 ctx->style.scrollv.dec_button.normal = nk_style_item_image(media.scrollbar_dec_button);
893 ctx->style.scrollv.dec_button.hover = nk_style_item_image(media.scrollbar_dec_button_hover);
894 ctx->style.scrollv.dec_button.active = nk_style_item_image(media.scrollbar_dec_button_hover);
895 ctx->style.scrollv.dec_button.border_color = nk_rgba(0, 0, 0, 0);
896 ctx->style.scrollv.dec_button.text_background = nk_rgba(0, 0, 0, 0);
897 ctx->style.scrollv.dec_button.text_normal = nk_rgba(0, 0, 0, 0);
898 ctx->style.scrollv.dec_button.text_hover = nk_rgba(0, 0, 0, 0);
899 ctx->style.scrollv.dec_button.text_active = nk_rgba(0, 0, 0, 0);
900 ctx->style.scrollv.dec_button.border = 0.0f;
901
902 /* checkbox toggle */
903 {
904 struct nk_style_toggle* toggle;
905 toggle = &ctx->style.checkbox;
906 toggle->normal = nk_style_item_image(media.check);
907 toggle->hover = nk_style_item_image(media.check);
908 toggle->active = nk_style_item_image(media.check);
909 toggle->cursor_normal = nk_style_item_image(media.check_cursor);
910 toggle->cursor_hover = nk_style_item_image(media.check_cursor);
911 toggle->text_normal = nk_rgb(95, 95, 95);
912 toggle->text_hover = nk_rgb(95, 95, 95);
913 toggle->text_active = nk_rgb(95, 95, 95);
914 }
915
916 /* option toggle */
917 {
918 struct nk_style_toggle* toggle;
919 toggle = &ctx->style.option;
920 toggle->normal = nk_style_item_image(media.option);
921 toggle->hover = nk_style_item_image(media.option);
922 toggle->active = nk_style_item_image(media.option);
923 toggle->cursor_normal = nk_style_item_image(media.option_cursor);
924 toggle->cursor_hover = nk_style_item_image(media.option_cursor);
925 toggle->text_normal = nk_rgb(95, 95, 95);
926 toggle->text_hover = nk_rgb(95, 95, 95);
927 toggle->text_active = nk_rgb(95, 95, 95);
928 }
929
930 /* default button */
931 ctx->style.button.normal = nk_style_item_image(media.button);
932 ctx->style.button.hover = nk_style_item_image(media.button_hover);
933 ctx->style.button.active = nk_style_item_image(media.button_active);
934 ctx->style.button.border_color = nk_rgba(0, 0, 0, 0);
935 ctx->style.button.text_background = nk_rgba(0, 0, 0, 0);
936 ctx->style.button.text_normal = nk_rgb(95, 95, 95);
937 ctx->style.button.text_hover = nk_rgb(95, 95, 95);
938 ctx->style.button.text_active = nk_rgb(95, 95, 95);
939
940 /* default text */
941 ctx->style.text.color = nk_rgb(95, 95, 95);
942
943 /* contextual button */
944 ctx->style.contextual_button.normal = nk_style_item_color(nk_rgb(206, 206, 206));
945 ctx->style.contextual_button.hover = nk_style_item_color(nk_rgb(229, 229, 229));
946 ctx->style.contextual_button.active = nk_style_item_color(nk_rgb(99, 202, 255));
947 ctx->style.contextual_button.border_color = nk_rgba(0, 0, 0, 0);
948 ctx->style.contextual_button.text_background = nk_rgba(0, 0, 0, 0);
949 ctx->style.contextual_button.text_normal = nk_rgb(95, 95, 95);
950 ctx->style.contextual_button.text_hover = nk_rgb(95, 95, 95);
951 ctx->style.contextual_button.text_active = nk_rgb(95, 95, 95);
952
953 /* menu button */
954 ctx->style.menu_button.normal = nk_style_item_color(nk_rgb(206, 206, 206));
955 ctx->style.menu_button.hover = nk_style_item_color(nk_rgb(229, 229, 229));
956 ctx->style.menu_button.active = nk_style_item_color(nk_rgb(99, 202, 255));
957 ctx->style.menu_button.border_color = nk_rgba(0, 0, 0, 0);
958 ctx->style.menu_button.text_background = nk_rgba(0, 0, 0, 0);
959 ctx->style.menu_button.text_normal = nk_rgb(95, 95, 95);
960 ctx->style.menu_button.text_hover = nk_rgb(95, 95, 95);
961 ctx->style.menu_button.text_active = nk_rgb(95, 95, 95);
962
963 /* tree */
964 ctx->style.tab.text = nk_rgb(95, 95, 95);
965 ctx->style.tab.tab_minimize_button.normal = nk_style_item_image(media.tab_minimize);
966 ctx->style.tab.tab_minimize_button.hover = nk_style_item_image(media.tab_minimize);
967 ctx->style.tab.tab_minimize_button.active = nk_style_item_image(media.tab_minimize);
968 ctx->style.tab.tab_minimize_button.text_background = nk_rgba(0, 0, 0, 0);
969 ctx->style.tab.tab_minimize_button.text_normal = nk_rgba(0, 0, 0, 0);
970 ctx->style.tab.tab_minimize_button.text_hover = nk_rgba(0, 0, 0, 0);
971 ctx->style.tab.tab_minimize_button.text_active = nk_rgba(0, 0, 0, 0);
972
973 ctx->style.tab.tab_maximize_button.normal = nk_style_item_image(media.tab_maximize);
974 ctx->style.tab.tab_maximize_button.hover = nk_style_item_image(media.tab_maximize);
975 ctx->style.tab.tab_maximize_button.active = nk_style_item_image(media.tab_maximize);
976 ctx->style.tab.tab_maximize_button.text_background = nk_rgba(0, 0, 0, 0);
977 ctx->style.tab.tab_maximize_button.text_normal = nk_rgba(0, 0, 0, 0);
978 ctx->style.tab.tab_maximize_button.text_hover = nk_rgba(0, 0, 0, 0);
979 ctx->style.tab.tab_maximize_button.text_active = nk_rgba(0, 0, 0, 0);
980
981 ctx->style.tab.node_minimize_button.normal = nk_style_item_image(media.tab_minimize);
982 ctx->style.tab.node_minimize_button.hover = nk_style_item_image(media.tab_minimize);
983 ctx->style.tab.node_minimize_button.active = nk_style_item_image(media.tab_minimize);
984 ctx->style.tab.node_minimize_button.text_background = nk_rgba(0, 0, 0, 0);
985 ctx->style.tab.node_minimize_button.text_normal = nk_rgba(0, 0, 0, 0);
986 ctx->style.tab.node_minimize_button.text_hover = nk_rgba(0, 0, 0, 0);
987 ctx->style.tab.node_minimize_button.text_active = nk_rgba(0, 0, 0, 0);
988
989 ctx->style.tab.node_maximize_button.normal = nk_style_item_image(media.tab_maximize);
990 ctx->style.tab.node_maximize_button.hover = nk_style_item_image(media.tab_maximize);
991 ctx->style.tab.node_maximize_button.active = nk_style_item_image(media.tab_maximize);
992 ctx->style.tab.node_maximize_button.text_background = nk_rgba(0, 0, 0, 0);
993 ctx->style.tab.node_maximize_button.text_normal = nk_rgba(0, 0, 0, 0);
994 ctx->style.tab.node_maximize_button.text_hover = nk_rgba(0, 0, 0, 0);
995 ctx->style.tab.node_maximize_button.text_active = nk_rgba(0, 0, 0, 0);
996
997 /* selectable */
998 ctx->style.selectable.normal = nk_style_item_color(nk_rgb(206, 206, 206));
999 ctx->style.selectable.hover = nk_style_item_color(nk_rgb(206, 206, 206));
1000 ctx->style.selectable.pressed = nk_style_item_color(nk_rgb(206, 206, 206));
1001 ctx->style.selectable.normal_active = nk_style_item_color(nk_rgb(185, 205, 248));
1002 ctx->style.selectable.hover_active = nk_style_item_color(nk_rgb(185, 205, 248));
1003 ctx->style.selectable.pressed_active = nk_style_item_color(nk_rgb(185, 205, 248));
1004 ctx->style.selectable.text_normal = nk_rgb(95, 95, 95);
1005 ctx->style.selectable.text_hover = nk_rgb(95, 95, 95);
1006 ctx->style.selectable.text_pressed = nk_rgb(95, 95, 95);
1007 ctx->style.selectable.text_normal_active = nk_rgb(95, 95, 95);
1008 ctx->style.selectable.text_hover_active = nk_rgb(95, 95, 95);
1009 ctx->style.selectable.text_pressed_active = nk_rgb(95, 95, 95);
1010
1011 /* slider */
1012 ctx->style.slider.normal = nk_style_item_hide();
1013 ctx->style.slider.hover = nk_style_item_hide();
1014 ctx->style.slider.active = nk_style_item_hide();
1015 ctx->style.slider.bar_normal = nk_rgb(156, 156, 156);
1016 ctx->style.slider.bar_hover = nk_rgb(156, 156, 156);
1017 ctx->style.slider.bar_active = nk_rgb(156, 156, 156);
1018 ctx->style.slider.bar_filled = nk_rgb(156, 156, 156);
1019 ctx->style.slider.cursor_normal = nk_style_item_image(media.slider);
1020 ctx->style.slider.cursor_hover = nk_style_item_image(media.slider_hover);
1021 ctx->style.slider.cursor_active = nk_style_item_image(media.slider_active);
1022 ctx->style.slider.cursor_size = nk_vec2(16.5f, 21);
1023 ctx->style.slider.bar_height = 1;
1024
1025 /* progressbar */
1026 ctx->style.progress.normal = nk_style_item_color(nk_rgb(231, 231, 231));
1027 ctx->style.progress.hover = nk_style_item_color(nk_rgb(231, 231, 231));
1028 ctx->style.progress.active = nk_style_item_color(nk_rgb(231, 231, 231));
1029 ctx->style.progress.cursor_normal = nk_style_item_color(nk_rgb(63, 242, 93));
1030 ctx->style.progress.cursor_hover = nk_style_item_color(nk_rgb(63, 242, 93));
1031 ctx->style.progress.cursor_active = nk_style_item_color(nk_rgb(63, 242, 93));
1032 ctx->style.progress.border_color = nk_rgb(114, 116, 115);
1033 ctx->style.progress.padding = nk_vec2(0, 0);
1034 ctx->style.progress.border = 2;
1035 ctx->style.progress.rounding = 1;
1036
1037 /* combo */
1038 ctx->style.combo.normal = nk_style_item_color(nk_rgb(216, 216, 216));
1039 ctx->style.combo.hover = nk_style_item_color(nk_rgb(216, 216, 216));
1040 ctx->style.combo.active = nk_style_item_color(nk_rgb(216, 216, 216));
1041 ctx->style.combo.border_color = nk_rgb(95, 95, 95);
1042 ctx->style.combo.label_normal = nk_rgb(95, 95, 95);
1043 ctx->style.combo.label_hover = nk_rgb(95, 95, 95);
1044 ctx->style.combo.label_active = nk_rgb(95, 95, 95);
1045 ctx->style.combo.border = 1;
1046 ctx->style.combo.rounding = 1;
1047
1048 /* combo button */
1049 ctx->style.combo.button.normal = nk_style_item_color(nk_rgb(216, 216, 216));
1050 ctx->style.combo.button.hover = nk_style_item_color(nk_rgb(216, 216, 216));
1051 ctx->style.combo.button.active = nk_style_item_color(nk_rgb(216, 216, 216));
1052 ctx->style.combo.button.text_background = nk_rgb(216, 216, 216);
1053 ctx->style.combo.button.text_normal = nk_rgb(95, 95, 95);
1054 ctx->style.combo.button.text_hover = nk_rgb(95, 95, 95);
1055 ctx->style.combo.button.text_active = nk_rgb(95, 95, 95);
1056
1057 /* property */
1058 ctx->style.property.normal = nk_style_item_color(nk_rgb(216, 216, 216));
1059 ctx->style.property.hover = nk_style_item_color(nk_rgb(216, 216, 216));
1060 ctx->style.property.active = nk_style_item_color(nk_rgb(216, 216, 216));
1061 ctx->style.property.border_color = nk_rgb(81, 81, 81);
1062 ctx->style.property.label_normal = nk_rgb(95, 95, 95);
1063 ctx->style.property.label_hover = nk_rgb(95, 95, 95);
1064 ctx->style.property.label_active = nk_rgb(95, 95, 95);
1065 ctx->style.property.sym_left = NK_SYMBOL_TRIANGLE_LEFT;
1066 ctx->style.property.sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
1067 ctx->style.property.rounding = 10;
1068 ctx->style.property.border = 1;
1069
1070 /* edit */
1071 ctx->style.edit.normal = nk_style_item_color(nk_rgb(240, 240, 240));
1072 ctx->style.edit.hover = nk_style_item_color(nk_rgb(240, 240, 240));
1073 ctx->style.edit.active = nk_style_item_color(nk_rgb(240, 240, 240));
1074 ctx->style.edit.border_color = nk_rgb(62, 62, 62);
1075 ctx->style.edit.cursor_normal = nk_rgb(99, 202, 255);
1076 ctx->style.edit.cursor_hover = nk_rgb(99, 202, 255);
1077 ctx->style.edit.cursor_text_normal = nk_rgb(95, 95, 95);
1078 ctx->style.edit.cursor_text_hover = nk_rgb(95, 95, 95);
1079 ctx->style.edit.text_normal = nk_rgb(95, 95, 95);
1080 ctx->style.edit.text_hover = nk_rgb(95, 95, 95);
1081 ctx->style.edit.text_active = nk_rgb(95, 95, 95);
1082 ctx->style.edit.selected_normal = nk_rgb(99, 202, 255);
1083 ctx->style.edit.selected_hover = nk_rgb(99, 202, 255);
1084 ctx->style.edit.selected_text_normal = nk_rgb(95, 95, 95);
1085 ctx->style.edit.selected_text_hover = nk_rgb(95, 95, 95);
1086 ctx->style.edit.border = 1;
1087 ctx->style.edit.rounding = 2;
1088
1089 /* property buttons */
1090 ctx->style.property.dec_button.normal = nk_style_item_color(nk_rgb(216, 216, 216));
1091 ctx->style.property.dec_button.hover = nk_style_item_color(nk_rgb(216, 216, 216));
1092 ctx->style.property.dec_button.active = nk_style_item_color(nk_rgb(216, 216, 216));
1093 ctx->style.property.dec_button.text_background = nk_rgba(0, 0, 0, 0);
1094 ctx->style.property.dec_button.text_normal = nk_rgb(95, 95, 95);
1095 ctx->style.property.dec_button.text_hover = nk_rgb(95, 95, 95);
1096 ctx->style.property.dec_button.text_active = nk_rgb(95, 95, 95);
1097 ctx->style.property.inc_button = ctx->style.property.dec_button;
1098
1099 /* property edit */
1100 ctx->style.property.edit.normal = nk_style_item_color(nk_rgb(216, 216, 216));
1101 ctx->style.property.edit.hover = nk_style_item_color(nk_rgb(216, 216, 216));
1102 ctx->style.property.edit.active = nk_style_item_color(nk_rgb(216, 216, 216));
1103 ctx->style.property.edit.border_color = nk_rgba(0, 0, 0, 0);
1104 ctx->style.property.edit.cursor_normal = nk_rgb(95, 95, 95);
1105 ctx->style.property.edit.cursor_hover = nk_rgb(95, 95, 95);
1106 ctx->style.property.edit.cursor_text_normal = nk_rgb(216, 216, 216);
1107 ctx->style.property.edit.cursor_text_hover = nk_rgb(216, 216, 216);
1108 ctx->style.property.edit.text_normal = nk_rgb(95, 95, 95);
1109 ctx->style.property.edit.text_hover = nk_rgb(95, 95, 95);
1110 ctx->style.property.edit.text_active = nk_rgb(95, 95, 95);
1111 ctx->style.property.edit.selected_normal = nk_rgb(95, 95, 95);
1112 ctx->style.property.edit.selected_hover = nk_rgb(95, 95, 95);
1113 ctx->style.property.edit.selected_text_normal = nk_rgb(216, 216, 216);
1114 ctx->style.property.edit.selected_text_hover = nk_rgb(216, 216, 216);
1115
1116 /* chart */
1117 ctx->style.chart.background = nk_style_item_color(nk_rgb(216, 216, 216));
1118 ctx->style.chart.border_color = nk_rgb(81, 81, 81);
1119 ctx->style.chart.color = nk_rgb(95, 95, 95);
1120 ctx->style.chart.selected_color = nk_rgb(255, 0, 0);
1121 ctx->style.chart.border = 1;
1122 }
1123
1124 while (running)
1125 {
1126 /* Input */
1127 SDL_Event evt;
1128 nk_input_begin(ctx);
1129 while (SDL_PollEvent(&evt)) {
1130 if (evt.type == SDL_QUIT) running = false;
1131 nk_sdl_handle_event(&evt);
1132 }
1133 nk_sdl_handle_grab(); /* optional grabbing behavior */
1134 nk_input_end(ctx);
1135
1136 // Skinning gui demo
1137 if (nk_begin(ctx, "Demo", nk_rect(50, 50, 300, 400),
1138 NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_TITLE))
1139 {
1140 int i;
1141 float id;
1142 static int slider = 10;
1143 static int field_len;
1144 static nk_size prog_value = 60;
1145 static int current_weapon = 0;
1146 static char field_buffer[64];
1147 static float pos;
1148 static const char* weapons[] = { "Fist","Pistol","Shotgun","Plasma","BFG" };
1149 const float step = (2 * 3.141592654f) / 32;
1150
1151 nk_layout_row_static(ctx, 30, 120, 1);
1152 if (nk_button_label(ctx, "button"))
1153 fprintf(stdout, "button pressed\n");
1154
1155 nk_layout_row_dynamic(ctx, 20, 1);
1156 nk_label(ctx, "Label", NK_TEXT_LEFT);
1157 nk_layout_row_dynamic(ctx, 30, 2);
1158 nk_check_label(ctx, "inactive", 0);
1159 nk_check_label(ctx, "active", 1);
1160 nk_option_label(ctx, "active", 1);
1161 nk_option_label(ctx, "inactive", 0);
1162
1163 nk_layout_row_dynamic(ctx, 30, 1);
1164 nk_slider_int(ctx, 0, &slider, 16, 1);
1165 nk_layout_row_dynamic(ctx, 20, 1);
1166 nk_progress(ctx, &prog_value, 100, NK_MODIFIABLE);
1167
1168 nk_layout_row_dynamic(ctx, 25, 1);
1169 nk_edit_string(ctx, NK_EDIT_FIELD, field_buffer, &field_len, 64, nk_filter_default);
1170 nk_property_float(ctx, "#X:", -1024.0f, &pos, 1024.0f, 1, 1);
1171 current_weapon = nk_combo(ctx, weapons, LEN(weapons), current_weapon, 25, nk_vec2(nk_widget_width(ctx), 200));
1172
1173 nk_layout_row_dynamic(ctx, 100, 1);
1174 if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255, 0, 0), nk_rgb(150, 0, 0), 32, 0.0f, 1.0f)) {
1175 nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0, 0, 255), nk_rgb(0, 0, 150), 32, -1.0f, 1.0f);
1176 nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0, 255, 0), nk_rgb(0, 150, 0), 32, -1.0f, 1.0f);
1177 for (id = 0, i = 0; i < 32; ++i) {
1178 nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0);
1179 nk_chart_push_slot(ctx, (float)cos(id), 1);
1180 nk_chart_push_slot(ctx, (float)sin(id), 2);
1181 id += step;
1182 }
1183 }
1184 nk_chart_end(ctx);
1185
1186 nk_layout_row_dynamic(ctx, 250, 1);
1187 if (nk_group_begin(ctx, "Standard", NK_WINDOW_BORDER | NK_WINDOW_BORDER))
1188 {
1189 if (nk_tree_push(ctx, NK_TREE_NODE, "Window", NK_MAXIMIZED)) {
1190 static int selected[8];
1191 if (nk_tree_push(ctx, NK_TREE_NODE, "Next", NK_MAXIMIZED)) {
1192 nk_layout_row_dynamic(ctx, 20, 1);
1193 for (i = 0; i < 4; ++i)
1194 nk_selectable_label(ctx, (selected[i]) ? "Selected" : "Unselected", NK_TEXT_LEFT, &selected[i]);
1195 nk_tree_pop(ctx);
1196 }
1197 if (nk_tree_push(ctx, NK_TREE_NODE, "Previous", NK_MAXIMIZED)) {
1198 nk_layout_row_dynamic(ctx, 20, 1);
1199 for (i = 4; i < 8; ++i)
1200 nk_selectable_label(ctx, (selected[i]) ? "Selected" : "Unselected", NK_TEXT_LEFT, &selected[i]);
1201 nk_tree_pop(ctx);
1202 }
1203 nk_tree_pop(ctx);
1204 }
1205 nk_group_end(ctx);
1206 }
1207 }
1208 nk_end(ctx);
1209
1210 // Old gui demo
1211 /* GUI */
1212 if (nk_begin(ctx, "Demo 2", nk_rect(50, 50, 230, 250),
1213 NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE |
1214 NK_WINDOW_MINIMIZABLE | NK_WINDOW_TITLE))
1215 {
1216 enum { EASY, HARD };
1217 static int op = EASY;
1218 static int property = 20;
1219
1220 nk_layout_row_static(ctx, 30, 80, 1);
1221 if (nk_button_label(ctx, "button"))
1222 printf("button pressed!\n");
1223 nk_layout_row_dynamic(ctx, 30, 2);
1224 if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
1225 if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
1226 nk_layout_row_dynamic(ctx, 22, 1);
1227 nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
1228
1229 nk_layout_row_dynamic(ctx, 20, 1);
1230 nk_label(ctx, "background:", NK_TEXT_LEFT);
1231 nk_layout_row_dynamic(ctx, 25, 1);
1232 if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx), 400))) {
1233 nk_layout_row_dynamic(ctx, 120, 1);
1234 bg = nk_color_picker(ctx, bg, NK_RGBA);
1235 nk_layout_row_dynamic(ctx, 25, 1);
1236 bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f, 0.005f);
1237 bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f, 0.005f);
1238 bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f, 0.005f);
1239 bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f, 0.005f);
1240 nk_combo_end(ctx);
1241 }
1242 }
1243 nk_end(ctx);
1244
1245 /* -------------- EXAMPLES ---------------- */
1246 #ifdef INCLUDE_CALCULATOR
1247 calculator(ctx);
1248 #endif
1249
1250 // including the canvas makes the gui weird...
1251 #ifdef INCLUDE_CANVAS
1252 // canvas(ctx);
1253 #endif
1254
1255 #ifdef INCLUDE_OVERVIEW
1256 overview(ctx);
1257 #endif
1258
1259 #ifdef INCLUDE_CONFIGURATOR
1260 style_configurator(ctx, color_table);
1261 #endif
1262
1263 #ifdef INCLUDE_NODE_EDITOR
1264 node_editor(ctx);
1265 #endif
1266 /* ----------------------------------------- */
1267
1268
1269 /* Draw */
1270 SDL_GetWindowSize(win, &win_width, &win_height);
1271 glViewport(0, 0, win_width, win_height);
1272 glClear(GL_COLOR_BUFFER_BIT);
1273 glClearColor(bg.r, bg.g, bg.b, bg.a);
1274 /* IMPORTANT: `nk_sdl_render` modifies some global OpenGL state
1275 * with blending, scissor, face culling, depth test and viewport and
1276 * defaults everything back into a default state.
1277 * Make sure to either a.) save and restore or b.) reset your own state after
1278 * rendering the UI. */
1279 nk_sdl_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_MEMORY, MAX_ELEMENT_MEMORY);
1280 SDL_GL_SwapWindow(win);
1281 }
1282
1283 glDeleteTextures(1, (const GLuint*)&media.skin);
1284 nk_sdl_shutdown();
1285 SDL_GL_DeleteContext(glContext);
1286 SDL_DestroyWindow(win);
1287 SDL_Quit();
1288 return 0;
1289 }
1290 #endif
1291