DPF OpenGL examples
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1311 lines
44KB

  1. //
  2. // based on NanoVG's example code by Mikko Mononen
  3. #include <stdio.h>
  4. #include <stdbool.h>
  5. #ifdef NANOVG_GLEW
  6. # include <GL/glew.h>
  7. #endif
  8. #ifdef __APPLE__
  9. # define GLFW_INCLUDE_GLCOREARB
  10. #endif
  11. #include <GLFW/glfw3.h>
  12. #include "nanovg.h"
  13. #define NANOVG_GL3_IMPLEMENTATION
  14. #include "nanovg_gl.h"
  15. #define BLENDISH_IMPLEMENTATION
  16. #include "blendish.h"
  17. #define OUI_IMPLEMENTATION
  18. #include "oui.h"
  19. ////////////////////////////////////////////////////////////////////////////////
  20. typedef struct exContext {
  21. NVGcontext *vg;
  22. UIcontext *uictx;
  23. } exContext;
  24. typedef enum {
  25. // label
  26. ST_LABEL = 0,
  27. // button
  28. ST_BUTTON = 1,
  29. // radio button
  30. ST_RADIO = 2,
  31. // progress slider
  32. ST_SLIDER = 3,
  33. // column
  34. ST_COLUMN = 4,
  35. // row
  36. ST_ROW = 5,
  37. // check button
  38. ST_CHECK = 6,
  39. // panel
  40. ST_PANEL = 7,
  41. // text
  42. ST_TEXT = 8,
  43. //
  44. ST_IGNORE = 9,
  45. ST_DEMOSTUFF = 10,
  46. // colored rectangle
  47. ST_RECT = 11,
  48. ST_HBOX = 12,
  49. ST_VBOX = 13,
  50. } SubType;
  51. typedef struct {
  52. int subtype;
  53. UIhandler handler;
  54. } UIData;
  55. typedef struct {
  56. UIData head;
  57. const char *label;
  58. NVGcolor color;
  59. } UIRectData;
  60. typedef struct {
  61. UIData head;
  62. int iconid;
  63. const char *label;
  64. } UIButtonData;
  65. typedef struct {
  66. UIData head;
  67. const char *label;
  68. bool *option;
  69. } UICheckData;
  70. typedef struct {
  71. UIData head;
  72. int iconid;
  73. const char *label;
  74. int *value;
  75. } UIRadioData;
  76. typedef struct {
  77. UIData head;
  78. const char *label;
  79. float *progress;
  80. } UISliderData;
  81. typedef struct {
  82. UIData head;
  83. char *text;
  84. int maxsize;
  85. } UITextData;
  86. ////////////////////////////////////////////////////////////////////////////////
  87. void draw_demostuff(NVGcontext *vg, int x, int y, float w, float h);
  88. void ui_handler(UIcontext *uictx, int item, UIevent event) {
  89. UIData *data = (UIData *)uiGetHandle(uictx, item);
  90. if (data && data->handler) {
  91. data->handler(uictx, item, event);
  92. }
  93. }
  94. void init(NVGcontext *vg) {
  95. bndSetFont(nvgCreateFont(vg, "system", "../DejaVuSans.ttf"));
  96. bndSetIconImage(nvgCreateImage(vg, "../blender_icons16.png", 0));
  97. }
  98. void testrect(NVGcontext *vg, UIrect rect) {
  99. #if 0
  100. nvgBeginPath(vg);
  101. nvgRect(vg,rect.x+0.5,rect.y+0.5,rect.w-1,rect.h-1);
  102. nvgStrokeColor(vg,nvgRGBf(1,0,0));
  103. nvgStrokeWidth(vg,1);
  104. nvgStroke(vg);
  105. #endif
  106. }
  107. void drawUI(exContext *ectx, int item, int corners);
  108. void drawUIItems(exContext *ectx, int item, int corners) {
  109. int kid = uiFirstChild(ectx->uictx, item);
  110. while (kid > 0) {
  111. drawUI(ectx, kid, corners);
  112. kid = uiNextSibling(ectx->uictx, kid);
  113. }
  114. }
  115. void drawUIItemsHbox(exContext *ectx, int item) {
  116. int kid = uiFirstChild(ectx->uictx, item);
  117. if (kid < 0) return;
  118. int nextkid = uiNextSibling(ectx->uictx, kid);
  119. if (nextkid < 0) {
  120. drawUI(ectx, kid, BND_CORNER_NONE);
  121. } else {
  122. drawUI(ectx, kid, BND_CORNER_RIGHT);
  123. kid = nextkid;
  124. while (uiNextSibling(ectx->uictx, kid) > 0) {
  125. drawUI(ectx, kid, BND_CORNER_ALL);
  126. kid = uiNextSibling(ectx->uictx, kid);
  127. }
  128. drawUI(ectx, kid, BND_CORNER_LEFT);
  129. }
  130. }
  131. void drawUIItemsVbox(exContext *ectx, int item) {
  132. int kid = uiFirstChild(ectx->uictx, item);
  133. if (kid < 0) return;
  134. int nextkid = uiNextSibling(ectx->uictx, kid);
  135. if (nextkid < 0) {
  136. drawUI(ectx, kid, BND_CORNER_NONE);
  137. } else {
  138. drawUI(ectx, kid, BND_CORNER_DOWN);
  139. kid = nextkid;
  140. while (uiNextSibling(ectx->uictx, kid) > 0) {
  141. drawUI(ectx, kid, BND_CORNER_ALL);
  142. kid = uiNextSibling(ectx->uictx, kid);
  143. }
  144. drawUI(ectx, kid, BND_CORNER_TOP);
  145. }
  146. }
  147. void drawUI(exContext *ectx, int item, int corners) {
  148. NVGcontext *vg = ectx->vg;
  149. UIcontext *uictx = ectx->uictx;
  150. const UIData *head = (const UIData *)uiGetHandle(uictx, item);
  151. UIrect rect = uiGetRect(uictx, item);
  152. if (uiGetState(uictx, item) == UI_FROZEN) {
  153. nvgGlobalAlpha(vg, BND_DISABLED_ALPHA);
  154. }
  155. if (head) {
  156. switch(head->subtype) {
  157. default: {
  158. testrect(vg, rect);
  159. drawUIItems(ectx,item,corners);
  160. } break;
  161. case ST_HBOX: {
  162. drawUIItemsHbox(ectx, item);
  163. } break;
  164. case ST_VBOX: {
  165. drawUIItemsVbox(ectx, item);
  166. } break;
  167. case ST_PANEL: {
  168. bndBevel(vg,rect.x,rect.y,rect.w,rect.h);
  169. drawUIItems(ectx,item,corners);
  170. } break;
  171. case ST_LABEL: {
  172. assert(head);
  173. const UIButtonData *data = (UIButtonData*)head;
  174. bndLabel(vg,rect.x,rect.y,rect.w,rect.h,
  175. data->iconid,data->label);
  176. } break;
  177. case ST_BUTTON: {
  178. const UIButtonData *data = (UIButtonData*)head;
  179. bndToolButton(vg,rect.x,rect.y,rect.w,rect.h,
  180. corners,(BNDwidgetState)uiGetState(uictx, item),
  181. data->iconid,data->label);
  182. } break;
  183. case ST_CHECK: {
  184. const UICheckData *data = (UICheckData*)head;
  185. BNDwidgetState state = (BNDwidgetState)uiGetState(uictx, item);
  186. if (*data->option)
  187. state = BND_ACTIVE;
  188. bndOptionButton(vg,rect.x,rect.y,rect.w,rect.h, state,
  189. data->label);
  190. } break;
  191. case ST_RADIO:{
  192. const UIRadioData *data = (UIRadioData*)head;
  193. BNDwidgetState state = (BNDwidgetState)uiGetState(uictx, item);
  194. if (*data->value == item)
  195. state = BND_ACTIVE;
  196. bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h,
  197. corners,state,
  198. data->iconid,data->label);
  199. } break;
  200. case ST_SLIDER:{
  201. const UISliderData *data = (UISliderData*)head;
  202. BNDwidgetState state = (BNDwidgetState)uiGetState(uictx, item);
  203. static char value[32];
  204. sprintf(value,"%.0f%%",(*data->progress)*100.0f);
  205. bndSlider(vg,rect.x,rect.y,rect.w,rect.h,
  206. corners,state,
  207. *data->progress,data->label,value);
  208. } break;
  209. case ST_TEXT: {
  210. const UITextData *data = (UITextData*)head;
  211. BNDwidgetState state = (BNDwidgetState)uiGetState(uictx, item);
  212. int idx = strlen(data->text);
  213. bndTextField(vg,rect.x,rect.y,rect.w,rect.h,
  214. corners,state, -1, data->text, idx, idx);
  215. } break;
  216. case ST_DEMOSTUFF: {
  217. draw_demostuff(vg, rect.x, rect.y, rect.w, rect.h);
  218. } break;
  219. case ST_RECT: {
  220. const UIRectData *data = (UIRectData*)head;
  221. if (rect.w && rect.h) {
  222. BNDwidgetState state = (BNDwidgetState)uiGetState(uictx, item);
  223. nvgSave(vg);
  224. nvgStrokeColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.9f));
  225. if (state != BND_DEFAULT) {
  226. nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.5f));
  227. } else {
  228. nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.1f));
  229. }
  230. nvgStrokeWidth(vg,2);
  231. nvgBeginPath(vg);
  232. #if 0
  233. nvgRect(vg,rect.x,rect.y,rect.w,rect.h);
  234. #else
  235. nvgRoundedRect(vg,rect.x,rect.y,rect.w,rect.h,3);
  236. #endif
  237. nvgFill(vg);
  238. nvgStroke(vg);
  239. if (state != BND_DEFAULT) {
  240. nvgFillColor(vg, nvgRGBAf(0.0f,0.0f,0.0f,1.0f));
  241. nvgFontSize(vg, 15.0f);
  242. nvgBeginPath(vg);
  243. nvgTextAlign(vg, NVG_ALIGN_TOP|NVG_ALIGN_CENTER);
  244. nvgTextBox(vg, rect.x, rect.y+rect.h*0.3f, rect.w, data->label, NULL);
  245. }
  246. nvgRestore(vg);
  247. }
  248. nvgSave(vg);
  249. nvgIntersectScissor(vg, rect.x, rect.y, rect.w, rect.h);
  250. drawUIItems(ectx,item,corners);
  251. nvgRestore(vg);
  252. } break;
  253. }
  254. } else {
  255. testrect(vg,rect);
  256. drawUIItems(ectx,item,corners);
  257. }
  258. if (uiGetState(uictx, item) == UI_FROZEN) {
  259. nvgGlobalAlpha(vg, 1.0);
  260. }
  261. }
  262. int colorrect(UIcontext *uictx, const char *label, NVGcolor color) {
  263. int item = uiItem(uictx);
  264. UIRectData *data = (UIRectData *)uiAllocHandle(uictx, item, sizeof(UIRectData));
  265. data->head.subtype = ST_RECT;
  266. data->head.handler = NULL;
  267. data->label = label;
  268. data->color = color;
  269. uiSetEvents(uictx, item, UI_BUTTON0_DOWN);
  270. return item;
  271. }
  272. int label(UIcontext *uictx, int iconid, const char *label) {
  273. int item = uiItem(uictx);
  274. uiSetSize(uictx, item, 0, BND_WIDGET_HEIGHT);
  275. UIButtonData *data = (UIButtonData *)uiAllocHandle(uictx, item, sizeof(UIButtonData));
  276. data->head.subtype = ST_LABEL;
  277. data->head.handler = NULL;
  278. data->iconid = iconid;
  279. data->label = label;
  280. return item;
  281. }
  282. void demohandler(UIcontext *uictx, int item, UIevent event) {
  283. const UIButtonData *data = (const UIButtonData *)uiGetHandle(uictx, item);
  284. printf("clicked: %p %s\n", uiGetHandle(uictx, item), data->label);
  285. }
  286. int button(UIcontext *uictx, int iconid, const char *label, UIhandler handler) {
  287. // create new ui item
  288. int item = uiItem(uictx);
  289. // set size of wiget; horizontal size is dynamic, vertical is fixed
  290. uiSetSize(uictx, item, 0, BND_WIDGET_HEIGHT);
  291. uiSetEvents(uictx, item, UI_BUTTON0_HOT_UP);
  292. // store some custom data with the button that we use for styling
  293. UIButtonData *data = (UIButtonData *)uiAllocHandle(uictx, item, sizeof(UIButtonData));
  294. data->head.subtype = ST_BUTTON;
  295. data->head.handler = handler;
  296. data->iconid = iconid;
  297. data->label = label;
  298. return item;
  299. }
  300. void checkhandler(UIcontext *uictx, int item, UIevent event) {
  301. const UICheckData *data = (const UICheckData *)uiGetHandle(uictx, item);
  302. *data->option = !(*data->option);
  303. }
  304. int check(UIcontext *uictx, const char *label, bool *option) {
  305. // create new ui item
  306. int item = uiItem(uictx);
  307. // set size of wiget; horizontal size is dynamic, vertical is fixed
  308. uiSetSize(uictx, item, 0, BND_WIDGET_HEIGHT);
  309. // attach event handler e.g. demohandler above
  310. uiSetEvents(uictx, item, UI_BUTTON0_DOWN);
  311. // store some custom data with the button that we use for styling
  312. UICheckData *data = (UICheckData *)uiAllocHandle(uictx, item, sizeof(UICheckData));
  313. data->head.subtype = ST_CHECK;
  314. data->head.handler = checkhandler;
  315. data->label = label;
  316. data->option = option;
  317. return item;
  318. }
  319. // simple logic for a slider
  320. // starting offset of the currently active slider
  321. static float sliderstart = 0.0;
  322. // event handler for slider (same handler for all sliders)
  323. void sliderhandler(UIcontext *uictx, int item, UIevent event) {
  324. // retrieve the custom data we saved with the slider
  325. UISliderData *data = (UISliderData *)uiGetHandle(uictx, item);
  326. switch(event) {
  327. default: break;
  328. case UI_BUTTON0_DOWN: {
  329. // button was pressed for the first time; capture initial
  330. // slider value.
  331. sliderstart = *data->progress;
  332. } break;
  333. case UI_BUTTON0_CAPTURE: {
  334. // called for every frame that the button is pressed.
  335. // get the delta between the click point and the current
  336. // mouse position
  337. UIvec2 pos = uiGetCursorStartDelta(uictx);
  338. // get the items layouted rectangle
  339. UIrect rc = uiGetRect(uictx, item);
  340. // calculate our new offset and clamp
  341. float value = sliderstart + ((float)pos.x / (float)rc.w);
  342. value = (value<0)?0:(value>1)?1:value;
  343. // assign the new value
  344. *data->progress = value;
  345. } break;
  346. }
  347. }
  348. int slider(UIcontext *uictx, const char *label, float *progress) {
  349. // create new ui item
  350. int item = uiItem(uictx);
  351. // set size of wiget; horizontal size is dynamic, vertical is fixed
  352. uiSetSize(uictx, item, 0, BND_WIDGET_HEIGHT);
  353. // attach our slider event handler and capture two classes of events
  354. uiSetEvents(uictx, item, UI_BUTTON0_DOWN | UI_BUTTON0_CAPTURE);
  355. // store some custom data with the button that we use for styling
  356. // and logic, e.g. the pointer to the data we want to alter.
  357. UISliderData *data = (UISliderData *)uiAllocHandle(uictx, item, sizeof(UISliderData));
  358. data->head.subtype = ST_SLIDER;
  359. data->head.handler = sliderhandler;
  360. data->label = label;
  361. data->progress = progress;
  362. return item;
  363. }
  364. void textboxhandler(UIcontext *uictx, int item, UIevent event) {
  365. UITextData *data = (UITextData *)uiGetHandle(uictx, item);
  366. switch(event) {
  367. default: break;
  368. case UI_BUTTON0_DOWN: {
  369. uiFocus(uictx, item);
  370. } break;
  371. case UI_KEY_DOWN: {
  372. unsigned int key = uiGetKey(uictx);
  373. switch(key) {
  374. default: break;
  375. case GLFW_KEY_BACKSPACE: {
  376. int size = strlen(data->text);
  377. if (!size) return;
  378. data->text[size-1] = 0;
  379. } break;
  380. case GLFW_KEY_ENTER: {
  381. uiFocus(uictx, -1);
  382. } break;
  383. }
  384. } break;
  385. case UI_CHAR: {
  386. unsigned int key = uiGetKey(uictx);
  387. if ((key > 255)||(key < 32)) return;
  388. int size = strlen(data->text);
  389. if (size >= (data->maxsize-1)) return;
  390. data->text[size] = (char)key;
  391. } break;
  392. }
  393. }
  394. int textbox(UIcontext *uictx, char *text, int maxsize) {
  395. int item = uiItem(uictx);
  396. uiSetSize(uictx, item, 0, BND_WIDGET_HEIGHT);
  397. uiSetEvents(uictx, item, UI_BUTTON0_DOWN | UI_KEY_DOWN | UI_CHAR);
  398. // store some custom data with the button that we use for styling
  399. // and logic, e.g. the pointer to the data we want to alter.
  400. UITextData *data = (UITextData *)uiAllocHandle(uictx, item, sizeof(UITextData));
  401. data->head.subtype = ST_TEXT;
  402. data->head.handler = textboxhandler;
  403. data->text = text;
  404. data->maxsize = maxsize;
  405. return item;
  406. }
  407. // simple logic for a radio button
  408. void radiohandler(UIcontext *uictx, int item, UIevent event) {
  409. UIRadioData *data = (UIRadioData *)uiGetHandle(uictx, item);
  410. *data->value = item;
  411. }
  412. int radio(UIcontext *uictx, int iconid, const char *label, int *value) {
  413. int item = uiItem(uictx);
  414. uiSetSize(uictx, item, label?0:BND_TOOL_WIDTH, BND_WIDGET_HEIGHT);
  415. UIRadioData *data = (UIRadioData *)uiAllocHandle(uictx, item, sizeof(UIRadioData));
  416. data->head.subtype = ST_RADIO;
  417. data->head.handler = radiohandler;
  418. data->iconid = iconid;
  419. data->label = label;
  420. data->value = value;
  421. uiSetEvents(uictx, item, UI_BUTTON0_DOWN);
  422. return item;
  423. }
  424. int panel(UIcontext *uictx) {
  425. int item = uiItem(uictx);
  426. UIData *data = (UIData *)uiAllocHandle(uictx, item, sizeof(UIData));
  427. data->subtype = ST_PANEL;
  428. data->handler = NULL;
  429. return item;
  430. }
  431. int hbox(UIcontext *uictx) {
  432. int item = uiItem(uictx);
  433. UIData *data = (UIData *)uiAllocHandle(uictx, item, sizeof(UIData));
  434. data->subtype = ST_HBOX;
  435. data->handler = NULL;
  436. uiSetBox(uictx, item, UI_ROW);
  437. return item;
  438. }
  439. int vbox(UIcontext *uictx) {
  440. int item = uiItem(uictx);
  441. UIData *data = (UIData *)uiAllocHandle(uictx, item, sizeof(UIData));
  442. data->subtype = ST_VBOX;
  443. data->handler = NULL;
  444. uiSetBox(uictx, item, UI_COLUMN);
  445. return item;
  446. }
  447. int column_append(UIcontext *uictx, int parent, int item) {
  448. uiInsert(uictx, parent, item);
  449. // fill parent horizontally, anchor to previous item vertically
  450. uiSetLayout(uictx, item, UI_HFILL);
  451. uiSetMargins(uictx, item, 0, 1, 0, 0);
  452. return item;
  453. }
  454. int column(UIcontext *uictx) {
  455. int item = uiItem(uictx);
  456. uiSetBox(uictx, item, UI_COLUMN);
  457. return item;
  458. }
  459. int vgroup_append(UIcontext *uictx, int parent, int item) {
  460. uiInsert(uictx, parent, item);
  461. // fill parent horizontally, anchor to previous item vertically
  462. uiSetLayout(uictx, item, UI_HFILL);
  463. return item;
  464. }
  465. int vgroup(UIcontext *uictx) {
  466. int item = uiItem(uictx);
  467. uiSetBox(uictx, item, UI_COLUMN);
  468. return item;
  469. }
  470. int hgroup_append(UIcontext *uictx, int parent, int item) {
  471. uiInsert(uictx, parent, item);
  472. uiSetLayout(uictx, item, UI_HFILL);
  473. return item;
  474. }
  475. int hgroup_append_fixed(UIcontext *uictx, int parent, int item) {
  476. uiInsert(uictx, parent, item);
  477. return item;
  478. }
  479. int hgroup(UIcontext *uictx) {
  480. int item = uiItem(uictx);
  481. uiSetBox(uictx, item, UI_ROW);
  482. return item;
  483. }
  484. int row_append(UIcontext *uictx, int parent, int item) {
  485. uiInsert(uictx, parent, item);
  486. uiSetLayout(uictx, item, UI_HFILL);
  487. return item;
  488. }
  489. int row(UIcontext *uictx) {
  490. int item = uiItem(uictx);
  491. uiSetBox(uictx, item, UI_ROW);
  492. return item;
  493. }
  494. void draw_noodles(NVGcontext *vg, int x, int y) {
  495. int w = 200;
  496. int s = 70;
  497. int i;
  498. bndNodeBackground(vg, x+w, y-50, 100, 200, BND_DEFAULT, BND_ICONID(6,3),
  499. "Default", nvgRGBf(0.392f,0.392f,0.392f));
  500. bndNodeBackground(vg, x+w+120, y-50, 100, 200, BND_HOVER, BND_ICONID(6,3),
  501. "Hover", nvgRGBf(0.392f,0.392f,0.392f));
  502. bndNodeBackground(vg, x+w+240, y-50, 100, 200, BND_ACTIVE, BND_ICONID(6,3),
  503. "Active", nvgRGBf(0.392f,0.392f,0.392f));
  504. for (i = 0; i < 9; ++i) {
  505. int a = i%3;
  506. int b = i/3;
  507. bndNodeWire(vg, x, y+s*a, x+w, y+s*b, (BNDwidgetState)a, (BNDwidgetState)b);
  508. }
  509. bndNodePort(vg, x, y, BND_DEFAULT, nvgRGBf(0.5f, 0.5f, 0.5f));
  510. bndNodePort(vg, x+w, y, BND_DEFAULT, nvgRGBf(0.5f, 0.5f, 0.5f));
  511. bndNodePort(vg, x, y+s, BND_HOVER, nvgRGBf(0.5f, 0.5f, 0.5f));
  512. bndNodePort(vg, x+w, y+s, BND_HOVER, nvgRGBf(0.5f, 0.5f, 0.5f));
  513. bndNodePort(vg, x, y+2*s, BND_ACTIVE, nvgRGBf(0.5f, 0.5f, 0.5f));
  514. bndNodePort(vg, x+w, y+2*s, BND_ACTIVE, nvgRGBf(0.5f, 0.5f, 0.5f));
  515. }
  516. static void roothandler(UIcontext *uictx, int parent, UIevent event) {
  517. switch(event) {
  518. default: break;
  519. case UI_SCROLL: {
  520. UIvec2 pos = uiGetScroll(uictx);
  521. printf("scroll! %d %d\n", pos.x, pos.y);
  522. } break;
  523. case UI_BUTTON0_DOWN: {
  524. printf("%d clicks\n", uiGetClicks(uictx));
  525. } break;
  526. }
  527. }
  528. void draw_demostuff(NVGcontext *vg, int x, int y, float w, float h) {
  529. nvgSave(vg);
  530. nvgTranslate(vg, x, y);
  531. bndSplitterWidgets(vg, 0, 0, w, h);
  532. x = 10;
  533. y = 10;
  534. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  535. BND_ICONID(6,3),"Default");
  536. y += 25;
  537. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  538. BND_ICONID(6,3),"Hovered");
  539. y += 25;
  540. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  541. BND_ICONID(6,3),"Active");
  542. y += 40;
  543. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  544. -1,"Default");
  545. y += 25;
  546. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  547. -1,"Hovered");
  548. y += 25;
  549. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  550. -1,"Active");
  551. y += 25;
  552. bndLabel(vg,x,y,120,BND_WIDGET_HEIGHT,-1,"Label:");
  553. y += BND_WIDGET_HEIGHT;
  554. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  555. -1, "Default");
  556. y += 25;
  557. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  558. -1, "Hovered");
  559. y += 25;
  560. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  561. -1, "Active");
  562. y += 25;
  563. int ry = y;
  564. int rx = x;
  565. y = 10;
  566. x += 130;
  567. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_DEFAULT,"Default");
  568. y += 25;
  569. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_HOVER,"Hovered");
  570. y += 25;
  571. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_ACTIVE,"Active");
  572. y += 40;
  573. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_DOWN,BND_DEFAULT,
  574. "Top","100");
  575. y += BND_WIDGET_HEIGHT-2;
  576. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  577. "Center","100");
  578. y += BND_WIDGET_HEIGHT-2;
  579. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_TOP,BND_DEFAULT,
  580. "Bottom","100");
  581. int mx = x-30;
  582. int my = y-12;
  583. int mw = 120;
  584. bndMenuBackground(vg,mx,my,mw,120,BND_CORNER_TOP);
  585. bndMenuLabel(vg,mx,my,mw,BND_WIDGET_HEIGHT,-1,"Menu Title");
  586. my += BND_WIDGET_HEIGHT-2;
  587. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_DEFAULT,
  588. BND_ICONID(17,3),"Default");
  589. my += BND_WIDGET_HEIGHT-2;
  590. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_HOVER,
  591. BND_ICONID(18,3),"Hovered");
  592. my += BND_WIDGET_HEIGHT-2;
  593. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_ACTIVE,
  594. BND_ICONID(19,3),"Active");
  595. y = 10;
  596. x += 130;
  597. int ox = x;
  598. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  599. "Default","100");
  600. y += 25;
  601. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  602. "Hovered","100");
  603. y += 25;
  604. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  605. "Active","100");
  606. y += 40;
  607. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,BND_DEFAULT,
  608. -1,"One");
  609. x += 60-1;
  610. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  611. -1,"Two");
  612. x += 60-1;
  613. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  614. -1,"Three");
  615. x += 60-1;
  616. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,BND_ACTIVE,
  617. -1,"Butts");
  618. x = ox;
  619. y += 40;
  620. float progress_value = fmodf(glfwGetTime()/10.0,1.0);
  621. char progress_label[32];
  622. sprintf(progress_label, "%d%%", (int)(progress_value*100+0.5f));
  623. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  624. progress_value,"Default",progress_label);
  625. y += 25;
  626. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  627. progress_value,"Hovered",progress_label);
  628. y += 25;
  629. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  630. progress_value,"Active",progress_label);
  631. int rw = x+240-rx;
  632. float s_offset = sinf(glfwGetTime()/2.0)*0.5+0.5;
  633. float s_size = cosf(glfwGetTime()/3.11)*0.5+0.5;
  634. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_DEFAULT,s_offset,s_size);
  635. ry += 20;
  636. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_HOVER,s_offset,s_size);
  637. ry += 20;
  638. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_ACTIVE,s_offset,s_size);
  639. const char edit_text[] = "The quick brown fox";
  640. int textlen = strlen(edit_text)+1;
  641. int t = (int)(glfwGetTime()*2);
  642. int idx1 = (t/textlen)%textlen;
  643. int idx2 = idx1 + (t%(textlen-idx1));
  644. ry += 25;
  645. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  646. -1, edit_text, idx1, idx2);
  647. ry += 25;
  648. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  649. -1, edit_text, idx1, idx2);
  650. ry += 25;
  651. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  652. -1, edit_text, idx1, idx2);
  653. draw_noodles(vg, 20, ry+50);
  654. rx += rw + 20;
  655. ry = 10;
  656. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_DEFAULT,s_offset,s_size);
  657. rx += 20;
  658. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_HOVER,s_offset,s_size);
  659. rx += 20;
  660. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_ACTIVE,s_offset,s_size);
  661. x = ox;
  662. y += 40;
  663. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  664. BND_DEFAULT,BND_ICONID(0,10),NULL);
  665. x += BND_TOOL_WIDTH-1;
  666. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  667. BND_DEFAULT,BND_ICONID(1,10),NULL);
  668. x += BND_TOOL_WIDTH-1;
  669. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  670. BND_DEFAULT,BND_ICONID(2,10),NULL);
  671. x += BND_TOOL_WIDTH-1;
  672. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  673. BND_DEFAULT,BND_ICONID(3,10),NULL);
  674. x += BND_TOOL_WIDTH-1;
  675. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  676. BND_DEFAULT,BND_ICONID(4,10),NULL);
  677. x += BND_TOOL_WIDTH-1;
  678. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  679. BND_DEFAULT,BND_ICONID(5,10),NULL);
  680. x += BND_TOOL_WIDTH-1;
  681. x += 5;
  682. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  683. BND_DEFAULT,BND_ICONID(0,11),NULL);
  684. x += BND_TOOL_WIDTH-1;
  685. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  686. BND_DEFAULT,BND_ICONID(1,11),NULL);
  687. x += BND_TOOL_WIDTH-1;
  688. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  689. BND_DEFAULT,BND_ICONID(2,11),NULL);
  690. x += BND_TOOL_WIDTH-1;
  691. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  692. BND_DEFAULT,BND_ICONID(3,11),NULL);
  693. x += BND_TOOL_WIDTH-1;
  694. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  695. BND_ACTIVE,BND_ICONID(4,11),NULL);
  696. x += BND_TOOL_WIDTH-1;
  697. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  698. BND_DEFAULT,BND_ICONID(5,11),NULL);
  699. nvgRestore(vg);
  700. }
  701. static int enum1 = -1;
  702. void build_democontent(UIcontext *uictx, int parent) {
  703. // some persistent variables for demonstration
  704. static float progress1 = 0.25f;
  705. static float progress2 = 0.75f;
  706. static bool option1 = true;
  707. static bool option2 = false;
  708. static bool option3 = false;
  709. int col = column(uictx);
  710. uiInsert(uictx, parent, col);
  711. uiSetMargins(uictx, col, 10, 10, 10, 10);
  712. uiSetLayout(uictx, col, UI_TOP|UI_HFILL);
  713. column_append(uictx, col, button(uictx, BND_ICON_GHOST, "Item 1", demohandler));
  714. if (option3)
  715. column_append(uictx, col, button(uictx, BND_ICON_GHOST, "Item 2", demohandler));
  716. {
  717. int h = column_append(uictx, col, hbox(uictx));
  718. hgroup_append(uictx, h, radio(uictx, BND_ICON_GHOST, "Item 3.0", &enum1));
  719. if (option2)
  720. uiSetMargins(uictx, hgroup_append_fixed(uictx, h, radio(uictx, BND_ICON_REC, NULL, &enum1)), -1,0,0,0);
  721. uiSetMargins(uictx, hgroup_append_fixed(uictx, h, radio(uictx, BND_ICON_PLAY, NULL, &enum1)), -1,0,0,0);
  722. uiSetMargins(uictx, hgroup_append(uictx, h, radio(uictx, BND_ICON_GHOST, "Item 3.3", &enum1)), -1,0,0,0);
  723. }
  724. {
  725. int rows = column_append(uictx, col, row(uictx));
  726. int coll = row_append(uictx, rows, vgroup(uictx));
  727. vgroup_append(uictx, coll, label(uictx, -1, "Items 4.0:"));
  728. coll = vgroup_append(uictx, coll, vbox(uictx));
  729. vgroup_append(uictx, coll, button(uictx, BND_ICON_GHOST, "Item 4.0.0", demohandler));
  730. uiSetMargins(uictx, vgroup_append(uictx, coll, button(uictx, BND_ICON_GHOST, "Item 4.0.1", demohandler)),0,-2,0,0);
  731. int colr = row_append(uictx, rows, vgroup(uictx));
  732. uiSetMargins(uictx, colr, 8, 0, 0, 0);
  733. uiSetFrozen(uictx, colr, option1);
  734. vgroup_append(uictx, colr, label(uictx, -1, "Items 4.1:"));
  735. colr = vgroup_append(uictx, colr, vbox(uictx));
  736. vgroup_append(uictx, colr, slider(uictx, "Item 4.1.0", &progress1));
  737. uiSetMargins(uictx, vgroup_append(uictx, colr, slider(uictx, "Item 4.1.1", &progress2)),0,-2,0,0);
  738. }
  739. column_append(uictx, col, button(uictx, BND_ICON_GHOST, "Item 5", NULL));
  740. static char textbuffer[1024] = "The quick brown fox.";
  741. column_append(uictx, col, textbox(uictx, textbuffer, 1024));
  742. column_append(uictx, col, check(uictx, "Frozen", &option1));
  743. column_append(uictx, col, check(uictx, "Item 7", &option2));
  744. column_append(uictx, col, check(uictx, "Item 8", &option3));
  745. }
  746. int demorect(UIcontext *uictx, int parent, const char *label, float hue, int box, int layout, int w, int h, int m1, int m2, int m3, int m4) {
  747. int item = colorrect(uictx, label, nvgHSL(hue, 1.0f, 0.8f));
  748. uiSetLayout(uictx, item, layout);
  749. uiSetBox(uictx, item, box);
  750. uiSetMargins(uictx, item, m1, m2, m3, m4);
  751. uiSetSize(uictx, item, w, h);
  752. uiInsert(uictx, parent, item);
  753. return item;
  754. }
  755. void build_layoutdemo(UIcontext *uictx, int parent) {
  756. const int M = 10;
  757. const int S = 150;
  758. int box = demorect(uictx, parent, "Box( UI_LAYOUT )\nLayout( UI_FILL )", 0.6f, UI_LAYOUT, UI_FILL, 0, 0, M, M, M, M);
  759. demorect(uictx, box, "Layout( UI_HFILL | UI_TOP )", 0.7f, 0, UI_HFILL|UI_TOP, S, S+M, M, M, M, 0);
  760. demorect(uictx, box, "Layout( UI_HFILL )", 0.7f, 0, UI_HFILL, S, S+2*M, M, 0, M, 0);
  761. demorect(uictx, box, "Layout( UI_HFILL | UI_DOWN )", 0.7f, 0, UI_HFILL|UI_DOWN, S, S+M, M, 0, M, M);
  762. demorect(uictx, box, "Layout( UI_LEFT | UI_VFILL )", 0.7f, 0, UI_LEFT|UI_VFILL, S+M, S, M, M, 0, M);
  763. demorect(uictx, box, "Layout( UI_VFILL )", 0.7f, 0, UI_VFILL, S+2*M, S, 0, M, 0, M);
  764. demorect(uictx, box, "Layout( UI_RIGHT | UI_VFILL )", 0.7f, 0, UI_RIGHT|UI_VFILL, S+M, S, 0, M, M, M);
  765. demorect(uictx, box, "Layout( UI_LEFT | UI_TOP )", 0.55f, 0, UI_LEFT|UI_TOP, S, S, M, M, 0, 0);
  766. demorect(uictx, box, "Layout( UI_TOP )", 0.57f, 0, UI_TOP, S, S, 0, M, 0, 0);
  767. demorect(uictx, box, "Layout( UI_RIGHT | UI_TOP )", 0.55f, 0, UI_RIGHT|UI_TOP, S, S, 0, M, M, 0);
  768. demorect(uictx, box, "Layout( UI_LEFT )", 0.57f, 0, UI_LEFT, S, S, M, 0, 0, 0);
  769. demorect(uictx, box, "Layout( UI_CENTER )", 0.59f, 0, UI_CENTER, S, S, 0, 0, 0, 0);
  770. demorect(uictx, box, "Layout( UI_RIGHT )", 0.57f, 0, UI_RIGHT, S, S, 0, 0, M, 0);
  771. demorect(uictx, box, "Layout( UI_LEFT | UI_DOWN )", 0.55f, 0, UI_LEFT|UI_DOWN, S, S, M, 0, 0, M);
  772. demorect(uictx, box, "Layout( UI_DOWN)", 0.57f, 0, UI_DOWN, S, S, 0, 0, 0, M);
  773. demorect(uictx, box, "Layout( UI_RIGHT | UI_DOWN )", 0.55f, 0, UI_RIGHT|UI_DOWN, S, S, 0, 0, M, M);
  774. }
  775. void build_rowdemo(UIcontext *uictx, int parent) {
  776. uiSetBox(uictx, parent, UI_COLUMN);
  777. const int M = 10;
  778. const int S = 200;
  779. const int T = 100;
  780. {
  781. int box = demorect(uictx, parent, "Box( UI_ROW )\nLayout( UI_LEFT | UI_VFILL )", 0.6f, UI_ROW, UI_LEFT|UI_VFILL, 0, S, M, M, M, M);
  782. demorect(uictx, box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0);
  783. demorect(uictx, box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0);
  784. demorect(uictx, box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M);
  785. demorect(uictx, box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M);
  786. }
  787. {
  788. int box = demorect(uictx, parent, "Box( UI_ROW | UI_JUSTIFY )\nLayout( UI_FILL )", 0.6f, UI_ROW|UI_JUSTIFY, UI_FILL, 0, S, M, 0, M, M);
  789. demorect(uictx, box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0);
  790. demorect(uictx, box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0);
  791. demorect(uictx, box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M);
  792. demorect(uictx, box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M);
  793. }
  794. {
  795. int box = demorect(uictx, parent, "Box( UI_ROW )\nLayout( UI_FILL )", 0.6f, UI_ROW, UI_FILL, 0, S, M, 0, M, M);
  796. demorect(uictx, box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0);
  797. demorect(uictx, box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0);
  798. demorect(uictx, box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M);
  799. demorect(uictx, box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0);
  800. demorect(uictx, box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0);
  801. demorect(uictx, box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0);
  802. demorect(uictx, box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M);
  803. }
  804. }
  805. void build_columndemo(UIcontext *uictx, int parent) {
  806. uiSetBox(uictx, parent, UI_ROW);
  807. const int M = 10;
  808. const int S = 200;
  809. const int T = 100;
  810. {
  811. int box = demorect(uictx, parent, "Box( UI_COLUMN )\nLayout( UI_TOP | UI_HFILL )", 0.6f, UI_COLUMN, UI_TOP|UI_HFILL, S, 0, M, M, M, M);
  812. demorect(uictx, box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M);
  813. demorect(uictx, box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M);
  814. demorect(uictx, box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M);
  815. demorect(uictx, box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M);
  816. }
  817. {
  818. int box = demorect(uictx, parent, "Box( UI_COLUMN )\nLayout( UI_FILL )", 0.6f, UI_COLUMN, UI_FILL, S, 0, 0, M, M, M);
  819. demorect(uictx, box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M);
  820. demorect(uictx, box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M);
  821. demorect(uictx, box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M);
  822. demorect(uictx, box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M);
  823. }
  824. {
  825. int box = demorect(uictx, parent, "Box( UI_COLUMN )\nLayout( UI_FILL )", 0.6f, UI_COLUMN, UI_FILL, S, 0, 0, M, M, M);
  826. demorect(uictx, box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M);
  827. demorect(uictx, box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M);
  828. demorect(uictx, box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M);
  829. demorect(uictx, box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M);
  830. demorect(uictx, box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M);
  831. demorect(uictx, box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M);
  832. demorect(uictx, box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M);
  833. }
  834. }
  835. void fill_wrap_row_box(UIcontext *uictx, int box) {
  836. const int M = 5;
  837. const int T = 50;
  838. int i;
  839. srand(303);
  840. for (i = 0; i < 20; ++i) {
  841. float hue = (float)(rand()%360)/360.0f;
  842. int width = 10 + (rand()%5)*10;
  843. int u;
  844. switch(rand()%4) {
  845. default: break;
  846. case 0: {
  847. u = demorect(uictx, box, "Layout( UI_TOP )",
  848. hue, 0, UI_TOP, width, T, M, M, M, M);
  849. } break;
  850. case 1: {
  851. u = demorect(uictx, box, "Layout( UI_VCENTER )",
  852. hue, 0, UI_VCENTER, width, T/2, M, M, M, M);
  853. } break;
  854. case 2: {
  855. u = demorect(uictx, box, "Layout( UI_VFILL )",
  856. hue, 0, UI_VFILL, width, T, M, M, M, M);
  857. } break;
  858. case 3: {
  859. u = demorect(uictx, box, "Layout( UI_DOWN )",
  860. hue, 0, UI_DOWN, width, T/2, M, M, M, M);
  861. } break;
  862. }
  863. if (rand()%10 == 0)
  864. uiSetLayout(uictx, u, uiGetLayout(uictx, u)|UI_BREAK);
  865. }
  866. }
  867. void fill_wrap_column_box(UIcontext *uictx, int box) {
  868. const int M = 5;
  869. const int T = 50;
  870. int i;
  871. srand(303);
  872. for (i = 0; i < 20; ++i) {
  873. float hue = (float)(rand()%360)/360.0f;
  874. int height = 10 + (rand()%5)*10;
  875. int u;
  876. switch(rand()%4) {
  877. default: break;
  878. case 0: {
  879. u = demorect(uictx, box, "Layout( UI_LEFT )",
  880. hue, 0, UI_LEFT, T, height, M, M, M, M);
  881. } break;
  882. case 1: {
  883. u = demorect(uictx, box, "Layout( UI_HCENTER )",
  884. hue, 0, UI_HCENTER, T/2, height, M, M, M, M);
  885. } break;
  886. case 2: {
  887. u = demorect(uictx, box, "Layout( UI_HFILL )",
  888. hue, 0, UI_HFILL, T, height, M, M, M, M);
  889. } break;
  890. case 3: {
  891. u = demorect(uictx, box, "Layout( UI_RIGHT )",
  892. hue, 0, UI_RIGHT, T/2, height, M, M, M, M);
  893. } break;
  894. }
  895. if (rand()%10 == 0)
  896. uiSetLayout(uictx, u, uiGetLayout(uictx, u)|UI_BREAK);
  897. }
  898. }
  899. void build_wrapdemo(UIcontext *uictx, int parent) {
  900. int col = uiItem(uictx);
  901. uiInsert(uictx, parent, col);
  902. uiSetBox(uictx, col, UI_COLUMN);
  903. uiSetLayout(uictx, col, UI_FILL);
  904. const int M = 5;
  905. int box;
  906. box = demorect(uictx, col, "Box( UI_ROW | UI_WRAP | UI_START )\nLayout( UI_HFILL | UI_TOP )",
  907. 0.6f, UI_ROW | UI_WRAP | UI_START, UI_TOP, 0, 0, M, M, M, M);
  908. fill_wrap_row_box(uictx, box);
  909. box = demorect(uictx, col, "Box( UI_ROW | UI_WRAP | UI_MIDDLE )\nLayout( UI_HFILL | UI_TOP )",
  910. 0.6f, UI_ROW | UI_WRAP, UI_HFILL | UI_TOP, 0, 0, M, M, M, M);
  911. fill_wrap_row_box(uictx, box);
  912. box = demorect(uictx, col, "Box( UI_ROW | UI_WRAP | UI_END )\nLayout( UI_HFILL | UI_TOP )",
  913. 0.6f, UI_ROW | UI_WRAP | UI_END, UI_HFILL | UI_TOP, 0, 0, M, M, M, M);
  914. fill_wrap_row_box(uictx, box);
  915. box = demorect(uictx, col, "Box( UI_ROW | UI_WRAP | UI_JUSTIFY )\nLayout( UI_HFILL | UI_TOP )",
  916. 0.6f, UI_ROW | UI_WRAP | UI_JUSTIFY, UI_HFILL | UI_TOP, 0, 0, M, M, M, M);
  917. fill_wrap_row_box(uictx, box);
  918. box = demorect(uictx, col, "Box( UI_COLUMN | UI_WRAP | UI_START )\nLayout( UI_LEFT | UI_VFILL )",
  919. 0.6f, UI_COLUMN | UI_WRAP | UI_START, UI_LEFT | UI_VFILL, 0, 0, M, M, M, M);
  920. fill_wrap_column_box(uictx, box);
  921. }
  922. int add_menu_option(UIcontext *uictx, int parent, const char *name, int *choice) {
  923. int opt = radio(uictx, -1, name, choice);
  924. uiInsert(uictx, parent, opt);
  925. uiSetLayout(uictx, opt, UI_HFILL|UI_TOP);
  926. uiSetMargins(uictx, opt, 1, 1, 1, 1);
  927. return opt;
  928. }
  929. void draw(exContext *ec, float w, float h) {
  930. UIcontext *uictx = ec->uictx;
  931. NVGcontext *vg = ec->vg;
  932. bndBackground(vg, 0, 0, w, h);
  933. // some OUI stuff
  934. uiBeginLayout(uictx);
  935. int root = panel(uictx);
  936. // position root element
  937. uiSetSize(uictx, 0,w,h);
  938. ((UIData*)uiGetHandle(uictx, root))->handler = roothandler;
  939. uiSetEvents(uictx, root, UI_SCROLL|UI_BUTTON0_DOWN);
  940. uiSetBox(uictx, root, UI_COLUMN);
  941. static int choice = -1;
  942. int menu = uiItem(uictx);
  943. uiSetLayout(uictx, menu, UI_HFILL|UI_TOP);
  944. uiSetBox(uictx, menu, UI_ROW);
  945. uiInsert(uictx, root, menu);
  946. int opt_blendish_demo = add_menu_option(uictx, menu, "Blendish Demo", &choice);
  947. int opt_oui_demo = add_menu_option(uictx, menu, "OUI Demo", &choice);
  948. int opt_layouts = add_menu_option(uictx, menu, "UI_LAYOUT", &choice);
  949. int opt_row = add_menu_option(uictx, menu, "UI_ROW", &choice);
  950. int opt_column = add_menu_option(uictx, menu, "UI_COLUMN", &choice);
  951. int opt_wrap = add_menu_option(uictx, menu, "UI_WRAP", &choice);
  952. if (choice < 0)
  953. choice = opt_blendish_demo;
  954. int content = uiItem(uictx);
  955. uiSetLayout(uictx, content, UI_FILL);
  956. uiInsert(uictx, root, content);
  957. if (choice == opt_blendish_demo) {
  958. int democontent = uiItem(uictx);
  959. uiSetLayout(uictx, democontent, UI_FILL);
  960. uiInsert(uictx, content, democontent);
  961. UIData *data = (UIData *)uiAllocHandle(uictx, democontent, sizeof(UIData));
  962. data->handler = 0;
  963. data->subtype = ST_DEMOSTUFF;
  964. } else if (choice == opt_oui_demo) {
  965. int democontent = uiItem(uictx);
  966. uiSetLayout(uictx, democontent, UI_TOP);
  967. uiSetSize(uictx, democontent, 250, 0);
  968. uiInsert(uictx, content, democontent);
  969. build_democontent(uictx, democontent);
  970. } else if (choice == opt_layouts) {
  971. build_layoutdemo(uictx, content);
  972. } else if (choice == opt_row) {
  973. build_rowdemo(uictx, content);
  974. } else if (choice == opt_column) {
  975. build_columndemo(uictx, content);
  976. } else if (choice == opt_wrap) {
  977. build_wrapdemo(uictx, content);
  978. }
  979. uiEndLayout(uictx);
  980. drawUI(ec, 0, BND_CORNER_NONE);
  981. #if 0
  982. for (int i = 0; i < uiGetLastItemCount(); ++i) {
  983. if (uiRecoverItem(i) == -1) {
  984. UIitem *pitem = uiLastItemPtr(i);
  985. nvgBeginPath(vg);
  986. nvgRect(vg,pitem->margins[0],pitem->margins[1],pitem->size[0],pitem->size[1]);
  987. nvgStrokeWidth(vg, 2);
  988. nvgStrokeColor(vg, nvgRGBAf(1.0f,0.0f,0.0f,0.5f));
  989. nvgStroke(vg);
  990. }
  991. }
  992. #endif
  993. if (choice == opt_blendish_demo) {
  994. UIvec2 cursor = uiGetCursor(uictx);
  995. cursor.x -= w/2;
  996. cursor.y -= h/2;
  997. if (abs(cursor.x) > (w/3)) {
  998. bndJoinAreaOverlay(vg, 0, 0, w, h, 0, (cursor.x > 0));
  999. } else if (abs(cursor.y) > (h/3)) {
  1000. bndJoinAreaOverlay(vg, 0, 0, w, h, 1, (cursor.y > 0));
  1001. }
  1002. }
  1003. uiProcess(uictx, (int)(glfwGetTime()*1000.0));
  1004. }
  1005. ////////////////////////////////////////////////////////////////////////////////
  1006. void errorcb(int error, const char* desc)
  1007. {
  1008. printf("GLFW error %d: %s\n", error, desc);
  1009. }
  1010. static void mousebutton(GLFWwindow *window, int button, int action, int mods) {
  1011. exContext *ec;
  1012. switch(button) {
  1013. case 1: button = 2; break;
  1014. case 2: button = 1; break;
  1015. }
  1016. ec = (exContext*)glfwGetWindowUserPointer(window);
  1017. uiSetButton(ec->uictx, button, mods, (action == GLFW_PRESS));
  1018. }
  1019. static void cursorpos(GLFWwindow *window, double x, double y) {
  1020. exContext *ec = (exContext*)glfwGetWindowUserPointer(window);
  1021. uiSetCursor(ec->uictx, (int)x,(int)y);
  1022. }
  1023. static void scrollevent(GLFWwindow *window, double x, double y) {
  1024. exContext *ec = (exContext*)glfwGetWindowUserPointer(window);
  1025. uiSetScroll(ec->uictx, (int)x, (int)y);
  1026. }
  1027. static void charevent(GLFWwindow *window, unsigned int value) {
  1028. exContext *ec = (exContext*)glfwGetWindowUserPointer(window);
  1029. uiSetChar(ec->uictx, value);
  1030. }
  1031. static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
  1032. {
  1033. exContext *ec;
  1034. NVG_NOTUSED(scancode);
  1035. if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
  1036. glfwSetWindowShouldClose(window, GL_TRUE);
  1037. ec = (exContext*)glfwGetWindowUserPointer(window);
  1038. uiSetKey(ec->uictx, key, mods, action ? true : false);
  1039. }
  1040. int main()
  1041. {
  1042. GLFWwindow* window;
  1043. exContext ec;
  1044. memset(&ec, 0, sizeof(exContext));
  1045. ec.uictx = uiCreateContext(4096, 1<<20);
  1046. uiSetHandler(ec.uictx, ui_handler);
  1047. if (!glfwInit()) {
  1048. printf("Failed to init GLFW.");
  1049. return -1;
  1050. }
  1051. glfwSetErrorCallback(errorcb);
  1052. #ifndef _WIN32 // don't require this on win32, and works with more cards
  1053. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  1054. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  1055. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  1056. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  1057. #endif
  1058. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
  1059. window = glfwCreateWindow(650, 650, "OUI Blendish Demo", NULL, NULL);
  1060. if (!window) {
  1061. glfwTerminate();
  1062. return -1;
  1063. }
  1064. glfwSetWindowUserPointer(window, &ec);
  1065. glfwSetKeyCallback(window, key);
  1066. glfwSetCharCallback(window, charevent);
  1067. glfwSetCursorPosCallback(window, cursorpos);
  1068. glfwSetMouseButtonCallback(window, mousebutton);
  1069. glfwSetScrollCallback(window, scrollevent);
  1070. glfwMakeContextCurrent(window);
  1071. #ifdef NANOVG_GLEW
  1072. glewExperimental = GL_TRUE;
  1073. if(glewInit() != GLEW_OK) {
  1074. printf("Could not init glew.\n");
  1075. return -1;
  1076. }
  1077. // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
  1078. glGetError();
  1079. #endif
  1080. //ec.vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
  1081. ec.vg = nvgCreateGL3(NVG_ANTIALIAS);
  1082. if (ec.vg == NULL) {
  1083. printf("Could not init nanovg.\n");
  1084. return -1;
  1085. }
  1086. init(ec.vg);
  1087. printf("sizeof(UIitem)=%lu\n", sizeof(UIitem));
  1088. glfwSwapInterval(0);
  1089. glfwSetTime(0);
  1090. double c = 0.0;
  1091. int total = 0;
  1092. int peak_items = 0;
  1093. unsigned int peak_alloc = 0;
  1094. while (!glfwWindowShouldClose(window))
  1095. {
  1096. double mx, my;
  1097. int winWidth, winHeight;
  1098. int fbWidth, fbHeight;
  1099. float pxRatio;
  1100. glfwGetCursorPos(window, &mx, &my);
  1101. glfwGetWindowSize(window, &winWidth, &winHeight);
  1102. glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
  1103. // Calculate pixel ration for hi-dpi devices.
  1104. pxRatio = (float)fbWidth / (float)winWidth;
  1105. // Update and render
  1106. glViewport(0, 0, fbWidth, fbHeight);
  1107. glClearColor(0,0,0,1);
  1108. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  1109. double t = glfwGetTime();
  1110. nvgBeginFrame(ec.vg, winWidth, winHeight, pxRatio);
  1111. draw(&ec, winWidth, winHeight);
  1112. peak_items = (peak_items > uiGetItemCount(ec.uictx))?peak_items:uiGetItemCount(ec.uictx);
  1113. peak_alloc = (peak_alloc > uiGetAllocSize(ec.uictx))?peak_alloc:uiGetAllocSize(ec.uictx);
  1114. nvgEndFrame(ec.vg);
  1115. double t2 = glfwGetTime();
  1116. c += (t2 - t);
  1117. total++;
  1118. if (total > (1*60)) {
  1119. printf("%fms\n", (c / (double)total)*1000.0);
  1120. total = 0;
  1121. c = 0.0;
  1122. }
  1123. glfwSwapBuffers(window);
  1124. glfwPollEvents();
  1125. }
  1126. printf("Peak item count: %i (%lu bytes)\nPeak allocated handles: %u bytes\n",
  1127. peak_items, peak_items * sizeof(UIitem), peak_alloc);
  1128. uiDestroyContext(ec.uictx);
  1129. nvgDeleteGL3(ec.vg);
  1130. glfwTerminate();
  1131. return 0;
  1132. }