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.

1179 lines
38KB

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