sokol_imgui.h 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219
  1. #ifndef SOKOL_IMGUI_INCLUDED
  2. /*
  3. sokol_imgui.h -- drop-in Dear ImGui renderer/event-handler for sokol_gfx.h
  4. Project URL: https://github.com/floooh/sokol
  5. Do this:
  6. #define SOKOL_IMGUI_IMPL
  7. before you include this file in *one* C or C++ file to create the
  8. implementation.
  9. NOTE that the implementation can be compiled either as C++ or as C.
  10. When compiled as C++, sokol_imgui.h will directly call into the
  11. Dear ImGui C++ API. When compiled as C, sokol_imgui.h will call
  12. cimgui.h functions instead.
  13. NOTE that the formerly separate header sokol_cimgui.h has been
  14. merged into sokol_imgui.h
  15. The following defines are used by the implementation to select the
  16. platform-specific embedded shader code (these are the same defines as
  17. used by sokol_gfx.h and sokol_app.h):
  18. SOKOL_GLCORE33
  19. SOKOL_GLES2
  20. SOKOL_GLES3
  21. SOKOL_D3D11
  22. SOKOL_METAL
  23. Optionally provide the following configuration defines before including the
  24. implementation:
  25. SOKOL_IMGUI_NO_SOKOL_APP - don't depend on sokol_app.h (see below for details)
  26. Optionally provide the following macros before including the implementation
  27. to override defaults:
  28. SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
  29. SOKOL_API_DECL - public function declaration prefix (default: extern)
  30. SOKOL_API_IMPL - public function implementation prefix (default: -)
  31. If sokol_imgui.h is compiled as a DLL, define the following before
  32. including the declaration or implementation:
  33. SOKOL_DLL
  34. On Windows, SOKOL_DLL will define SOKOL_API_DECL as __declspec(dllexport)
  35. or __declspec(dllimport) as needed.
  36. Include the following headers before sokol_imgui.h (both before including
  37. the declaration and implementation):
  38. sokol_gfx.h
  39. sokol_app.h (except SOKOL_IMGUI_NO_SOKOL_APP)
  40. Additionally, include the following headers before including the
  41. implementation:
  42. If the implementation is compiled as C++:
  43. imgui.h
  44. If the implementation is compiled as C:
  45. cimgui.h
  46. FEATURE OVERVIEW:
  47. =================
  48. sokol_imgui.h implements the initialization, rendering and event-handling
  49. code for Dear ImGui (https://github.com/ocornut/imgui) on top of
  50. sokol_gfx.h and (optionally) sokol_app.h.
  51. The sokol_app.h dependency is optional and used for input event handling.
  52. If you only use sokol_gfx.h but not sokol_app.h in your application,
  53. define SOKOL_IMGUI_NO_SOKOL_APP before including the implementation
  54. of sokol_imgui.h, this will remove any dependency to sokol_app.h, but
  55. you must feed input events into Dear ImGui yourself.
  56. sokol_imgui.h is not thread-safe, all calls must be made from the
  57. same thread where sokol_gfx.h is running.
  58. HOWTO:
  59. ======
  60. --- To initialize sokol-imgui, call:
  61. simgui_setup(const simgui_desc_t* desc)
  62. This will initialize Dear ImGui and create sokol-gfx resources
  63. (two buffers for vertices and indices, a font texture and a pipeline-
  64. state-object).
  65. Use the following simgui_desc_t members to configure behaviour:
  66. int max_vertices
  67. The maximum number of vertices used for UI rendering, default is 65536.
  68. sokol-imgui will use this to compute the size of the vertex-
  69. and index-buffers allocated via sokol_gfx.h
  70. sg_pixel_format color_format
  71. The color pixel format of the render pass where the UI
  72. will be rendered. The default is SG_PIXELFORMAT_RGBA8
  73. sg_pixel_format depth_format
  74. The depth-buffer pixel format of the render pass where
  75. the UI will be rendered. The default is SG_PIXELFORMAT_DEPTHSTENCIL.
  76. int sample_count
  77. The MSAA sample-count of the render pass where the UI
  78. will be rendered. The default is 1.
  79. float dpi_scale
  80. DPI scaling factor. Set this to the result of sapp_dpi_scale().
  81. To render in high resolution on a Retina Mac this would
  82. typically be 2.0. The default value is 1.0
  83. const char* ini_filename
  84. Use this path as ImGui::GetIO().IniFilename. By default
  85. this is 0, so that Dear ImGui will not do any
  86. filesystem calls.
  87. bool no_default_font
  88. Set this to true if you don't want to use ImGui's default
  89. font. In this case you need to initialize the font
  90. yourself after simgui_setup() is called.
  91. --- At the start of a frame, call:
  92. simgui_new_frame(int width, int height, double delta_time)
  93. 'width' and 'height' are the dimensions of the rendering surface,
  94. passed to ImGui::GetIO().DisplaySize.
  95. 'delta_time' is the frame duration passed to ImGui::GetIO().DeltaTime.
  96. For example, if you're using sokol_app.h and render to the
  97. default framebuffer:
  98. simgui_new_frame(sapp_width(), sapp_height(), delta_time);
  99. --- at the end of the frame, before the sg_end_pass() where you
  100. want to render the UI, call:
  101. simgui_render()
  102. This will first call ImGui::Render(), and then render ImGui's draw list
  103. through sokol_gfx.h
  104. --- if you're using sokol_app.h, from inside the sokol_app.h event callback,
  105. call:
  106. bool simgui_handle_event(const sapp_event* ev);
  107. The return value is the value of ImGui::GetIO().WantCaptureKeyboard,
  108. if this is true, you might want to skip keyboard input handling
  109. in your own event handler.
  110. --- finally, on application shutdown, call
  111. simgui_shutdown()
  112. LICENSE
  113. =======
  114. zlib/libpng license
  115. Copyright (c) 2018 Andre Weissflog
  116. This software is provided 'as-is', without any express or implied warranty.
  117. In no event will the authors be held liable for any damages arising from the
  118. use of this software.
  119. Permission is granted to anyone to use this software for any purpose,
  120. including commercial applications, and to alter it and redistribute it
  121. freely, subject to the following restrictions:
  122. 1. The origin of this software must not be misrepresented; you must not
  123. claim that you wrote the original software. If you use this software in a
  124. product, an acknowledgment in the product documentation would be
  125. appreciated but is not required.
  126. 2. Altered source versions must be plainly marked as such, and must not
  127. be misrepresented as being the original software.
  128. 3. This notice may not be removed or altered from any source
  129. distribution.
  130. */
  131. #define SOKOL_IMGUI_INCLUDED (1)
  132. #include <stdint.h>
  133. #include <stdbool.h>
  134. #if !defined(SOKOL_GFX_INCLUDED)
  135. #error "Please include sokol_gfx.h before sokol_imgui.h"
  136. #endif
  137. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP) && !defined(SOKOL_APP_INCLUDED)
  138. #error "Please include sokol_app.h before sokol_imgui.h"
  139. #endif
  140. #ifndef SOKOL_API_DECL
  141. #if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_IMPL)
  142. #define SOKOL_API_DECL __declspec(dllexport)
  143. #elif defined(_WIN32) && defined(SOKOL_DLL)
  144. #define SOKOL_API_DECL __declspec(dllimport)
  145. #else
  146. #define SOKOL_API_DECL extern
  147. #endif
  148. #endif
  149. #ifdef __cplusplus
  150. extern "C" {
  151. #endif
  152. typedef struct simgui_desc_t {
  153. int max_vertices;
  154. sg_pixel_format color_format;
  155. sg_pixel_format depth_format;
  156. int sample_count;
  157. float dpi_scale;
  158. const char* ini_filename;
  159. bool no_default_font;
  160. bool disable_hotkeys; /* don't let ImGui handle Ctrl-A,C,V,X,Y,Z */
  161. } simgui_desc_t;
  162. SOKOL_API_DECL void simgui_setup(const simgui_desc_t* desc);
  163. SOKOL_API_DECL void simgui_new_frame(int width, int height, double delta_time);
  164. SOKOL_API_DECL void simgui_render(void);
  165. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  166. SOKOL_API_DECL bool simgui_handle_event(const sapp_event* ev);
  167. #endif
  168. SOKOL_API_DECL void simgui_shutdown(void);
  169. #ifdef __cplusplus
  170. } /* extern "C" */
  171. #endif
  172. #endif /* SOKOL_IMGUI_INCLUDED */
  173. /*-- IMPLEMENTATION ----------------------------------------------------------*/
  174. #ifdef SOKOL_IMGUI_IMPL
  175. #define SOKOL_IMGUI_IMPL_INCLUDED (1)
  176. #if defined(__cplusplus)
  177. #if !defined(IMGUI_VERSION)
  178. #error "Please include imgui.h before the sokol_imgui.h implementation"
  179. #endif
  180. #else
  181. #if !defined(CIMGUI_INCLUDED)
  182. #error "Please include cimgui.h before the sokol_imgui.h implementation"
  183. #endif
  184. #endif
  185. #include <stddef.h> /* offsetof */
  186. #include <string.h> /* memset */
  187. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP) && defined(__EMSCRIPTEN__)
  188. #include <emscripten.h>
  189. #endif
  190. #ifndef SOKOL_API_IMPL
  191. #define SOKOL_API_IMPL
  192. #endif
  193. #ifndef SOKOL_DEBUG
  194. #ifndef NDEBUG
  195. #define SOKOL_DEBUG (1)
  196. #endif
  197. #endif
  198. #ifndef SOKOL_ASSERT
  199. #include <assert.h>
  200. #define SOKOL_ASSERT(c) assert(c)
  201. #endif
  202. #ifndef _SOKOL_PRIVATE
  203. #if defined(__GNUC__)
  204. #define _SOKOL_PRIVATE __attribute__((unused)) static
  205. #else
  206. #define _SOKOL_PRIVATE static
  207. #endif
  208. #endif
  209. /* helper macros */
  210. #define _simgui_def(val, def) (((val) == 0) ? (def) : (val))
  211. typedef struct {
  212. ImVec2 disp_size;
  213. } _simgui_vs_params_t;
  214. #define SIMGUI_MAX_KEY_VALUE (512) // same as ImGuis IO.KeysDown array
  215. typedef struct {
  216. simgui_desc_t desc;
  217. sg_buffer vbuf;
  218. sg_buffer ibuf;
  219. sg_image img;
  220. sg_shader shd;
  221. sg_pipeline pip;
  222. bool is_osx; // return true if running on OSX (or HTML5 OSX), needed for copy/paste
  223. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  224. bool btn_down[SAPP_MAX_MOUSEBUTTONS];
  225. bool btn_up[SAPP_MAX_MOUSEBUTTONS];
  226. uint8_t keys_down[SIMGUI_MAX_KEY_VALUE]; // bits 0..3 or modifiers, != 0 is key-down
  227. uint8_t keys_up[SIMGUI_MAX_KEY_VALUE]; // same is keys_down
  228. #endif
  229. } _simgui_state_t;
  230. static _simgui_state_t _simgui;
  231. /* embedded shader sources */
  232. #if defined(SOKOL_GLCORE33)
  233. static const char* _simgui_vs_src =
  234. "#version 330\n"
  235. "uniform vec2 disp_size;\n"
  236. "in vec2 position;\n"
  237. "in vec2 texcoord0;\n"
  238. "in vec4 color0;\n"
  239. "out vec2 uv;\n"
  240. "out vec4 color;\n"
  241. "void main() {\n"
  242. " gl_Position = vec4(((position/disp_size)-0.5)*vec2(2.0,-2.0), 0.5, 1.0);\n"
  243. " uv = texcoord0;\n"
  244. " color = color0;\n"
  245. "}\n";
  246. static const char* _simgui_fs_src =
  247. "#version 330\n"
  248. "uniform sampler2D tex;\n"
  249. "in vec2 uv;\n"
  250. "in vec4 color;\n"
  251. "out vec4 frag_color;\n"
  252. "void main() {\n"
  253. " frag_color = texture(tex, uv) * color;\n"
  254. "}\n";
  255. #elif defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  256. static const char* _simgui_vs_src =
  257. "uniform vec2 disp_size;\n"
  258. "attribute vec2 position;\n"
  259. "attribute vec2 texcoord0;\n"
  260. "attribute vec4 color0;\n"
  261. "varying vec2 uv;\n"
  262. "varying vec4 color;\n"
  263. "void main() {\n"
  264. " gl_Position = vec4(((position/disp_size)-0.5)*vec2(2.0,-2.0), 0.5, 1.0);\n"
  265. " uv = texcoord0;\n"
  266. " color = color0;\n"
  267. "}\n";
  268. static const char* _simgui_fs_src =
  269. "precision mediump float;\n"
  270. "uniform sampler2D tex;\n"
  271. "varying vec2 uv;\n"
  272. "varying vec4 color;\n"
  273. "void main() {\n"
  274. " gl_FragColor = texture2D(tex, uv) * color;\n"
  275. "}\n";
  276. #elif defined(SOKOL_METAL)
  277. static const char* _simgui_vs_src =
  278. "#include <metal_stdlib>\n"
  279. "using namespace metal;\n"
  280. "struct params_t {\n"
  281. " float2 disp_size;\n"
  282. "};\n"
  283. "struct vs_in {\n"
  284. " float2 pos [[attribute(0)]];\n"
  285. " float2 uv [[attribute(1)]];\n"
  286. " float4 color [[attribute(2)]];\n"
  287. "};\n"
  288. "struct vs_out {\n"
  289. " float4 pos [[position]];\n"
  290. " float2 uv;\n"
  291. " float4 color;\n"
  292. "};\n"
  293. "vertex vs_out _main(vs_in in [[stage_in]], constant params_t& params [[buffer(0)]]) {\n"
  294. " vs_out out;\n"
  295. " out.pos = float4(((in.pos / params.disp_size)-0.5)*float2(2.0,-2.0), 0.5, 1.0);\n"
  296. " out.uv = in.uv;\n"
  297. " out.color = in.color;\n"
  298. " return out;\n"
  299. "}\n";
  300. static const char* _simgui_fs_src =
  301. "#include <metal_stdlib>\n"
  302. "using namespace metal;\n"
  303. "struct fs_in {\n"
  304. " float2 uv;\n"
  305. " float4 color;\n"
  306. "};\n"
  307. "fragment float4 _main(fs_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]]) {\n"
  308. " return tex.sample(smp, in.uv) * in.color;\n"
  309. "}\n";
  310. #elif defined(SOKOL_D3D11)
  311. /*
  312. Shader blobs for D3D11, compiled with:
  313. fxc.exe /T vs_5_0 /Fh vs.h /Gec /O3 vs.hlsl
  314. fxc.exe /T ps_5_0 /Fh fs.h /Gec /O3 fs.hlsl
  315. Vertex shader source:
  316. cbuffer params {
  317. float2 disp_size;
  318. };
  319. struct vs_in {
  320. float2 pos: POSITION;
  321. float2 uv: TEXCOORD0;
  322. float4 color: COLOR0;
  323. };
  324. struct vs_out {
  325. float2 uv: TEXCOORD0;
  326. float4 color: COLOR0;
  327. float4 pos: SV_Position;
  328. };
  329. vs_out main(vs_in inp) {
  330. vs_out outp;
  331. outp.pos = float4(((inp.pos/disp_size)-0.5)*float2(2.0,-2.0), 0.5, 1.0);
  332. outp.uv = inp.uv;
  333. outp.color = inp.color;
  334. return outp;
  335. }
  336. Fragment shader source:
  337. Texture2D<float4> tex: register(t0);
  338. sampler smp: register(s0);
  339. float4 main(float2 uv: TEXCOORD0, float4 color: COLOR0): SV_Target0 {
  340. return tex.Sample(smp, uv) * color;
  341. }
  342. */
  343. static const uint8_t _simgui_vs_bin[] = {
  344. 68, 88, 66, 67, 204, 137,
  345. 115, 177, 245, 67, 161, 195,
  346. 58, 224, 90, 35, 76, 123,
  347. 88, 146, 1, 0, 0, 0,
  348. 244, 3, 0, 0, 5, 0,
  349. 0, 0, 52, 0, 0, 0,
  350. 64, 1, 0, 0, 176, 1,
  351. 0, 0, 36, 2, 0, 0,
  352. 88, 3, 0, 0, 82, 68,
  353. 69, 70, 4, 1, 0, 0,
  354. 1, 0, 0, 0, 100, 0,
  355. 0, 0, 1, 0, 0, 0,
  356. 60, 0, 0, 0, 0, 5,
  357. 254, 255, 0, 145, 0, 0,
  358. 220, 0, 0, 0, 82, 68,
  359. 49, 49, 60, 0, 0, 0,
  360. 24, 0, 0, 0, 32, 0,
  361. 0, 0, 40, 0, 0, 0,
  362. 36, 0, 0, 0, 12, 0,
  363. 0, 0, 0, 0, 0, 0,
  364. 92, 0, 0, 0, 0, 0,
  365. 0, 0, 0, 0, 0, 0,
  366. 0, 0, 0, 0, 0, 0,
  367. 0, 0, 0, 0, 0, 0,
  368. 1, 0, 0, 0, 0, 0,
  369. 0, 0, 112, 97, 114, 97,
  370. 109, 115, 0, 171, 92, 0,
  371. 0, 0, 1, 0, 0, 0,
  372. 124, 0, 0, 0, 16, 0,
  373. 0, 0, 0, 0, 0, 0,
  374. 0, 0, 0, 0, 164, 0,
  375. 0, 0, 0, 0, 0, 0,
  376. 8, 0, 0, 0, 2, 0,
  377. 0, 0, 184, 0, 0, 0,
  378. 0, 0, 0, 0, 255, 255,
  379. 255, 255, 0, 0, 0, 0,
  380. 255, 255, 255, 255, 0, 0,
  381. 0, 0, 100, 105, 115, 112,
  382. 95, 115, 105, 122, 101, 0,
  383. 102, 108, 111, 97, 116, 50,
  384. 0, 171, 171, 171, 1, 0,
  385. 3, 0, 1, 0, 2, 0,
  386. 0, 0, 0, 0, 0, 0,
  387. 0, 0, 0, 0, 0, 0,
  388. 0, 0, 0, 0, 0, 0,
  389. 0, 0, 0, 0, 0, 0,
  390. 174, 0, 0, 0, 77, 105,
  391. 99, 114, 111, 115, 111, 102,
  392. 116, 32, 40, 82, 41, 32,
  393. 72, 76, 83, 76, 32, 83,
  394. 104, 97, 100, 101, 114, 32,
  395. 67, 111, 109, 112, 105, 108,
  396. 101, 114, 32, 49, 48, 46,
  397. 49, 0, 73, 83, 71, 78,
  398. 104, 0, 0, 0, 3, 0,
  399. 0, 0, 8, 0, 0, 0,
  400. 80, 0, 0, 0, 0, 0,
  401. 0, 0, 0, 0, 0, 0,
  402. 3, 0, 0, 0, 0, 0,
  403. 0, 0, 3, 3, 0, 0,
  404. 89, 0, 0, 0, 0, 0,
  405. 0, 0, 0, 0, 0, 0,
  406. 3, 0, 0, 0, 1, 0,
  407. 0, 0, 3, 3, 0, 0,
  408. 98, 0, 0, 0, 0, 0,
  409. 0, 0, 0, 0, 0, 0,
  410. 3, 0, 0, 0, 2, 0,
  411. 0, 0, 15, 15, 0, 0,
  412. 80, 79, 83, 73, 84, 73,
  413. 79, 78, 0, 84, 69, 88,
  414. 67, 79, 79, 82, 68, 0,
  415. 67, 79, 76, 79, 82, 0,
  416. 79, 83, 71, 78, 108, 0,
  417. 0, 0, 3, 0, 0, 0,
  418. 8, 0, 0, 0, 80, 0,
  419. 0, 0, 0, 0, 0, 0,
  420. 0, 0, 0, 0, 3, 0,
  421. 0, 0, 0, 0, 0, 0,
  422. 3, 12, 0, 0, 89, 0,
  423. 0, 0, 0, 0, 0, 0,
  424. 0, 0, 0, 0, 3, 0,
  425. 0, 0, 1, 0, 0, 0,
  426. 15, 0, 0, 0, 95, 0,
  427. 0, 0, 0, 0, 0, 0,
  428. 1, 0, 0, 0, 3, 0,
  429. 0, 0, 2, 0, 0, 0,
  430. 15, 0, 0, 0, 84, 69,
  431. 88, 67, 79, 79, 82, 68,
  432. 0, 67, 79, 76, 79, 82,
  433. 0, 83, 86, 95, 80, 111,
  434. 115, 105, 116, 105, 111, 110,
  435. 0, 171, 83, 72, 69, 88,
  436. 44, 1, 0, 0, 80, 0,
  437. 1, 0, 75, 0, 0, 0,
  438. 106, 8, 0, 1, 89, 0,
  439. 0, 4, 70, 142, 32, 0,
  440. 0, 0, 0, 0, 1, 0,
  441. 0, 0, 95, 0, 0, 3,
  442. 50, 16, 16, 0, 0, 0,
  443. 0, 0, 95, 0, 0, 3,
  444. 50, 16, 16, 0, 1, 0,
  445. 0, 0, 95, 0, 0, 3,
  446. 242, 16, 16, 0, 2, 0,
  447. 0, 0, 101, 0, 0, 3,
  448. 50, 32, 16, 0, 0, 0,
  449. 0, 0, 101, 0, 0, 3,
  450. 242, 32, 16, 0, 1, 0,
  451. 0, 0, 103, 0, 0, 4,
  452. 242, 32, 16, 0, 2, 0,
  453. 0, 0, 1, 0, 0, 0,
  454. 104, 0, 0, 2, 1, 0,
  455. 0, 0, 54, 0, 0, 5,
  456. 50, 32, 16, 0, 0, 0,
  457. 0, 0, 70, 16, 16, 0,
  458. 1, 0, 0, 0, 54, 0,
  459. 0, 5, 242, 32, 16, 0,
  460. 1, 0, 0, 0, 70, 30,
  461. 16, 0, 2, 0, 0, 0,
  462. 14, 0, 0, 8, 50, 0,
  463. 16, 0, 0, 0, 0, 0,
  464. 70, 16, 16, 0, 0, 0,
  465. 0, 0, 70, 128, 32, 0,
  466. 0, 0, 0, 0, 0, 0,
  467. 0, 0, 0, 0, 0, 10,
  468. 50, 0, 16, 0, 0, 0,
  469. 0, 0, 70, 0, 16, 0,
  470. 0, 0, 0, 0, 2, 64,
  471. 0, 0, 0, 0, 0, 191,
  472. 0, 0, 0, 191, 0, 0,
  473. 0, 0, 0, 0, 0, 0,
  474. 56, 0, 0, 10, 50, 32,
  475. 16, 0, 2, 0, 0, 0,
  476. 70, 0, 16, 0, 0, 0,
  477. 0, 0, 2, 64, 0, 0,
  478. 0, 0, 0, 64, 0, 0,
  479. 0, 192, 0, 0, 0, 0,
  480. 0, 0, 0, 0, 54, 0,
  481. 0, 8, 194, 32, 16, 0,
  482. 2, 0, 0, 0, 2, 64,
  483. 0, 0, 0, 0, 0, 0,
  484. 0, 0, 0, 0, 0, 0,
  485. 0, 63, 0, 0, 128, 63,
  486. 62, 0, 0, 1, 83, 84,
  487. 65, 84, 148, 0, 0, 0,
  488. 7, 0, 0, 0, 1, 0,
  489. 0, 0, 0, 0, 0, 0,
  490. 6, 0, 0, 0, 3, 0,
  491. 0, 0, 0, 0, 0, 0,
  492. 0, 0, 0, 0, 1, 0,
  493. 0, 0, 0, 0, 0, 0,
  494. 0, 0, 0, 0, 0, 0,
  495. 0, 0, 0, 0, 0, 0,
  496. 0, 0, 0, 0, 0, 0,
  497. 0, 0, 0, 0, 0, 0,
  498. 0, 0, 0, 0, 0, 0,
  499. 0, 0, 0, 0, 0, 0,
  500. 0, 0, 0, 0, 3, 0,
  501. 0, 0, 0, 0, 0, 0,
  502. 0, 0, 0, 0, 0, 0,
  503. 0, 0, 0, 0, 0, 0,
  504. 0, 0, 0, 0, 0, 0,
  505. 0, 0, 0, 0, 0, 0,
  506. 0, 0, 0, 0, 0, 0,
  507. 0, 0, 0, 0, 0, 0,
  508. 0, 0, 0, 0, 0, 0,
  509. 0, 0, 0, 0, 0, 0,
  510. 0, 0, 0, 0, 0, 0,
  511. 0, 0, 0, 0, 0, 0,
  512. 0, 0, 0, 0
  513. };
  514. static const uint8_t _simgui_fs_bin[] = {
  515. 68, 88, 66, 67, 116, 27,
  516. 191, 2, 170, 79, 42, 154,
  517. 39, 13, 69, 105, 240, 12,
  518. 136, 97, 1, 0, 0, 0,
  519. 176, 2, 0, 0, 5, 0,
  520. 0, 0, 52, 0, 0, 0,
  521. 232, 0, 0, 0, 56, 1,
  522. 0, 0, 108, 1, 0, 0,
  523. 20, 2, 0, 0, 82, 68,
  524. 69, 70, 172, 0, 0, 0,
  525. 0, 0, 0, 0, 0, 0,
  526. 0, 0, 2, 0, 0, 0,
  527. 60, 0, 0, 0, 0, 5,
  528. 255, 255, 0, 145, 0, 0,
  529. 132, 0, 0, 0, 82, 68,
  530. 49, 49, 60, 0, 0, 0,
  531. 24, 0, 0, 0, 32, 0,
  532. 0, 0, 40, 0, 0, 0,
  533. 36, 0, 0, 0, 12, 0,
  534. 0, 0, 0, 0, 0, 0,
  535. 124, 0, 0, 0, 3, 0,
  536. 0, 0, 0, 0, 0, 0,
  537. 0, 0, 0, 0, 0, 0,
  538. 0, 0, 0, 0, 0, 0,
  539. 1, 0, 0, 0, 1, 0,
  540. 0, 0, 128, 0, 0, 0,
  541. 2, 0, 0, 0, 5, 0,
  542. 0, 0, 4, 0, 0, 0,
  543. 255, 255, 255, 255, 0, 0,
  544. 0, 0, 1, 0, 0, 0,
  545. 13, 0, 0, 0, 115, 109,
  546. 112, 0, 116, 101, 120, 0,
  547. 77, 105, 99, 114, 111, 115,
  548. 111, 102, 116, 32, 40, 82,
  549. 41, 32, 72, 76, 83, 76,
  550. 32, 83, 104, 97, 100, 101,
  551. 114, 32, 67, 111, 109, 112,
  552. 105, 108, 101, 114, 32, 49,
  553. 48, 46, 49, 0, 73, 83,
  554. 71, 78, 72, 0, 0, 0,
  555. 2, 0, 0, 0, 8, 0,
  556. 0, 0, 56, 0, 0, 0,
  557. 0, 0, 0, 0, 0, 0,
  558. 0, 0, 3, 0, 0, 0,
  559. 0, 0, 0, 0, 3, 3,
  560. 0, 0, 65, 0, 0, 0,
  561. 0, 0, 0, 0, 0, 0,
  562. 0, 0, 3, 0, 0, 0,
  563. 1, 0, 0, 0, 15, 15,
  564. 0, 0, 84, 69, 88, 67,
  565. 79, 79, 82, 68, 0, 67,
  566. 79, 76, 79, 82, 0, 171,
  567. 79, 83, 71, 78, 44, 0,
  568. 0, 0, 1, 0, 0, 0,
  569. 8, 0, 0, 0, 32, 0,
  570. 0, 0, 0, 0, 0, 0,
  571. 0, 0, 0, 0, 3, 0,
  572. 0, 0, 0, 0, 0, 0,
  573. 15, 0, 0, 0, 83, 86,
  574. 95, 84, 97, 114, 103, 101,
  575. 116, 0, 171, 171, 83, 72,
  576. 69, 88, 160, 0, 0, 0,
  577. 80, 0, 0, 0, 40, 0,
  578. 0, 0, 106, 8, 0, 1,
  579. 90, 0, 0, 3, 0, 96,
  580. 16, 0, 0, 0, 0, 0,
  581. 88, 24, 0, 4, 0, 112,
  582. 16, 0, 0, 0, 0, 0,
  583. 85, 85, 0, 0, 98, 16,
  584. 0, 3, 50, 16, 16, 0,
  585. 0, 0, 0, 0, 98, 16,
  586. 0, 3, 242, 16, 16, 0,
  587. 1, 0, 0, 0, 101, 0,
  588. 0, 3, 242, 32, 16, 0,
  589. 0, 0, 0, 0, 104, 0,
  590. 0, 2, 1, 0, 0, 0,
  591. 69, 0, 0, 139, 194, 0,
  592. 0, 128, 67, 85, 21, 0,
  593. 242, 0, 16, 0, 0, 0,
  594. 0, 0, 70, 16, 16, 0,
  595. 0, 0, 0, 0, 70, 126,
  596. 16, 0, 0, 0, 0, 0,
  597. 0, 96, 16, 0, 0, 0,
  598. 0, 0, 56, 0, 0, 7,
  599. 242, 32, 16, 0, 0, 0,
  600. 0, 0, 70, 14, 16, 0,
  601. 0, 0, 0, 0, 70, 30,
  602. 16, 0, 1, 0, 0, 0,
  603. 62, 0, 0, 1, 83, 84,
  604. 65, 84, 148, 0, 0, 0,
  605. 3, 0, 0, 0, 1, 0,
  606. 0, 0, 0, 0, 0, 0,
  607. 3, 0, 0, 0, 1, 0,
  608. 0, 0, 0, 0, 0, 0,
  609. 0, 0, 0, 0, 1, 0,
  610. 0, 0, 0, 0, 0, 0,
  611. 0, 0, 0, 0, 0, 0,
  612. 0, 0, 0, 0, 0, 0,
  613. 0, 0, 0, 0, 0, 0,
  614. 0, 0, 1, 0, 0, 0,
  615. 0, 0, 0, 0, 0, 0,
  616. 0, 0, 0, 0, 0, 0,
  617. 0, 0, 0, 0, 0, 0,
  618. 0, 0, 0, 0, 0, 0,
  619. 0, 0, 0, 0, 0, 0,
  620. 0, 0, 0, 0, 0, 0,
  621. 0, 0, 0, 0, 0, 0,
  622. 0, 0, 0, 0, 0, 0,
  623. 0, 0, 0, 0, 0, 0,
  624. 0, 0, 0, 0, 0, 0,
  625. 0, 0, 0, 0, 0, 0,
  626. 0, 0, 0, 0, 0, 0,
  627. 0, 0, 0, 0, 0, 0,
  628. 0, 0, 0, 0, 0, 0,
  629. 0, 0, 0, 0
  630. };
  631. #else
  632. #error "sokol_imgui.h: No sokol_gfx.h backend selected (SOKOL_GLCORE33, SOKOL_GLES2, SOKOL_GLES3, SOKOL_D3D11 or SOKOL_METAL)"
  633. #endif
  634. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  635. static void _simgui_set_clipboard(void* user_data, const char* text) {
  636. (void)user_data;
  637. sapp_set_clipboard_string(text);
  638. }
  639. static const char* _simgui_get_clipboard(void* user_data) {
  640. (void)user_data;
  641. return sapp_get_clipboard_string();
  642. }
  643. #endif
  644. #if defined(__EMSCRIPTEN__)
  645. EM_JS(int, simgui_js_is_osx, (void), {
  646. if (navigator.userAgent.includes('Macintosh')) {
  647. return 1;
  648. }
  649. else {
  650. return 0;
  651. }
  652. });
  653. #endif
  654. static bool _simgui_is_osx(void) {
  655. #if defined(__EMSCRIPTEN__)
  656. return simgui_js_is_osx();
  657. #elif defined(__APPLE__)
  658. return true;
  659. #else
  660. return false;
  661. #endif
  662. }
  663. SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
  664. SOKOL_ASSERT(desc);
  665. memset(&_simgui, 0, sizeof(_simgui));
  666. _simgui.desc = *desc;
  667. _simgui.desc.max_vertices = _simgui_def(_simgui.desc.max_vertices, 65536);
  668. _simgui.desc.dpi_scale = _simgui_def(_simgui.desc.dpi_scale, 1.0f);
  669. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  670. _simgui.is_osx = _simgui_is_osx();
  671. #endif
  672. /* can keep color_format, depth_format and sample_count as is,
  673. since sokol_gfx.h will do its own default-value handling
  674. */
  675. /* initialize Dear ImGui */
  676. #if defined(__cplusplus)
  677. ImGui::CreateContext();
  678. ImGui::StyleColorsDark();
  679. ImGuiIO* io = &ImGui::GetIO();
  680. if (!_simgui.desc.no_default_font) {
  681. io->Fonts->AddFontDefault();
  682. }
  683. #else
  684. igCreateContext(NULL);
  685. igStyleColorsDark(igGetStyle());
  686. ImGuiIO* io = igGetIO();
  687. if (!_simgui.desc.no_default_font) {
  688. ImFontAtlas_AddFontDefault(io->Fonts, NULL);
  689. }
  690. #endif
  691. io->IniFilename = _simgui.desc.ini_filename;
  692. io->ConfigMacOSXBehaviors = _simgui_is_osx();
  693. io->BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
  694. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  695. io->KeyMap[ImGuiKey_Tab] = SAPP_KEYCODE_TAB;
  696. io->KeyMap[ImGuiKey_LeftArrow] = SAPP_KEYCODE_LEFT;
  697. io->KeyMap[ImGuiKey_RightArrow] = SAPP_KEYCODE_RIGHT;
  698. io->KeyMap[ImGuiKey_UpArrow] = SAPP_KEYCODE_UP;
  699. io->KeyMap[ImGuiKey_DownArrow] = SAPP_KEYCODE_DOWN;
  700. io->KeyMap[ImGuiKey_PageUp] = SAPP_KEYCODE_PAGE_UP;
  701. io->KeyMap[ImGuiKey_PageDown] = SAPP_KEYCODE_PAGE_DOWN;
  702. io->KeyMap[ImGuiKey_Home] = SAPP_KEYCODE_HOME;
  703. io->KeyMap[ImGuiKey_End] = SAPP_KEYCODE_END;
  704. io->KeyMap[ImGuiKey_Delete] = SAPP_KEYCODE_DELETE;
  705. io->KeyMap[ImGuiKey_Backspace] = SAPP_KEYCODE_BACKSPACE;
  706. io->KeyMap[ImGuiKey_Space] = SAPP_KEYCODE_SPACE;
  707. io->KeyMap[ImGuiKey_Enter] = SAPP_KEYCODE_ENTER;
  708. io->KeyMap[ImGuiKey_Escape] = SAPP_KEYCODE_ESCAPE;
  709. if (!_simgui.desc.disable_hotkeys) {
  710. io->KeyMap[ImGuiKey_A] = SAPP_KEYCODE_A;
  711. io->KeyMap[ImGuiKey_C] = SAPP_KEYCODE_C;
  712. io->KeyMap[ImGuiKey_V] = SAPP_KEYCODE_V;
  713. io->KeyMap[ImGuiKey_X] = SAPP_KEYCODE_X;
  714. io->KeyMap[ImGuiKey_Y] = SAPP_KEYCODE_Y;
  715. io->KeyMap[ImGuiKey_Z] = SAPP_KEYCODE_Z;
  716. }
  717. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  718. io->SetClipboardTextFn = _simgui_set_clipboard;
  719. io->GetClipboardTextFn = _simgui_get_clipboard;
  720. #endif
  721. #endif
  722. /* create sokol-gfx resources */
  723. sg_push_debug_group("sokol-imgui");
  724. /* NOTE: since we're in C++ mode here we can't use C99 designated init */
  725. sg_buffer_desc vb_desc;
  726. memset(&vb_desc, 0, sizeof(vb_desc));
  727. vb_desc.usage = SG_USAGE_STREAM;
  728. vb_desc.size = _simgui.desc.max_vertices * sizeof(ImDrawVert);
  729. vb_desc.label = "sokol-imgui-vertices";
  730. _simgui.vbuf = sg_make_buffer(&vb_desc);
  731. sg_buffer_desc ib_desc;
  732. memset(&ib_desc, 0, sizeof(ib_desc));
  733. ib_desc.type = SG_BUFFERTYPE_INDEXBUFFER;
  734. ib_desc.usage = SG_USAGE_STREAM;
  735. ib_desc.size = _simgui.desc.max_vertices * 3 * sizeof(uint16_t);
  736. ib_desc.label = "sokol-imgui-indices";
  737. _simgui.ibuf = sg_make_buffer(&ib_desc);
  738. /* default font texture */
  739. if (!_simgui.desc.no_default_font) {
  740. unsigned char* font_pixels;
  741. int font_width, font_height;
  742. #if defined(__cplusplus)
  743. io->Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height);
  744. #else
  745. int bytes_per_pixel;
  746. ImFontAtlas_GetTexDataAsRGBA32(io->Fonts, &font_pixels, &font_width, &font_height, &bytes_per_pixel);
  747. #endif
  748. sg_image_desc img_desc;
  749. memset(&img_desc, 0, sizeof(img_desc));
  750. img_desc.width = font_width;
  751. img_desc.height = font_height;
  752. img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
  753. img_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE;
  754. img_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE;
  755. img_desc.min_filter = SG_FILTER_LINEAR;
  756. img_desc.mag_filter = SG_FILTER_LINEAR;
  757. img_desc.content.subimage[0][0].ptr = font_pixels;
  758. img_desc.content.subimage[0][0].size = font_width * font_height * sizeof(uint32_t);
  759. img_desc.label = "sokol-imgui-font";
  760. _simgui.img = sg_make_image(&img_desc);
  761. io->Fonts->TexID = (ImTextureID)(uintptr_t) _simgui.img.id;
  762. }
  763. /* shader object for using the embedded shader source (or bytecode) */
  764. sg_shader_desc shd_desc;
  765. memset(&shd_desc, 0, sizeof(shd_desc));
  766. sg_shader_uniform_block_desc* ub = &shd_desc.vs.uniform_blocks[0];
  767. ub->size = sizeof(_simgui_vs_params_t);
  768. ub->uniforms[0].name = "disp_size";
  769. ub->uniforms[0].type = SG_UNIFORMTYPE_FLOAT2;
  770. shd_desc.attrs[0].name = "position";
  771. shd_desc.attrs[0].sem_name = "POSITION";
  772. shd_desc.attrs[1].name = "texcoord0";
  773. shd_desc.attrs[1].sem_name = "TEXCOORD";
  774. shd_desc.attrs[2].name = "color0";
  775. shd_desc.attrs[2].sem_name = "COLOR";
  776. shd_desc.fs.images[0].name = "tex";
  777. shd_desc.fs.images[0].type = SG_IMAGETYPE_2D;
  778. #if defined(SOKOL_D3D11)
  779. shd_desc.vs.byte_code = _simgui_vs_bin;
  780. shd_desc.vs.byte_code_size = sizeof(_simgui_vs_bin);
  781. shd_desc.fs.byte_code = _simgui_fs_bin;
  782. shd_desc.fs.byte_code_size = sizeof(_simgui_fs_bin);
  783. #else
  784. shd_desc.vs.source = _simgui_vs_src;
  785. shd_desc.fs.source = _simgui_fs_src;
  786. #endif
  787. shd_desc.label = "sokol-imgui-shader";
  788. _simgui.shd = sg_make_shader(&shd_desc);
  789. /* pipeline object for imgui rendering */
  790. sg_pipeline_desc pip_desc;
  791. memset(&pip_desc, 0, sizeof(pip_desc));
  792. pip_desc.layout.buffers[0].stride = sizeof(ImDrawVert);
  793. {
  794. sg_vertex_attr_desc* attr = &pip_desc.layout.attrs[0];
  795. attr->offset = offsetof(ImDrawVert, pos);
  796. attr->format = SG_VERTEXFORMAT_FLOAT2;
  797. }
  798. {
  799. sg_vertex_attr_desc* attr = &pip_desc.layout.attrs[1];
  800. attr->offset = offsetof(ImDrawVert, uv);
  801. attr->format = SG_VERTEXFORMAT_FLOAT2;
  802. }
  803. {
  804. sg_vertex_attr_desc* attr = &pip_desc.layout.attrs[2];
  805. attr->offset = offsetof(ImDrawVert, col);
  806. attr->format = SG_VERTEXFORMAT_UBYTE4N;
  807. }
  808. pip_desc.shader = _simgui.shd;
  809. pip_desc.index_type = SG_INDEXTYPE_UINT16;
  810. pip_desc.blend.enabled = true;
  811. pip_desc.blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA;
  812. pip_desc.blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
  813. pip_desc.blend.color_write_mask = SG_COLORMASK_RGB;
  814. pip_desc.blend.color_format = _simgui.desc.color_format;
  815. pip_desc.blend.depth_format = _simgui.desc.depth_format;
  816. pip_desc.rasterizer.sample_count = _simgui.desc.sample_count;
  817. pip_desc.label = "sokol-imgui-pipeline";
  818. _simgui.pip = sg_make_pipeline(&pip_desc);
  819. sg_pop_debug_group();
  820. }
  821. SOKOL_API_IMPL void simgui_shutdown(void) {
  822. #if defined(__cplusplus)
  823. ImGui::DestroyContext();
  824. #else
  825. igDestroyContext(0);
  826. #endif
  827. /* NOTE: it's valid to call the destroy funcs with SG_INVALID_ID */
  828. sg_destroy_pipeline(_simgui.pip);
  829. sg_destroy_shader(_simgui.shd);
  830. sg_destroy_image(_simgui.img);
  831. sg_destroy_buffer(_simgui.ibuf);
  832. sg_destroy_buffer(_simgui.vbuf);
  833. }
  834. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  835. _SOKOL_PRIVATE void _simgui_set_imgui_modifiers(ImGuiIO* io, uint32_t mods) {
  836. io->KeyAlt = (mods & SAPP_MODIFIER_ALT) != 0;
  837. io->KeyCtrl = (mods & SAPP_MODIFIER_CTRL) != 0;
  838. io->KeyShift = (mods & SAPP_MODIFIER_SHIFT) != 0;
  839. io->KeySuper = (mods & SAPP_MODIFIER_SUPER) != 0;
  840. }
  841. #endif
  842. SOKOL_API_IMPL void simgui_new_frame(int width, int height, double delta_time) {
  843. #if defined(__cplusplus)
  844. ImGuiIO* io = &ImGui::GetIO();
  845. #else
  846. ImGuiIO* io = igGetIO();
  847. #endif
  848. io->DisplaySize.x = ((float) width) / _simgui.desc.dpi_scale;
  849. io->DisplaySize.y = ((float) height) / _simgui.desc.dpi_scale;
  850. io->DeltaTime = (float) delta_time;
  851. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  852. for (int i = 0; i < SAPP_MAX_MOUSEBUTTONS; i++) {
  853. if (_simgui.btn_down[i]) {
  854. _simgui.btn_down[i] = false;
  855. io->MouseDown[i] = true;
  856. }
  857. else if (_simgui.btn_up[i]) {
  858. _simgui.btn_up[i] = false;
  859. io->MouseDown[i] = false;
  860. }
  861. }
  862. for (int i = 0; i < SIMGUI_MAX_KEY_VALUE; i++) {
  863. if (_simgui.keys_down[i]) {
  864. io->KeysDown[i] = true;
  865. _simgui_set_imgui_modifiers(io, _simgui.keys_down[i]);
  866. _simgui.keys_down[i] = 0;
  867. }
  868. else if (_simgui.keys_up[i]) {
  869. io->KeysDown[i] = false;
  870. _simgui_set_imgui_modifiers(io, _simgui.keys_up[i]);
  871. _simgui.keys_up[i] = 0;
  872. }
  873. }
  874. if (io->WantTextInput && !sapp_keyboard_shown()) {
  875. sapp_show_keyboard(true);
  876. }
  877. if (!io->WantTextInput && sapp_keyboard_shown()) {
  878. sapp_show_keyboard(false);
  879. }
  880. #endif
  881. #if defined(__cplusplus)
  882. ImGui::NewFrame();
  883. #else
  884. igNewFrame();
  885. #endif
  886. }
  887. SOKOL_API_IMPL void simgui_render(void) {
  888. #if defined(__cplusplus)
  889. ImGui::Render();
  890. ImDrawData* draw_data = ImGui::GetDrawData();
  891. ImGuiIO* io = &ImGui::GetIO();
  892. #else
  893. igRender();
  894. ImDrawData* draw_data = igGetDrawData();
  895. ImGuiIO* io = igGetIO();
  896. #endif
  897. if (0 == draw_data) {
  898. return;
  899. }
  900. if (draw_data->CmdListsCount == 0) {
  901. return;
  902. }
  903. /* render the ImGui command list */
  904. sg_push_debug_group("sokol-imgui");
  905. const float dpi_scale = _simgui.desc.dpi_scale;
  906. const int fb_width = (int) (io->DisplaySize.x * dpi_scale);
  907. const int fb_height = (int) (io->DisplaySize.y * dpi_scale);
  908. sg_apply_viewport(0, 0, fb_width, fb_height, true);
  909. sg_apply_scissor_rect(0, 0, fb_width, fb_height, true);
  910. sg_apply_pipeline(_simgui.pip);
  911. _simgui_vs_params_t vs_params;
  912. vs_params.disp_size.x = io->DisplaySize.x;
  913. vs_params.disp_size.y = io->DisplaySize.y;
  914. sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
  915. sg_bindings bind;
  916. memset(&bind, 0, sizeof(bind));
  917. bind.vertex_buffers[0] = _simgui.vbuf;
  918. bind.index_buffer = _simgui.ibuf;
  919. ImTextureID tex_id = io->Fonts->TexID;
  920. bind.fs_images[0].id = (uint32_t)(uintptr_t)tex_id;
  921. uint32_t vb_offset = 0;
  922. uint32_t ib_offset = 0;
  923. for (int cl_index = 0; cl_index < draw_data->CmdListsCount; cl_index++) {
  924. ImDrawList* cl = draw_data->CmdLists[cl_index];
  925. /* append vertices and indices to buffers, record start offsets in draw state */
  926. #if defined(__cplusplus)
  927. const int vtx_size = cl->VtxBuffer.size() * sizeof(ImDrawVert);
  928. const int idx_size = cl->IdxBuffer.size() * sizeof(ImDrawIdx);
  929. const ImDrawVert* vtx_ptr = &cl->VtxBuffer.front();
  930. const ImDrawIdx* idx_ptr = &cl->IdxBuffer.front();
  931. #else
  932. const int vtx_size = cl->VtxBuffer.Size * sizeof(ImDrawVert);
  933. const int idx_size = cl->IdxBuffer.Size * sizeof(ImDrawIdx);
  934. const ImDrawVert* vtx_ptr = cl->VtxBuffer.Data;
  935. const ImDrawIdx* idx_ptr = cl->IdxBuffer.Data;
  936. #endif
  937. if (vtx_ptr) {
  938. vb_offset = sg_append_buffer(bind.vertex_buffers[0], vtx_ptr, vtx_size);
  939. }
  940. if (idx_ptr) {
  941. ib_offset = sg_append_buffer(bind.index_buffer, idx_ptr, idx_size);
  942. }
  943. /* don't render anything if the buffer is in overflow state (this is also
  944. checked internally in sokol_gfx, draw calls that attempt to draw with
  945. overflowed buffers will be silently dropped)
  946. */
  947. if (sg_query_buffer_overflow(bind.vertex_buffers[0]) ||
  948. sg_query_buffer_overflow(bind.index_buffer))
  949. {
  950. break;
  951. }
  952. bind.vertex_buffer_offsets[0] = vb_offset;
  953. bind.index_buffer_offset = ib_offset;
  954. sg_apply_bindings(&bind);
  955. int base_element = 0;
  956. #if defined(__cplusplus)
  957. const int num_cmds = cl->CmdBuffer.size();
  958. #else
  959. const int num_cmds = cl->CmdBuffer.Size;
  960. #endif
  961. uint32_t vtx_offset = 0;
  962. for (int cmd_index = 0; cmd_index < num_cmds; cmd_index++) {
  963. ImDrawCmd* pcmd = &cl->CmdBuffer.Data[cmd_index];
  964. if (pcmd->UserCallback) {
  965. pcmd->UserCallback(cl, pcmd);
  966. // need to re-apply all state after calling a user callback
  967. sg_apply_viewport(0, 0, fb_width, fb_height, true);
  968. sg_apply_pipeline(_simgui.pip);
  969. sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
  970. sg_apply_bindings(&bind);
  971. }
  972. else {
  973. if ((tex_id != pcmd->TextureId) || (vtx_offset != pcmd->VtxOffset)) {
  974. tex_id = pcmd->TextureId;
  975. vtx_offset = pcmd->VtxOffset * sizeof(ImDrawVert);
  976. bind.fs_images[0].id = (uint32_t)(uintptr_t)tex_id;
  977. bind.vertex_buffer_offsets[0] = vb_offset + vtx_offset;
  978. sg_apply_bindings(&bind);
  979. }
  980. const int scissor_x = (int) (pcmd->ClipRect.x * dpi_scale);
  981. const int scissor_y = (int) (pcmd->ClipRect.y * dpi_scale);
  982. const int scissor_w = (int) ((pcmd->ClipRect.z - pcmd->ClipRect.x) * dpi_scale);
  983. const int scissor_h = (int) ((pcmd->ClipRect.w - pcmd->ClipRect.y) * dpi_scale);
  984. sg_apply_scissor_rect(scissor_x, scissor_y, scissor_w, scissor_h, true);
  985. sg_draw(base_element, pcmd->ElemCount, 1);
  986. }
  987. base_element += pcmd->ElemCount;
  988. }
  989. }
  990. sg_apply_viewport(0, 0, fb_width, fb_height, true);
  991. sg_apply_scissor_rect(0, 0, fb_width, fb_height, true);
  992. sg_pop_debug_group();
  993. }
  994. #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
  995. _SOKOL_PRIVATE bool _simgui_is_ctrl(uint32_t modifiers) {
  996. if (_simgui.is_osx) {
  997. return 0 != (modifiers & SAPP_MODIFIER_SUPER);
  998. }
  999. else {
  1000. return 0 != (modifiers & SAPP_MODIFIER_CTRL);
  1001. }
  1002. }
  1003. SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
  1004. const float dpi_scale = _simgui.desc.dpi_scale;
  1005. #if defined(__cplusplus)
  1006. ImGuiIO* io = &ImGui::GetIO();
  1007. #else
  1008. ImGuiIO* io = igGetIO();
  1009. #endif
  1010. _simgui_set_imgui_modifiers(io, ev->modifiers);
  1011. switch (ev->type) {
  1012. case SAPP_EVENTTYPE_MOUSE_DOWN:
  1013. io->MousePos.x = ev->mouse_x / dpi_scale;
  1014. io->MousePos.y = ev->mouse_y / dpi_scale;
  1015. if (ev->mouse_button < 3) {
  1016. _simgui.btn_down[ev->mouse_button] = true;
  1017. }
  1018. break;
  1019. case SAPP_EVENTTYPE_MOUSE_UP:
  1020. io->MousePos.x = ev->mouse_x / dpi_scale;
  1021. io->MousePos.y = ev->mouse_y / dpi_scale;
  1022. if (ev->mouse_button < 3) {
  1023. _simgui.btn_up[ev->mouse_button] = true;
  1024. }
  1025. break;
  1026. case SAPP_EVENTTYPE_MOUSE_MOVE:
  1027. io->MousePos.x = ev->mouse_x / dpi_scale;
  1028. io->MousePos.y = ev->mouse_y / dpi_scale;
  1029. break;
  1030. case SAPP_EVENTTYPE_MOUSE_ENTER:
  1031. case SAPP_EVENTTYPE_MOUSE_LEAVE:
  1032. for (int i = 0; i < 3; i++) {
  1033. _simgui.btn_down[i] = false;
  1034. _simgui.btn_up[i] = false;
  1035. io->MouseDown[i] = false;
  1036. }
  1037. break;
  1038. case SAPP_EVENTTYPE_MOUSE_SCROLL:
  1039. io->MouseWheelH = ev->scroll_x;
  1040. io->MouseWheel = ev->scroll_y;
  1041. break;
  1042. case SAPP_EVENTTYPE_TOUCHES_BEGAN:
  1043. _simgui.btn_down[0] = true;
  1044. io->MousePos.x = ev->touches[0].pos_x / dpi_scale;
  1045. io->MousePos.y = ev->touches[0].pos_y / dpi_scale;
  1046. break;
  1047. case SAPP_EVENTTYPE_TOUCHES_MOVED:
  1048. io->MousePos.x = ev->touches[0].pos_x / dpi_scale;
  1049. io->MousePos.y = ev->touches[0].pos_y / dpi_scale;
  1050. break;
  1051. case SAPP_EVENTTYPE_TOUCHES_ENDED:
  1052. _simgui.btn_up[0] = true;
  1053. io->MousePos.x = ev->touches[0].pos_x / dpi_scale;
  1054. io->MousePos.y = ev->touches[0].pos_y / dpi_scale;
  1055. break;
  1056. case SAPP_EVENTTYPE_TOUCHES_CANCELLED:
  1057. _simgui.btn_up[0] = _simgui.btn_down[0] = false;
  1058. break;
  1059. case SAPP_EVENTTYPE_KEY_DOWN:
  1060. /* intercept Ctrl-V, this is handled via EVENTTYPE_CLIPBOARD_PASTED */
  1061. if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_V)) {
  1062. break;
  1063. }
  1064. /* on web platform, don't forward Ctrl-X, Ctrl-V to the browser */
  1065. if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_X)) {
  1066. sapp_consume_event();
  1067. }
  1068. if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_C)) {
  1069. sapp_consume_event();
  1070. }
  1071. _simgui.keys_down[ev->key_code] = 0x80 | (uint8_t)ev->modifiers;
  1072. break;
  1073. case SAPP_EVENTTYPE_KEY_UP:
  1074. /* intercept Ctrl-V, this is handled via EVENTTYPE_CLIPBOARD_PASTED */
  1075. if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_V)) {
  1076. break;
  1077. }
  1078. /* on web platform, don't forward Ctrl-X, Ctrl-V to the browser */
  1079. if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_X)) {
  1080. sapp_consume_event();
  1081. }
  1082. if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_C)) {
  1083. sapp_consume_event();
  1084. }
  1085. _simgui.keys_up[ev->key_code] = 0x80 | (uint8_t)ev->modifiers;
  1086. break;
  1087. case SAPP_EVENTTYPE_CHAR:
  1088. /* on some platforms, special keys may be reported as
  1089. characters, which may confuse some ImGui widgets,
  1090. drop those, also don't forward characters if some
  1091. modifiers have been pressed
  1092. */
  1093. if ((ev->char_code >= 32) &&
  1094. (ev->char_code != 127) &&
  1095. (0 == (ev->modifiers & (SAPP_MODIFIER_ALT|SAPP_MODIFIER_CTRL|SAPP_MODIFIER_SUPER))))
  1096. {
  1097. #if defined(__cplusplus)
  1098. io->AddInputCharacter((ImWchar)ev->char_code);
  1099. #else
  1100. ImGuiIO_AddInputCharacter(io, (ImWchar)ev->char_code);
  1101. #endif
  1102. }
  1103. break;
  1104. case SAPP_EVENTTYPE_CLIPBOARD_PASTED:
  1105. /* simulate a Ctrl-V key down/up */
  1106. _simgui.keys_down[SAPP_KEYCODE_V] = _simgui.keys_up[SAPP_KEYCODE_V] =
  1107. 0x80 | (_simgui.is_osx ? SAPP_MODIFIER_SUPER:SAPP_MODIFIER_CTRL);
  1108. break;
  1109. default:
  1110. break;
  1111. }
  1112. return io->WantCaptureKeyboard || io->WantCaptureMouse;
  1113. }
  1114. #endif
  1115. #endif /* SOKOL_IMPL */