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.

741 lines
23KB

  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 UI_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. } SubType;
  35. typedef struct {
  36. int subtype;
  37. } UIData;
  38. typedef struct {
  39. UIData head;
  40. int iconid;
  41. const char *label;
  42. } UIButtonData;
  43. typedef struct {
  44. UIData head;
  45. const char *label;
  46. int *option;
  47. } UICheckData;
  48. typedef struct {
  49. UIData head;
  50. int iconid;
  51. const char *label;
  52. int *value;
  53. } UIRadioData;
  54. typedef struct {
  55. UIData head;
  56. const char *label;
  57. float *progress;
  58. } UISliderData;
  59. ////////////////////////////////////////////////////////////////////////////////
  60. void init(NVGcontext *vg) {
  61. bndSetFont(nvgCreateFont(vg, "system", "../droidsans.ttf"));
  62. bndSetIconImage(nvgCreateImage(vg, "../blender_icons16.png"));
  63. }
  64. // calculate which corners are sharp for an item, depending on whether
  65. // the container the item is in has negative spacing, and the item
  66. // is first or last element in a sequence of 2 or more elements.
  67. int cornerFlags(int item) {
  68. int parent = uiParent(item);
  69. int numkids = uiGetChildCount(parent);
  70. if (numkids < 2) return BND_CORNER_NONE;
  71. const UIData *head = (const UIData *)uiGetData(parent);
  72. if (head) {
  73. int numid = uiGetChildId(item);
  74. switch(head->subtype) {
  75. case ST_COLUMN: {
  76. if (!numid) return BND_CORNER_DOWN;
  77. else if (numid == numkids-1) return BND_CORNER_TOP;
  78. else return BND_CORNER_ALL;
  79. } break;
  80. case ST_ROW: {
  81. if (!numid) return BND_CORNER_RIGHT;
  82. else if (numid == numkids-1) return BND_CORNER_LEFT;
  83. else return BND_CORNER_ALL;
  84. } break;
  85. default: break;
  86. }
  87. }
  88. return BND_CORNER_NONE;
  89. }
  90. void testrect(NVGcontext *vg, UIrect rect) {
  91. #if 0
  92. nvgBeginPath(vg);
  93. nvgRect(vg,rect.x+0.5,rect.y+0.5,rect.w-1,rect.h-1);
  94. nvgStrokeColor(vg,nvgRGBf(1,0,0));
  95. nvgStrokeWidth(vg,1);
  96. nvgStroke(vg);
  97. #endif
  98. }
  99. void drawUI(NVGcontext *vg, int item, int x, int y) {
  100. const UIData *head = (const UIData *)uiGetData(item);
  101. UIrect rect = uiGetRect(item);
  102. rect.x += x;
  103. rect.y += y;
  104. if (head) {
  105. switch(head->subtype) {
  106. default: {
  107. testrect(vg,rect);
  108. } break;
  109. case ST_LABEL: {
  110. assert(head);
  111. const UIButtonData *data = (UIButtonData*)head;
  112. bndLabel(vg,rect.x,rect.y,rect.w,rect.h,
  113. data->iconid,data->label);
  114. } break;
  115. case ST_BUTTON: {
  116. const UIButtonData *data = (UIButtonData*)head;
  117. bndToolButton(vg,rect.x,rect.y,rect.w,rect.h,
  118. cornerFlags(item),(BNDwidgetState)uiGetState(item),
  119. data->iconid,data->label);
  120. } break;
  121. case ST_CHECK: {
  122. const UICheckData *data = (UICheckData*)head;
  123. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  124. if (*data->option)
  125. state = BND_ACTIVE;
  126. bndOptionButton(vg,rect.x,rect.y,rect.w,rect.h, state,
  127. data->label);
  128. } break;
  129. case ST_RADIO:{
  130. const UIRadioData *data = (UIRadioData*)head;
  131. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  132. if (*data->value == uiGetChildId(item))
  133. state = BND_ACTIVE;
  134. bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h,
  135. cornerFlags(item),state,
  136. data->iconid,data->label);
  137. } break;
  138. case ST_SLIDER:{
  139. const UISliderData *data = (UISliderData*)head;
  140. BNDwidgetState state = (BNDwidgetState)uiGetState(item);
  141. static char value[32];
  142. sprintf(value,"%.0f%%",(*data->progress)*100.0f);
  143. bndSlider(vg,rect.x,rect.y,rect.w,rect.h,
  144. cornerFlags(item),state,
  145. *data->progress,data->label,value);
  146. } break;
  147. }
  148. } else {
  149. testrect(vg,rect);
  150. }
  151. int kid = uiFirstChild(item);
  152. while (kid > 0) {
  153. drawUI(vg, kid, rect.x, rect.y);
  154. kid = uiNextSibling(kid);
  155. }
  156. }
  157. int label(int parent, int iconid, const char *label) {
  158. int item = uiItem();
  159. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  160. UIButtonData *data = (UIButtonData *)uiAllocData(item, sizeof(UIButtonData));
  161. data->head.subtype = ST_LABEL;
  162. data->iconid = iconid;
  163. data->label = label;
  164. uiAppend(parent, item);
  165. return item;
  166. }
  167. void demohandler(int item, UIevent event) {
  168. const UIButtonData *data = (const UIButtonData *)uiGetData(item);
  169. printf("clicked: %lld %s\n", uiGetHandle(item), data->label);
  170. }
  171. int button(int parent, UIhandle handle, int iconid, const char *label,
  172. UIhandler handler) {
  173. // create new ui item
  174. int item = uiItem();
  175. // set persistent handle for item that is used
  176. // to track activity over time
  177. uiSetHandle(item, handle);
  178. // set size of wiget; horizontal size is dynamic, vertical is fixed
  179. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  180. // attach event handler e.g. demohandler above
  181. uiSetHandler(item, handler, UI_BUTTON0_HOT_UP);
  182. // store some custom data with the button that we use for styling
  183. UIButtonData *data = (UIButtonData *)uiAllocData(item, sizeof(UIButtonData));
  184. data->head.subtype = ST_BUTTON;
  185. data->iconid = iconid;
  186. data->label = label;
  187. uiAppend(parent, item);
  188. return item;
  189. }
  190. void checkhandler(int item, UIevent event) {
  191. const UICheckData *data = (const UICheckData *)uiGetData(item);
  192. *data->option = !(*data->option);
  193. }
  194. int check(int parent, UIhandle handle, const char *label, int *option) {
  195. // create new ui item
  196. int item = uiItem();
  197. // set persistent handle for item that is used
  198. // to track activity over time
  199. uiSetHandle(item, handle);
  200. // set size of wiget; horizontal size is dynamic, vertical is fixed
  201. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  202. // attach event handler e.g. demohandler above
  203. uiSetHandler(item, checkhandler, UI_BUTTON0_DOWN);
  204. // store some custom data with the button that we use for styling
  205. UICheckData *data = (UICheckData *)uiAllocData(item, sizeof(UICheckData));
  206. data->head.subtype = ST_CHECK;
  207. data->label = label;
  208. data->option = option;
  209. uiAppend(parent, item);
  210. return item;
  211. }
  212. // simple logic for a slider
  213. // starting offset of the currently active slider
  214. static float sliderstart = 0.0;
  215. // event handler for slider (same handler for all sliders)
  216. void sliderhandler(int item, UIevent event) {
  217. // retrieve the custom data we saved with the slider
  218. UISliderData *data = (UISliderData *)uiGetData(item);
  219. switch(event) {
  220. default: break;
  221. case UI_BUTTON0_DOWN: {
  222. // button was pressed for the first time; capture initial
  223. // slider value.
  224. sliderstart = *data->progress;
  225. } break;
  226. case UI_BUTTON0_CAPTURE: {
  227. // called for every frame that the button is pressed.
  228. // get the delta between the click point and the current
  229. // mouse position
  230. UIvec2 pos = uiGetCursorStartDelta();
  231. // get the items layouted rectangle
  232. UIrect rc = uiGetRect(item);
  233. // calculate our new offset and clamp
  234. float value = sliderstart + ((float)pos.x / (float)rc.w);
  235. value = (value<0)?0:(value>1)?1:value;
  236. // assign the new value
  237. *data->progress = value;
  238. } break;
  239. }
  240. }
  241. int slider(int parent, UIhandle handle, const char *label, float *progress) {
  242. // create new ui item
  243. int item = uiItem();
  244. // set persistent handle for item that is used
  245. // to track activity over time
  246. uiSetHandle(item, handle);
  247. // set size of wiget; horizontal size is dynamic, vertical is fixed
  248. uiSetSize(item, 0, BND_WIDGET_HEIGHT);
  249. // attach our slider event handler and capture two classes of events
  250. uiSetHandler(item, sliderhandler,
  251. UI_BUTTON0_DOWN | UI_BUTTON0_CAPTURE);
  252. // store some custom data with the button that we use for styling
  253. // and logic, e.g. the pointer to the data we want to alter.
  254. UISliderData *data = (UISliderData *)uiAllocData(item, sizeof(UISliderData));
  255. data->head.subtype = ST_SLIDER;
  256. data->label = label;
  257. data->progress = progress;
  258. uiAppend(parent, item);
  259. return item;
  260. }
  261. // simple logic for a radio button
  262. void radiohandler(int item, UIevent event) {
  263. UIRadioData *data = (UIRadioData *)uiGetData(item);
  264. *data->value = uiGetChildId(item);
  265. }
  266. int radio(int parent, UIhandle handle, int iconid, const char *label, int *value) {
  267. int item = uiItem();
  268. uiSetHandle(item, handle);
  269. uiSetSize(item, label?0:BND_TOOL_WIDTH, BND_WIDGET_HEIGHT);
  270. UIRadioData *data = (UIRadioData *)uiAllocData(item, sizeof(UIRadioData));
  271. data->head.subtype = ST_RADIO;
  272. data->iconid = iconid;
  273. data->label = label;
  274. data->value = value;
  275. uiSetHandler(item, radiohandler, UI_BUTTON0_DOWN);
  276. uiAppend(parent, item);
  277. return item;
  278. }
  279. void columnhandler(int parent, UIevent event) {
  280. int item = uiLastChild(parent);
  281. int last = uiPrevSibling(item);
  282. // mark the new item as positioned under the previous item
  283. uiSetRelToTop(item, last);
  284. // fill parent horizontally, anchor to previous item vertically
  285. uiSetLayout(item, UI_HFILL|UI_TOP);
  286. // if not the first item, add a margin of 1
  287. uiSetMargins(item, 0, (last < 0)?0:1, 0, 0);
  288. }
  289. int column(int parent) {
  290. int item = uiItem();
  291. uiSetHandler(item, columnhandler, UI_APPEND);
  292. uiAppend(parent, item);
  293. return item;
  294. }
  295. void vgrouphandler(int parent, UIevent event) {
  296. int item = uiLastChild(parent);
  297. int last = uiPrevSibling(item);
  298. // mark the new item as positioned under the previous item
  299. uiSetRelToTop(item, last);
  300. // fill parent horizontally, anchor to previous item vertically
  301. uiSetLayout(item, UI_HFILL|UI_TOP);
  302. // if not the first item, add a margin
  303. uiSetMargins(item, 0, (last < 0)?0:-2, 0, 0);
  304. }
  305. int vgroup(int parent) {
  306. int item = uiItem();
  307. UIData *data = (UIData *)uiAllocData(item, sizeof(UIData));
  308. data->subtype = ST_COLUMN;
  309. uiSetHandler(item, vgrouphandler, UI_APPEND);
  310. uiAppend(parent, item);
  311. return item;
  312. }
  313. void hgrouphandler(int parent, UIevent event) {
  314. int item = uiLastChild(parent);
  315. int last = uiPrevSibling(item);
  316. uiSetRelToLeft(item, last);
  317. if (last > 0)
  318. uiSetRelToRight(last, item);
  319. uiSetLayout(item, UI_LEFT|UI_RIGHT);
  320. uiSetMargins(item, (last < 0)?0:-1, 0, 0, 0);
  321. }
  322. int hgroup(int parent) {
  323. int item = uiItem();
  324. UIData *data = (UIData *)uiAllocData(item, sizeof(UIData));
  325. data->subtype = ST_ROW;
  326. uiSetHandler(item, hgrouphandler, UI_APPEND);
  327. uiAppend(parent, item);
  328. return item;
  329. }
  330. void rowhandler(int parent, UIevent event) {
  331. int item = uiLastChild(parent);
  332. int last = uiPrevSibling(item);
  333. uiSetRelToLeft(item, last);
  334. if (last > 0)
  335. uiSetRelToRight(last, item);
  336. uiSetLayout(item, UI_LEFT|UI_RIGHT);
  337. uiSetMargins(item, (last < 0)?0:8, 0, 0, 0);
  338. }
  339. int row(int parent) {
  340. int item = uiItem();
  341. uiSetHandler(item, rowhandler, UI_APPEND);
  342. uiAppend(parent, item);
  343. return item;
  344. }
  345. void draw(NVGcontext *vg, float w, float h) {
  346. bndBackground(vg, 0, 0, w, h);
  347. int x = 10;
  348. int y = 10;
  349. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  350. BND_ICONID(6,3),"Default");
  351. y += 25;
  352. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  353. BND_ICONID(6,3),"Hovered");
  354. y += 25;
  355. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  356. BND_ICONID(6,3),"Active");
  357. y += 40;
  358. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  359. -1,"Default");
  360. y += 25;
  361. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  362. -1,"Hovered");
  363. y += 25;
  364. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  365. -1,"Active");
  366. y += 25;
  367. bndLabel(vg,x,y,120,BND_WIDGET_HEIGHT,-1,"Label:");
  368. y += BND_WIDGET_HEIGHT;
  369. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  370. -1, "Default");
  371. y += 25;
  372. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  373. -1, "Hovered");
  374. y += 25;
  375. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  376. -1, "Active");
  377. y += 25;
  378. int ry = y;
  379. int rx = x;
  380. y = 10;
  381. x += 130;
  382. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_DEFAULT,"Default");
  383. y += 25;
  384. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_HOVER,"Hovered");
  385. y += 25;
  386. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_ACTIVE,"Active");
  387. y += 40;
  388. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_DOWN,BND_DEFAULT,
  389. "Top","100");
  390. y += BND_WIDGET_HEIGHT-2;
  391. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  392. "Center","100");
  393. y += BND_WIDGET_HEIGHT-2;
  394. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_TOP,BND_DEFAULT,
  395. "Bottom","100");
  396. int mx = x-30;
  397. int my = y-12;
  398. int mw = 120;
  399. bndMenuBackground(vg,mx,my,mw,120,BND_CORNER_TOP);
  400. bndMenuLabel(vg,mx,my,mw,BND_WIDGET_HEIGHT,-1,"Menu Title");
  401. my += BND_WIDGET_HEIGHT-2;
  402. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_DEFAULT,
  403. BND_ICONID(17,3),"Default");
  404. my += BND_WIDGET_HEIGHT-2;
  405. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_HOVER,
  406. BND_ICONID(18,3),"Hovered");
  407. my += BND_WIDGET_HEIGHT-2;
  408. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_ACTIVE,
  409. BND_ICONID(19,3),"Active");
  410. y = 10;
  411. x += 130;
  412. int ox = x;
  413. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  414. "Default","100");
  415. y += 25;
  416. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  417. "Hovered","100");
  418. y += 25;
  419. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  420. "Active","100");
  421. y += 40;
  422. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,BND_DEFAULT,
  423. -1,"One");
  424. x += 60-1;
  425. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  426. -1,"Two");
  427. x += 60-1;
  428. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  429. -1,"Three");
  430. x += 60-1;
  431. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,BND_ACTIVE,
  432. -1,"Butts");
  433. x = ox;
  434. y += 40;
  435. float progress_value = fmodf(glfwGetTime()/10.0,1.0);
  436. char progress_label[32];
  437. sprintf(progress_label, "%d%%", int(progress_value*100+0.5f));
  438. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  439. progress_value,"Default",progress_label);
  440. y += 25;
  441. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  442. progress_value,"Hovered",progress_label);
  443. y += 25;
  444. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  445. progress_value,"Active",progress_label);
  446. int rw = x+240-rx;
  447. float s_offset = sinf(glfwGetTime()/2.0)*0.5+0.5;
  448. float s_size = cosf(glfwGetTime()/3.11)*0.5+0.5;
  449. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_DEFAULT,s_offset,s_size);
  450. ry += 20;
  451. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_HOVER,s_offset,s_size);
  452. ry += 20;
  453. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_ACTIVE,s_offset,s_size);
  454. const char edit_text[] = "The quick brown fox";
  455. int textlen = strlen(edit_text)+1;
  456. int t = int(glfwGetTime()*2);
  457. int idx1 = (t/textlen)%textlen;
  458. int idx2 = idx1 + (t%(textlen-idx1));
  459. ry += 25;
  460. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  461. -1, edit_text, idx1, idx2);
  462. ry += 25;
  463. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  464. -1, edit_text, idx1, idx2);
  465. ry += 25;
  466. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  467. -1, edit_text, idx1, idx2);
  468. rx += rw + 20;
  469. ry = 10;
  470. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_DEFAULT,s_offset,s_size);
  471. rx += 20;
  472. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_HOVER,s_offset,s_size);
  473. rx += 20;
  474. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_ACTIVE,s_offset,s_size);
  475. x = ox;
  476. y += 40;
  477. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  478. BND_DEFAULT,BND_ICONID(0,10),NULL);
  479. x += BND_TOOL_WIDTH-1;
  480. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  481. BND_DEFAULT,BND_ICONID(1,10),NULL);
  482. x += BND_TOOL_WIDTH-1;
  483. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  484. BND_DEFAULT,BND_ICONID(2,10),NULL);
  485. x += BND_TOOL_WIDTH-1;
  486. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  487. BND_DEFAULT,BND_ICONID(3,10),NULL);
  488. x += BND_TOOL_WIDTH-1;
  489. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  490. BND_DEFAULT,BND_ICONID(4,10),NULL);
  491. x += BND_TOOL_WIDTH-1;
  492. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  493. BND_DEFAULT,BND_ICONID(5,10),NULL);
  494. x += BND_TOOL_WIDTH-1;
  495. x += 5;
  496. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  497. BND_DEFAULT,BND_ICONID(0,11),NULL);
  498. x += BND_TOOL_WIDTH-1;
  499. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  500. BND_DEFAULT,BND_ICONID(1,11),NULL);
  501. x += BND_TOOL_WIDTH-1;
  502. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  503. BND_DEFAULT,BND_ICONID(2,11),NULL);
  504. x += BND_TOOL_WIDTH-1;
  505. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  506. BND_DEFAULT,BND_ICONID(3,11),NULL);
  507. x += BND_TOOL_WIDTH-1;
  508. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  509. BND_ACTIVE,BND_ICONID(4,11),NULL);
  510. x += BND_TOOL_WIDTH-1;
  511. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  512. BND_DEFAULT,BND_ICONID(5,11),NULL);
  513. // some OUI stuff
  514. uiClear();
  515. int root = uiItem();
  516. // position root element
  517. uiSetLayout(0,UI_LEFT|UI_TOP);
  518. uiSetMargins(0,600,10,0,0);
  519. uiSetSize(0,250,400);
  520. int col = column(0);
  521. uiSetLayout(col, UI_TOP|UI_HFILL);
  522. button(col, 1, BND_ICONID(6,3), "Item 1", demohandler);
  523. button(col, 2, BND_ICONID(6,3), "Item 2", demohandler);
  524. static int enum1 = 0;
  525. {
  526. int h = hgroup(col);
  527. radio(h, 3, BND_ICONID(6,3), "Item 3.0", &enum1);
  528. radio(h, 4, BND_ICONID(0,10), NULL, &enum1);
  529. radio(h, 5, BND_ICONID(1,10), NULL, &enum1);
  530. radio(h, 6, BND_ICONID(6,3), "Item 3.3", &enum1);
  531. }
  532. static float progress1 = 0.25f;
  533. static float progress2 = 0.75f;
  534. {
  535. int rows = row(col);
  536. int coll = vgroup(rows);
  537. label(coll, -1, "Items 4.0:");
  538. coll = vgroup(coll);
  539. button(coll, 7, BND_ICONID(6,3), "Item 4.0.0", demohandler);
  540. button(coll, 8, BND_ICONID(6,3), "Item 4.0.1", demohandler);
  541. int colr = vgroup(rows);
  542. label(colr, -1, "Items 4.1:");
  543. colr = vgroup(colr);
  544. slider(colr, 9, "Item 4.1.0", &progress1);
  545. slider(colr,10, "Item 4.1.1", &progress2);
  546. }
  547. button(col, 11, BND_ICONID(6,3), "Item 5", NULL);
  548. static int option1,option2,option3;
  549. check(col, 12, "Item 6", &option1);
  550. check(col, 13, "Item 7", &option2);
  551. check(col, 14, "Item 8", &option3);
  552. uiProcess();
  553. drawUI(vg, 0, 0, 0);
  554. }
  555. ////////////////////////////////////////////////////////////////////////////////
  556. void errorcb(int error, const char* desc)
  557. {
  558. printf("GLFW error %d: %s\n", error, desc);
  559. }
  560. static void mousebutton(GLFWwindow *window, int button, int action, int mods) {
  561. NVG_NOTUSED(window);
  562. NVG_NOTUSED(mods);
  563. uiSetButton(button, (action==GLFW_PRESS)?1:0);
  564. }
  565. static void cursorpos(GLFWwindow *window, double x, double y) {
  566. NVG_NOTUSED(window);
  567. uiSetCursor((int)x,(int)y);
  568. }
  569. static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
  570. {
  571. NVG_NOTUSED(scancode);
  572. NVG_NOTUSED(mods);
  573. if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
  574. glfwSetWindowShouldClose(window, GL_TRUE);
  575. }
  576. int main()
  577. {
  578. GLFWwindow* window;
  579. struct NVGcontext* vg = NULL;
  580. UIcontext *uictx;
  581. uictx = uiCreateContext();
  582. uiMakeCurrent(uictx);
  583. if (!glfwInit()) {
  584. printf("Failed to init GLFW.");
  585. return -1;
  586. }
  587. glfwSetErrorCallback(errorcb);
  588. #ifndef _WIN32 // don't require this on win32, and works with more cards
  589. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  590. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  591. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  592. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  593. #endif
  594. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
  595. window = glfwCreateWindow(1000, 600, "OUI Blendish Demo", NULL, NULL);
  596. if (!window) {
  597. glfwTerminate();
  598. return -1;
  599. }
  600. glfwSetKeyCallback(window, key);
  601. glfwSetCursorPosCallback(window, cursorpos);
  602. glfwSetMouseButtonCallback(window, mousebutton);
  603. glfwMakeContextCurrent(window);
  604. #ifdef NANOVG_GLEW
  605. glewExperimental = GL_TRUE;
  606. if(glewInit() != GLEW_OK) {
  607. printf("Could not init glew.\n");
  608. return -1;
  609. }
  610. // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
  611. glGetError();
  612. #endif
  613. vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
  614. if (vg == NULL) {
  615. printf("Could not init nanovg.\n");
  616. return -1;
  617. }
  618. init(vg);
  619. glfwSwapInterval(0);
  620. glfwSetTime(0);
  621. while (!glfwWindowShouldClose(window))
  622. {
  623. double mx, my;
  624. int winWidth, winHeight;
  625. int fbWidth, fbHeight;
  626. float pxRatio;
  627. glfwGetCursorPos(window, &mx, &my);
  628. glfwGetWindowSize(window, &winWidth, &winHeight);
  629. glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
  630. // Calculate pixel ration for hi-dpi devices.
  631. pxRatio = (float)fbWidth / (float)winWidth;
  632. // Update and render
  633. glViewport(0, 0, fbWidth, fbHeight);
  634. glClearColor(0,0,0,1);
  635. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  636. nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
  637. draw(vg, winWidth, winHeight);
  638. nvgEndFrame(vg);
  639. glfwSwapBuffers(window);
  640. glfwPollEvents();
  641. }
  642. uiDestroyContext(uictx);
  643. nvgDeleteGL3(vg);
  644. glfwTerminate();
  645. return 0;
  646. }