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.

405 lines
11KB

  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. #include <assert.h>
  17. ////////////////////////////////////////////////////////////////////////////////
  18. #define UI_IMPLEMENTATION
  19. #ifndef _UI_H_
  20. #define _UI_H_
  21. typedef struct UIcontext UIcontext;
  22. UIcontext *uiCreateContext();
  23. void uiMakeCurrent(UIcontext *ctx);
  24. void uiDestroyContext(UIcontext *ctx);
  25. void uiSetButton(int button, int enabled);
  26. int uiGetButton(int button);
  27. void uiSetCursor(int x, int y);
  28. void uiGetCursor(int *x, int *y);
  29. #endif // _UI_H_
  30. #ifdef UI_IMPLEMENTATION
  31. struct UIcontext {
  32. int cx, cy;
  33. unsigned long long buttons;
  34. };
  35. static UIcontext *ui_context = NULL;
  36. UIcontext *uiCreateContext() {
  37. UIcontext *ctx = (UIcontext *)malloc(sizeof(UIcontext));
  38. return ctx;
  39. }
  40. void uiMakeCurrent(UIcontext *ctx) {
  41. ui_context = ctx;
  42. }
  43. void uiDestroyContext(UIcontext *ctx) {
  44. free(ctx);
  45. }
  46. void uiSetButton(int button, int enabled) {
  47. assert(ui_context);
  48. unsigned long long mask = 1ull<<button;
  49. ui_context->buttons = (enabled)?
  50. (ui_context->buttons | mask):
  51. (ui_context->buttons & ~mask);
  52. }
  53. int uiGetButton(int button) {
  54. assert(ui_context);
  55. return (ui_context->buttons & (1ull<<button))?1:0;
  56. }
  57. void uiSetCursor(int x, int y) {
  58. assert(ui_context);
  59. ui_context->cx = x;
  60. ui_context->cy = y;
  61. }
  62. void uiGetCursor(int *x, int *y) {
  63. assert(ui_context);
  64. *x = ui_context->cx;
  65. *y = ui_context->cy;
  66. }
  67. #endif // UI_IMPLEMENTATION
  68. ////////////////////////////////////////////////////////////////////////////////
  69. void init(NVGcontext *vg) {
  70. bndSetFont(nvgCreateFont(vg, "system", "../droidsans.ttf"));
  71. bndSetIconImage(nvgCreateImage(vg, "../blender_icons16.png"));
  72. }
  73. void draw(NVGcontext *vg, float w, float h) {
  74. bndBackground(vg, 0, 0, w, h);
  75. int x = 10;
  76. int y = 10;
  77. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  78. BND_ICONID(6,3),"Default");
  79. y += 25;
  80. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  81. BND_ICONID(6,3),"Hovered");
  82. y += 25;
  83. bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  84. BND_ICONID(6,3),"Active");
  85. y += 40;
  86. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  87. -1,"Default");
  88. y += 25;
  89. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  90. -1,"Hovered");
  91. y += 25;
  92. bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  93. -1,"Active");
  94. y += 25;
  95. bndLabel(vg,x,y,120,BND_WIDGET_HEIGHT,-1,"Label:");
  96. y += BND_WIDGET_HEIGHT;
  97. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  98. -1, "Default");
  99. y += 25;
  100. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  101. -1, "Hovered");
  102. y += 25;
  103. bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  104. -1, "Active");
  105. y += 25;
  106. int ry = y;
  107. int rx = x;
  108. y = 10;
  109. x += 130;
  110. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_DEFAULT,"Default");
  111. y += 25;
  112. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_HOVER,"Hovered");
  113. y += 25;
  114. bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_ACTIVE,"Active");
  115. y += 40;
  116. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_DOWN,BND_DEFAULT,
  117. "Top","100");
  118. y += BND_WIDGET_HEIGHT-2;
  119. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  120. "Center","100");
  121. y += BND_WIDGET_HEIGHT-2;
  122. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_TOP,BND_DEFAULT,
  123. "Bottom","100");
  124. int mx = x-30;
  125. int my = y-12;
  126. int mw = 120;
  127. bndMenuBackground(vg,mx,my,mw,120,BND_CORNER_TOP);
  128. bndMenuLabel(vg,mx,my,mw,BND_WIDGET_HEIGHT,-1,"Menu Title");
  129. my += BND_WIDGET_HEIGHT-2;
  130. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_DEFAULT,
  131. BND_ICONID(17,3),"Default");
  132. my += BND_WIDGET_HEIGHT-2;
  133. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_HOVER,
  134. BND_ICONID(18,3),"Hovered");
  135. my += BND_WIDGET_HEIGHT-2;
  136. bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_ACTIVE,
  137. BND_ICONID(19,3),"Active");
  138. y = 10;
  139. x += 130;
  140. int ox = x;
  141. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  142. "Default","100");
  143. y += 25;
  144. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  145. "Hovered","100");
  146. y += 25;
  147. bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  148. "Active","100");
  149. y += 40;
  150. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,BND_DEFAULT,
  151. -1,"One");
  152. x += 60-1;
  153. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  154. -1,"Two");
  155. x += 60-1;
  156. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT,
  157. -1,"Three");
  158. x += 60-1;
  159. bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,BND_ACTIVE,
  160. -1,"Butts");
  161. x = ox;
  162. y += 40;
  163. float progress_value = fmodf(glfwGetTime()/10.0,1.0);
  164. char progress_label[32];
  165. sprintf(progress_label, "%d%%", int(progress_value*100+0.5f));
  166. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  167. progress_value,"Default",progress_label);
  168. y += 25;
  169. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  170. progress_value,"Hovered",progress_label);
  171. y += 25;
  172. bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  173. progress_value,"Active",progress_label);
  174. int rw = x+240-rx;
  175. float s_offset = sinf(glfwGetTime()/2.0)*0.5+0.5;
  176. float s_size = cosf(glfwGetTime()/3.11)*0.5+0.5;
  177. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_DEFAULT,s_offset,s_size);
  178. ry += 20;
  179. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_HOVER,s_offset,s_size);
  180. ry += 20;
  181. bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_ACTIVE,s_offset,s_size);
  182. const char edit_text[] = "The quick brown fox";
  183. int textlen = strlen(edit_text)+1;
  184. int t = int(glfwGetTime()*2);
  185. int idx1 = (t/textlen)%textlen;
  186. int idx2 = idx1 + (t%(textlen-idx1));
  187. ry += 25;
  188. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
  189. -1, edit_text, idx1, idx2);
  190. ry += 25;
  191. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
  192. -1, edit_text, idx1, idx2);
  193. ry += 25;
  194. bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
  195. -1, edit_text, idx1, idx2);
  196. rx += rw + 20;
  197. ry = 10;
  198. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_DEFAULT,s_offset,s_size);
  199. rx += 20;
  200. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_HOVER,s_offset,s_size);
  201. rx += 20;
  202. bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_ACTIVE,s_offset,s_size);
  203. x = ox;
  204. y += 40;
  205. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  206. BND_DEFAULT,BND_ICONID(0,10),NULL);
  207. x += BND_TOOL_WIDTH-1;
  208. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  209. BND_DEFAULT,BND_ICONID(1,10),NULL);
  210. x += BND_TOOL_WIDTH-1;
  211. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  212. BND_DEFAULT,BND_ICONID(2,10),NULL);
  213. x += BND_TOOL_WIDTH-1;
  214. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  215. BND_DEFAULT,BND_ICONID(3,10),NULL);
  216. x += BND_TOOL_WIDTH-1;
  217. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  218. BND_DEFAULT,BND_ICONID(4,10),NULL);
  219. x += BND_TOOL_WIDTH-1;
  220. bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  221. BND_DEFAULT,BND_ICONID(5,10),NULL);
  222. x += BND_TOOL_WIDTH-1;
  223. x += 5;
  224. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,
  225. BND_DEFAULT,BND_ICONID(0,11),NULL);
  226. x += BND_TOOL_WIDTH-1;
  227. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  228. BND_DEFAULT,BND_ICONID(1,11),NULL);
  229. x += BND_TOOL_WIDTH-1;
  230. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  231. BND_DEFAULT,BND_ICONID(2,11),NULL);
  232. x += BND_TOOL_WIDTH-1;
  233. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  234. BND_DEFAULT,BND_ICONID(3,11),NULL);
  235. x += BND_TOOL_WIDTH-1;
  236. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL,
  237. BND_ACTIVE,BND_ICONID(4,11),NULL);
  238. x += BND_TOOL_WIDTH-1;
  239. bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
  240. BND_DEFAULT,BND_ICONID(5,11),NULL);
  241. }
  242. ////////////////////////////////////////////////////////////////////////////////
  243. void errorcb(int error, const char* desc)
  244. {
  245. printf("GLFW error %d: %s\n", error, desc);
  246. }
  247. static void mousebutton(GLFWwindow *window, int button, int action, int mods) {
  248. NVG_NOTUSED(window);
  249. NVG_NOTUSED(mods);
  250. uiSetButton(button, (action==GLFW_PRESS)?1:0);
  251. }
  252. static void cursorpos(GLFWwindow *window, double x, double y) {
  253. NVG_NOTUSED(window);
  254. uiSetCursor((int)x,(int)y);
  255. }
  256. static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
  257. {
  258. NVG_NOTUSED(scancode);
  259. NVG_NOTUSED(mods);
  260. if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
  261. glfwSetWindowShouldClose(window, GL_TRUE);
  262. }
  263. int main()
  264. {
  265. GLFWwindow* window;
  266. struct NVGcontext* vg = NULL;
  267. UIcontext *uictx;
  268. uictx = uiCreateContext();
  269. uiMakeCurrent(uictx);
  270. if (!glfwInit()) {
  271. printf("Failed to init GLFW.");
  272. return -1;
  273. }
  274. glfwSetErrorCallback(errorcb);
  275. #ifndef _WIN32 // don't require this on win32, and works with more cards
  276. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  277. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  278. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  279. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  280. #endif
  281. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
  282. window = glfwCreateWindow(1000, 600, "Blendish Demo", NULL, NULL);
  283. if (!window) {
  284. glfwTerminate();
  285. return -1;
  286. }
  287. glfwSetKeyCallback(window, key);
  288. glfwSetCursorPosCallback(window, cursorpos);
  289. glfwSetMouseButtonCallback(window, mousebutton);
  290. glfwMakeContextCurrent(window);
  291. #ifdef NANOVG_GLEW
  292. glewExperimental = GL_TRUE;
  293. if(glewInit() != GLEW_OK) {
  294. printf("Could not init glew.\n");
  295. return -1;
  296. }
  297. // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
  298. glGetError();
  299. #endif
  300. vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
  301. if (vg == NULL) {
  302. printf("Could not init nanovg.\n");
  303. return -1;
  304. }
  305. init(vg);
  306. glfwSwapInterval(0);
  307. glfwSetTime(0);
  308. while (!glfwWindowShouldClose(window))
  309. {
  310. double mx, my;
  311. int winWidth, winHeight;
  312. int fbWidth, fbHeight;
  313. float pxRatio;
  314. glfwGetCursorPos(window, &mx, &my);
  315. glfwGetWindowSize(window, &winWidth, &winHeight);
  316. glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
  317. // Calculate pixel ration for hi-dpi devices.
  318. pxRatio = (float)fbWidth / (float)winWidth;
  319. // Update and render
  320. glViewport(0, 0, fbWidth, fbHeight);
  321. glClearColor(0,0,0,1);
  322. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  323. nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
  324. draw(vg, winWidth, winHeight);
  325. nvgEndFrame(vg);
  326. glfwSwapBuffers(window);
  327. glfwPollEvents();
  328. }
  329. uiDestroyContext(uictx);
  330. nvgDeleteGL3(vg);
  331. glfwTerminate();
  332. return 0;
  333. }