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.

598 lines
18KB

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