1 //------------------------------------------------------------------------------
2 //  nuklear.d
3 //
4 //  Using nuklear + sokol
5 // https://github.com/floooh/sokol-samples/blob/master/sapp/nuklear-sapp.c
6 //------------------------------------------------------------------------------
7 
8 module nuklear_app;
9 
10 private:
11 
12 import sg = sokol.gfx;
13 import sgapp = sokol.glue;
14 import sapp = sokol.app;
15 import log = sokol.log;
16 import snk = sokol.nuklear;
17 import nuklear;
18 
19 extern (C):
20 @safe:
21 
22 struct State
23 {
24     sg.PassAction pass_action = {
25         colors: [
26             {
27                 load_action: sg.LoadAction.Clear,
28                 clear_value: {r: 0.25, g: 0.5, b: 0.7, a: 1.0},
29             }
30         ]
31     };
32 }
33 
34 State state;
35 
36 void init() nothrow
37 {
38     sg.Desc gfx = {
39         environment: sgapp.environment,
40         logger: {func: &log.slog_func}
41     };
42     sg.setup(gfx);
43     snk.Desc nk_desc = {
44         enable_set_mouse_cursor: true,
45         dpi_scale: sapp.dpiScale,
46         logger: {func: &log.slog_func},
47     };
48     snk.setup(nk_desc);
49 }
50 
51 void frame() @trusted
52 {
53     auto ctx = cast(nk_context*) snk.newFrame;
54 
55     // Show a basic Nuklear Window
56     if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200),
57         NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
58         NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
59     {
60         nk_menubar_begin(ctx);
61         nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
62         nk_layout_row_push(ctx, 45);
63         if (nk_menu_begin_label(ctx, "FILE", NK_TEXT_LEFT, nk_vec2(120, 200))) {
64             nk_layout_row_dynamic(ctx, 30, 1);
65             nk_menu_item_label(ctx, "OPEN", NK_TEXT_LEFT);
66             nk_menu_item_label(ctx, "CLOSE", NK_TEXT_LEFT);
67             nk_menu_end(ctx);
68         }
69         nk_layout_row_push(ctx, 45);
70         if (nk_menu_begin_label(ctx, "EDIT", NK_TEXT_LEFT, nk_vec2(120, 200))) {
71             nk_layout_row_dynamic(ctx, 30, 1);
72             nk_menu_item_label(ctx, "COPY", NK_TEXT_LEFT);
73             nk_menu_item_label(ctx, "CUT", NK_TEXT_LEFT);
74             nk_menu_item_label(ctx, "PASTE", NK_TEXT_LEFT);
75             nk_menu_end(ctx);
76         }
77         nk_layout_row_end(ctx);
78         nk_menubar_end(ctx);
79 
80         enum {EASY, HARD};
81         static int op = EASY;
82         static int property = 20;
83         nk_layout_row_static(ctx, 30, 80, 1);
84         if (nk_button_label(ctx, "button"))
85             printf("button pressed\n");
86         nk_layout_row_dynamic(ctx, 30, 2);
87         if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
88         if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
89         nk_layout_row_dynamic(ctx, 25, 1);
90         nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
91     }
92     nk_end(ctx);
93 
94     sg.Pass pass = {action: state.pass_action, swapchain: sgapp.swapchain};
95     sg.beginPass(pass);
96     snk.render(sapp.width, sapp.height);
97     sg.endPass;
98     sg.commit;
99 }
100 
101 void event(const(sapp.Event)* ev) @trusted nothrow
102 {
103     snk.snk_handle_event(ev);
104 }
105 
106 void cleanup() @safe nothrow
107 {
108     snk.shutdown;
109     sg.shutdown;
110 }
111 
112 void main() @safe nothrow
113 {
114     sapp.Desc runner = {
115         window_title: "nuklear.d",
116         init_cb: &init,
117         frame_cb: &frame,
118         cleanup_cb: &cleanup,
119         event_cb: &event,
120         enable_clipboard: true,
121         width: 800,
122         height: 600,
123         ios_keyboard_resizes_canvas: true,
124         icon: {sokol_default: true},
125         logger: {func: &log.func}
126     };
127     sapp.run(runner);
128 }
129 
130 version (WebAssembly)
131 {
132     debug
133     {
134         import emscripten.assertd;
135     }
136 }