raylib-nuklear.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. /**********************************************************************************************
  2. *
  3. * raylib-nuklear - Nuklear for Raylib.
  4. *
  5. * FEATURES:
  6. * - Use the nuklear immediate-mode graphical user interface in raylib.
  7. *
  8. * DEPENDENCIES:
  9. * - raylib 4.2 https://www.raylib.com/
  10. * - nuklear https://github.com/Immediate-Mode-UI/Nuklear
  11. *
  12. * LICENSE: zlib/libpng
  13. *
  14. * raylib-nuklear is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
  15. * BSD-like license that allows static linking with closed source software:
  16. *
  17. * Copyright (c) 2020 Rob Loach (@RobLoach)
  18. *
  19. * This software is provided "as-is", without any express or implied warranty. In no event
  20. * will the authors be held liable for any damages arising from the use of this software.
  21. *
  22. * Permission is granted to anyone to use this software for any purpose, including commercial
  23. * applications, and to alter it and redistribute it freely, subject to the following restrictions:
  24. *
  25. * 1. The origin of this software must not be misrepresented; you must not claim that you
  26. * wrote the original software. If you use this software in a product, an acknowledgment
  27. * in the product documentation would be appreciated but is not required.
  28. *
  29. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
  30. * as being the original software.
  31. *
  32. * 3. This notice may not be removed or altered from any source distribution.
  33. *
  34. **********************************************************************************************/
  35. #ifndef RAYLIB_NUKLEAR_H
  36. #define RAYLIB_NUKLEAR_H
  37. #include "raylib.h"
  38. // Nuklear defines
  39. #define NK_INCLUDE_STANDARD_VARARGS
  40. #define NK_INCLUDE_COMMAND_USERDATA
  41. // TODO: Replace NK_INCLUDE_DEFAULT_ALLOCATOR with MemAlloc() and MemFree()
  42. #define NK_INCLUDE_DEFAULT_ALLOCATOR
  43. #define NK_INCLUDE_COMMAND_USERDATA
  44. // TODO: Figure out if we can use STANDARD_BOOL here?
  45. //#define NK_INCLUDE_STANDARD_BOOL
  46. //#ifndef NK_BOOL
  47. //#define NK_BOOL bool
  48. //#endif // NK_BOOL
  49. #ifndef NK_ASSERT
  50. #define NK_ASSERT(condition) do { if (!(condition)) { TraceLog(LOG_WARNING, "NUKLEAR: Failed assert \"%s\" (%s:%i)", #condition, "nuklear.h", __LINE__); }} while (0)
  51. #endif // NK_ASSERT
  52. #include "nuklear.h"
  53. #ifdef __cplusplus
  54. extern "C" {
  55. #endif
  56. NK_API struct nk_context* InitNuklear(int fontSize); // Initialize the Nuklear GUI context
  57. NK_API struct nk_context* InitNuklearEx(Font font, float fontSize); // Initialize the Nuklear GUI context, with a custom font
  58. NK_API void UpdateNuklear(struct nk_context * ctx); // Update the input state and internal components for Nuklear
  59. NK_API void DrawNuklear(struct nk_context * ctx); // Render the Nuklear GUI on the screen
  60. NK_API void UnloadNuklear(struct nk_context * ctx); // Deinitialize the Nuklear context
  61. NK_API struct nk_color ColorToNuklear(Color color); // Convert a raylib Color to a Nuklear color object
  62. NK_API struct nk_colorf ColorToNuklearF(Color color); // Convert a raylib Color to a Nuklear floating color
  63. NK_API struct Color ColorFromNuklear(struct nk_color color); // Convert a Nuklear color to a raylib Color
  64. NK_API struct Color ColorFromNuklearF(struct nk_colorf color); // Convert a Nuklear floating color to a raylib Color
  65. NK_API struct Rectangle RectangleFromNuklear(struct nk_context * ctx, struct nk_rect rect); // Convert a Nuklear rectangle to a raylib Rectangle
  66. NK_API struct nk_rect RectangleToNuklear(struct nk_context * ctx, Rectangle rect); // Convert a raylib Rectangle to a Nuklear Rectangle
  67. NK_API struct nk_image TextureToNuklear(Texture tex); // Convert a raylib Texture to A Nuklear image
  68. NK_API struct Texture TextureFromNuklear(struct nk_image img); // Convert a Nuklear image to a raylib Texture
  69. NK_API struct nk_image LoadNuklearImage(const char* path); // Load a Nuklear image
  70. NK_API void UnloadNuklearImage(struct nk_image img); // Unload a Nuklear image. And free its data
  71. NK_API void CleanupNuklearImage(struct nk_image img); // Frees the data stored by the Nuklear image
  72. NK_API void SetNuklearScaling(struct nk_context * ctx, float scaling); // Sets the scaling for the given Nuklear context
  73. NK_API float GetNuklearScaling(struct nk_context * ctx); // Retrieves the scaling of the given Nuklear context
  74. NK_API void SetNuklearPosition(struct nk_context * ctx, Vector2 position); // Sets the position for the given Nuklear context
  75. NK_API Vector2 GetNuklearPosition(struct nk_context * ctx); // Retrieves the position of the given Nuklear context
  76. #ifdef __cplusplus
  77. }
  78. #endif
  79. #endif // RAYLIB_NUKLEAR_H
  80. #ifdef RAYLIB_NUKLEAR_IMPLEMENTATION
  81. #ifndef RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE
  82. #define RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE
  83. // Math
  84. #ifndef NK_COS
  85. #define NK_COS cosf
  86. #endif // NK_COS
  87. #ifndef NK_SIN
  88. #define NK_SIN sinf
  89. #endif // NK_SIN
  90. #ifndef NK_INV_SQRT
  91. #define NK_INV_SQRT(value) (1.0f / sqrtf(value))
  92. #endif // NK_INV_SQRT
  93. #define NK_IMPLEMENTATION
  94. #define NK_KEYSTATE_BASED_INPUT
  95. #include "nuklear.h"
  96. #ifdef __cplusplus
  97. extern "C" {
  98. #endif
  99. #ifndef RAYLIB_NUKLEAR_DEFAULT_FONTSIZE
  100. /**
  101. * The default font size that is used when a font size is not provided.
  102. */
  103. #define RAYLIB_NUKLEAR_DEFAULT_FONTSIZE 10
  104. #endif // RAYLIB_NUKLEAR_DEFAULT_FONTSIZE
  105. #ifndef RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS
  106. /**
  107. * The amount of segments used when drawing an arc.
  108. *
  109. * @see NK_COMMAND_ARC_FILLED
  110. */
  111. #define RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 20
  112. #endif // RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS
  113. /**
  114. * The user data that's leverages internally through Nuklear.
  115. */
  116. typedef struct NuklearUserData {
  117. float scaling;
  118. Vector2 position;
  119. } NuklearUserData;
  120. /**
  121. * Nuklear callback; Get the width of the given text.
  122. *
  123. * @internal
  124. */
  125. NK_API float
  126. nk_raylib_font_get_text_width(nk_handle handle, float height, const char *text, int len)
  127. {
  128. NK_UNUSED(handle);
  129. if (len > 0) {
  130. // Grab the text with the cropped length so that it only measures the desired string length.
  131. const char* subtext = TextSubtext(text, 0, len);
  132. return (float)MeasureText(subtext, (int)height);
  133. }
  134. return 0;
  135. }
  136. /**
  137. * Nuklear callback; Get the width of the given text (userFont version)
  138. *
  139. * @internal
  140. */
  141. NK_API float
  142. nk_raylib_font_get_text_width_user_font(nk_handle handle, float height, const char *text, int len)
  143. {
  144. if (len > 0) {
  145. // Grab the text with the cropped length so that it only measures the desired string length.
  146. const char* subtext = TextSubtext(text, 0, len);
  147. // Spacing is determined by the font size divided by 10.
  148. return MeasureTextEx(*(Font*)handle.ptr, subtext, height, height / 10.0f).x;
  149. }
  150. return 0;
  151. }
  152. /**
  153. * Nuklear callback; Paste the current clipboard.
  154. *
  155. * @internal
  156. */
  157. NK_API void
  158. nk_raylib_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
  159. {
  160. const char *text = GetClipboardText();
  161. NK_UNUSED(usr);
  162. if (text != NULL) {
  163. nk_textedit_paste(edit, text, (int)TextLength(text));
  164. }
  165. }
  166. /**
  167. * Nuklear callback; Copy the given text.
  168. *
  169. * @internal
  170. */
  171. NK_API void
  172. nk_raylib_clipboard_copy(nk_handle usr, const char *text, int len)
  173. {
  174. NK_UNUSED(usr);
  175. NK_UNUSED(len);
  176. SetClipboardText(text);
  177. }
  178. /**
  179. * Initialize the Nuklear context for use with Raylib, with the given Nuklear user font.
  180. *
  181. * @param userFont The Nuklear user font to initialize the Nuklear context with.
  182. *
  183. * @internal
  184. */
  185. NK_API struct nk_context*
  186. InitNuklearContext(struct nk_user_font* userFont)
  187. {
  188. struct nk_context* ctx = (struct nk_context*)MemAlloc(sizeof(struct nk_context));
  189. struct NuklearUserData* userData = (struct NuklearUserData*)MemAlloc(sizeof(struct NuklearUserData));
  190. // Clipboard
  191. ctx->clip.copy = nk_raylib_clipboard_copy;
  192. ctx->clip.paste = nk_raylib_clipboard_paste;
  193. ctx->clip.userdata = nk_handle_ptr(0);
  194. // Create the nuklear environment.
  195. if (nk_init_default(ctx, userFont) == 0) {
  196. TraceLog(LOG_ERROR, "NUKLEAR: Failed to initialize nuklear");
  197. return NULL;
  198. }
  199. // Set the internal user data.
  200. userData->scaling = 1.0f;
  201. userData->position.x = 0.0f;
  202. userData->position.y = 0.0f;
  203. nk_handle userDataHandle;
  204. userDataHandle.id = 1;
  205. userDataHandle.ptr = (void*)userData;
  206. nk_set_user_data(ctx, userDataHandle);
  207. TraceLog(LOG_INFO, "NUKLEAR: Initialized GUI");
  208. return ctx;
  209. }
  210. /**
  211. * Initialize the Nuklear context for use with Raylib.
  212. *
  213. * @param fontSize The size of the font to use for GUI text. Use 0 to use the default font size of 10.
  214. *
  215. * @return The nuklear context, or NULL on error.
  216. */
  217. NK_API struct nk_context*
  218. InitNuklear(int fontSize)
  219. {
  220. // User font.
  221. struct nk_user_font* userFont = (struct nk_user_font*)MemAlloc(sizeof(struct nk_user_font));
  222. // Use the default font size if desired.
  223. if (fontSize <= 0) {
  224. fontSize = RAYLIB_NUKLEAR_DEFAULT_FONTSIZE;
  225. }
  226. userFont->height = (float)fontSize;
  227. userFont->width = nk_raylib_font_get_text_width;
  228. userFont->userdata = nk_handle_ptr(0);
  229. // Nuklear context.
  230. return InitNuklearContext(userFont);
  231. }
  232. /**
  233. * Initialize the Nuklear context for use with Raylib, with a supplied custom font.
  234. *
  235. * @param font The custom raylib font to use with Nuklear.
  236. * @param fontSize The desired size of the font. Use 0 to set the default size of 10.
  237. *
  238. * @return The nuklear context, or NULL on error.
  239. */
  240. NK_API struct nk_context*
  241. InitNuklearEx(Font font, float fontSize)
  242. {
  243. // Copy the font to a new raylib font pointer.
  244. struct Font* newFont = (struct Font*)MemAlloc(sizeof(struct Font));
  245. // Use the default font size if desired.
  246. if (fontSize <= 0.0f) {
  247. fontSize = (float)RAYLIB_NUKLEAR_DEFAULT_FONTSIZE;
  248. }
  249. newFont->baseSize = font.baseSize;
  250. newFont->glyphCount = font.glyphCount;
  251. newFont->glyphPadding = font.glyphPadding;
  252. newFont->glyphs = font.glyphs;
  253. newFont->recs = font.recs;
  254. newFont->texture = font.texture;
  255. // Create the nuklear user font.
  256. struct nk_user_font* userFont = (struct nk_user_font*)MemAlloc(sizeof(struct nk_user_font));
  257. userFont->userdata = nk_handle_ptr(newFont);
  258. userFont->height = fontSize;
  259. userFont->width = nk_raylib_font_get_text_width_user_font;
  260. // Nuklear context.
  261. return InitNuklearContext(userFont);
  262. }
  263. /**
  264. * Convert the given Nuklear color to a raylib color.
  265. */
  266. NK_API Color
  267. ColorFromNuklear(struct nk_color color)
  268. {
  269. Color rc;
  270. rc.a = color.a;
  271. rc.r = color.r;
  272. rc.g = color.g;
  273. rc.b = color.b;
  274. return rc;
  275. }
  276. /**
  277. * Convert the given raylib color to a Nuklear color.
  278. */
  279. NK_API struct nk_color
  280. ColorToNuklear(Color color)
  281. {
  282. struct nk_color rc;
  283. rc.a = color.a;
  284. rc.r = color.r;
  285. rc.g = color.g;
  286. rc.b = color.b;
  287. return rc;
  288. }
  289. /**
  290. * Convert the given Nuklear float color to a raylib color.
  291. */
  292. NK_API Color
  293. ColorFromNuklearF(struct nk_colorf color)
  294. {
  295. return ColorFromNuklear(nk_rgba_cf(color));
  296. }
  297. /**
  298. * Convert the given raylib color to a raylib float color.
  299. */
  300. NK_API struct nk_colorf
  301. ColorToNuklearF(Color color)
  302. {
  303. return nk_color_cf(ColorToNuklear(color));
  304. }
  305. /**
  306. * Draw the given Nuklear context in raylib.
  307. *
  308. * @param ctx The nuklear context.
  309. */
  310. NK_API void
  311. DrawNuklear(struct nk_context * ctx)
  312. {
  313. const struct nk_command *cmd;
  314. const float scale = GetNuklearScaling(ctx);
  315. const Vector2 position = GetNuklearPosition(ctx);
  316. nk_foreach(cmd, ctx) {
  317. switch (cmd->type) {
  318. case NK_COMMAND_NOP: {
  319. break;
  320. }
  321. case NK_COMMAND_SCISSOR: {
  322. // TODO(RobLoach): Verify if NK_COMMAND_SCISSOR works.
  323. const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
  324. BeginScissorMode((int)(position.x + s->x * scale), (int)(position.y + s->y * scale), (int)(s->w * scale), (int)(s->h * scale));
  325. } break;
  326. case NK_COMMAND_LINE: {
  327. const struct nk_command_line *l = (const struct nk_command_line *)cmd;
  328. Color color = ColorFromNuklear(l->color);
  329. Vector2 startPos = {position.x + (float)l->begin.x * scale, position.y + (float)l->begin.y * scale};
  330. Vector2 endPos = {position.x + (float)l->end.x * scale, position.y + (float)l->end.y * scale};
  331. DrawLineEx(startPos, endPos, l->line_thickness * scale, color);
  332. } break;
  333. case NK_COMMAND_CURVE: {
  334. const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
  335. Color color = ColorFromNuklear(q->color);
  336. // Vector2 start = {(float)q->begin.x, (float)q->begin.y};
  337. Vector2 start = {position.x + (float)q->begin.x * scale, position.y + (float)q->begin.y * scale};
  338. // Vector2 controlPoint1 = (Vector2){q->ctrl[0].x, q->ctrl[0].y};
  339. // Vector2 controlPoint2 = (Vector2){q->ctrl[1].x, q->ctrl[1].y};
  340. // Vector2 end = {(float)q->end.x, (float)q->end.y};
  341. Vector2 end = {position.x + (float)q->end.x * scale, position.y + (float)q->end.y * scale};
  342. // TODO: Encorporate segmented control point bezier curve?
  343. // DrawLineBezier(start, controlPoint1, (float)q->line_thickness, color);
  344. // DrawLineBezier(controlPoint1, controlPoint2, (float)q->line_thickness, color);
  345. // DrawLineBezier(controlPoint2, end, (float)q->line_thickness, color);
  346. // DrawLineBezier(start, end, (float)q->line_thickness, color);
  347. DrawLineBezier(start, end, (float)q->line_thickness * scale, color);
  348. } break;
  349. case NK_COMMAND_RECT: {
  350. const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
  351. Color color = ColorFromNuklear(r->color);
  352. Rectangle rect = {position.x + (float)r->x * scale, position.y + (float)r->y * scale, (float)r->w * scale, (float)r->h * scale};
  353. if (r->rounding > 0) {
  354. float roundness = (float)r->rounding * 4.0f / (rect.width + rect.height);
  355. // TODO: DrawRectangleRoundedLines - Is 1 the correct line segments?
  356. DrawRectangleRoundedLines(rect, roundness, 1, r->line_thickness * scale, color);
  357. }
  358. else {
  359. DrawRectangleLinesEx(rect, r->line_thickness * scale, color);
  360. }
  361. } break;
  362. case NK_COMMAND_RECT_FILLED: {
  363. const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
  364. Color color = ColorFromNuklear(r->color);
  365. Rectangle rect = {position.x + (float)r->x * scale, position.y + (float)r->y * scale, (float)r->w * scale, (float)r->h * scale};
  366. if (r->rounding > 0) {
  367. float roundness = (float)r->rounding * 4.0f / (rect.width + rect.height);
  368. DrawRectangleRounded(rect, roundness, 1, color);
  369. }
  370. else {
  371. DrawRectangleRec(rect, color);
  372. }
  373. } break;
  374. case NK_COMMAND_RECT_MULTI_COLOR: {
  375. const struct nk_command_rect_multi_color* rectangle = (const struct nk_command_rect_multi_color *)cmd;
  376. Rectangle rectPosition = {position.x + (float)rectangle->x * scale, position.y + (float)rectangle->y * scale, (float)rectangle->w * scale, (float)rectangle->h * scale};
  377. Color left = ColorFromNuklear(rectangle->left);
  378. Color top = ColorFromNuklear(rectangle->top);
  379. Color bottom = ColorFromNuklear(rectangle->bottom);
  380. Color right = ColorFromNuklear(rectangle->right);
  381. DrawRectangleGradientEx(rectPosition, left, bottom, right, top);
  382. } break;
  383. case NK_COMMAND_CIRCLE: {
  384. const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
  385. Color color = ColorFromNuklear(c->color);
  386. DrawEllipseLines((int)(position.x + c->x * scale + c->w * scale / 2.0f), (int)(position.y + c->y * scale + c->h * scale / 2.0f), (int)(c->w * scale / 2.0f), (int)(c->h * scale / 2.0f), color);
  387. } break;
  388. case NK_COMMAND_CIRCLE_FILLED: {
  389. const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
  390. Color color = ColorFromNuklear(c->color);
  391. DrawEllipse((int)(position.x + c->x * scale + c->w * scale / 2.0f), (int)(position.y + c->y * scale + c->h * scale / 2.0f), (int)(c->w * scale / 2), (int)(c->h * scale / 2), color);
  392. } break;
  393. case NK_COMMAND_ARC: {
  394. const struct nk_command_arc *a = (const struct nk_command_arc*)cmd;
  395. Color color = ColorFromNuklear(a->color);
  396. Vector2 center = {position.x + (float)a->cx, position.y + (float)a->cy};
  397. DrawRingLines(center, 0, a->r * scale, a->a[0] * RAD2DEG - 45, a->a[1] * RAD2DEG - 45, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color);
  398. } break;
  399. case NK_COMMAND_ARC_FILLED: {
  400. const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled*)cmd;
  401. Color color = ColorFromNuklear(a->color);
  402. Vector2 center = {position.x + (float)a->cx * scale, position.y + (float)a->cy * scale};
  403. DrawRing(center, 0, a->r * scale, a->a[0] * RAD2DEG - 45, a->a[1] * RAD2DEG - 45, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color);
  404. } break;
  405. case NK_COMMAND_TRIANGLE: {
  406. const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
  407. Color color = ColorFromNuklear(t->color);
  408. Vector2 point1 = {position.x + (float)t->b.x * scale, position.y + (float)t->b.y * scale};
  409. Vector2 point2 = {position.x + (float)t->a.x * scale, position.y + (float)t->a.y * scale};
  410. Vector2 point3 = {position.x + (float)t->c.x * scale, position.y + (float)t->c.y * scale};
  411. DrawTriangleLines(point1, point2, point3, color);
  412. } break;
  413. case NK_COMMAND_TRIANGLE_FILLED: {
  414. const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
  415. Color color = ColorFromNuklear(t->color);
  416. Vector2 point1 = {position.x + (float)t->b.x * scale, position.y + (float)t->b.y * scale};
  417. Vector2 point2 = {position.x + (float)t->a.x * scale, position.y + (float)t->a.y * scale};
  418. Vector2 point3 = {position.x + (float)t->c.x * scale, position.y + (float)t->c.y * scale};
  419. DrawTriangle(point1, point2, point3, color);
  420. } break;
  421. case NK_COMMAND_POLYGON: {
  422. // TODO: Confirm Polygon
  423. const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
  424. Color color = ColorFromNuklear(p->color);
  425. struct Vector2* points = (struct Vector2*)MemAlloc(p->point_count * (unsigned short)sizeof(Vector2));
  426. unsigned short i;
  427. for (i = 0; i < p->point_count; i++) {
  428. points[i].x = position.x + p->points[i].x * scale;
  429. points[i].y = position.y + p->points[i].y * scale;
  430. }
  431. DrawTriangleStrip(points, p->point_count, color);
  432. MemFree(points);
  433. } break;
  434. case NK_COMMAND_POLYGON_FILLED: {
  435. // TODO: Polygon filled expects counter clockwise order
  436. const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
  437. Color color = ColorFromNuklear(p->color);
  438. struct Vector2* points = (struct Vector2*)MemAlloc(p->point_count * (unsigned short)sizeof(Vector2));
  439. unsigned short i;
  440. for (i = 0; i < p->point_count; i++) {
  441. points[i].x = position.x + p->points[i].x * scale;
  442. points[i].y = position.y + p->points[i].y * scale;
  443. }
  444. DrawTriangleFan(points, p->point_count, color);
  445. MemFree(points);
  446. } break;
  447. case NK_COMMAND_POLYLINE: {
  448. // TODO: Polygon expects counter clockwise order
  449. const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
  450. Color color = ColorFromNuklear(p->color);
  451. struct Vector2* points = (struct Vector2*)MemAlloc(p->point_count * (unsigned short)sizeof(Vector2));
  452. unsigned short i;
  453. for (i = 0; i < p->point_count; i++) {
  454. points[i].x = position.x + p->points[i].x * scale;
  455. points[i].y = position.y + p->points[i].y * scale;
  456. }
  457. DrawTriangleStrip(points, p->point_count, color);
  458. MemFree(points);
  459. } break;
  460. case NK_COMMAND_TEXT: {
  461. const struct nk_command_text *text = (const struct nk_command_text*)cmd;
  462. Color color = ColorFromNuklear(text->foreground);
  463. float fontSize = text->font->height * scale;
  464. Font* font = (Font*)text->font->userdata.ptr;
  465. if (font != NULL) {
  466. Vector2 vecPosition = {position.x + (float)text->x * scale, position.y + (float)text->y * scale};
  467. DrawTextEx(*font, (const char*)text->string, vecPosition, fontSize, fontSize / 10.0f, color);
  468. }
  469. else {
  470. DrawText((const char*)text->string, (int)(position.x + text->x * scale), (int)(position.y + text->y * scale), (int)fontSize, color);
  471. }
  472. } break;
  473. case NK_COMMAND_IMAGE: {
  474. const struct nk_command_image *i = (const struct nk_command_image *)cmd;
  475. Texture texture = *(Texture*)i->img.handle.ptr;
  476. Rectangle source = {0, 0, (float)texture.width, (float)texture.height};
  477. Rectangle dest = {position.x + (float)i->x * scale, position.y + (float)i->y * scale, (float)i->w * scale, (float)i->h * scale};
  478. Vector2 origin = {0, 0};
  479. Color tint = ColorFromNuklear(i->col);
  480. DrawTexturePro(texture, source, dest, origin, 0, tint);
  481. } break;
  482. case NK_COMMAND_CUSTOM: {
  483. TraceLog(LOG_WARNING, "NUKLEAR: Unverified custom callback implementation NK_COMMAND_CUSTOM");
  484. const struct nk_command_custom *custom = (const struct nk_command_custom *)cmd;
  485. custom->callback(NULL, (short)(position.x + custom->x * scale), (short)(position.y + custom->y * scale), (unsigned short)(custom->w * scale), (unsigned short)(custom->h * scale), custom->callback_data);
  486. } break;
  487. default: {
  488. TraceLog(LOG_WARNING, "NUKLEAR: Missing implementation %i", cmd->type);
  489. } break;
  490. }
  491. }
  492. nk_clear(ctx);
  493. }
  494. /**
  495. * Update the Nuklear context for the keyboard input from raylib.
  496. *
  497. * @param ctx The nuklear context.
  498. *
  499. * @internal
  500. */
  501. NK_API void nk_raylib_input_keyboard(struct nk_context * ctx)
  502. {
  503. bool control = IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL);
  504. bool shift = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT);
  505. nk_input_key(ctx, NK_KEY_SHIFT, shift);
  506. nk_input_key(ctx, NK_KEY_CTRL, control);
  507. nk_input_key(ctx, NK_KEY_DEL, IsKeyDown(KEY_DELETE));
  508. nk_input_key(ctx, NK_KEY_ENTER, IsKeyDown(KEY_ENTER) || IsKeyDown(KEY_KP_ENTER));
  509. nk_input_key(ctx, NK_KEY_TAB, IsKeyDown(KEY_TAB));
  510. nk_input_key(ctx, NK_KEY_BACKSPACE, IsKeyDown(KEY_BACKSPACE));
  511. nk_input_key(ctx, NK_KEY_COPY, IsKeyPressed(KEY_C) && control);
  512. nk_input_key(ctx, NK_KEY_CUT, IsKeyPressed(KEY_X) && control);
  513. nk_input_key(ctx, NK_KEY_PASTE, IsKeyPressed(KEY_V) && control);
  514. nk_input_key(ctx, NK_KEY_TEXT_LINE_START, IsKeyPressed(KEY_B) && control);
  515. nk_input_key(ctx, NK_KEY_TEXT_LINE_END, IsKeyPressed(KEY_E) && control);
  516. nk_input_key(ctx, NK_KEY_TEXT_UNDO, IsKeyDown(KEY_Z) && control);
  517. nk_input_key(ctx, NK_KEY_TEXT_REDO, IsKeyDown(KEY_R) && control);
  518. nk_input_key(ctx, NK_KEY_TEXT_SELECT_ALL, IsKeyDown(KEY_A) && control);
  519. nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, IsKeyDown(KEY_LEFT) && control);
  520. nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, IsKeyDown(KEY_RIGHT) && control);
  521. nk_input_key(ctx, NK_KEY_LEFT, IsKeyDown(KEY_LEFT) && !control);
  522. nk_input_key(ctx, NK_KEY_RIGHT, IsKeyDown(KEY_RIGHT) && !control);
  523. //nk_input_key(ctx, NK_KEY_TEXT_INSERT_MODE, IsKeyDown());
  524. //nk_input_key(ctx, NK_KEY_TEXT_REPLACE_MODE, IsKeyDown());
  525. //nk_input_key(ctx, NK_KEY_TEXT_RESET_MODE, IsKeyDown());
  526. nk_input_key(ctx, NK_KEY_UP, IsKeyDown(KEY_UP));
  527. nk_input_key(ctx, NK_KEY_DOWN, IsKeyDown(KEY_DOWN));
  528. nk_input_key(ctx, NK_KEY_TEXT_START, IsKeyDown(KEY_HOME));
  529. nk_input_key(ctx, NK_KEY_TEXT_END, IsKeyDown(KEY_END));
  530. nk_input_key(ctx, NK_KEY_SCROLL_START, IsKeyDown(KEY_HOME) && control);
  531. nk_input_key(ctx, NK_KEY_SCROLL_END, IsKeyDown(KEY_END) && control);
  532. nk_input_key(ctx, NK_KEY_SCROLL_DOWN, IsKeyDown(KEY_PAGE_DOWN));
  533. nk_input_key(ctx, NK_KEY_SCROLL_UP, IsKeyDown(KEY_PAGE_UP));
  534. // Keys
  535. if (IsKeyPressed(KEY_APOSTROPHE)) nk_input_unicode(ctx, shift ? 34 : (nk_rune)KEY_APOSTROPHE);
  536. if (IsKeyPressed(KEY_COMMA)) nk_input_unicode(ctx, shift ? 60 : (nk_rune)KEY_COMMA);
  537. if (IsKeyPressed(KEY_MINUS)) nk_input_unicode(ctx, shift ? 95 : (nk_rune)KEY_MINUS);
  538. if (IsKeyPressed(KEY_PERIOD)) nk_input_unicode(ctx, shift ? 62 : (nk_rune)KEY_PERIOD);
  539. if (IsKeyPressed(KEY_SLASH)) nk_input_unicode(ctx, shift ? 63 : (nk_rune)KEY_SLASH);
  540. if (IsKeyPressed(KEY_ZERO)) nk_input_unicode(ctx, shift ? 41 : (nk_rune)KEY_ZERO);
  541. if (IsKeyPressed(KEY_ONE)) nk_input_unicode(ctx, shift ? 33 : (nk_rune)KEY_ONE);
  542. if (IsKeyPressed(KEY_TWO)) nk_input_unicode(ctx, shift ? 64 : (nk_rune)KEY_TWO);
  543. if (IsKeyPressed(KEY_THREE)) nk_input_unicode(ctx, shift ? 35 : (nk_rune)KEY_THREE);
  544. if (IsKeyPressed(KEY_FOUR)) nk_input_unicode(ctx, shift ? 36 : (nk_rune)KEY_FOUR);
  545. if (IsKeyPressed(KEY_FIVE)) nk_input_unicode(ctx, shift ? 37 : (nk_rune)KEY_FIVE);
  546. if (IsKeyPressed(KEY_SIX)) nk_input_unicode(ctx, shift ? 94 : (nk_rune)KEY_SIX);
  547. if (IsKeyPressed(KEY_SEVEN)) nk_input_unicode(ctx, shift ? 38 : (nk_rune)KEY_SEVEN);
  548. if (IsKeyPressed(KEY_EIGHT)) nk_input_unicode(ctx, shift ? 42 : (nk_rune)KEY_EIGHT);
  549. if (IsKeyPressed(KEY_NINE)) nk_input_unicode(ctx, shift ? 40 : (nk_rune)KEY_NINE);
  550. if (IsKeyPressed(KEY_SEMICOLON)) nk_input_unicode(ctx, shift ? 41 : (nk_rune)KEY_SEMICOLON);
  551. if (IsKeyPressed(KEY_EQUAL)) nk_input_unicode(ctx, shift ? 43 : (nk_rune)KEY_EQUAL);
  552. if (IsKeyPressed(KEY_A)) nk_input_unicode(ctx, shift ? KEY_A : KEY_A + 32);
  553. if (IsKeyPressed(KEY_B)) nk_input_unicode(ctx, shift ? KEY_B : KEY_B + 32);
  554. if (IsKeyPressed(KEY_C)) nk_input_unicode(ctx, shift ? KEY_C : KEY_C + 32);
  555. if (IsKeyPressed(KEY_D)) nk_input_unicode(ctx, shift ? KEY_D : KEY_D + 32);
  556. if (IsKeyPressed(KEY_E)) nk_input_unicode(ctx, shift ? KEY_E : KEY_E + 32);
  557. if (IsKeyPressed(KEY_F)) nk_input_unicode(ctx, shift ? KEY_F : KEY_F + 32);
  558. if (IsKeyPressed(KEY_G)) nk_input_unicode(ctx, shift ? KEY_G : KEY_G + 32);
  559. if (IsKeyPressed(KEY_H)) nk_input_unicode(ctx, shift ? KEY_H : KEY_H + 32);
  560. if (IsKeyPressed(KEY_I)) nk_input_unicode(ctx, shift ? KEY_I : KEY_I + 32);
  561. if (IsKeyPressed(KEY_J)) nk_input_unicode(ctx, shift ? KEY_J : KEY_J + 32);
  562. if (IsKeyPressed(KEY_K)) nk_input_unicode(ctx, shift ? KEY_K : KEY_K + 32);
  563. if (IsKeyPressed(KEY_L)) nk_input_unicode(ctx, shift ? KEY_L : KEY_L + 32);
  564. if (IsKeyPressed(KEY_M)) nk_input_unicode(ctx, shift ? KEY_M : KEY_M + 32);
  565. if (IsKeyPressed(KEY_N)) nk_input_unicode(ctx, shift ? KEY_N : KEY_N + 32);
  566. if (IsKeyPressed(KEY_O)) nk_input_unicode(ctx, shift ? KEY_O : KEY_O + 32);
  567. if (IsKeyPressed(KEY_P)) nk_input_unicode(ctx, shift ? KEY_P : KEY_P + 32);
  568. if (IsKeyPressed(KEY_Q)) nk_input_unicode(ctx, shift ? KEY_Q : KEY_Q + 32);
  569. if (IsKeyPressed(KEY_R)) nk_input_unicode(ctx, shift ? KEY_R : KEY_R + 32);
  570. if (IsKeyPressed(KEY_S)) nk_input_unicode(ctx, shift ? KEY_S : KEY_S + 32);
  571. if (IsKeyPressed(KEY_T)) nk_input_unicode(ctx, shift ? KEY_T : KEY_T + 32);
  572. if (IsKeyPressed(KEY_U)) nk_input_unicode(ctx, shift ? KEY_U : KEY_U + 32);
  573. if (IsKeyPressed(KEY_V)) nk_input_unicode(ctx, shift ? KEY_V : KEY_V + 32);
  574. if (IsKeyPressed(KEY_W)) nk_input_unicode(ctx, shift ? KEY_W : KEY_W + 32);
  575. if (IsKeyPressed(KEY_X)) nk_input_unicode(ctx, shift ? KEY_X : KEY_X + 32);
  576. if (IsKeyPressed(KEY_Y)) nk_input_unicode(ctx, shift ? KEY_Y : KEY_Y + 32);
  577. if (IsKeyPressed(KEY_Z)) nk_input_unicode(ctx, shift ? KEY_Z : KEY_Z + 32);
  578. if (IsKeyPressed(KEY_LEFT_BRACKET)) nk_input_unicode(ctx, shift ? 123 : (nk_rune)KEY_LEFT_BRACKET);
  579. if (IsKeyPressed(KEY_BACKSLASH)) nk_input_unicode(ctx, shift ? 124 : (nk_rune)KEY_BACKSLASH);
  580. if (IsKeyPressed(KEY_RIGHT_BRACKET)) nk_input_unicode(ctx, shift ? 125 : (nk_rune)KEY_RIGHT_BRACKET);
  581. if (IsKeyPressed(KEY_GRAVE)) nk_input_unicode(ctx, shift ? 126 : (nk_rune)KEY_GRAVE);
  582. // Functions
  583. if (IsKeyPressed(KEY_SPACE)) nk_input_unicode(ctx, KEY_SPACE);
  584. if (IsKeyPressed(KEY_TAB)) nk_input_unicode(ctx, 9);
  585. // Keypad
  586. if (IsKeyPressed(KEY_KP_0)) nk_input_unicode(ctx, KEY_ZERO);
  587. if (IsKeyPressed(KEY_KP_1)) nk_input_unicode(ctx, KEY_ONE);
  588. if (IsKeyPressed(KEY_KP_2)) nk_input_unicode(ctx, KEY_TWO);
  589. if (IsKeyPressed(KEY_KP_3)) nk_input_unicode(ctx, KEY_THREE);
  590. if (IsKeyPressed(KEY_KP_4)) nk_input_unicode(ctx, KEY_FOUR);
  591. if (IsKeyPressed(KEY_KP_5)) nk_input_unicode(ctx, KEY_FIVE);
  592. if (IsKeyPressed(KEY_KP_6)) nk_input_unicode(ctx, KEY_SIX);
  593. if (IsKeyPressed(KEY_KP_7)) nk_input_unicode(ctx, KEY_SEVEN);
  594. if (IsKeyPressed(KEY_KP_8)) nk_input_unicode(ctx, KEY_EIGHT);
  595. if (IsKeyPressed(KEY_KP_9)) nk_input_unicode(ctx, KEY_NINE);
  596. if (IsKeyPressed(KEY_KP_DECIMAL)) nk_input_unicode(ctx, KEY_PERIOD);
  597. if (IsKeyPressed(KEY_KP_DIVIDE)) nk_input_unicode(ctx, KEY_SLASH);
  598. if (IsKeyPressed(KEY_KP_MULTIPLY)) nk_input_unicode(ctx, 48);
  599. if (IsKeyPressed(KEY_KP_SUBTRACT)) nk_input_unicode(ctx, 45);
  600. if (IsKeyPressed(KEY_KP_ADD)) nk_input_unicode(ctx, 43);
  601. }
  602. /**
  603. * Update the Nuklear context for the mouse input from raylib.
  604. *
  605. * @param ctx The nuklear context.
  606. *
  607. * @internal
  608. */
  609. NK_API void nk_raylib_input_mouse(struct nk_context * ctx)
  610. {
  611. const float scale = GetNuklearScaling(ctx);
  612. Vector2 position = GetNuklearPosition(ctx);
  613. const int mouseX = (int)(((float)GetMouseX() - position.x) / scale);
  614. const int mouseY = (int)(((float)GetMouseY() - position.y) / scale);
  615. nk_input_motion(ctx, mouseX, mouseY);
  616. nk_input_button(ctx, NK_BUTTON_LEFT, mouseX, mouseY, IsMouseButtonDown(MOUSE_LEFT_BUTTON));
  617. nk_input_button(ctx, NK_BUTTON_RIGHT, mouseX, mouseY, IsMouseButtonDown(MOUSE_RIGHT_BUTTON));
  618. nk_input_button(ctx, NK_BUTTON_MIDDLE, mouseX, mouseY, IsMouseButtonDown(MOUSE_MIDDLE_BUTTON));
  619. // Mouse Wheel
  620. float mouseWheel = GetMouseWheelMove();
  621. if (mouseWheel != 0.0f) {
  622. struct nk_vec2 mouseWheelMove;
  623. mouseWheelMove.x = 0.0f;
  624. mouseWheelMove.y = mouseWheel;
  625. nk_input_scroll(ctx, mouseWheelMove);
  626. }
  627. }
  628. /**
  629. * Update the Nuklear context for raylib's state.
  630. *
  631. * @param ctx The nuklear context to act upon.
  632. */
  633. NK_API void
  634. UpdateNuklear(struct nk_context * ctx)
  635. {
  636. // Update the time that has changed since last frame.
  637. ctx->delta_time_seconds = GetFrameTime();
  638. // Update the input state.
  639. nk_input_begin(ctx);
  640. {
  641. nk_raylib_input_mouse(ctx);
  642. nk_raylib_input_keyboard(ctx);
  643. }
  644. nk_input_end(ctx);
  645. }
  646. /**
  647. * Unload the given Nuklear context, along with all internal raylib textures.
  648. *
  649. * @param ctx The nuklear context.
  650. */
  651. NK_API void
  652. UnloadNuklear(struct nk_context * ctx)
  653. {
  654. struct nk_user_font* userFont;
  655. // Skip unloading if it's not set.
  656. if (ctx == NULL) {
  657. return;
  658. }
  659. // Unload the font.
  660. userFont = (struct nk_user_font*)ctx->style.font;
  661. if (userFont != NULL) {
  662. // Clear the raylib Font object.
  663. void* fontPtr = userFont->userdata.ptr;
  664. if (fontPtr != NULL) {
  665. MemFree(fontPtr);
  666. }
  667. // Clear the user font.
  668. MemFree(userFont);
  669. ctx->style.font = NULL;
  670. }
  671. // Unload the custom user data.
  672. if (ctx->userdata.ptr != NULL) {
  673. MemFree(ctx->userdata.ptr);
  674. }
  675. // Unload the nuklear context.
  676. nk_free(ctx);
  677. TraceLog(LOG_INFO, "NUKLEAR: Unloaded GUI");
  678. }
  679. /**
  680. * Convert the given Nuklear rectangle to a raylib Rectangle.
  681. */
  682. NK_API struct
  683. Rectangle RectangleFromNuklear(struct nk_context* ctx, struct nk_rect rect)
  684. {
  685. float scaling = GetNuklearScaling(ctx);
  686. Vector2 position = GetNuklearPosition(ctx);
  687. Rectangle output;
  688. output.x = position.x + rect.x * scaling;
  689. output.y = position.y + rect.y * scaling;
  690. output.width = rect.w * scaling;
  691. output.height = rect.h * scaling;
  692. return output;
  693. }
  694. /**
  695. * Convert the given raylib Rectangle to a Nuklear rectangle.
  696. */
  697. NK_API struct
  698. nk_rect RectangleToNuklear(struct nk_context* ctx, Rectangle rect)
  699. {
  700. float scaling = GetNuklearScaling(ctx);
  701. Vector2 position = GetNuklearPosition(ctx);
  702. return nk_rect(rect.x / scaling - position.x, rect.y / scaling - position.y, rect.width / scaling, rect.height / scaling);
  703. }
  704. /**
  705. * Convert the given raylib texture to a Nuklear image
  706. */
  707. NK_API struct nk_image TextureToNuklear(Texture tex)
  708. {
  709. // Declare the img to store data and allocate memory
  710. // For the texture
  711. struct nk_image img;
  712. struct Texture* stored_tex = (struct Texture*)MemAlloc(sizeof(Texture));
  713. // Copy the data from the texture given into the new texture
  714. stored_tex->id = tex.id;
  715. stored_tex->width = tex.width;
  716. stored_tex->height = tex.height;
  717. stored_tex->mipmaps = tex.mipmaps;
  718. stored_tex->format = tex.format;
  719. // Initialize the nk_image struct
  720. img.handle.ptr = stored_tex;
  721. img.w = (nk_ushort)stored_tex->width;
  722. img.h = (nk_ushort)stored_tex->height;
  723. return img;
  724. }
  725. /**
  726. * Convert the given Nuklear image to a raylib Texture
  727. */
  728. NK_API struct Texture TextureFromNuklear(struct nk_image img)
  729. {
  730. // Declare texture for storage
  731. // And get back the stored texture
  732. Texture tex;
  733. Texture* stored_tex = (Texture*)img.handle.ptr;
  734. // Copy the data from the stored texture to the texture
  735. tex.id = stored_tex->id;
  736. tex.width = stored_tex->width;
  737. tex.height = stored_tex->height;
  738. tex.mipmaps = stored_tex->mipmaps;
  739. tex.format = stored_tex->format;
  740. return tex;
  741. }
  742. /**
  743. * Load a Nuklear image directly
  744. *
  745. * @param path The path to the image
  746. */
  747. NK_API struct nk_image LoadNuklearImage(const char* path)
  748. {
  749. return TextureToNuklear(LoadTexture(path));
  750. }
  751. /**
  752. * Unload a loaded Nuklear image
  753. *
  754. * @param img The Nuklear image to unload
  755. */
  756. NK_API void UnloadNuklearImage(struct nk_image img)
  757. {
  758. Texture tex = TextureFromNuklear(img);
  759. UnloadTexture(tex);
  760. CleanupNuklearImage(img);
  761. }
  762. /**
  763. * Cleans up memory used by a Nuklear image
  764. * Does not unload the image.
  765. *
  766. * @param img The Nuklear image to cleanup
  767. */
  768. NK_API void CleanupNuklearImage(struct nk_image img)
  769. {
  770. MemFree(img.handle.ptr);
  771. }
  772. /**
  773. * Sets the scaling of the given Nuklear context.
  774. *
  775. * @param ctx The nuklear context.
  776. * @param scaling How much scale to apply to the graphical user interface.
  777. */
  778. NK_API void SetNuklearScaling(struct nk_context * ctx, float scaling)
  779. {
  780. if (ctx == NULL) {
  781. return;
  782. }
  783. if (scaling <= 0.0f) {
  784. TraceLog(LOG_WARNING, "NUKLEAR: Cannot set scaling to be less than 0");
  785. return;
  786. }
  787. struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr;
  788. if (userData != NULL) {
  789. userData->scaling = scaling;
  790. }
  791. }
  792. /**
  793. * Retrieves the scale value of the given Nuklear context.
  794. *
  795. * @return The scale value that had been set for the Nuklear context. 1.0f is the default scale value.
  796. */
  797. NK_API float GetNuklearScaling(struct nk_context * ctx)
  798. {
  799. if (ctx == NULL) {
  800. return 1.0f;
  801. }
  802. struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr;
  803. if (userData != NULL) {
  804. return userData->scaling;
  805. }
  806. return 1.0f;
  807. }
  808. /**
  809. * Sets the position of the given Nuklear context.
  810. *
  811. * @param ctx The nuklear context.
  812. * @param position Where to position the graphical user interface.
  813. */
  814. NK_API void SetNuklearPosition(struct nk_context * ctx, Vector2 position)
  815. {
  816. if (ctx == NULL) {
  817. return;
  818. }
  819. struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr;
  820. if (userData != NULL) {
  821. userData->position = position;
  822. }
  823. }
  824. /**
  825. * Retrieves the position of the given Nuklear context.
  826. *
  827. * @return The position that had been set for the Nuklear context.
  828. */
  829. NK_API Vector2 GetNuklearPosition(struct nk_context * ctx)
  830. {
  831. if (ctx == NULL) {
  832. return (Vector2){0.0f, 0.0f};
  833. }
  834. struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr;
  835. if (userData != NULL) {
  836. return userData->position;
  837. }
  838. return (Vector2){0.0f, 0.0f};
  839. }
  840. #ifdef __cplusplus
  841. }
  842. #endif
  843. #endif // RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE
  844. #endif // RAYLIB_NUKLEAR_IMPLEMENTATION