Nuklear
This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.
 
Loading...
Searching...
No Matches
nuklear_context.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ==============================================================
5 *
6 * CONTEXT
7 *
8 * ===============================================================*/
9NK_INTERN void
10nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
11{
12 NK_ASSERT(ctx);
13 if (!ctx) return;
14 nk_zero_struct(*ctx);
15 nk_style_default(ctx);
16 ctx->seq = 1;
17 if (font) ctx->style.font = font;
18#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
19 nk_draw_list_init(&ctx->draw_list);
20#endif
21}
22#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
23NK_API nk_bool
24nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
25{
26 struct nk_allocator alloc;
27 alloc.userdata.ptr = 0;
28 alloc.alloc = nk_malloc;
29 alloc.free = nk_mfree;
30 return nk_init(ctx, &alloc, font);
31}
32#endif
33NK_API nk_bool
34nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
35 const struct nk_user_font *font)
36{
37 NK_ASSERT(memory);
38 if (!memory) return 0;
39 nk_setup(ctx, font);
40 nk_buffer_init_fixed(&ctx->memory, memory, size);
41 ctx->use_pool = nk_false;
42 return 1;
43}
44NK_API nk_bool
45nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
46 struct nk_buffer *pool, const struct nk_user_font *font)
47{
48 NK_ASSERT(cmds);
49 NK_ASSERT(pool);
50 if (!cmds || !pool) return 0;
51
52 nk_setup(ctx, font);
53 ctx->memory = *cmds;
54 if (pool->type == NK_BUFFER_FIXED) {
55 /* take memory from buffer and alloc fixed pool */
56 nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
57 } else {
58 /* create dynamic pool from buffer allocator */
59 struct nk_allocator *alloc = &pool->pool;
60 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
61 }
62 ctx->use_pool = nk_true;
63 return 1;
64}
65NK_API nk_bool
66nk_init(struct nk_context *ctx, const struct nk_allocator *alloc,
67 const struct nk_user_font *font)
68{
69 NK_ASSERT(alloc);
70 if (!alloc) return 0;
71 nk_setup(ctx, font);
72 nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
73 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
74 ctx->use_pool = nk_true;
75 return 1;
76}
77#ifdef NK_INCLUDE_COMMAND_USERDATA
78NK_API void
79nk_set_user_data(struct nk_context *ctx, nk_handle handle)
80{
81 if (!ctx) return;
82 ctx->userdata = handle;
83 if (ctx->current)
84 ctx->current->buffer.userdata = handle;
85}
86#endif
87NK_API void
88nk_free(struct nk_context *ctx)
89{
90 NK_ASSERT(ctx);
91 if (!ctx) return;
92 nk_buffer_free(&ctx->memory);
93 if (ctx->use_pool)
94 nk_pool_free(&ctx->pool);
95
96 nk_zero(&ctx->input, sizeof(ctx->input));
97 nk_zero(&ctx->style, sizeof(ctx->style));
98 nk_zero(&ctx->memory, sizeof(ctx->memory));
99
100 ctx->seq = 0;
101 ctx->build = 0;
102 ctx->begin = 0;
103 ctx->end = 0;
104 ctx->active = 0;
105 ctx->current = 0;
106 ctx->freelist = 0;
107 ctx->count = 0;
108}
109NK_API void
111{
112 struct nk_window *iter;
113 struct nk_window *next;
114 NK_ASSERT(ctx);
115
116 if (!ctx) return;
117 if (ctx->use_pool)
118 nk_buffer_clear(&ctx->memory);
119 else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
120
121 ctx->build = 0;
122 ctx->memory.calls = 0;
123 ctx->last_widget_state = 0;
124 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
125 NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
126
127 /* garbage collector */
128 iter = ctx->begin;
129 while (iter) {
130 /* make sure valid minimized windows do not get removed */
131 if ((iter->flags & NK_WINDOW_MINIMIZED) &&
132 !(iter->flags & NK_WINDOW_CLOSED) &&
133 iter->seq == ctx->seq) {
134 iter = iter->next;
135 continue;
136 }
137 /* remove hotness from hidden or closed windows*/
138 if (((iter->flags & NK_WINDOW_HIDDEN) ||
139 (iter->flags & NK_WINDOW_CLOSED)) &&
140 iter == ctx->active) {
141 ctx->active = iter->prev;
142 ctx->end = iter->prev;
143 if (!ctx->end)
144 ctx->begin = 0;
145 if (ctx->active)
146 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
147 }
148 /* free unused popup windows */
149 if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
150 nk_free_window(ctx, iter->popup.win);
151 iter->popup.win = 0;
152 }
153 /* remove unused window state tables */
154 {struct nk_table *n, *it = iter->tables;
155 while (it) {
156 n = it->next;
157 if (it->seq != ctx->seq) {
158 nk_remove_table(iter, it);
159 nk_zero(it, sizeof(union nk_page_data));
160 nk_free_table(ctx, it);
161 if (it == iter->tables)
162 iter->tables = n;
163 } it = n;
164 }}
165 /* window itself is not used anymore so free */
166 if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
167 next = iter->next;
168 nk_remove_window(ctx, iter);
169 nk_free_window(ctx, iter);
170 iter = next;
171 } else iter = iter->next;
172 }
173 ctx->seq++;
174}
175NK_LIB void
176nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
177{
178 NK_ASSERT(ctx);
179 NK_ASSERT(buffer);
180 if (!ctx || !buffer) return;
181 buffer->begin = ctx->memory.allocated;
182 buffer->end = buffer->begin;
183 buffer->last = buffer->begin;
184 buffer->clip = nk_null_rect;
185}
186NK_LIB void
187nk_start(struct nk_context *ctx, struct nk_window *win)
188{
189 NK_ASSERT(ctx);
190 NK_ASSERT(win);
191 nk_start_buffer(ctx, &win->buffer);
192}
193NK_LIB void
194nk_start_popup(struct nk_context *ctx, struct nk_window *win)
195{
196 struct nk_popup_buffer *buf;
197 NK_ASSERT(ctx);
198 NK_ASSERT(win);
199 if (!ctx || !win) return;
200
201 /* save buffer fill state for popup */
202 buf = &win->popup.buf;
203 buf->begin = win->buffer.end;
204 buf->end = win->buffer.end;
205 buf->parent = win->buffer.last;
206 buf->last = buf->begin;
207 buf->active = nk_true;
208}
209NK_LIB void
210nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
211{
212 struct nk_popup_buffer *buf;
213 NK_ASSERT(ctx);
214 NK_ASSERT(win);
215 if (!ctx || !win) return;
216
217 buf = &win->popup.buf;
218 buf->last = win->buffer.last;
219 buf->end = win->buffer.end;
220}
221NK_LIB void
222nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
223{
224 NK_ASSERT(ctx);
225 NK_ASSERT(buffer);
226 if (!ctx || !buffer) return;
227 buffer->end = ctx->memory.allocated;
228}
229NK_LIB void
230nk_finish(struct nk_context *ctx, struct nk_window *win)
231{
232 struct nk_popup_buffer *buf;
233 struct nk_command *parent_last;
234 void *memory;
235
236 NK_ASSERT(ctx);
237 NK_ASSERT(win);
238 if (!ctx || !win) return;
239 nk_finish_buffer(ctx, &win->buffer);
240 if (!win->popup.buf.active) return;
241
242 buf = &win->popup.buf;
243 memory = ctx->memory.memory.ptr;
244 parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
245 parent_last->next = buf->end;
246}
247NK_LIB void
248nk_build(struct nk_context *ctx)
249{
250 struct nk_window *it = 0;
251 struct nk_command *cmd = 0;
252 nk_byte *buffer = 0;
253
254 /* draw cursor overlay */
255 if (!ctx->style.cursor_active)
256 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
257 if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
258 struct nk_rect mouse_bounds;
259 const struct nk_cursor *cursor = ctx->style.cursor_active;
260 nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
261 nk_start_buffer(ctx, &ctx->overlay);
262
263 mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
264 mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
265 mouse_bounds.w = cursor->size.x;
266 mouse_bounds.h = cursor->size.y;
267
268 nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
269 nk_finish_buffer(ctx, &ctx->overlay);
270 }
271 /* build one big draw command list out of all window buffers */
272 it = ctx->begin;
273 buffer = (nk_byte*)ctx->memory.memory.ptr;
274 while (it != 0) {
275 struct nk_window *next = it->next;
276 if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
277 it->seq != ctx->seq)
278 goto cont;
279
280 cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
281 while (next && ((next->buffer.last == next->buffer.begin) ||
282 (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
283 next = next->next; /* skip empty command buffers */
284
285 if (next) cmd->next = next->buffer.begin;
286 cont: it = next;
287 }
288 /* append all popup draw commands into lists */
289 it = ctx->begin;
290 while (it != 0) {
291 struct nk_window *next = it->next;
292 struct nk_popup_buffer *buf;
293 if (!it->popup.buf.active)
294 goto skip;
295
296 buf = &it->popup.buf;
297 cmd->next = buf->begin;
298 cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
299 buf->active = nk_false;
300 skip: it = next;
301 }
302 if (cmd) {
303 /* append overlay commands */
304 if (ctx->overlay.end != ctx->overlay.begin)
305 cmd->next = ctx->overlay.begin;
306 else cmd->next = ctx->memory.allocated;
307 }
308}
309NK_API const struct nk_command*
311{
312 struct nk_window *iter;
313 nk_byte *buffer;
314 NK_ASSERT(ctx);
315 if (!ctx) return 0;
316 if (!ctx->count) return 0;
317
318 buffer = (nk_byte*)ctx->memory.memory.ptr;
319 if (!ctx->build) {
320 nk_build(ctx);
321 ctx->build = nk_true;
322 }
323 iter = ctx->begin;
324 while (iter && ((iter->buffer.begin == iter->buffer.end) ||
325 (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
326 iter = iter->next;
327 if (!iter) return 0;
328 return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
329}
330
331NK_API const struct nk_command*
332nk__next(struct nk_context *ctx, const struct nk_command *cmd)
333{
334 nk_byte *buffer;
335 const struct nk_command *next;
336 NK_ASSERT(ctx);
337 if (!ctx || !cmd || !ctx->count) return 0;
338 if (cmd->next >= ctx->memory.allocated) return 0;
339 buffer = (nk_byte*)ctx->memory.memory.ptr;
340 next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
341 return next;
342}
343
344
main API and documentation file
NK_API void nk_free(struct nk_context *)
Frees all memory allocated by nuklear; Not needed if context was initialized with nk_init_fixed.
NK_API nk_bool nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
@ NK_WINDOW_CLOSED
Directly closes and frees the window at the end of the frame.
Definition nuklear.h:5495
@ NK_WINDOW_MINIMIZED
marks the window as minimized
Definition nuklear.h:5496
@ NK_WINDOW_HIDDEN
Hides window and stops any window interaction and drawing.
Definition nuklear.h:5494
@ NK_WINDOW_ROM
sets window widgets into a read only mode and does not allow input changes
Definition nuklear.h:5492
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
misc
NK_API nk_bool nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
Initializes a nk_context struct from two different either fixed or growing buffers.
NK_API const struct nk_command * nk__begin(struct nk_context *)
Returns a draw command list iterator to iterate all draw commands accumulated over one frame.
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
Returns draw command pointer pointing to the next command inside the draw command list.
NK_API nk_bool nk_init(struct nk_context *, const struct nk_allocator *, const struct nk_user_font *)
NK_API void nk_clear(struct nk_context *)
Resets the context state at the end of the frame.
struct nk_allocator pool
!< buffer marker to free a buffer to a certain offset
Definition nuklear.h:4191
struct nk_memory memory
!< memory management type
Definition nuklear.h:4193
enum nk_allocation_type type
!< allocator callback for dynamic buffers
Definition nuklear.h:4192
nk_size allocated
!< growing factor for dynamic memory management
Definition nuklear.h:4195
nk_size calls
!< totally consumed memory given that enough memory is present
Definition nuklear.h:4197
command base and header of every command inside the buffer
Definition nuklear.h:4467
int build
windows
Definition nuklear.h:5733
struct nk_command_buffer overlay
draw buffer used for overlay drawing operation like cursor
Definition nuklear.h:5730