nanovg.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  1. /*
  2. * Copyright 2011-2015 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. //
  6. // Copyright (c) 2013 Mikko Mononen [email protected]
  7. //
  8. // This software is provided 'as-is', without any express or implied
  9. // warranty. In no event will the authors be held liable for any damages
  10. // arising from the use of this software.
  11. // Permission is granted to anyone to use this software for any purpose,
  12. // including commercial applications, and to alter it and redistribute it
  13. // freely, subject to the following restrictions:
  14. // 1. The origin of this software must not be misrepresented; you must not
  15. // claim that you wrote the original software. If you use this software
  16. // in a product, an acknowledgment in the product documentation would be
  17. // appreciated but is not required.
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. // 3. This notice may not be removed or altered from any source distribution.
  21. //
  22. #include "common.h"
  23. #include <stdio.h>
  24. #include <math.h>
  25. #include <bgfx/bgfx.h>
  26. #include <bx/string.h>
  27. #include <bx/timer.h>
  28. #include "entry/entry.h"
  29. #include "imgui/imgui.h"
  30. #include "nanovg/nanovg.h"
  31. BX_PRAGMA_DIAGNOSTIC_PUSH();
  32. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-parameter");
  33. #define BLENDISH_IMPLEMENTATION
  34. #include "blendish.h"
  35. BX_PRAGMA_DIAGNOSTIC_POP();
  36. #define ICON_SEARCH 0x1F50D
  37. #define ICON_CIRCLED_CROSS 0x2716
  38. #define ICON_CHEVRON_RIGHT 0xE75E
  39. #define ICON_CHECK 0x2713
  40. #define ICON_LOGIN 0xE740
  41. #define ICON_TRASH 0xE729
  42. // Returns 1 if col.rgba is 0.0f,0.0f,0.0f,0.0f, 0 otherwise
  43. int isBlack( struct NVGcolor col )
  44. {
  45. if( col.r == 0.0f && col.g == 0.0f && col.b == 0.0f && col.a == 0.0f )
  46. {
  47. return 1;
  48. }
  49. return 0;
  50. }
  51. static char* cpToUTF8(int cp, char* str)
  52. {
  53. int n = 0;
  54. if (cp < 0x80) n = 1;
  55. else if (cp < 0x800) n = 2;
  56. else if (cp < 0x10000) n = 3;
  57. else if (cp < 0x200000) n = 4;
  58. else if (cp < 0x4000000) n = 5;
  59. else if (cp <= 0x7fffffff) n = 6;
  60. str[n] = '\0';
  61. switch (n)
  62. {
  63. case 6: str[5] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x4000000;
  64. case 5: str[4] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x200000;
  65. case 4: str[3] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x10000;
  66. case 3: str[2] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0x800;
  67. case 2: str[1] = 0x80 | (cp & 0x3f); cp = cp >> 6; cp |= 0xc0;
  68. case 1: str[0] = cp;
  69. }
  70. return str;
  71. }
  72. void drawWindow(struct NVGcontext* vg, const char* title, float x, float y, float w, float h)
  73. {
  74. float cornerRadius = 3.0f;
  75. struct NVGpaint shadowPaint;
  76. struct NVGpaint headerPaint;
  77. nvgSave(vg);
  78. // nvgClearState(vg);
  79. // Window
  80. nvgBeginPath(vg);
  81. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  82. nvgFillColor(vg, nvgRGBA(28,30,34,192) );
  83. // nvgFillColor(vg, nvgRGBA(0,0,0,128) );
  84. nvgFill(vg);
  85. // Drop shadow
  86. shadowPaint = nvgBoxGradient(vg, x,y+2, w,h, cornerRadius*2, 10, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0) );
  87. nvgBeginPath(vg);
  88. nvgRect(vg, x-10,y-10, w+20,h+30);
  89. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  90. nvgPathWinding(vg, NVG_HOLE);
  91. nvgFillPaint(vg, shadowPaint);
  92. nvgFill(vg);
  93. // Header
  94. headerPaint = nvgLinearGradient(vg, x,y,x,y+15, nvgRGBA(255,255,255,8), nvgRGBA(0,0,0,16) );
  95. nvgBeginPath(vg);
  96. nvgRoundedRect(vg, x+1,y+1, w-2,30, cornerRadius-1);
  97. nvgFillPaint(vg, headerPaint);
  98. nvgFill(vg);
  99. nvgBeginPath(vg);
  100. nvgMoveTo(vg, x+0.5f, y+0.5f+30);
  101. nvgLineTo(vg, x+0.5f+w-1, y+0.5f+30);
  102. nvgStrokeColor(vg, nvgRGBA(0,0,0,32) );
  103. nvgStroke(vg);
  104. nvgFontSize(vg, 18.0f);
  105. nvgFontFace(vg, "sans-bold");
  106. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  107. nvgFontBlur(vg,2);
  108. nvgFillColor(vg, nvgRGBA(0,0,0,128) );
  109. nvgText(vg, x+w/2,y+16+1, title, NULL);
  110. nvgFontBlur(vg,0);
  111. nvgFillColor(vg, nvgRGBA(220,220,220,160) );
  112. nvgText(vg, x+w/2,y+16, title, NULL);
  113. nvgRestore(vg);
  114. }
  115. void drawSearchBox(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 = h/2-1;
  120. // Edit
  121. bg = nvgBoxGradient(vg, x,y+1.5f, w,h, h/2,5, nvgRGBA(0,0,0,16), nvgRGBA(0,0,0,92) );
  122. nvgBeginPath(vg);
  123. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  124. nvgFillPaint(vg, bg);
  125. nvgFill(vg);
  126. /* nvgBeginPath(vg);
  127. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f);
  128. nvgStrokeColor(vg, nvgRGBA(0,0,0,48) );
  129. nvgStroke(vg);*/
  130. nvgFontSize(vg, h*1.3f);
  131. nvgFontFace(vg, "icons");
  132. nvgFillColor(vg, nvgRGBA(255,255,255,64) );
  133. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  134. nvgText(vg, x+h*0.55f, y+h*0.55f, cpToUTF8(ICON_SEARCH,icon), NULL);
  135. nvgFontSize(vg, 20.0f);
  136. nvgFontFace(vg, "sans");
  137. nvgFillColor(vg, nvgRGBA(255,255,255,32) );
  138. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  139. nvgText(vg, x+h*1.05f,y+h*0.5f,text, NULL);
  140. nvgFontSize(vg, h*1.3f);
  141. nvgFontFace(vg, "icons");
  142. nvgFillColor(vg, nvgRGBA(255,255,255,32) );
  143. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  144. nvgText(vg, x+w-h*0.55f, y+h*0.55f, cpToUTF8(ICON_CIRCLED_CROSS,icon), NULL);
  145. }
  146. void drawDropDown(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  147. {
  148. struct NVGpaint bg;
  149. char icon[8];
  150. float cornerRadius = 4.0f;
  151. bg = nvgLinearGradient(vg, x,y,x,y+h, nvgRGBA(255,255,255,16), nvgRGBA(0,0,0,16) );
  152. nvgBeginPath(vg);
  153. nvgRoundedRect(vg, x+1,y+1, w-2,h-2, cornerRadius-1);
  154. nvgFillPaint(vg, bg);
  155. nvgFill(vg);
  156. nvgBeginPath(vg);
  157. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f);
  158. nvgStrokeColor(vg, nvgRGBA(0,0,0,48) );
  159. nvgStroke(vg);
  160. nvgFontSize(vg, 20.0f);
  161. nvgFontFace(vg, "sans");
  162. nvgFillColor(vg, nvgRGBA(255,255,255,160) );
  163. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  164. nvgText(vg, x+h*0.3f,y+h*0.5f,text, NULL);
  165. nvgFontSize(vg, h*1.3f);
  166. nvgFontFace(vg, "icons");
  167. nvgFillColor(vg, nvgRGBA(255,255,255,64) );
  168. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  169. nvgText(vg, x+w-h*0.5f, y+h*0.5f, cpToUTF8(ICON_CHEVRON_RIGHT,icon), NULL);
  170. }
  171. void drawLabel(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  172. {
  173. NVG_NOTUSED(w);
  174. nvgFontSize(vg, 18.0f);
  175. nvgFontFace(vg, "sans");
  176. nvgFillColor(vg, nvgRGBA(255,255,255,128) );
  177. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  178. nvgText(vg, x,y+h*0.5f,text, NULL);
  179. }
  180. void drawEditBoxBase(struct NVGcontext* vg, float x, float y, float w, float h)
  181. {
  182. struct NVGpaint bg;
  183. // Edit
  184. 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) );
  185. nvgBeginPath(vg);
  186. nvgRoundedRect(vg, x+1,y+1, w-2,h-2, 4-1);
  187. nvgFillPaint(vg, bg);
  188. nvgFill(vg);
  189. nvgBeginPath(vg);
  190. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, 4-0.5f);
  191. nvgStrokeColor(vg, nvgRGBA(0,0,0,48) );
  192. nvgStroke(vg);
  193. }
  194. void drawEditBox(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  195. {
  196. drawEditBoxBase(vg, x,y, w,h);
  197. nvgFontSize(vg, 20.0f);
  198. nvgFontFace(vg, "sans");
  199. nvgFillColor(vg, nvgRGBA(255,255,255,64) );
  200. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  201. nvgText(vg, x+h*0.3f,y+h*0.5f,text, NULL);
  202. }
  203. void drawEditBoxNum(struct NVGcontext* vg,
  204. const char* text, const char* units, float x, float y, float w, float h)
  205. {
  206. float uw;
  207. drawEditBoxBase(vg, x,y, w,h);
  208. uw = nvgTextBounds(vg, 0,0, units, NULL, NULL);
  209. nvgFontSize(vg, 18.0f);
  210. nvgFontFace(vg, "sans");
  211. nvgFillColor(vg, nvgRGBA(255,255,255,64) );
  212. nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);
  213. nvgText(vg, x+w-h*0.3f,y+h*0.5f,units, NULL);
  214. nvgFontSize(vg, 20.0f);
  215. nvgFontFace(vg, "sans");
  216. nvgFillColor(vg, nvgRGBA(255,255,255,128) );
  217. nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);
  218. nvgText(vg, x+w-uw-h*0.5f,y+h*0.5f,text, NULL);
  219. }
  220. void drawCheckBox(struct NVGcontext* vg, const char* text, float x, float y, float w, float h)
  221. {
  222. struct NVGpaint bg;
  223. char icon[8];
  224. NVG_NOTUSED(w);
  225. nvgFontSize(vg, 18.0f);
  226. nvgFontFace(vg, "sans");
  227. nvgFillColor(vg, nvgRGBA(255,255,255,160) );
  228. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  229. nvgText(vg, x+28,y+h*0.5f,text, NULL);
  230. 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) );
  231. nvgBeginPath(vg);
  232. nvgRoundedRect(vg, x+1,y+(int)(h*0.5f)-9, 18,18, 3);
  233. nvgFillPaint(vg, bg);
  234. nvgFill(vg);
  235. nvgFontSize(vg, 40);
  236. nvgFontFace(vg, "icons");
  237. nvgFillColor(vg, nvgRGBA(255,255,255,128) );
  238. nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
  239. nvgText(vg, x+9+2, y+h*0.5f, cpToUTF8(ICON_CHECK,icon), NULL);
  240. }
  241. void drawButton(struct NVGcontext* vg, int preicon, const char* text, float x, float y, float w, float h, struct NVGcolor col)
  242. {
  243. struct NVGpaint bg;
  244. char icon[8];
  245. float cornerRadius = 4.0f;
  246. float tw = 0, iw = 0;
  247. bg = nvgLinearGradient(vg, x,y,x,y+h, nvgRGBA(255,255,255,isBlack(col)?16:32), nvgRGBA(0,0,0,isBlack(col)?16:32) );
  248. nvgBeginPath(vg);
  249. nvgRoundedRect(vg, x+1,y+1, w-2,h-2, cornerRadius-1);
  250. if (!isBlack(col) ) {
  251. nvgFillColor(vg, col);
  252. nvgFill(vg);
  253. }
  254. nvgFillPaint(vg, bg);
  255. nvgFill(vg);
  256. nvgBeginPath(vg);
  257. nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f);
  258. nvgStrokeColor(vg, nvgRGBA(0,0,0,48) );
  259. nvgStroke(vg);
  260. nvgFontSize(vg, 20.0f);
  261. nvgFontFace(vg, "sans-bold");
  262. tw = nvgTextBounds(vg, 0,0, text, NULL, NULL);
  263. if (preicon != 0) {
  264. nvgFontSize(vg, h*1.3f);
  265. nvgFontFace(vg, "icons");
  266. iw = nvgTextBounds(vg, 0,0, cpToUTF8(preicon,icon), NULL, NULL);
  267. iw += h*0.15f;
  268. }
  269. if (preicon != 0) {
  270. nvgFontSize(vg, h*1.3f);
  271. nvgFontFace(vg, "icons");
  272. nvgFillColor(vg, nvgRGBA(255,255,255,96) );
  273. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  274. nvgText(vg, x+w*0.5f-tw*0.5f-iw*0.75f, y+h*0.5f, cpToUTF8(preicon,icon), NULL);
  275. }
  276. nvgFontSize(vg, 20.0f);
  277. nvgFontFace(vg, "sans-bold");
  278. nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
  279. nvgFillColor(vg, nvgRGBA(0,0,0,160) );
  280. nvgText(vg, x+w*0.5f-tw*0.5f+iw*0.25f,y+h*0.5f-1,text, NULL);
  281. nvgFillColor(vg, nvgRGBA(255,255,255,160) );
  282. nvgText(vg, x+w*0.5f-tw*0.5f+iw*0.25f,y+h*0.5f,text, NULL);
  283. }
  284. void drawSlider(struct NVGcontext* vg, float pos, float x, float y, float w, float h)
  285. {
  286. struct NVGpaint bg, knob;
  287. float cy = y+(int)(h*0.5f);
  288. float kr = (float)( (int)(h*0.25f) );
  289. nvgSave(vg);
  290. // nvgClearState(vg);
  291. // Slot
  292. bg = nvgBoxGradient(vg, x,cy-2+1, w,4, 2,2, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,128) );
  293. nvgBeginPath(vg);
  294. nvgRoundedRect(vg, x,cy-2, w,4, 2);
  295. nvgFillPaint(vg, bg);
  296. nvgFill(vg);
  297. // Knob Shadow
  298. bg = nvgRadialGradient(vg, x+(int)(pos*w),cy+1, kr-3,kr+3, nvgRGBA(0,0,0,64), nvgRGBA(0,0,0,0) );
  299. nvgBeginPath(vg);
  300. nvgRect(vg, x+(int)(pos*w)-kr-5,cy-kr-5,kr*2+5+5,kr*2+5+5+3);
  301. nvgCircle(vg, x+(int)(pos*w),cy, kr);
  302. nvgPathWinding(vg, NVG_HOLE);
  303. nvgFillPaint(vg, bg);
  304. nvgFill(vg);
  305. // Knob
  306. knob = nvgLinearGradient(vg, x,cy-kr,x,cy+kr, nvgRGBA(255,255,255,16), nvgRGBA(0,0,0,16) );
  307. nvgBeginPath(vg);
  308. nvgCircle(vg, x+(int)(pos*w),cy, kr-1);
  309. nvgFillColor(vg, nvgRGBA(40,43,48,255) );
  310. nvgFill(vg);
  311. nvgFillPaint(vg, knob);
  312. nvgFill(vg);
  313. nvgBeginPath(vg);
  314. nvgCircle(vg, x+(int)(pos*w),cy, kr-0.5f);
  315. nvgStrokeColor(vg, nvgRGBA(0,0,0,92) );
  316. nvgStroke(vg);
  317. nvgRestore(vg);
  318. }
  319. void drawEyes(struct NVGcontext* vg, float x, float y, float w, float h, float mx, float my, float t)
  320. {
  321. struct NVGpaint gloss, bg;
  322. float ex = w *0.23f;
  323. float ey = h * 0.5f;
  324. float lx = x + ex;
  325. float ly = y + ey;
  326. float rx = x + w - ex;
  327. float ry = y + ey;
  328. float dx,dy,d;
  329. float br = (ex < ey ? ex : ey) * 0.5f;
  330. float blink = 1 - powf(sinf(t*0.5f),200)*0.8f;
  331. bg = nvgLinearGradient(vg, x,y+h*0.5f,x+w*0.1f,y+h, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,16) );
  332. nvgBeginPath(vg);
  333. nvgEllipse(vg, lx+3.0f,ly+16.0f, ex,ey);
  334. nvgEllipse(vg, rx+3.0f,ry+16.0f, ex,ey);
  335. nvgFillPaint(vg, bg);
  336. nvgFill(vg);
  337. bg = nvgLinearGradient(vg, x,y+h*0.25f,x+w*0.1f,y+h, nvgRGBA(220,220,220,255), nvgRGBA(128,128,128,255) );
  338. nvgBeginPath(vg);
  339. nvgEllipse(vg, lx,ly, ex,ey);
  340. nvgEllipse(vg, rx,ry, ex,ey);
  341. nvgFillPaint(vg, bg);
  342. nvgFill(vg);
  343. dx = (mx - rx) / (ex * 10);
  344. dy = (my - ry) / (ey * 10);
  345. d = sqrtf(dx*dx+dy*dy);
  346. if (d > 1.0f) {
  347. dx /= d; dy /= d;
  348. }
  349. dx *= ex*0.4f;
  350. dy *= ey*0.5f;
  351. nvgBeginPath(vg);
  352. nvgEllipse(vg, lx+dx,ly+dy+ey*0.25f*(1-blink), br,br*blink);
  353. nvgFillColor(vg, nvgRGBA(32,32,32,255) );
  354. nvgFill(vg);
  355. dx = (mx - rx) / (ex * 10);
  356. dy = (my - ry) / (ey * 10);
  357. d = sqrtf(dx*dx+dy*dy);
  358. if (d > 1.0f) {
  359. dx /= d; dy /= d;
  360. }
  361. dx *= ex*0.4f;
  362. dy *= ey*0.5f;
  363. nvgBeginPath(vg);
  364. nvgEllipse(vg, rx+dx,ry+dy+ey*0.25f*(1-blink), br,br*blink);
  365. nvgFillColor(vg, nvgRGBA(32,32,32,255) );
  366. nvgFill(vg);
  367. 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) );
  368. nvgBeginPath(vg);
  369. nvgEllipse(vg, lx,ly, ex,ey);
  370. nvgFillPaint(vg, gloss);
  371. nvgFill(vg);
  372. 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) );
  373. nvgBeginPath(vg);
  374. nvgEllipse(vg, rx,ry, ex,ey);
  375. nvgFillPaint(vg, gloss);
  376. nvgFill(vg);
  377. }
  378. void drawGraph(struct NVGcontext* vg, float x, float y, float w, float h, float t)
  379. {
  380. struct NVGpaint bg;
  381. float samples[6];
  382. float sx[6], sy[6];
  383. float dx = w/5.0f;
  384. int i;
  385. samples[0] = (1+sinf(t*1.2345f+cosf(t*0.33457f)*0.44f) )*0.5f;
  386. samples[1] = (1+sinf(t*0.68363f+cosf(t*1.3f)*1.55f) )*0.5f;
  387. samples[2] = (1+sinf(t*1.1642f+cosf(t*0.33457f)*1.24f) )*0.5f;
  388. samples[3] = (1+sinf(t*0.56345f+cosf(t*1.63f)*0.14f) )*0.5f;
  389. samples[4] = (1+sinf(t*1.6245f+cosf(t*0.254f)*0.3f) )*0.5f;
  390. samples[5] = (1+sinf(t*0.345f+cosf(t*0.03f)*0.6f) )*0.5f;
  391. for (i = 0; i < 6; i++) {
  392. sx[i] = x+i*dx;
  393. sy[i] = y+h*samples[i]*0.8f;
  394. }
  395. // Graph background
  396. bg = nvgLinearGradient(vg, x,y,x,y+h, nvgRGBA(0,160,192,0), nvgRGBA(0,160,192,64) );
  397. nvgBeginPath(vg);
  398. nvgMoveTo(vg, sx[0], sy[0]);
  399. for (i = 1; i < 6; i++)
  400. nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1], sx[i]-dx*0.5f,sy[i], sx[i],sy[i]);
  401. nvgLineTo(vg, x+w, y+h);
  402. nvgLineTo(vg, x, y+h);
  403. nvgFillPaint(vg, bg);
  404. nvgFill(vg);
  405. // Graph line
  406. nvgBeginPath(vg);
  407. nvgMoveTo(vg, sx[0], sy[0]+2);
  408. for (i = 1; i < 6; i++)
  409. 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);
  410. nvgStrokeColor(vg, nvgRGBA(0,0,0,32) );
  411. nvgStrokeWidth(vg, 3.0f);
  412. nvgStroke(vg);
  413. nvgBeginPath(vg);
  414. nvgMoveTo(vg, sx[0], sy[0]);
  415. for (i = 1; i < 6; i++)
  416. nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1], sx[i]-dx*0.5f,sy[i], sx[i],sy[i]);
  417. nvgStrokeColor(vg, nvgRGBA(0,160,192,255) );
  418. nvgStrokeWidth(vg, 3.0f);
  419. nvgStroke(vg);
  420. // Graph sample pos
  421. for (i = 0; i < 6; i++) {
  422. bg = nvgRadialGradient(vg, sx[i],sy[i]+2, 3.0f,8.0f, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,0) );
  423. nvgBeginPath(vg);
  424. nvgRect(vg, sx[i]-10, sy[i]-10+2, 20,20);
  425. nvgFillPaint(vg, bg);
  426. nvgFill(vg);
  427. }
  428. nvgBeginPath(vg);
  429. for (i = 0; i < 6; i++)
  430. nvgCircle(vg, sx[i], sy[i], 4.0f);
  431. nvgFillColor(vg, nvgRGBA(0,160,192,255) );
  432. nvgFill(vg);
  433. nvgBeginPath(vg);
  434. for (i = 0; i < 6; i++)
  435. nvgCircle(vg, sx[i], sy[i], 2.0f);
  436. nvgFillColor(vg, nvgRGBA(220,220,220,255) );
  437. nvgFill(vg);
  438. nvgStrokeWidth(vg, 1.0f);
  439. }
  440. void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, const int* images, int nimages, float t)
  441. {
  442. float cornerRadius = 3.0f;
  443. struct NVGpaint shadowPaint, imgPaint, fadePaint;
  444. float ix,iy,iw,ih;
  445. float thumb = 60.0f;
  446. float arry = 30.5f;
  447. int imgw, imgh;
  448. float stackh = (nimages/2) * (thumb+10) + 10;
  449. int i;
  450. float u = (1+cosf(t*0.5f) )*0.5f;
  451. float scrollh;
  452. nvgSave(vg);
  453. // nvgClearState(vg);
  454. // Drop shadow
  455. shadowPaint = nvgBoxGradient(vg, x,y+4, w,h, cornerRadius*2, 20, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0) );
  456. nvgBeginPath(vg);
  457. nvgRect(vg, x-10,y-10, w+20,h+30);
  458. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  459. nvgPathWinding(vg, NVG_HOLE);
  460. nvgFillPaint(vg, shadowPaint);
  461. nvgFill(vg);
  462. // Window
  463. nvgBeginPath(vg);
  464. nvgRoundedRect(vg, x,y, w,h, cornerRadius);
  465. nvgMoveTo(vg, x-10,y+arry);
  466. nvgLineTo(vg, x+1,y+arry-11);
  467. nvgLineTo(vg, x+1,y+arry+11);
  468. nvgFillColor(vg, nvgRGBA(200,200,200,255) );
  469. nvgFill(vg);
  470. nvgSave(vg);
  471. nvgScissor(vg, x,y,w,h);
  472. nvgTranslate(vg, 0, -(stackh - h)*u);
  473. for (i = 0; i < nimages; i++) {
  474. float tx, ty;
  475. tx = x+10;
  476. ty = y+10;
  477. tx += (i%2) * (thumb+10);
  478. ty += (i/2) * (thumb+10);
  479. nvgImageSize(vg, images[i], &imgw, &imgh);
  480. if (imgw < imgh) {
  481. iw = thumb;
  482. ih = iw * (float)imgh/(float)imgw;
  483. ix = 0;
  484. iy = -(ih-thumb)*0.5f;
  485. } else {
  486. ih = thumb;
  487. iw = ih * (float)imgw/(float)imgh;
  488. ix = -(iw-thumb)*0.5f;
  489. iy = 0;
  490. }
  491. imgPaint = nvgImagePattern(vg, tx+ix, ty+iy, iw,ih, 0.0f/180.0f*NVG_PI, images[i], 0);
  492. nvgBeginPath(vg);
  493. nvgRoundedRect(vg, tx,ty, thumb,thumb, 5);
  494. nvgFillPaint(vg, imgPaint);
  495. nvgFill(vg);
  496. shadowPaint = nvgBoxGradient(vg, tx-1,ty, thumb+2,thumb+2, 5, 3, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0) );
  497. nvgBeginPath(vg);
  498. nvgRect(vg, tx-5,ty-5, thumb+10,thumb+10);
  499. nvgRoundedRect(vg, tx,ty, thumb,thumb, 6);
  500. nvgPathWinding(vg, NVG_HOLE);
  501. nvgFillPaint(vg, shadowPaint);
  502. nvgFill(vg);
  503. nvgBeginPath(vg);
  504. nvgRoundedRect(vg, tx+0.5f,ty+0.5f, thumb-1,thumb-1, 4-0.5f);
  505. nvgStrokeWidth(vg,1.0f);
  506. nvgStrokeColor(vg, nvgRGBA(255,255,255,192) );
  507. nvgStroke(vg);
  508. }
  509. nvgRestore(vg);
  510. // Hide fades
  511. fadePaint = nvgLinearGradient(vg, x,y,x,y+6, nvgRGBA(200,200,200,255), nvgRGBA(200,200,200,0) );
  512. nvgBeginPath(vg);
  513. nvgRect(vg, x+4,y,w-8,6);
  514. nvgFillPaint(vg, fadePaint);
  515. nvgFill(vg);
  516. fadePaint = nvgLinearGradient(vg, x,y+h,x,y+h-6, nvgRGBA(200,200,200,255), nvgRGBA(200,200,200,0) );
  517. nvgBeginPath(vg);
  518. nvgRect(vg, x+4,y+h-6,w-8,6);
  519. nvgFillPaint(vg, fadePaint);
  520. nvgFill(vg);
  521. // Scroll bar
  522. 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) );
  523. nvgBeginPath(vg);
  524. nvgRoundedRect(vg, x+w-12,y+4, 8,h-8, 3);
  525. nvgFillPaint(vg, shadowPaint);
  526. // nvgFillColor(vg, nvgRGBA(255,0,0,128) );
  527. nvgFill(vg);
  528. scrollh = (h/stackh) * (h-8);
  529. 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) );
  530. nvgBeginPath(vg);
  531. nvgRoundedRect(vg, x+w-12+1,y+4+1 + (h-8-scrollh)*u, 8-2,scrollh-2, 2);
  532. nvgFillPaint(vg, shadowPaint);
  533. // nvgFillColor(vg, nvgRGBA(0,0,0,128) );
  534. nvgFill(vg);
  535. nvgRestore(vg);
  536. }
  537. void drawColorwheel(struct NVGcontext* vg, float x, float y, float w, float h, float t)
  538. {
  539. int i;
  540. float r0, r1, ax,ay, bx,by, cx,cy, aeps, r;
  541. float hue = sinf(t * 0.12f);
  542. struct NVGpaint paint;
  543. nvgSave(vg);
  544. /* nvgBeginPath(vg);
  545. nvgRect(vg, x,y,w,h);
  546. nvgFillColor(vg, nvgRGBA(255,0,0,128) );
  547. nvgFill(vg);*/
  548. cx = x + w*0.5f;
  549. cy = y + h*0.5f;
  550. r1 = (w < h ? w : h) * 0.5f - 5.0f;
  551. r0 = r1 - 20.0f;
  552. aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out).
  553. for (i = 0; i < 6; i++)
  554. {
  555. float a0 = (float)i / 6.0f * NVG_PI * 2.0f - aeps;
  556. float a1 = (float)(i+1.0f) / 6.0f * NVG_PI * 2.0f + aeps;
  557. nvgBeginPath(vg);
  558. nvgArc(vg, cx,cy, r0, a0, a1, NVG_CW);
  559. nvgArc(vg, cx,cy, r1, a1, a0, NVG_CCW);
  560. nvgClosePath(vg);
  561. ax = cx + cosf(a0) * (r0+r1)*0.5f;
  562. ay = cy + sinf(a0) * (r0+r1)*0.5f;
  563. bx = cx + cosf(a1) * (r0+r1)*0.5f;
  564. by = cy + sinf(a1) * (r0+r1)*0.5f;
  565. 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) );
  566. nvgFillPaint(vg, paint);
  567. nvgFill(vg);
  568. }
  569. nvgBeginPath(vg);
  570. nvgCircle(vg, cx,cy, r0-0.5f);
  571. nvgCircle(vg, cx,cy, r1+0.5f);
  572. nvgStrokeColor(vg, nvgRGBA(0,0,0,64) );
  573. nvgStrokeWidth(vg, 1.0f);
  574. nvgStroke(vg);
  575. // Selector
  576. nvgSave(vg);
  577. nvgTranslate(vg, cx,cy);
  578. nvgRotate(vg, hue*NVG_PI*2);
  579. // Marker on
  580. nvgStrokeWidth(vg, 2.0f);
  581. nvgBeginPath(vg);
  582. nvgRect(vg, r0-1,-3,r1-r0+2,6);
  583. nvgStrokeColor(vg, nvgRGBA(255,255,255,192) );
  584. nvgStroke(vg);
  585. paint = nvgBoxGradient(vg, r0-3,-5,r1-r0+6,10, 2,4, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0) );
  586. nvgBeginPath(vg);
  587. nvgRect(vg, r0-2-10,-4-10,r1-r0+4+20,8+20);
  588. nvgRect(vg, r0-2,-4,r1-r0+4,8);
  589. nvgPathWinding(vg, NVG_HOLE);
  590. nvgFillPaint(vg, paint);
  591. nvgFill(vg);
  592. // Center triangle
  593. r = r0 - 6;
  594. ax = cosf(120.0f/180.0f*NVG_PI) * r;
  595. ay = sinf(120.0f/180.0f*NVG_PI) * r;
  596. bx = cosf(-120.0f/180.0f*NVG_PI) * r;
  597. by = sinf(-120.0f/180.0f*NVG_PI) * r;
  598. nvgBeginPath(vg);
  599. nvgMoveTo(vg, r,0);
  600. nvgLineTo(vg, ax,ay);
  601. nvgLineTo(vg, bx,by);
  602. nvgClosePath(vg);
  603. paint = nvgLinearGradient(vg, r,0, ax,ay, nvgHSLA(hue,1.0f,0.5f,255), nvgRGBA(255,255,255,255) );
  604. nvgFillPaint(vg, paint);
  605. nvgFill(vg);
  606. paint = nvgLinearGradient(vg, (r+ax)*0.5f,(0+ay)*0.5f, bx,by, nvgRGBA(0,0,0,0), nvgRGBA(0,0,0,255) );
  607. nvgFillPaint(vg, paint);
  608. nvgFill(vg);
  609. nvgStrokeColor(vg, nvgRGBA(0,0,0,64) );
  610. nvgStroke(vg);
  611. // Select circle on triangle
  612. ax = cosf(120.0f/180.0f*NVG_PI) * r*0.3f;
  613. ay = sinf(120.0f/180.0f*NVG_PI) * r*0.4f;
  614. nvgStrokeWidth(vg, 2.0f);
  615. nvgBeginPath(vg);
  616. nvgCircle(vg, ax,ay,5);
  617. nvgStrokeColor(vg, nvgRGBA(255,255,255,192) );
  618. nvgStroke(vg);
  619. paint = nvgRadialGradient(vg, ax,ay, 7,9, nvgRGBA(0,0,0,64), nvgRGBA(0,0,0,0) );
  620. nvgBeginPath(vg);
  621. nvgRect(vg, ax-20,ay-20,40,40);
  622. nvgCircle(vg, ax,ay,7);
  623. nvgPathWinding(vg, NVG_HOLE);
  624. nvgFillPaint(vg, paint);
  625. nvgFill(vg);
  626. nvgRestore(vg);
  627. nvgRestore(vg);
  628. }
  629. void drawLines(struct NVGcontext* vg, float x, float y, float w, float h, float t)
  630. {
  631. int i, j;
  632. float pad = 5.0f, s = w/9.0f - pad*2;
  633. float pts[4*2], fx, fy;
  634. int joins[3] = {NVG_MITER, NVG_ROUND, NVG_BEVEL};
  635. int caps[3] = {NVG_BUTT, NVG_ROUND, NVG_SQUARE};
  636. NVG_NOTUSED(h);
  637. nvgSave(vg);
  638. pts[0] = -s*0.25f + cosf(t*0.3f) * s*0.5f;
  639. pts[1] = sinf(t*0.3f) * s*0.5f;
  640. pts[2] = -s*0.25f;
  641. pts[3] = 0;
  642. pts[4] = s*0.25f;
  643. pts[5] = 0;
  644. pts[6] = s*0.25f + cosf(-t*0.3f) * s*0.5f;
  645. pts[7] = sinf(-t*0.3f) * s*0.5f;
  646. for (i = 0; i < 3; i++)
  647. {
  648. for (j = 0; j < 3; j++)
  649. {
  650. fx = x + s*0.5f + (i*3+j)/9.0f*w + pad;
  651. fy = y - s*0.5f + pad;
  652. nvgLineCap(vg, caps[i]);
  653. nvgLineJoin(vg, joins[j]);
  654. nvgStrokeWidth(vg, s*0.3f);
  655. nvgStrokeColor(vg, nvgRGBA(0,0,0,160) );
  656. nvgBeginPath(vg);
  657. nvgMoveTo(vg, fx+pts[0], fy+pts[1]);
  658. nvgLineTo(vg, fx+pts[2], fy+pts[3]);
  659. nvgLineTo(vg, fx+pts[4], fy+pts[5]);
  660. nvgLineTo(vg, fx+pts[6], fy+pts[7]);
  661. nvgStroke(vg);
  662. nvgLineCap(vg, NVG_BUTT);
  663. nvgLineJoin(vg, NVG_BEVEL);
  664. nvgStrokeWidth(vg, 1.0f);
  665. nvgStrokeColor(vg, nvgRGBA(0,192,255,255) );
  666. nvgBeginPath(vg);
  667. nvgMoveTo(vg, fx+pts[0], fy+pts[1]);
  668. nvgLineTo(vg, fx+pts[2], fy+pts[3]);
  669. nvgLineTo(vg, fx+pts[4], fy+pts[5]);
  670. nvgLineTo(vg, fx+pts[6], fy+pts[7]);
  671. nvgStroke(vg);
  672. }
  673. }
  674. nvgRestore(vg);
  675. }
  676. void drawBlendish(struct NVGcontext* _vg, float _x, float _y, float _w, float _h, float _t)
  677. {
  678. float x = _x;
  679. float y = _y;
  680. bndBackground(_vg, _x - 10.0f, _y - 10.0f, _w, _h);
  681. bndToolButton(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_DEFAULT, BND_ICONID(6, 3), "Default");
  682. y += 25.0f;
  683. bndToolButton(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_HOVER, BND_ICONID(6, 3), "Hovered");
  684. y += 25.0f;
  685. bndToolButton(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_ACTIVE, BND_ICONID(6, 3), "Active");
  686. y += 40.0f;
  687. bndRadioButton(_vg, x, y, 80.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_DEFAULT, -1, "Default");
  688. y += 25.0f;
  689. bndRadioButton(_vg, x, y, 80.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_HOVER, -1, "Hovered");
  690. y += 25.0f;
  691. bndRadioButton(_vg, x, y, 80.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_ACTIVE, -1, "Active");
  692. y += 25.0f;
  693. bndLabel(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, -1, "Label:");
  694. y += BND_WIDGET_HEIGHT;
  695. bndChoiceButton(_vg, x, y, 80.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_DEFAULT, -1, "Default");
  696. y += 25.0f;
  697. bndChoiceButton(_vg, x, y, 80.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_HOVER, -1, "Hovered");
  698. y += 25.0f;
  699. bndChoiceButton(_vg, x, y, 80.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_ACTIVE, -1, "Active");
  700. y += 25.0f;
  701. float ry = y;
  702. float rx = x;
  703. y = _y;
  704. x += 130.0f;
  705. bndOptionButton(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_DEFAULT, "Default");
  706. y += 25.0f;
  707. bndOptionButton(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_HOVER, "Hovered");
  708. y += 25.0f;
  709. bndOptionButton(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_ACTIVE, "Active");
  710. y += 40.0f;
  711. bndNumberField(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_DOWN, BND_DEFAULT, "Top", "100");
  712. y += BND_WIDGET_HEIGHT - 2.0f;
  713. bndNumberField(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, "Center", "100");
  714. y += BND_WIDGET_HEIGHT - 2.0f;
  715. bndNumberField(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_TOP, BND_DEFAULT, "Bottom", "100");
  716. float mx = x - 30.0f;
  717. float my = y - 12.0f;
  718. float mw = 120.0f;
  719. bndMenuBackground(_vg, mx, my, mw, 120.0f, BND_CORNER_TOP);
  720. bndMenuLabel(_vg, mx, my, mw, BND_WIDGET_HEIGHT, -1, "Menu Title");
  721. my += BND_WIDGET_HEIGHT - 2.0f;
  722. bndMenuItem(_vg, mx, my, mw, BND_WIDGET_HEIGHT, BND_DEFAULT, BND_ICONID(17, 3), "Default");
  723. my += BND_WIDGET_HEIGHT - 2.0f;
  724. bndMenuItem(_vg, mx, my, mw, BND_WIDGET_HEIGHT, BND_HOVER, BND_ICONID(18, 3), "Hovered");
  725. my += BND_WIDGET_HEIGHT - 2.0f;
  726. bndMenuItem(_vg, mx, my, mw, BND_WIDGET_HEIGHT, BND_ACTIVE, BND_ICONID(19, 3), "Active");
  727. y = _y;
  728. x += 130.0f;
  729. float ox = x;
  730. bndNumberField(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_DEFAULT, "Default", "100");
  731. y += 25.0f;
  732. bndNumberField(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_HOVER, "Hovered", "100");
  733. y += 25.0f;
  734. bndNumberField(_vg, x, y, 120.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_ACTIVE, "Active", "100");
  735. y += 40.0f;
  736. bndRadioButton(_vg, x, y, 60.0f, BND_WIDGET_HEIGHT, BND_CORNER_RIGHT, BND_DEFAULT, -1, "One");
  737. x += 60.0f - 1.0f;
  738. bndRadioButton(_vg, x, y, 60.0f, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, -1, "Two");
  739. x += 60.0f - 1.0f;
  740. bndRadioButton(_vg, x, y, 60.0f, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, -1, "Three");
  741. x += 60.0f - 1.0f;
  742. bndRadioButton(_vg, x, y, 60.0f, BND_WIDGET_HEIGHT, BND_CORNER_LEFT, BND_ACTIVE, -1, "Butts");
  743. x = ox;
  744. y += 40.0f;
  745. float progress_value = fmodf(_t / 10.0f, 1.0f);
  746. char progress_label[32];
  747. bx::snprintf(progress_label, BX_COUNTOF(progress_label), "%d%%", int(progress_value * 100 + 0.5f) );
  748. bndSlider(_vg, x, y, 240, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_DEFAULT, progress_value, "Default", progress_label);
  749. y += 25.0f;
  750. bndSlider(_vg, x, y, 240, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_HOVER, progress_value, "Hovered", progress_label);
  751. y += 25.0f;
  752. bndSlider(_vg, x, y, 240, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_ACTIVE, progress_value, "Active", progress_label);
  753. float rw = x + 240.0f - rx;
  754. float s_offset = sinf(_t / 2.0f) * 0.5f + 0.5f;
  755. float s_size = cosf(_t / 3.11f) * 0.5f + 0.5f;
  756. bndScrollBar(_vg, rx, ry, rw, BND_SCROLLBAR_HEIGHT, BND_DEFAULT, s_offset, s_size);
  757. ry += 20.0f;
  758. bndScrollBar(_vg, rx, ry, rw, BND_SCROLLBAR_HEIGHT, BND_HOVER, s_offset, s_size);
  759. ry += 20.0f;
  760. bndScrollBar(_vg, rx, ry, rw, BND_SCROLLBAR_HEIGHT, BND_ACTIVE, s_offset, s_size);
  761. const char edit_text[] = "The quick brown fox";
  762. int textlen = int(strlen(edit_text) + 1);
  763. int t = int(_t * 2);
  764. int idx1 = (t / textlen) % textlen;
  765. int idx2 = idx1 + (t % (textlen - idx1) );
  766. ry += 25.0f;
  767. bndTextField(_vg, rx, ry, 240.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_DEFAULT, -1, edit_text, idx1, idx2);
  768. ry += 25.0f;
  769. bndTextField(_vg, rx, ry, 240.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_HOVER, -1, edit_text, idx1, idx2);
  770. ry += 25.0f;
  771. bndTextField(_vg, rx, ry, 240.0f, BND_WIDGET_HEIGHT, BND_CORNER_NONE, BND_ACTIVE, -1, edit_text, idx1, idx2);
  772. rx += rw + 20.0f;
  773. ry = _y;
  774. bndScrollBar(_vg, rx, ry, BND_SCROLLBAR_WIDTH, 240.0f, BND_DEFAULT, s_offset, s_size);
  775. rx += 20.0f;
  776. bndScrollBar(_vg, rx, ry, BND_SCROLLBAR_WIDTH, 240.0f, BND_HOVER, s_offset, s_size);
  777. rx += 20.0f;
  778. bndScrollBar(_vg, rx, ry, BND_SCROLLBAR_WIDTH, 240.0f, BND_ACTIVE, s_offset, s_size);
  779. x = ox;
  780. y += 40.0f;
  781. bndToolButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_RIGHT, BND_DEFAULT, BND_ICONID(0, 10), NULL);
  782. x += BND_TOOL_WIDTH - 1;
  783. bndToolButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, BND_ICONID(1, 10), NULL);
  784. x += BND_TOOL_WIDTH - 1;
  785. bndToolButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, BND_ICONID(2, 10), NULL);
  786. x += BND_TOOL_WIDTH - 1;
  787. bndToolButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, BND_ICONID(3, 10), NULL);
  788. x += BND_TOOL_WIDTH - 1;
  789. bndToolButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, BND_ICONID(4, 10), NULL);
  790. x += BND_TOOL_WIDTH - 1;
  791. bndToolButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_LEFT, BND_DEFAULT, BND_ICONID(5, 10), NULL);
  792. x += BND_TOOL_WIDTH - 1;
  793. x += 5.0f;
  794. bndRadioButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_RIGHT, BND_DEFAULT, BND_ICONID(0, 11), NULL);
  795. x += BND_TOOL_WIDTH - 1;
  796. bndRadioButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, BND_ICONID(1, 11), NULL);
  797. x += BND_TOOL_WIDTH - 1;
  798. bndRadioButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, BND_ICONID(2, 11), NULL);
  799. x += BND_TOOL_WIDTH - 1;
  800. bndRadioButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_DEFAULT, BND_ICONID(3, 11), NULL);
  801. x += BND_TOOL_WIDTH - 1;
  802. bndRadioButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_ALL, BND_ACTIVE, BND_ICONID(4, 11), NULL);
  803. x += BND_TOOL_WIDTH - 1;
  804. bndRadioButton(_vg, x, y, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, BND_CORNER_LEFT, BND_DEFAULT, BND_ICONID(5, 11), NULL);
  805. }
  806. struct DemoData
  807. {
  808. int fontNormal, fontBold, fontIcons;
  809. int images[12];
  810. };
  811. int loadDemoData(struct NVGcontext* vg, struct DemoData* data)
  812. {
  813. for (uint32_t ii = 0; ii < 12; ++ii)
  814. {
  815. char file[128];
  816. bx::snprintf(file, 128, "images/image%d.jpg", ii+1);
  817. data->images[ii] = nvgCreateImage(vg, file, 0);
  818. if (data->images[ii] == bgfx::invalidHandle)
  819. {
  820. printf("Could not load %s.\n", file);
  821. return -1;
  822. }
  823. }
  824. data->fontIcons = nvgCreateFont(vg, "icons", "font/entypo.ttf");
  825. if (data->fontIcons == -1)
  826. {
  827. printf("Could not add font icons.\n");
  828. return -1;
  829. }
  830. data->fontNormal = nvgCreateFont(vg, "sans", "font/roboto-regular.ttf");
  831. if (data->fontNormal == -1)
  832. {
  833. printf("Could not add font italic.\n");
  834. return -1;
  835. }
  836. data->fontBold = nvgCreateFont(vg, "sans-bold", "font/roboto-bold.ttf");
  837. if (data->fontBold == -1)
  838. {
  839. printf("Could not add font bold.\n");
  840. return -1;
  841. }
  842. return 0;
  843. }
  844. void freeDemoData(struct NVGcontext* vg, struct DemoData* data)
  845. {
  846. int i;
  847. if (vg == NULL)
  848. return;
  849. for (i = 0; i < 12; i++)
  850. nvgDeleteImage(vg, data->images[i]);
  851. }
  852. #if defined(_MSC_VER) && (_MSC_VER < 1800)
  853. inline float round(float _f)
  854. {
  855. return float(int(_f) );
  856. }
  857. #endif
  858. void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float height, float mx, float my)
  859. {
  860. struct NVGtextRow rows[3];
  861. struct NVGglyphPosition glyphs[100];
  862. const char* text = "This is longer chunk of text.\n \n Would have used lorem ipsum but she was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party.";
  863. const char* start;
  864. const char* end;
  865. int nrows, i, nglyphs, j, lnum = 0;
  866. float lineh;
  867. float caretx, px;
  868. float bounds[4];
  869. float gx = 0.0f, gy = 0.0f;
  870. int gutter = 0;
  871. NVG_NOTUSED(height);
  872. nvgSave(vg);
  873. nvgFontSize(vg, 18.0f);
  874. nvgFontFace(vg, "sans");
  875. nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
  876. nvgTextMetrics(vg, NULL, NULL, &lineh);
  877. // The text break API can be used to fill a large buffer of rows,
  878. // or to iterate over the text just few lines (or just one) at a time.
  879. // The "next" variable of the last returned item tells where to continue.
  880. start = text;
  881. end = text + strlen(text);
  882. for (nrows = nvgTextBreakLines(vg, start, end, width, rows, 3); 0 != nrows; nrows = nvgTextBreakLines(vg, start, end, width, rows, 3) )
  883. {
  884. for (i = 0; i < nrows; i++) {
  885. struct NVGtextRow* row = &rows[i];
  886. int hit = mx > x && mx < (x+width) && my >= y && my < (y+lineh);
  887. nvgBeginPath(vg);
  888. nvgFillColor(vg, nvgRGBA(255,255,255,hit?64:8) );
  889. nvgRect(vg, x, y, row->width, lineh);
  890. nvgFill(vg);
  891. nvgFillColor(vg, nvgRGBA(255,255,255,255) );
  892. nvgText(vg, x, y, row->start, row->end);
  893. if (hit) {
  894. caretx = (mx < x+row->width/2) ? x : x+row->width;
  895. px = x;
  896. nglyphs = nvgTextGlyphPositions(vg, x, y, row->start, row->end, glyphs, 100);
  897. for (j = 0; j < nglyphs; j++) {
  898. float x0 = glyphs[j].x;
  899. float x1 = (j+1 < nglyphs) ? glyphs[j+1].x : x+row->width;
  900. float tgx = x0 * 0.3f + x1 * 0.7f;
  901. if (mx >= px && mx < tgx)
  902. caretx = glyphs[j].x;
  903. px = tgx;
  904. }
  905. nvgBeginPath(vg);
  906. nvgFillColor(vg, nvgRGBA(255,192,0,255) );
  907. nvgRect(vg, caretx, y, 1, lineh);
  908. nvgFill(vg);
  909. gutter = lnum+1;
  910. gx = x - 10;
  911. gy = y + lineh/2;
  912. }
  913. lnum++;
  914. y += lineh;
  915. }
  916. // Keep going...
  917. start = rows[nrows-1].next;
  918. }
  919. if (gutter)
  920. {
  921. char txt[16];
  922. bx::snprintf(txt, sizeof(txt), "%d", gutter);
  923. nvgFontSize(vg, 13.0f);
  924. nvgTextAlign(vg, NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);
  925. nvgTextBounds(vg, gx,gy, txt, NULL, bounds);
  926. nvgBeginPath(vg);
  927. nvgFillColor(vg, nvgRGBA(255,192,0,255) );
  928. nvgRoundedRect(vg
  929. , bx::fround(bounds[0])-4.0f
  930. , bx::fround(bounds[1])-2.0f
  931. , bx::fround(bounds[2]-bounds[0])+8.0f
  932. , bx::fround(bounds[3]-bounds[1])+4.0f
  933. , (bx::fround(bounds[3]-bounds[1])+4.0f)/2.0f-1.0f
  934. );
  935. nvgFill(vg);
  936. nvgFillColor(vg, nvgRGBA(32,32,32,255) );
  937. nvgText(vg, gx,gy, txt, NULL);
  938. }
  939. y += 20.0f;
  940. nvgFontSize(vg, 13.0f);
  941. nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
  942. nvgTextLineHeight(vg, 1.2f);
  943. nvgTextBoxBounds(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL, bounds);
  944. nvgBeginPath(vg);
  945. nvgFillColor(vg, nvgRGBA(220,220,220,255) );
  946. nvgRoundedRect(vg
  947. , bx::fround(bounds[0]-2.0f)
  948. , bx::fround(bounds[1]-2.0f)
  949. , bx::fround(bounds[2]-bounds[0])+4.0f
  950. , bx::fround(bounds[3]-bounds[1])+4.0f
  951. , 3.0f
  952. );
  953. px = float( (int)( (bounds[2]+bounds[0])/2) );
  954. nvgMoveTo(vg, px,bounds[1] - 10);
  955. nvgLineTo(vg, px+7,bounds[1]+1);
  956. nvgLineTo(vg, px-7,bounds[1]+1);
  957. nvgFill(vg);
  958. nvgFillColor(vg, nvgRGBA(0,0,0,220) );
  959. nvgTextBox(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL);
  960. nvgRestore(vg);
  961. }
  962. void drawWidths(struct NVGcontext* vg, float x, float y, float width)
  963. {
  964. nvgSave(vg);
  965. nvgStrokeColor(vg, nvgRGBA(0,0,0,255) );
  966. for (uint32_t ii = 0; ii < 20; ++ii)
  967. {
  968. float w = (ii+0.5f)*0.1f;
  969. nvgStrokeWidth(vg, w);
  970. nvgBeginPath(vg);
  971. nvgMoveTo(vg, x,y);
  972. nvgLineTo(vg, x+width,y+width*0.3f);
  973. nvgStroke(vg);
  974. y += 10;
  975. }
  976. nvgRestore(vg);
  977. }
  978. void renderDemo(struct NVGcontext* vg, float mx, float my, float width, float height, float t, int blowup, struct DemoData* data)
  979. {
  980. float x,y,popx,popy;
  981. drawEyes(vg, width-800, height-240, 150, 100, mx, my, t);
  982. drawParagraph(vg, width - 550, 35, 150, 100, mx, my);
  983. drawGraph(vg, 0, height/2, width, height/2, t);
  984. drawColorwheel(vg, width-350, 35, 250.0f, 250.0f, t);
  985. // Line joints
  986. drawLines(vg, 50, height-50, 600, 35, t);
  987. nvgSave(vg);
  988. if (blowup)
  989. {
  990. nvgRotate(vg, sinf(t*0.3f)*5.0f/180.0f*NVG_PI);
  991. nvgScale(vg, 2.0f, 2.0f);
  992. }
  993. // Line width.
  994. drawWidths(vg, width-50, 35, 30);
  995. // Widgets.
  996. x = width-520; y = height-420;
  997. drawWindow(vg, "Widgets `n Stuff", x, y, 300, 400);
  998. x += 10;
  999. y += 45;
  1000. drawSearchBox(vg, "Search", x,y,280,25);
  1001. y += 40;
  1002. drawDropDown(vg, "Effects", x,y,280,28);
  1003. popx = x + 300;
  1004. popy = y + 14;
  1005. y += 45;
  1006. // Form
  1007. drawLabel(vg, "Login", x,y, 280,20);
  1008. y += 25;
  1009. drawEditBox(vg, "Email", x,y, 280,28);
  1010. y += 35;
  1011. drawEditBox(vg, "Password", x,y, 280,28);
  1012. y += 38;
  1013. drawCheckBox(vg, "Remember me", x,y, 140,28);
  1014. drawButton(vg, ICON_LOGIN, "Sign in", x+138, y, 140, 28, nvgRGBA(0,96,128,255) );
  1015. y += 45;
  1016. // Slider
  1017. drawLabel(vg, "Diameter", x,y, 280,20);
  1018. y += 25;
  1019. drawEditBoxNum(vg, "123.00", "px", x+180,y, 100,28);
  1020. drawSlider(vg, 0.4f, x,y, 170,28);
  1021. y += 55;
  1022. drawButton(vg, ICON_TRASH, "Delete", x, y, 160, 28, nvgRGBA(128,16,8,255) );
  1023. drawButton(vg, 0, "Cancel", x+170, y, 110, 28, nvgRGBA(0,0,0,0) );
  1024. // Thumbnails box
  1025. drawThumbnails(vg, popx, popy-30, 160, 300, data->images, 12, t);
  1026. // Blendish
  1027. drawBlendish(vg, 10, 62, 600.0f, 420.0f, t);
  1028. nvgRestore(vg);
  1029. }
  1030. int _main_(int /*_argc*/, char** /*_argv*/)
  1031. {
  1032. uint32_t width = 1280;
  1033. uint32_t height = 720;
  1034. uint32_t debug = BGFX_DEBUG_TEXT;
  1035. uint32_t reset = BGFX_RESET_VSYNC;
  1036. bgfx::init();
  1037. bgfx::reset(width, height, reset);
  1038. // Enable debug text.
  1039. bgfx::setDebug(debug);
  1040. // Set view 0 clear state.
  1041. bgfx::setViewClear(0
  1042. , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
  1043. , 0x303030ff
  1044. , 1.0f
  1045. , 0
  1046. );
  1047. imguiCreate();
  1048. NVGcontext* nvg = nvgCreate(1, 0);
  1049. bgfx::setViewSeq(0, true);
  1050. DemoData data;
  1051. loadDemoData(nvg, &data);
  1052. bndSetFont(nvgCreateFont(nvg, "droidsans", "font/droidsans.ttf") );
  1053. bndSetIconImage(nvgCreateImage(nvg, "images/blender_icons16.png", 0) );
  1054. int64_t timeOffset = bx::getHPCounter();
  1055. entry::MouseState mouseState;
  1056. while (!entry::processEvents(width, height, debug, reset, &mouseState) )
  1057. {
  1058. int64_t now = bx::getHPCounter();
  1059. const double freq = double(bx::getHPFrequency() );
  1060. float time = (float)( (now-timeOffset)/freq);
  1061. // Set view 0 default viewport.
  1062. bgfx::setViewRect(0, 0, 0, width, height);
  1063. // This dummy draw call is here to make sure that view 0 is cleared
  1064. // if no other draw calls are submitted to view 0.
  1065. bgfx::touch(0);
  1066. // Use debug font to print information about this example.
  1067. bgfx::dbgTextClear();
  1068. bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/20-nanovg");
  1069. bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: NanoVG is small antialiased vector graphics rendering library.");
  1070. nvgBeginFrame(nvg, width, height, 1.0f);
  1071. renderDemo(nvg, float(mouseState.m_mx), float(mouseState.m_my), float(width), float(height), time, 0, &data);
  1072. nvgEndFrame(nvg);
  1073. // Advance to next frame. Rendering thread will be kicked to
  1074. // process submitted rendering primitives.
  1075. bgfx::frame();
  1076. }
  1077. freeDemoData(nvg, &data);
  1078. nvgDelete(nvg);
  1079. imguiDestroy();
  1080. // Shutdown bgfx.
  1081. bgfx::shutdown();
  1082. return 0;
  1083. }