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.

852 lines
23KB

  1. #include "demo.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #ifdef NANOVG_GLEW
  6. # include <GL/glew.h>
  7. #endif
  8. #include <GLFW/glfw3.h>
  9. #include "nanovg.h"
  10. #ifdef _MSC_VER
  11. #define snprintf _snprintf
  12. #else
  13. #include <iconv.h>
  14. #endif
  15. #define ICON_SEARCH 0x1F50D
  16. #define ICON_CIRCLED_CROSS 0x2716
  17. #define ICON_CHEVRON_RIGHT 0xE75E
  18. #define ICON_CHECK 0x2713
  19. #define ICON_LOGIN 0xE740
  20. #define ICON_TRASH 0xE729
  21. static char* cpToUTF8(int cp, char* str)
  22. {
  23. int n = 0;
  24. if (cp < 0x80) n = 1;
  25. else if (cp < 0x800) n = 2;
  26. else if (cp < 0x10000) n = 3;
  27. else if (cp < 0x200000) n = 4;
  28. else if (cp < 0x4000000) n = 5;
  29. else if (cp <= 0x7fffffff) n = 6;
  30. str[n] = '\0';
  31. switch (n) {
  32. case 6: str[5] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x4000000;
  33. case 5: str[4] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x200000;
  34. case 4: str[3] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x10000;
  35. case 3: str[2] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x800;
  36. case 2: str[1] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0xc0;
  37. case 1: str[0] = cp;
  38. }
  39. return str;
  40. }
  41. void drawWindow(struct NVGcontext* vg, const char* title, float x, float y, float w, float h)
  42. {
  43. float cornerRadius = 3.0f;
  44. struct NVGpaint shadowPaint;
  45. struct NVGpaint headerPaint;
  46. nvgSave(vg);
  47. // nvgClearState(vg);
  48. // Window
  49. nvgBeginPath(vg);
  50. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  51. nvgFillColor(vg, nvgRGBA(28,30,34,192));
  52. // nvgFillColor(vg, nvgRGBA(0,0,0,128));
  53. nvgFill(vg);
  54. // Drop shadow
  55. shadowPaint = nvgBoxGradient(vg, x,y+2, w,h, cornerRadius*2, 10, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0));
  56. nvgBeginPath(vg);
  57. nvgRect(vg, x-10,y-10, w+20,h+30);
  58. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  59. nvgPathWinding(vg, NVG_HOLE);
  60. nvgFillPaint(vg, shadowPaint);
  61. nvgFill(vg);
  62. // Header
  63. headerPaint = nvgLinearGradient(vg, x,y,x,y+15, nvgRGBA(255,255,255,8), nvgRGBA(0,0,0,16));
  64. nvgBeginPath(vg);
  65. nvgRoundedRect(vg, x+1,y+1, w-2,30, cornerRadius-1);
  66. nvgFillPaint(vg, headerPaint);
  67. nvgFill(vg);
  68. nvgBeginPath(vg);
  69. nvgMoveTo(vg, x+0.5f, y+0.5f+30);
  70. nvgLineTo(vg, x+0.5f+w-1, y+0.5f+30);
  71. nvgStrokeColor(vg, nvgRGBA(0,0,0,32));
  72. nvgStroke(vg);
  73. nvgFontSize(vg, 18.0f);
  74. nvgFontFace(vg, "sans-bold");
  75. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  76. nvgFontBlur(vg,2);
  77. nvgFillColor(vg, nvgRGBA(0,0,0,128));
  78. nvgText(vg, x+w/2,y+16+1, title, NULL);
  79. nvgFontBlur(vg,0);
  80. nvgFillColor(vg, nvgRGBA(220,220,220,160));
  81. nvgText(vg, x+w/2,y+16, title, NULL);
  82. nvgRestore(vg);
  83. }
  84. void drawSearchBox(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  85. {
  86. struct NVGpaint bg;
  87. char icon[8];
  88. float cornerRadius = h/2-1;
  89. // Edit
  90. bg = nvgBoxGradient(vg, x,y+1.5f, w,h, h/2,5, nvgRGBA(0,0,0,16), nvgRGBA(0,0,0,92));
  91. nvgBeginPath(vg);
  92. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  93. nvgFillPaint(vg, bg);
  94. nvgFill(vg);
  95. /* nvgBeginPath(vg);
  96. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f);
  97. nvgStrokeColor(vg, nvgRGBA(0,0,0,48));
  98. nvgStroke(vg);*/
  99. nvgFontSize(vg, h*1.3f);
  100. nvgFontFace(vg, "icons");
  101. nvgFillColor(vg, nvgRGBA(255,255,255,64));
  102. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  103. nvgText(vg, x+h*0.55f, y+h*0.55f, cpToUTF8(ICON_SEARCH,icon), NULL);
  104. nvgFontSize(vg, 20.0f);
  105. nvgFontFace(vg, "sans");
  106. nvgFillColor(vg, nvgRGBA(255,255,255,32));
  107. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  108. nvgText(vg, x+h*1.05f,y+h*0.5f,text, NULL);
  109. nvgFontSize(vg, h*1.3f);
  110. nvgFontFace(vg, "icons");
  111. nvgFillColor(vg, nvgRGBA(255,255,255,32));
  112. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  113. nvgText(vg, x+w-h*0.55f, y+h*0.55f, cpToUTF8(ICON_CIRCLED_CROSS,icon), NULL);
  114. }
  115. void drawDropDown(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  116. {
  117. struct NVGpaint bg;
  118. char icon[8];
  119. float cornerRadius = 4.0f;
  120. bg = nvgLinearGradient(vg, x,y,x,y+h, nvgRGBA(255,255,255,16), nvgRGBA(0,0,0,16));
  121. nvgBeginPath(vg);
  122. nvgRoundedRect(vg, x+1,y+1, w-2,h-2, cornerRadius-1);
  123. nvgFillPaint(vg, bg);
  124. nvgFill(vg);
  125. nvgBeginPath(vg);
  126. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f);
  127. nvgStrokeColor(vg, nvgRGBA(0,0,0,48));
  128. nvgStroke(vg);
  129. nvgFontSize(vg, 20.0f);
  130. nvgFontFace(vg, "sans");
  131. nvgFillColor(vg, nvgRGBA(255,255,255,160));
  132. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  133. nvgText(vg, x+h*0.3f,y+h*0.5f,text, NULL);
  134. nvgFontSize(vg, h*1.3f);
  135. nvgFontFace(vg, "icons");
  136. nvgFillColor(vg, nvgRGBA(255,255,255,64));
  137. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  138. nvgText(vg, x+w-h*0.5f, y+h*0.5f, cpToUTF8(ICON_CHEVRON_RIGHT,icon), NULL);
  139. }
  140. void drawLabel(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  141. {
  142. NVG_NOTUSED(w);
  143. nvgFontSize(vg, 18.0f);
  144. nvgFontFace(vg, "sans");
  145. nvgFillColor(vg, nvgRGBA(255,255,255,128));
  146. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  147. nvgText(vg, x,y+h*0.5f,text, NULL);
  148. }
  149. void drawEditBoxBase(struct NVGcontext* vg, float x, float y, float w, float h)
  150. {
  151. struct NVGpaint bg;
  152. // Edit
  153. bg = nvgBoxGradient(vg, x+1,y+1+1.5f, w-2,h-2, 3,4, nvgRGBA(255,255,255,32), nvgRGBA(32,32,32,32));
  154. nvgBeginPath(vg);
  155. nvgRoundedRect(vg, x+1,y+1, w-2,h-2, 4-1);
  156. nvgFillPaint(vg, bg);
  157. nvgFill(vg);
  158. nvgBeginPath(vg);
  159. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, 4-0.5f);
  160. nvgStrokeColor(vg, nvgRGBA(0,0,0,48));
  161. nvgStroke(vg);
  162. }
  163. void drawEditBox(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  164. {
  165. drawEditBoxBase(vg, x,y, w,h);
  166. nvgFontSize(vg, 20.0f);
  167. nvgFontFace(vg, "sans");
  168. nvgFillColor(vg, nvgRGBA(255,255,255,64));
  169. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  170. nvgText(vg, x+h*0.3f,y+h*0.5f,text, NULL);
  171. }
  172. void drawEditBoxNum(struct NVGcontext* vg,
  173. const char* text, const char* units, float x, float y, float w, float h)
  174. {
  175. float uw;
  176. drawEditBoxBase(vg, x,y, w,h);
  177. uw = nvgTextBounds(vg, units, NULL, NULL);
  178. nvgFontSize(vg, 18.0f);
  179. nvgFontFace(vg, "sans");
  180. nvgFillColor(vg, nvgRGBA(255,255,255,64));
  181. nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);
  182. nvgText(vg, x+w-h*0.3f,y+h*0.5f,units, NULL);
  183. nvgFontSize(vg, 20.0f);
  184. nvgFontFace(vg, "sans");
  185. nvgFillColor(vg, nvgRGBA(255,255,255,128));
  186. nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);
  187. nvgText(vg, x+w-uw-h*0.5f,y+h*0.5f,text, NULL);
  188. }
  189. void drawCheckBox(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  190. {
  191. struct NVGpaint bg;
  192. char icon[8];
  193. NVG_NOTUSED(w);
  194. nvgFontSize(vg, 18.0f);
  195. nvgFontFace(vg, "sans");
  196. nvgFillColor(vg, nvgRGBA(255,255,255,160));
  197. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  198. nvgText(vg, x+28,y+h*0.5f,text, NULL);
  199. bg = nvgBoxGradient(vg, x+1,y+(int)(h*0.5f)-9+1, 18,18, 3,3, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,92));
  200. nvgBeginPath(vg);
  201. nvgRoundedRect(vg, x+1,y+(int)(h*0.5f)-9, 18,18, 3);
  202. nvgFillPaint(vg, bg);
  203. nvgFill(vg);
  204. nvgFontSize(vg, 40);
  205. nvgFontFace(vg, "icons");
  206. nvgFillColor(vg, nvgRGBA(255,255,255,128));
  207. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  208. nvgText(vg, x+9+2, y+h*0.5f, cpToUTF8(ICON_CHECK,icon), NULL);
  209. }
  210. void drawButton(struct NVGcontext* vg, int preicon, const char* text, float x, float y, float w, float h, unsigned int col)
  211. {
  212. struct NVGpaint bg;
  213. char icon[8];
  214. float cornerRadius = 4.0f;
  215. float tw = 0, iw = 0;
  216. bg = nvgLinearGradient(vg, x,y,x,y+h, nvgRGBA(255,255,255,col==0?16:32), nvgRGBA(0,0,0,col==0?16:32));
  217. nvgBeginPath(vg);
  218. nvgRoundedRect(vg, x+1,y+1, w-2,h-2, cornerRadius-1);
  219. if (col != 0) {
  220. nvgFillColor(vg, col);
  221. nvgFill(vg);
  222. }
  223. nvgFillPaint(vg, bg);
  224. nvgFill(vg);
  225. nvgBeginPath(vg);
  226. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f);
  227. nvgStrokeColor(vg, nvgRGBA(0,0,0,48));
  228. nvgStroke(vg);
  229. nvgFontSize(vg, 20.0f);
  230. nvgFontFace(vg, "sans-bold");
  231. tw = nvgTextBounds(vg, text, NULL, NULL);
  232. if (preicon != 0) {
  233. nvgFontSize(vg, h*1.3f);
  234. nvgFontFace(vg, "icons");
  235. iw = nvgTextBounds(vg, cpToUTF8(preicon,icon), NULL, NULL);
  236. iw += h*0.15f;
  237. }
  238. if (preicon != 0) {
  239. nvgFontSize(vg, h*1.3f);
  240. nvgFontFace(vg, "icons");
  241. nvgFillColor(vg, nvgRGBA(255,255,255,96));
  242. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  243. nvgText(vg, x+w*0.5f-tw*0.5f-iw*0.75f, y+h*0.5f, cpToUTF8(preicon,icon), NULL);
  244. }
  245. nvgFontSize(vg, 20.0f);
  246. nvgFontFace(vg, "sans-bold");
  247. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  248. nvgFillColor(vg, nvgRGBA(0,0,0,160));
  249. nvgText(vg, x+w*0.5f-tw*0.5f+iw*0.25f,y+h*0.5f-1,text, NULL);
  250. nvgFillColor(vg, nvgRGBA(255,255,255,160));
  251. nvgText(vg, x+w*0.5f-tw*0.5f+iw*0.25f,y+h*0.5f,text, NULL);
  252. }
  253. void drawSlider(struct NVGcontext* vg, float pos, float x, float y, float w, float h)
  254. {
  255. struct NVGpaint bg, knob;
  256. float cy = y+(int)(h*0.5f);
  257. float kr = (int)(h*0.25f);
  258. nvgSave(vg);
  259. // nvgClearState(vg);
  260. // Slot
  261. bg = nvgBoxGradient(vg, x,cy-2+1, w,4, 2,2, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,128));
  262. nvgBeginPath(vg);
  263. nvgRoundedRect(vg, x,cy-2, w,4, 2);
  264. nvgFillPaint(vg, bg);
  265. nvgFill(vg);
  266. // Knob Shadow
  267. bg = nvgRadialGradient(vg, x+(int)(pos*w),cy+1, kr-3,kr+3, nvgRGBA(0,0,0,64), nvgRGBA(0,0,0,0));
  268. nvgBeginPath(vg);
  269. nvgRect(vg, x+(int)(pos*w)-kr-5,cy-kr-5,kr*2+5+5,kr*2+5+5+3);
  270. nvgCircle(vg, x+(int)(pos*w),cy, kr);
  271. nvgPathWinding(vg, NVG_HOLE);
  272. nvgFillPaint(vg, bg);
  273. nvgFill(vg);
  274. // Knob
  275. knob = nvgLinearGradient(vg, x,cy-kr,x,cy+kr, nvgRGBA(255,255,255,16), nvgRGBA(0,0,0,16));
  276. nvgBeginPath(vg);
  277. nvgCircle(vg, x+(int)(pos*w),cy, kr-1);
  278. nvgFillColor(vg, nvgRGBA(40,43,48,255));
  279. nvgFill(vg);
  280. nvgFillPaint(vg, knob);
  281. nvgFill(vg);
  282. nvgBeginPath(vg);
  283. nvgCircle(vg, x+(int)(pos*w),cy, kr-0.5f);
  284. nvgStrokeColor(vg, nvgRGBA(0,0,0,92));
  285. nvgStroke(vg);
  286. nvgRestore(vg);
  287. }
  288. void drawEyes(struct NVGcontext* vg, float x, float y, float w, float h, float mx, float my, float t)
  289. {
  290. struct NVGpaint gloss, bg;
  291. float ex = w *0.23f;
  292. float ey = h * 0.5f;
  293. float lx = x + ex;
  294. float ly = y + ey;
  295. float rx = x + w - ex;
  296. float ry = y + ey;
  297. float dx,dy,d;
  298. float br = (ex < ey ? ex : ey) * 0.5f;
  299. float blink = 1 - pow(sinf(t*0.5f),200)*0.8f;
  300. bg = nvgLinearGradient(vg, x,y+h*0.5f,x+w*0.1f,y+h, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,16));
  301. nvgBeginPath(vg);
  302. nvgEllipse(vg, lx+3.0f,ly+16.0f, ex,ey);
  303. nvgEllipse(vg, rx+3.0f,ry+16.0f, ex,ey);
  304. nvgFillPaint(vg, bg);
  305. nvgFill(vg);
  306. bg = nvgLinearGradient(vg, x,y+h*0.25f,x+w*0.1f,y+h, nvgRGBA(220,220,220,255), nvgRGBA(128,128,128,255));
  307. nvgBeginPath(vg);
  308. nvgEllipse(vg, lx,ly, ex,ey);
  309. nvgEllipse(vg, rx,ry, ex,ey);
  310. nvgFillPaint(vg, bg);
  311. nvgFill(vg);
  312. dx = (mx - rx) / (ex * 10);
  313. dy = (my - ry) / (ey * 10);
  314. d = sqrtf(dx*dx+dy*dy);
  315. if (d > 1.0f) {
  316. dx /= d; dy /= d;
  317. }
  318. dx *= ex*0.4f;
  319. dy *= ey*0.5f;
  320. nvgBeginPath(vg);
  321. nvgEllipse(vg, lx+dx,ly+dy+ey*0.25f*(1-blink), br,br*blink);
  322. nvgFillColor(vg, nvgRGBA(32,32,32,255));
  323. nvgFill(vg);
  324. dx = (mx - rx) / (ex * 10);
  325. dy = (my - ry) / (ey * 10);
  326. d = sqrtf(dx*dx+dy*dy);
  327. if (d > 1.0f) {
  328. dx /= d; dy /= d;
  329. }
  330. dx *= ex*0.4f;
  331. dy *= ey*0.5f;
  332. nvgBeginPath(vg);
  333. nvgEllipse(vg, rx+dx,ry+dy+ey*0.25f*(1-blink), br,br*blink);
  334. nvgFillColor(vg, nvgRGBA(32,32,32,255));
  335. nvgFill(vg);
  336. gloss = nvgRadialGradient(vg, lx-ex*0.25f,ly-ey*0.5f, ex*0.1f,ex*0.75f, nvgRGBA(255,255,255,128), nvgRGBA(255,255,255,0));
  337. nvgBeginPath(vg);
  338. nvgEllipse(vg, lx,ly, ex,ey);
  339. nvgFillPaint(vg, gloss);
  340. nvgFill(vg);
  341. gloss = nvgRadialGradient(vg, rx-ex*0.25f,ry-ey*0.5f, ex*0.1f,ex*0.75f, nvgRGBA(255,255,255,128), nvgRGBA(255,255,255,0));
  342. nvgBeginPath(vg);
  343. nvgEllipse(vg, rx,ry, ex,ey);
  344. nvgFillPaint(vg, gloss);
  345. nvgFill(vg);
  346. }
  347. void drawGraph(struct NVGcontext* vg, float x, float y, float w, float h, float t)
  348. {
  349. struct NVGpaint bg;
  350. float samples[6];
  351. float sx[6], sy[6];
  352. float dx = w/5.0f;
  353. int i;
  354. samples[0] = (1+sinf(t*1.2345f+cosf(t*0.33457f)*0.44f))*0.5f;
  355. samples[1] = (1+sinf(t*0.68363f+cosf(t*1.3f)*1.55f))*0.5f;
  356. samples[2] = (1+sinf(t*1.1642f+cosf(t*0.33457)*1.24f))*0.5f;
  357. samples[3] = (1+sinf(t*0.56345f+cosf(t*1.63f)*0.14f))*0.5f;
  358. samples[4] = (1+sinf(t*1.6245f+cosf(t*0.254f)*0.3f))*0.5f;
  359. samples[5] = (1+sinf(t*0.345f+cosf(t*0.03f)*0.6f))*0.5f;
  360. for (i = 0; i < 6; i++) {
  361. sx[i] = x+i*dx;
  362. sy[i] = y+h*samples[i]*0.8f;
  363. }
  364. // Graph background
  365. bg = nvgLinearGradient(vg, x,y,x,y+h, nvgRGBA(0,160,192,0), nvgRGBA(0,160,192,64));
  366. nvgBeginPath(vg);
  367. nvgMoveTo(vg, sx[0], sy[0]);
  368. for (i = 1; i < 6; i++)
  369. nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1], sx[i]-dx*0.5f,sy[i], sx[i],sy[i]);
  370. nvgLineTo(vg, x+w, y+h);
  371. nvgLineTo(vg, x, y+h);
  372. nvgFillPaint(vg, bg);
  373. nvgFill(vg);
  374. // Graph line
  375. nvgBeginPath(vg);
  376. nvgMoveTo(vg, sx[0], sy[0]+2);
  377. for (i = 1; i < 6; i++)
  378. nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1]+2, sx[i]-dx*0.5f,sy[i]+2, sx[i],sy[i]+2);
  379. nvgStrokeColor(vg, nvgRGBA(0,0,0,32));
  380. nvgStrokeWidth(vg, 3.0f);
  381. nvgStroke(vg);
  382. nvgBeginPath(vg);
  383. nvgMoveTo(vg, sx[0], sy[0]);
  384. for (i = 1; i < 6; i++)
  385. nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1], sx[i]-dx*0.5f,sy[i], sx[i],sy[i]);
  386. nvgStrokeColor(vg, nvgRGBA(0,160,192,255));
  387. nvgStrokeWidth(vg, 3.0f);
  388. nvgStroke(vg);
  389. // Graph sample pos
  390. for (i = 0; i < 6; i++) {
  391. bg = nvgRadialGradient(vg, sx[i],sy[i]+2, 3.0f,8.0f, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,0));
  392. nvgBeginPath(vg);
  393. nvgRect(vg, sx[i]-10, sy[i]-10+2, 20,20);
  394. nvgFillPaint(vg, bg);
  395. nvgFill(vg);
  396. }
  397. nvgBeginPath(vg);
  398. for (i = 0; i < 6; i++)
  399. nvgCircle(vg, sx[i], sy[i], 4.0f);
  400. nvgFillColor(vg, nvgRGBA(0,160,192,255));
  401. nvgFill(vg);
  402. nvgBeginPath(vg);
  403. for (i = 0; i < 6; i++)
  404. nvgCircle(vg, sx[i], sy[i], 2.0f);
  405. nvgFillColor(vg, nvgRGBA(220,220,220,255));
  406. nvgFill(vg);
  407. nvgStrokeWidth(vg, 1.0f);
  408. }
  409. void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, const int* images, int nimages, float t)
  410. {
  411. float cornerRadius = 3.0f;
  412. struct NVGpaint shadowPaint, imgPaint, fadePaint;
  413. float ix,iy,iw,ih;
  414. float thumb = 60.0f;
  415. float arry = 30.5f;
  416. int imgw, imgh;
  417. float stackh = (nimages/2) * (thumb+10) + 10;
  418. int i;
  419. float u = (1+cosf(t*0.5f))*0.5f;
  420. nvgSave(vg);
  421. // nvgClearState(vg);
  422. // Drop shadow
  423. shadowPaint = nvgBoxGradient(vg, x,y+4, w,h, cornerRadius*2, 20, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0));
  424. nvgBeginPath(vg);
  425. nvgRect(vg, x-10,y-10, w+20,h+30);
  426. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  427. nvgPathWinding(vg, NVG_HOLE);
  428. nvgFillPaint(vg, shadowPaint);
  429. nvgFill(vg);
  430. // Window
  431. nvgBeginPath(vg);
  432. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  433. nvgMoveTo(vg, x-10,y+arry);
  434. nvgLineTo(vg, x+1,y+arry-11);
  435. nvgLineTo(vg, x+1,y+arry+11);
  436. nvgFillColor(vg, nvgRGBA(200,200,200,255));
  437. nvgFill(vg);
  438. nvgSave(vg);
  439. nvgScissor(vg, x,y,w,h);
  440. nvgTranslate(vg, 0, -(stackh - h)*u);
  441. for (i = 0; i < nimages; i++) {
  442. float tx, ty;
  443. tx = x+10;
  444. ty = y+10;
  445. tx += (i%2) * (thumb+10);
  446. ty += (i/2) * (thumb+10);
  447. nvgImageSize(vg, images[i], &imgw, &imgh);
  448. if (imgw < imgh) {
  449. iw = thumb;
  450. ih = iw * (float)imgh/(float)imgw;
  451. ix = 0;
  452. iy = -(ih-thumb)*0.5f;
  453. } else {
  454. ih = thumb;
  455. iw = ih * (float)imgw/(float)imgh;
  456. ix = -(iw-thumb)*0.5f;
  457. iy = 0;
  458. }
  459. imgPaint = nvgImagePattern(vg, tx+ix, ty+iy, iw,ih, 0.0f/180.0f*NVG_PI, images[i], 0);
  460. nvgBeginPath(vg);
  461. nvgRoundedRect(vg, tx,ty, thumb,thumb, 5);
  462. nvgFillPaint(vg, imgPaint);
  463. nvgFill(vg);
  464. shadowPaint = nvgBoxGradient(vg, tx-1,ty, thumb+2,thumb+2, 5, 3, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0));
  465. nvgBeginPath(vg);
  466. nvgRect(vg, tx-5,ty-5, thumb+10,thumb+10);
  467. nvgRoundedRect(vg, tx,ty, thumb,thumb, 6);
  468. nvgPathWinding(vg, NVG_HOLE);
  469. nvgFillPaint(vg, shadowPaint);
  470. nvgFill(vg);
  471. nvgBeginPath(vg);
  472. nvgRoundedRect(vg, tx+0.5f,ty+0.5f, thumb-1,thumb-1, 4-0.5f);
  473. nvgStrokeWidth(vg,1.0f);
  474. nvgStrokeColor(vg, nvgRGBA(255,255,255,192));
  475. nvgStroke(vg);
  476. }
  477. nvgRestore(vg);
  478. // Hide fades
  479. fadePaint = nvgLinearGradient(vg, x,y,x,y+6, nvgRGBA(200,200,200,255), nvgRGBA(200,200,200,0));
  480. nvgBeginPath(vg);
  481. nvgRect(vg, x+4,y,w-8,6);
  482. nvgFillPaint(vg, fadePaint);
  483. nvgFill(vg);
  484. fadePaint = nvgLinearGradient(vg, x,y+h,x,y+h-6, nvgRGBA(200,200,200,255), nvgRGBA(200,200,200,0));
  485. nvgBeginPath(vg);
  486. nvgRect(vg, x+4,y+h-6,w-8,6);
  487. nvgFillPaint(vg, fadePaint);
  488. nvgFill(vg);
  489. // Scroll bar
  490. shadowPaint = nvgBoxGradient(vg, x+w-12+1,y+4+1, 8,h-8, 3,4, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,92));
  491. nvgBeginPath(vg);
  492. nvgRoundedRect(vg, x+w-12,y+4, 8,h-8, 3);
  493. nvgFillPaint(vg, shadowPaint);
  494. // nvgFillColor(vg, nvgRGBA(255,0,0,128));
  495. nvgFill(vg);
  496. float scrollh = (h/stackh) * (h-8);
  497. shadowPaint = nvgBoxGradient(vg, x+w-12-1,y+4+(h-8-scrollh)*u-1, 8,scrollh, 3,4, nvgRGBA(220,220,220,255), nvgRGBA(128,128,128,255));
  498. nvgBeginPath(vg);
  499. nvgRoundedRect(vg, x+w-12+1,y+4+1 + (h-8-scrollh)*u, 8-2,scrollh-2, 2);
  500. nvgFillPaint(vg, shadowPaint);
  501. // nvgFillColor(vg, nvgRGBA(0,0,0,128));
  502. nvgFill(vg);
  503. nvgRestore(vg);
  504. }
  505. void drawColorwheel(struct NVGcontext* vg, float x, float y, float w, float h, float t)
  506. {
  507. int i;
  508. float r0, r1, ax,ay, bx,by, cx,cy, aeps, r;
  509. float hue = sinf(t * 0.12f);
  510. struct NVGpaint paint;
  511. nvgSave(vg);
  512. /* nvgBeginPath(vg);
  513. nvgRect(vg, x,y,w,h);
  514. nvgFillColor(vg, nvgRGBA(255,0,0,128));
  515. nvgFill(vg);*/
  516. cx = x + w*0.5f;
  517. cy = y + h*0.5f;
  518. r1 = (w < h ? w : h) * 0.5f - 5.0f;
  519. r0 = r1 - 20.0f;
  520. aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out).
  521. for (i = 0; i < 6; i++) {
  522. float a0 = (float)i / 6.0f * NVG_PI * 2.0f - aeps;
  523. float a1 = (float)(i+1.0f) / 6.0f * NVG_PI * 2.0f + aeps;
  524. nvgBeginPath(vg);
  525. nvgArc(vg, cx,cy, r0, a0, a1, NVG_CW);
  526. nvgArc(vg, cx,cy, r1, a1, a0, NVG_CCW);
  527. nvgClosePath(vg);
  528. ax = cx + cosf(a0) * (r0+r1)*0.5f;
  529. ay = cy + sinf(a0) * (r0+r1)*0.5f;
  530. bx = cx + cosf(a1) * (r0+r1)*0.5f;
  531. by = cy + sinf(a1) * (r0+r1)*0.5f;
  532. paint = nvgLinearGradient(vg, ax,ay, bx,by, nvgHSLA(a0/(NVG_PI*2),1.0f,0.55f,255), nvgHSLA(a1/(NVG_PI*2),1.0f,0.55f,255));
  533. nvgFillPaint(vg, paint);
  534. nvgFill(vg);
  535. }
  536. nvgBeginPath(vg);
  537. nvgCircle(vg, cx,cy, r0-0.5f);
  538. nvgCircle(vg, cx,cy, r1+0.5f);
  539. nvgStrokeColor(vg, nvgRGBA(0,0,0,64));
  540. nvgStrokeWidth(vg, 1.0f);
  541. nvgStroke(vg);
  542. // Selector
  543. nvgSave(vg);
  544. nvgTranslate(vg, cx,cy);
  545. nvgRotate(vg, hue*NVG_PI*2);
  546. // Marker on
  547. nvgStrokeWidth(vg, 2.0f);
  548. nvgBeginPath(vg);
  549. nvgRect(vg, r0-1,-3,r1-r0+2,6);
  550. nvgStrokeColor(vg, nvgRGBA(255,255,255,192));
  551. nvgStroke(vg);
  552. paint = nvgBoxGradient(vg, r0-3,-5,r1-r0+6,10, 2,4, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0));
  553. nvgBeginPath(vg);
  554. nvgRect(vg, r0-2-10,-4-10,r1-r0+4+20,8+20);
  555. nvgRect(vg, r0-2,-4,r1-r0+4,8);
  556. nvgPathWinding(vg, NVG_HOLE);
  557. nvgFillPaint(vg, paint);
  558. nvgFill(vg);
  559. // Center triangle
  560. r = r0 - 6;
  561. ax = cosf(120.0f/180.0f*NVG_PI) * r;
  562. ay = sinf(120.0f/180.0f*NVG_PI) * r;
  563. bx = cosf(-120.0f/180.0f*NVG_PI) * r;
  564. by = sinf(-120.0f/180.0f*NVG_PI) * r;
  565. nvgBeginPath(vg);
  566. nvgMoveTo(vg, r,0);
  567. nvgLineTo(vg, ax,ay);
  568. nvgLineTo(vg, bx,by);
  569. nvgClosePath(vg);
  570. paint = nvgLinearGradient(vg, r,0, ax,ay, nvgHSLA(hue,1.0f,0.5f,255), nvgRGBA(255,255,255,255));
  571. nvgFillPaint(vg, paint);
  572. nvgFill(vg);
  573. paint = nvgLinearGradient(vg, (r+ax)*0.5f,(0+ay)*0.5f, bx,by, nvgRGBA(0,0,0,0), nvgRGBA(0,0,0,255));
  574. nvgFillPaint(vg, paint);
  575. nvgFill(vg);
  576. nvgStrokeColor(vg, nvgRGBA(0,0,0,64));
  577. nvgStroke(vg);
  578. // Select circle on triangle
  579. ax = cosf(120.0f/180.0f*NVG_PI) * r*0.3f;
  580. ay = sinf(120.0f/180.0f*NVG_PI) * r*0.4f;
  581. nvgStrokeWidth(vg, 2.0f);
  582. nvgBeginPath(vg);
  583. nvgCircle(vg, ax,ay,5);
  584. nvgStrokeColor(vg, nvgRGBA(255,255,255,192));
  585. nvgStroke(vg);
  586. paint = nvgRadialGradient(vg, ax,ay, 7,9, nvgRGBA(0,0,0,64), nvgRGBA(0,0,0,0));
  587. nvgBeginPath(vg);
  588. nvgRect(vg, ax-20,ay-20,40,40);
  589. nvgCircle(vg, ax,ay,7);
  590. nvgPathWinding(vg, NVG_HOLE);
  591. nvgFillPaint(vg, paint);
  592. nvgFill(vg);
  593. nvgRestore(vg);
  594. nvgRestore(vg);
  595. }
  596. void drawLines(struct NVGcontext* vg, float x, float y, float w, float h, float t)
  597. {
  598. int i, j;
  599. float pad = 5.0f, s = w/9.0f - pad*2;
  600. float pts[4*2], fx, fy;
  601. int joins[3] = {NVG_MITER, NVG_ROUND, NVG_BEVEL};
  602. int caps[3] = {NVG_BUTT, NVG_ROUND, NVG_SQUARE};
  603. NVG_NOTUSED(h);
  604. nvgSave(vg);
  605. pts[0] = -s*0.25f + cosf(t*0.3f) * s*0.5f;
  606. pts[1] = sinf(t*0.3f) * s*0.5f;
  607. pts[2] = -s*0.25;
  608. pts[3] = 0;
  609. pts[4] = s*0.25f;
  610. pts[5] = 0;
  611. pts[6] = s*0.25f + cosf(-t*0.3f) * s*0.5f;
  612. pts[7] = sinf(-t*0.3f) * s*0.5f;
  613. for (i = 0; i < 3; i++) {
  614. for (j = 0; j < 3; j++) {
  615. fx = x + s*0.5f + (i*3+j)/9.0f*w + pad;
  616. fy = y - s*0.5f + pad;
  617. nvgLineCap(vg, caps[i]);
  618. nvgLineJoin(vg, joins[j]);
  619. nvgStrokeWidth(vg, s*0.3f);
  620. nvgStrokeColor(vg, nvgRGBA(0,0,0,160));
  621. nvgBeginPath(vg);
  622. nvgMoveTo(vg, fx+pts[0], fy+pts[1]);
  623. nvgLineTo(vg, fx+pts[2], fy+pts[3]);
  624. nvgLineTo(vg, fx+pts[4], fy+pts[5]);
  625. nvgLineTo(vg, fx+pts[6], fy+pts[7]);
  626. nvgStroke(vg);
  627. nvgLineCap(vg, NVG_BUTT);
  628. nvgLineJoin(vg, NVG_BEVEL);
  629. nvgStrokeWidth(vg, 1.0f);
  630. nvgStrokeColor(vg, nvgRGBA(0,192,255,255));
  631. nvgBeginPath(vg);
  632. nvgMoveTo(vg, fx+pts[0], fy+pts[1]);
  633. nvgLineTo(vg, fx+pts[2], fy+pts[3]);
  634. nvgLineTo(vg, fx+pts[4], fy+pts[5]);
  635. nvgLineTo(vg, fx+pts[6], fy+pts[7]);
  636. nvgStroke(vg);
  637. }
  638. }
  639. nvgRestore(vg);
  640. }
  641. int loadDemoData(struct NVGcontext* vg, struct DemoData* data)
  642. {
  643. int i;
  644. if (vg == NULL)
  645. return -1;
  646. for (i = 0; i < 12; i++) {
  647. char file[128];
  648. snprintf(file, 128, "../example/images/image%d.jpg", i+1);
  649. data->images[i] = nvgCreateImage(vg, file);
  650. if (data->images[i] == 0) {
  651. printf("Could not load %s.\n", file);
  652. return -1;
  653. }
  654. }
  655. data->fontIcons = nvgCreateFont(vg, "icons", "../example/entypo.ttf");
  656. if (data->fontIcons == -1) {
  657. printf("Could not add font icons.\n");
  658. return -1;
  659. }
  660. data->fontNormal = nvgCreateFont(vg, "sans", "../example/Roboto-Regular.ttf");
  661. if (data->fontNormal == -1) {
  662. printf("Could not add font italic.\n");
  663. return -1;
  664. }
  665. data->fontBold = nvgCreateFont(vg, "sans-bold", "../example/Roboto-Bold.ttf");
  666. if (data->fontBold == -1) {
  667. printf("Could not add font bold.\n");
  668. return -1;
  669. }
  670. return 0;
  671. }
  672. void freeDemoData(struct NVGcontext* vg, struct DemoData* data)
  673. {
  674. int i;
  675. if (vg == NULL)
  676. return;
  677. for (i = 0; i < 12; i++)
  678. nvgDeleteImage(vg, data->images[i]);
  679. }
  680. void renderDemo(struct NVGcontext* vg, float mx, float my, float width, float height,
  681. float t, int blowup, struct DemoData* data)
  682. {
  683. float x,y,popy;
  684. drawEyes(vg, width - 250, 50, 150, 100, mx, my, t);
  685. drawGraph(vg, 0, height/2, width, height/2, t);
  686. drawColorwheel(vg, width - 300, height - 300, 250.0f, 250.0f, t);
  687. // Line joints
  688. drawLines(vg, 50, height-50, 600, 50, t);
  689. nvgSave(vg);
  690. if (blowup) {
  691. nvgRotate(vg, sinf(t*0.3f)*5.0f/180.0f*NVG_PI);
  692. nvgScale(vg, 2.0f, 2.0f);
  693. }
  694. // Widgets
  695. drawWindow(vg, "Widgets `n Stuff", 50, 50, 300, 400);
  696. x = 60; y = 95;
  697. drawSearchBox(vg, "Search", x,y,280,25);
  698. y += 40;
  699. drawDropDown(vg, "Effects", x,y,280,28);
  700. popy = y + 14;
  701. y += 45;
  702. // Form
  703. drawLabel(vg, "Login", x,y, 280,20);
  704. y += 25;
  705. drawEditBox(vg, "Email", x,y, 280,28);
  706. y += 35;
  707. drawEditBox(vg, "Password", x,y, 280,28);
  708. y += 38;
  709. drawCheckBox(vg, "Remember me", x,y, 140,28);
  710. drawButton(vg, ICON_LOGIN, "Sign in", x+138, y, 140, 28, nvgRGBA(0,96,128,255));
  711. y += 45;
  712. // Slider
  713. drawLabel(vg, "Diameter", x,y, 280,20);
  714. y += 25;
  715. drawEditBoxNum(vg, "123.00", "px", x+180,y, 100,28);
  716. drawSlider(vg, 0.4f, x,y, 170,28);
  717. y += 55;
  718. drawButton(vg, ICON_TRASH, "Delete", x, y, 160, 28, nvgRGBA(128,16,8,255));
  719. drawButton(vg, 0, "Cancel", x+170, y, 110, 28, nvgRGBA(0,0,0,0));
  720. // Thumbnails box
  721. drawThumbnails(vg, 365, popy-30, 160, 300, data->images, 12, t);
  722. nvgRestore(vg);
  723. }