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.

695 lines
21KB

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