Compare commits

...

473 Commits
v1.41 ... v1.45

Author SHA1 Message Date
77bcb7152b Examples: DirectX11: fixed vertex shader which breaks with VS2015 somehow (DX11 version?) (#313) 2015-09-01 10:47:36 +01:00
f195bf744f Tabs to spaces 2015-08-30 22:15:33 +01:00
4ab43dce19 Comments 2015-08-30 22:10:49 +01:00
13daaf78a2 Update README.md 2015-08-30 19:41:02 +01:00
e4ef140e10 Speculative Linux build fix, not using itoa (#246) 2015-08-30 18:55:46 +01:00
350d96466e Demo: tweaks (#246) 2015-08-30 18:43:42 +01:00
1eef2c9108 Comment 2015-08-30 18:35:02 +01:00
71026d3655 Added GetScrollX(), GetScrollX(), GetScrollMaxX() apis + demo (#246) 2015-08-30 18:33:38 +01:00
7a31030978 Begin() windows flags are locked on the first begin of the frame, allowing using to not bother passing flags for append 2015-08-30 18:30:54 +01:00
e5e9c5cfbe Demo: removed extraneous flag in demo code + tweak comment (#246) 2015-08-30 18:07:51 +01:00
bbf09fd47d Fixed initial ScrollbarX decision when no vertical scrollbar is in (#246) 2015-08-30 18:07:04 +01:00
a3cad2ff06 BeginChild() fixed missing rounding for child sizes which leaked into layout 2015-08-30 18:06:54 +01:00
6eed3dc7c8 GetContentRegionMax() when window content size is explicit we don't adjust it with scrollbar sizes (#246) 2015-08-30 17:46:02 +01:00
73e73e6ef9 TextUnformatted(): simplifying 2015-08-30 17:45:05 +01:00
afa0346a0b Demo: using DragFloat instead of SliderFloat 2015-08-30 17:38:42 +01:00
e1f8fed734 Separator(): removed unnecessary computation + comment. 2015-08-30 17:25:26 +01:00
f128a8bce1 ColumnsStartX include window->Scroll.x to simplify code (#246) 2015-08-30 17:25:10 +01:00
8edbdb9775 Style: minor menubar bg alpha tweak. 2015-08-30 16:44:44 +01:00
e68d3c614e Style: made scrollbars rounded by default. Because nice. (#246) 2015-08-30 16:43:08 +01:00
9e5fb40ddd Demo: added horizontal scrolling example + enabled in console, log and child examples (#246) 2015-08-30 16:38:55 +01:00
65a191c005 Added optional Horizontal Scrollbar & allow user to explicitly set content width via SetNextWindowContentSize() etc (#246)
GetCursorPos, SetCursorPos, GetContentRegionMax,
GetWindowContentRegionMin, GetWindowContentRegionMax are now including
the scrolling amount. It PROBABLY shouldn't break anything for you, but
take note that SetCursorPosX(100.0f) puts you at +100 from the starting
x position which may include scrolling, not at +100 from the window left
side.
2015-08-30 16:37:56 +01:00
9eed672725 Bullet() fixed inconsistent layout behaviour when clipped. 2015-08-30 15:42:42 +01:00
d88b73a8b7 Added GetContentRegionAvailWidth() helper. Demo tweaks. 2015-08-30 15:35:59 +01:00
fc13ae2aa5 Turning float ScrollY into ImVec2 Scroll - no feature change, this is just to remove some syntax noise from the following commit (#246) 2015-08-30 15:08:13 +01:00
e0c375e7b8 Tidying up 2015-08-30 13:09:56 +01:00
b326c8fd1f Added GetCurrentWindowRead() for functions that don't write to the window 2015-08-30 11:56:04 +01:00
b994dd777a Fixed OpenPopup() accessing current window, effectively opening "Debug" on an empty window stack 2015-08-30 11:11:15 +01:00
0aa353868f Minor internal shortcuts not calling GetCurrentWindow() 2015-08-30 10:49:47 +01:00
aa35547f94 Demo: long text example uses ImGuiListClipper 2015-08-30 00:03:08 +01:00
2d565d4bfb Style: rename ScrollbarWidth to ScrollbarSize (sorry!) 2015-08-29 23:47:47 +01:00
64fcb5e568 TreeNode() fixed IsItemHovered() being inconsistent with visual behavior (#282) 2015-08-29 18:15:42 +01:00
65fe60f2b2 Split tree/collapsable into internal TreeNodeBehaviorIsOpened() helper (unsure..) (#282) 2015-08-29 18:13:30 +01:00
0bb46c824e Examples: OpenGL2/3: save/restore some more state correctly.
Might save an hour of staring at blank-screen to 5% of the population,
worth it.
2015-08-29 17:44:52 +01:00
f2c68109a6 Merge branch 'master' of https://github.com/ocornut/imgui 2015-08-29 14:45:15 +01:00
c381d58fb1 TreeNode(): arbitrary interaction padding after text label not part of layout (#282) 2015-08-29 14:12:53 +01:00
62a3142036 Demo: comments. 2015-08-29 13:31:30 +01:00
da807e55ea Examples: Ignore list a little more friendly to Unix systems. 2015-08-28 16:03:05 +01:00
5ebd61f89c Ignore list a little more friendly to Unix systems 2015-08-28 15:55:22 +01:00
e7cc048d81 Demo: custom rendering tweak. 2015-08-28 15:35:08 +01:00
0a11024459 IO.WantInputCharacters -> WantTextInput (#305) 2015-08-28 15:34:53 +01:00
30461345aa Removed default name parameter in Begin()
We already have a "Debug" window pushed to the stack in the first place
so it's not really a useful default.
2015-08-28 15:24:04 +01:00
8430c88451 Demo: added a bezier curve in the old custom rendering demo. 2015-08-28 14:41:10 +01:00
b803d284c3 InvisibleButton() honor negative size consistently with other widgets that do so 2015-08-28 14:18:50 +01:00
90e5c97f13 AddBezier()->AddBezierCurve(). PathBezierTo()->PathBezierCurveTo(), and reads current point back, more standard (#311) 2015-08-28 13:48:14 +01:00
d2e529e533 Merge branch 'master' of https://github.com/ocornut/imgui 2015-08-28 13:19:43 +01:00
80ad773c87 ImDrawList: added AddBezier(), PathBezierTo() for cubic bezier curves (#311) 2015-08-28 13:18:34 +01:00
55ea2988d2 Update README.md 2015-08-28 00:04:49 +01:00
e58f99179a Examples: OpenGL: fix for retina screens + io.DisplayFramebufferScale storage (#287) 2015-08-27 19:51:02 +01:00
a36001212f ImDrawData: added ScaleClipRects() helper (#287) 2015-08-27 18:45:43 +01:00
8b225923f8 Malformed UTF-8 don't terminate string, output 0xFFFD (#307) 2015-08-27 13:44:31 +01:00
59d498f3d0 Added ColorConvertU32ToFloat4() helper and ImColor(ImU32) constructor. 2015-08-26 21:18:08 +01:00
62671ef96e Examples: update readme 2015-08-25 22:14:31 +01:00
8cf7df7ec4 Added GetWindowHeight() for completeness + BeginGroup() comment. 2015-08-25 16:55:14 +01:00
822eaf1751 Examples: DX9, DX11: mapping missing middle mouse button. 2015-08-25 16:54:47 +01:00
08b345efd9 ImDrawList: Add comments on the usage of drawing channels 2015-08-25 16:31:20 +01:00
77b82ecad7 ImDrawList: Fixed issues with channels split/merge. Functional without manually adding a draw cmd. + Removed unnecessary parameter to Channe 2015-08-25 16:24:17 +01:00
ad00d88923 Window clipping rect fixes (for child windows with borders among others) 2015-08-25 15:01:33 +01:00
f0aca186cc Comments 2015-08-25 13:35:25 +01:00
ad3c9f620d Tabs to spaces 2015-08-25 12:40:40 +01:00
466f01b313 Fixed child windows with the ImGuiWindowFlags_NoMove flag not taking direct focus 2015-08-25 12:39:44 +01:00
43d073db1e Metrics: showing some internal state 2015-08-25 12:22:30 +01:00
b76353bbb1 Passing ImGuiWindowFlags_NoMove to BeginChild() allows to inhibit moving root window from this child 2015-08-25 11:54:13 +01:00
063d26a191 Removed obsolete comment 2015-08-24 18:13:31 +01:00
9a0650dbd0 Examples: imgui_impl* functions declared with IMGUI_API to ease copy & pasting into projects using DLL 2015-08-24 14:02:51 +02:00
b1987d697f Trim trailing whitespace (#305) 2015-08-24 13:50:18 +02:00
425c6cb3a3 Remove CaptureInputCharactersFromApp and minor cleanups (#305) 2015-08-24 13:47:27 +02:00
73917115a8 Added flag showing whether the GUI wants text input
Conflicts:
	imgui.cpp
2015-08-24 13:44:43 +02:00
7eca754094 Merge pull request #304 from yinjimmy/fix_ios
Examples: Fixed missing files in iOS example.
2015-08-23 11:05:39 +02:00
01a17aa78e fix ios compile error 2015-08-23 08:03:21 +08:00
e885b08914 Web: Fixed screenshot (Argh web editor is broken) 2015-08-22 11:54:47 +02:00
0e898fb480 Web: Fixed screenshot 2015-08-22 11:54:13 +02:00
5f4cbed7ce Web: Fixed screenshot 2015-08-22 11:53:45 +02:00
b28858b33b InputText: intentionally ignore character input when ctrl/alt are held (not sure if correct) (#279) 2015-08-21 00:24:47 +02:00
23ce837dc7 Revert "Examples: GLFW: using glfwSetCharModsCallback() to ensure characters aren't passed when using mods (fix #279)"
This reverts commit d80869189a.
2015-08-21 00:16:07 +02:00
d80869189a Examples: GLFW: using glfwSetCharModsCallback() to ensure characters aren't passed when using mods (fix #279) 2015-08-20 22:32:07 +01:00
06c7453ee2 Merge pull request #302 from andresv/mac-sdl2-example-build-instructions
Examples: SDL: Add Mac OS X build instructions for sdl_opengl_example
2015-08-20 22:21:01 +01:00
bbced3f0f0 Build fix 2015-08-18 19:31:44 -06:00
4ac4d1ac37 ImHash: defaults seed to zero + comment. 2015-08-18 19:17:09 -06:00
ccbc72e98b add mac os x build instructions for sdl_opengl_example 2015-08-18 10:16:16 +03:00
97be3428f1 Added GetMousePosOnOpeningCurrentPopup(). 2015-08-15 15:10:07 -06:00
215747635d Examples: DirectX11: resizing buffers dynamically (#299) 2015-08-13 23:13:20 -06:00
c016f6c171 Examples: DirectX9: tweaks. 2015-08-13 23:07:53 -06:00
698c7cae85 Examples: DirectX9: resizing vertex and index buffers dynamically (#299) 2015-08-13 23:06:11 -06:00
ede5956b28 Metrics window: shows indices along with triangles count (#299) 2015-08-13 22:33:33 -06:00
0a6d6da732 Demo: Log: removed unnecessary style change, 2015-08-13 22:11:32 -06:00
67b2b5f3a9 Demo: Log: removed broken clipping, tweaks. 2015-08-13 22:04:31 -06:00
07de0448f9 ImGuiTextFilter: default parameter width=0.0f for no override, allow override with negative values 2015-08-13 21:51:34 -06:00
307ed78006 ImGuITextBuffer: shallow tweak. 2015-08-13 21:48:08 -06:00
b770f3ffaf Demo: Add filtering to log with better-than-none storage of line offsets. 2015-08-13 21:47:50 -06:00
42567a9516 ImGuiTextFilter::PassFilter() supports string range. Added [] helper to ImGuiTextBuffer. 2015-08-13 21:25:32 -06:00
72d3fca52f Demo: added simple Log demo 2015-08-13 20:59:37 -06:00
d36a634ac8 Demo: Fixed incorrectly formed string passed to Combo (#298) 2015-08-13 11:55:48 -06:00
c98318a914 Renaming some argument to clarify the local vs screen coordinates 2015-08-12 22:46:39 -06:00
f421f2f47e IsWindowHovered() takes account of window hoverability (may be disabled because of a popup) + comment
Was a dupe of IsMouseHoveringWindow() anyway, they are now "clearly"
different.
2015-08-12 22:30:07 -06:00
bcb83ed24e Fixed minor typo in example 2015-08-12 12:29:51 -06:00
4630815fb0 Links 2015-08-11 14:45:42 -06:00
f1f4d68f7f Prevent imgui_internal.h from being included without imgui.h (piles of errors) 2015-08-10 10:26:39 -06:00
0c9fcdbe71 Allow to override ImDrawIdx type (#292) 2015-08-09 11:11:39 -06:00
915b46f1c1 Added assert on index overflow (#292) 2015-08-09 11:05:38 -06:00
48ed0a10d7 Minor code compaction (following #296) 2015-08-09 10:54:28 -06:00
9a97ef673e Merge pull request #296 from tpoechtrager/master
Fixes for compiling Windows target with non-MSVC compiler.
2015-08-09 10:49:06 -06:00
6a90ac2094 Tentative GCC/Clang warning fixes with unused functions (cf #296) 2015-08-09 10:45:58 -06:00
3604aecf8f Minor Windows adjustments 2015-08-09 17:24:10 +02:00
23e7bdebcf Warnings for clang (#295) 2015-08-08 12:30:56 -06:00
32f15b9c9a Merge branch 'tpoechtrager-master' 2015-08-08 12:26:44 -06:00
aa3c26fd30 IM_PRINTFARGS takes one argument. Moved pragma outside of .h (#295) 2015-08-08 12:26:22 -06:00
b637850260 Merge branch 'master' of https://github.com/tpoechtrager/imgui into tpoechtrager-master 2015-08-08 12:18:59 -06:00
14822609bd Version number 1.45 WIP 2015-08-08 12:18:37 -06:00
947cf3434f Added printf attribute to printf like text formatting functions 2015-08-08 19:29:11 +02:00
a99ba42a39 Version number 1.44 2015-08-08 07:57:29 -06:00
20cc65788d Build fix for Orbis / PS4 2015-08-07 21:52:57 -06:00
27961401c6 Cleanup (#219) 2015-08-06 08:37:51 -06:00
88a00f77e9 Cleanup - using ImRect more consistently for ImGui-side cliprect data 2015-08-06 08:23:05 -06:00
f1fb62fa6d Cleanup - shuffle functions around (#219) 2015-08-06 08:11:33 -06:00
b6313577bb Merge pull request #291 from twoscomplement/surplus_inlines
Remove inline qualifiers inside .cpp
2015-08-06 07:33:12 -06:00
0911597550 Remove inline qualifiers inside .cpp
Use of inline in the .cpp file causes link errors with gcc.
2015-08-07 15:41:22 -07:00
80fc576d07 Update README.md 2015-08-05 22:17:10 -06:00
96a7873622 Update documentation 2015-08-05 22:00:27 -06:00
470200ee5c Update documentation 2015-08-05 21:59:07 -06:00
85dab1a680 Fixed documentation 2015-08-05 19:19:12 -06:00
15cfa63e97 Comments 2015-08-05 19:09:13 -06:00
692a38c0fc Merge branch 'master' into 2015-07-cleanup 2015-08-05 17:41:43 -06:00
f2b652a39e Comments 2015-08-05 17:38:17 -06:00
e7f1e28b6b Merge branch 'master' into 2015-07-cleanup 2015-08-05 17:27:47 -06:00
4b4f6d78ee InputFloat() fixed 0 decimal_precision 2015-08-05 17:26:04 -06:00
a54995eace RoundScalar() fallback use powf(10.f, -x) instead of 1.0f/powf(10.0f,x) 2015-08-05 17:11:20 -06:00
9b19f8c19d Merge branch 'master' into 2015-07-cleanup
Conflicts:
	imgui.cpp
2015-08-05 16:57:31 -06:00
12d941a42a Merge branch 'master' of https://github.com/ocornut/imgui 2015-08-05 16:51:17 -06:00
f6e21b7ab7 InputInt() also hexadecimal input (awkwardly via ImGuiInputTextFlags_CharsHexadecimal but we will allow fmt string in InputInt* later)
+ Fix for large ints constant assignment
2015-08-05 16:47:46 -06:00
cc8ff4c8d1 RoundScalar() use a lookup table to avoid calling powf(10.0f, x); 2015-08-05 16:17:11 -06:00
f0f2afa87d InputInt() doesn't cast to float, fix handling lost of precision with large integer. Added primitives to support more data types. 2015-08-05 16:08:53 -06:00
a793ad682d Merge branch 'master' into 2015-07-cleanup
Conflicts:
	imgui.cpp
2015-08-05 15:29:38 -06:00
ebd25cf1a3 Minor comments 2015-08-05 15:13:13 -06:00
7fea3eacfe Minor comments 2015-08-05 12:50:13 -06:00
e20b90154c Comments 2015-08-05 11:04:13 -06:00
3ee2fac892 Slider: fixed using FramePadding between frame and grab visual. Scaling that spacing would look odd. 2015-08-05 11:00:00 -06:00
e42bec5ba2 Fixed scaling of checkbox and radio button for the filling of "active" visual 2015-08-05 10:50:20 -06:00
155873a6b0 Added GetContentRegionAvail() helper 2015-08-05 10:43:12 -06:00
1b0a8f9ac3 Comments 2015-08-05 10:00:05 -06:00
60b46cc712 Comment (#219) 2015-08-05 09:34:07 -06:00
8be4d41540 Merge remote-tracking branch 'origin' into 2015-07-cleanup 2015-08-05 09:32:29 -06:00
1befd21b37 Moved ShowUserGuide() after ShowTestWindow() (#219) 2015-08-05 09:31:03 -06:00
3658314638 imgui_demo.cpp doesn't redefine functions from imgui_internal.h so all files can be unity-built (#219) 2015-08-05 09:28:19 -06:00
a526b423e8 Merge pull request #290 from cmaughan/master
Examples: DirectX11: Clear font texture view pointer to ensure Release() doesn't get called twice
2015-08-04 07:48:31 -06:00
d667de9490 Clear font texture view to ensure Release() doesn't get called twice 2015-08-04 14:22:05 +01:00
815d1d9be4 Merge remote-tracking branch 'origin' into 2015-07-cleanup
Conflicts:
	imgui.cpp
2015-08-03 08:12:57 -06:00
3aca446817 Added ImFontAtlas::AddFontFromMemoryCompressedBase85TTF() 2015-08-03 08:10:10 -06:00
da3baebd43 Fixed lower-right resize grip hit box not scaling along with its rendered size (#287) 2015-08-02 09:15:36 -06:00
e099798c97 Merge remote-tracking branch 'origin' into 2015-07-cleanup 2015-08-01 22:12:51 -06:00
3ccbdc8423 Unnecessary .gitignore in root folder 2015-08-01 22:12:18 -06:00
4b29cc9e10 Exposed relevant functions in imgui_internal.h (#219) 2015-08-01 21:57:24 -06:00
e47bf041bf Clang warning fixes 2015-08-01 21:37:32 -06:00
11d91a27a4 Carriage return (#289) 2015-08-01 17:18:01 -06:00
040e427dad Merge pull request #289 from twoscomplement/sdl_error_out
Examples: Show SDL error message on init failure.
2015-08-01 17:07:05 -06:00
f158617551 Show SDL error message on init failure 2015-08-02 01:35:43 -07:00
1e76c63bb6 Fixed comment 2015-08-01 08:07:16 -06:00
2d8c134747 Merge remote-tracking branch 'origin' into 2015-07-cleanup
Conflicts:
	imgui.cpp
2015-08-01 07:26:09 -06:00
26a992c6f6 Updated to stb_truetype 1.07 (back to vanilla version as our minor changes are now in master & fix #280) 2015-08-01 07:22:52 -06:00
6c63d80aa4 Tidying up InputTextApplyArithmeticOp() 2015-07-30 23:59:51 -06:00
f63beeae86 Internal version of LogText() -> LogRenderedText() + shallow tidying up 2015-07-30 23:48:59 -06:00
faa609a43c Internal cleanup ParseFormatPrecision() doesn't take a reference 2015-07-30 23:14:29 -06:00
f8646338c3 Merge remote-tracking branch 'origin' into 2015-07-cleanup 2015-07-30 23:00:11 -06:00
7650d4cc67 Internal SliderFloatAsInputText() -> InputFloatReplaceWidget() 2015-07-30 22:59:30 -06:00
abf823c6f6 Tidying up 2015-07-30 22:49:10 -06:00
58ee08f214 Todo list notes 2015-07-30 22:18:07 -06:00
040f3950a3 Merge remote-tracking branch 'origin' into 2015-07-cleanup
Conflicts:
	imgui.cpp
2015-07-30 21:54:07 -06:00
e6b29b70b4 Make internal SliderFloatAsInputText() take a size to match the calling widget 2015-07-30 21:51:55 -06:00
a7e5945206 Merge 2015-07-30 21:37:59 -06:00
c639f65eb7 Merge remote-tracking branch 'origin' into 2015-07-cleanup
Conflicts:
	imgui.cpp
2015-07-30 21:37:47 -06:00
02fbb36918 ImDrawList: Add missing support for anti-aliased thick-lines (#133, also ref #288) 2015-07-30 21:11:07 -06:00
a79ee94fc4 Removed unnecessary assignment + added comment 2015-07-30 20:59:41 -06:00
709c4c3168 Merge remote-tracking branch 'origin' into 2015-07-cleanup
Conflicts:
	imgui.cpp
2015-07-30 20:42:12 -06:00
527208ad7c Default font encoded as base85 saves ~100 lines / 26 KB of source code (from @mmalex) 2015-07-30 19:36:55 -06:00
fddc871870 Columns: never assume horizontal space for scrollbar if NoScrollbar flag is set. 2015-07-30 12:32:20 -06:00
fc9ee2bc9b Merge pull request #286 from GHF/cleanup
Remove non-text character at start of imgui.cpp
2015-07-30 12:14:01 -06:00
8d45c89352 Remove non-text character at start of imgui.cpp 2015-07-26 19:18:04 -07:00
4468ec001e Fixed warning in console example (we're iterating chars) 2015-07-22 06:38:19 -06:00
fb83323b1d Tidying up 2015-07-21 20:13:12 -06:00
62c888177a Tweaks 2015-07-21 20:06:34 -06:00
e1ac5a3198 Honor IMGUI_DISABLE_TEST_WINDOWS as described (#219) 2015-07-21 19:57:32 -06:00
68962ae683 README update 2015-07-21 19:53:06 -06:00
7552f48d7b ImLoadFileToMemory() default parameters 2015-07-21 17:46:49 -06:00
94f085aa3e Update comments (#219) 2015-07-21 17:19:11 -06:00
5a29eef1fa Fixed further warnings with GCC/Clang (#219) 2015-07-21 17:13:56 -06:00
e32f0931e8 Missing includes for imgui_draw.cpp (#219) 2015-07-21 17:08:20 -06:00
52a74701f5 Updated projects to reference new files (#219)
Didn't update iOS example (#247)
2015-07-21 17:04:03 -06:00
dace68b6fd Big cleanup, split imgui.cpp into imgui_demo.cpp,imgui_draw.cpp imgui_internal.h (#219) 2015-07-21 17:00:28 -06:00
60dce8bc22 Fix to get all code ShowTestWindow() copiable outside. Moved ShowMetricsWindows() above. (#219) 2015-07-19 11:45:03 -06:00
0eb196d544 Examples: OpenGL3: simplified code using glBufferData for vertices as well (#277, #278) 2015-07-19 10:52:51 -06:00
dc1cb9e625 Tweak 2015-07-19 10:49:56 -06:00
d184730dd2 Merge branch 'trevex-master' 2015-07-19 10:45:59 -06:00
bc9bae6d01 To support drivers with strict core profiles, a buffer is used for the indices as well (fixes ocornut/imgui#277). 2015-07-19 17:56:14 +02:00
83ebbebadd Fixed inconsistent declaration of ImVec2 privates operators 2015-07-18 22:37:08 -06:00
5a4b521855 Added ImDrawList::AddText() shorthand helper 2015-07-18 21:50:23 -06:00
74908a9513 Fixed angles in ImDrawList::PathArcTo(), PathArcToFast() being off by an extra PI for no reason 2015-07-18 18:45:37 -06:00
479211808f ImDrawList::AddPolyLine() tidying up in AA path 2015-07-18 17:31:40 -06:00
82727d7119 Version number 1.44 WIP 2015-07-18 14:07:22 -06:00
cdbf71ac12 Added ImGuiWindowFlags_NoInputs for input-passthru window
Would be more useful with finer control over display layer
2015-07-17 16:36:04 -06:00
0ab620c2b9 Combo() clamp popup to lower edge of visible area 2015-07-17 16:14:04 -06:00
20db726a9a Version number 1.44 WIP 2015-07-17 16:03:13 -06:00
4015414978 InputtextMultiline(): honor negative size consistently with other widgets 2015-07-17 16:01:21 -06:00
3b53a6513a Button() honor negative size consistently with other widgets that do so 2015-07-17 15:58:23 -06:00
eca26ae91d Build fix for MinGW (#276) 2015-07-17 13:38:55 -06:00
99c5f5735c Tweak button sizes 2015-07-17 07:08:51 -06:00
e8cb874afe Version number 1.43 2015-07-17 06:51:25 -06:00
55ab515551 Binaries 2015-07-16 21:02:43 -06:00
1266e4a181 Added a gratuitous About window 2015-07-16 20:58:26 -06:00
f7f71043ca InputText: stb_textedit.h tentative fix for End key on multi-line fields (#275) 2015-07-16 20:46:27 -06:00
98047b1b65 Update README.txt 2015-07-16 14:28:16 -06:00
f53d5da0f8 Update README.txt 2015-07-16 14:27:35 -06:00
d6117e33d0 AddInputCharactersUTF8: shallow tweaks (#274) 2015-07-15 22:14:04 -06:00
bc4ede656b Merge pull request #274 from DanielGibson/utf8-char-input
ImGuiIO::AddInputCharactersUTF8(utf8str), use it in SDL2 example
2015-07-15 22:08:59 -06:00
b7d1b91e4b Use ImGuiIO::AddInputCharactersUTF8() in SDL2 example
Now Unicode text input works in this example.
2015-07-16 05:16:22 +02:00
be8fb858cc Add ImGuiIO::AddInputCharactersUTF8(char* utf8str)
It'll convert the utf8 string to ImWchar's and passes each of them
to AddInputCharacter().

Very handy for SDL2 SDL_TEXTINPUT events, which provide a buffer with an
UTF-8 string.
2015-07-16 05:15:03 +02:00
b4ac413868 Merge pull request #273 from DanielGibson/fix-sdl2-linux
Examples: Fix SDL2 example for Linux.
2015-07-15 20:15:33 -06:00
02a0967243 Fix SDL2-example for Linux
The header is called "SDL_opengl.h" - case matters on Linux.

The main() function must indeed be called main(), on Windows it'll be
renamed to SDL_main (for SDL2main.lib) by #define in SDL_main.h
(which is included by SDL.h)

I added an entry to the example's README that describes how to build
it on Linux.
2015-07-16 03:54:44 +02:00
3ff04c95d5 Minor tweaks 2015-07-15 17:18:46 -06:00
52dd99915b Update README.md 2015-07-15 17:05:14 -06:00
0f25885b3d Merge branch 'master' of https://github.com/ocornut/imgui 2015-07-15 17:02:38 -06:00
9d4d7f3381 Update README.md 2015-07-15 17:00:47 -06:00
298118fccc New screenshots 2015-07-15 16:58:38 -06:00
d19d8f40ba Removed web screenshots (moved to wiki repository) 2015-07-15 16:27:33 -06:00
d170620816 Comments 2015-07-15 14:59:42 -06:00
4842ac3bc6 Fonts: added Cousine-Regular.ttf 2015-07-15 14:56:29 -06:00
5e846612d3 ImFont: tweaks 2015-07-15 14:54:56 -06:00
80276ef07b Fixed ClearInputData() 2015-07-15 14:48:46 -06:00
6c3ab6fc9b ImFont: fixed minor bug with CPU-side vertical clipping of text. 2015-07-15 13:34:59 -06:00
a56768463a Examples: moved demo bits around. 2015-07-15 13:16:35 -06:00
d750df9189 Fix for Shutdown() 2015-07-15 12:37:42 -06:00
baa2328b99 Tweak to RenderCheckMark() 2015-07-15 12:31:37 -06:00
d7a2a23457 Updated to stb_truetype 1.06 (#133) 2015-07-15 12:12:36 -06:00
8081e81e55 Fixed warnings + label 2015-07-15 11:56:07 -06:00
1a3ef63132 Fixed parameters array size declaration (wouldn't have a side-effect but weird and misleading)
Thanks Coverity
2015-07-15 09:36:39 -06:00
368d2c3568 OverlayDrawList readier for pushing elements (not exposed yet) 2015-07-15 09:26:03 -06:00
0224d29a35 Examples: comments. 2015-07-15 09:05:17 -06:00
035ff302d2 ImFontAtlas: moved application of FontDataOwnedByAtlas to AddFont() 2015-07-15 08:45:10 -06:00
95f489ac1f Merged AA branch in master! (#133) 2015-07-15 08:00:12 -06:00
3e3d9f9a69 ImFontAtlas: allow AddFontDefault to take a config 2015-07-15 07:58:33 -06:00
7ad4843f57 Fixed comments 2015-07-15 07:52:20 -06:00
99a92ee7c5 Comments (fixed old comments) 2015-07-15 07:46:31 -06:00
8952b93b2f Include for alloca() 2015-07-15 07:31:32 -06:00
fcec337061 Examples: Simplified font examples comments. 2015-07-15 07:05:34 -06:00
815168c7ef ImFontAtlas: new AddFont() API, oversampling, subpositiong, merging fonts, etc. (#182, #220, #232, #242) 2015-07-15 07:01:21 -06:00
6ae8062ca0 ImFont: comments, minor bits 2015-07-14 15:51:19 -06:00
c02f9b58ef ImFont: Cleanup to be compatible with over-sampling (not enabled) 2015-07-14 12:41:02 -06:00
fc6545830b Examples: displaying more font information. 2015-07-14 10:28:55 -06:00
faec745438 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-14 09:23:50 -06:00
8cfd963fda Popups: removed an apparently unnecessary test in CloseInactivePopups() that broke Combo boxes inside menus (#272) 2015-07-14 09:21:41 -06:00
355cbf6326 Examples: added tests for Combo box in sub-menu test and MenuItem in a normal window (#272) 2015-07-14 09:10:31 -06:00
52c820e7b0 Metrics: more details in popup stack (#272) 2015-07-14 09:09:52 -06:00
ba9317b924 ImFont: storing offsets as X0/Y0/X1/Y1 analoguous to examples for stb_truetype 2015-07-13 16:08:49 -06:00
5b053dd350 Fix for OverlayDrawList being ready to append commands (not exposed publicly yet anyway) 2015-07-13 15:52:57 -06:00
7eca4e2a7f Merge bits 2015-07-12 11:05:30 -06:00
fbb9113118 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-07-12 11:02:46 -06:00
4565bf9813 Demo: custom rendering example uses AddRectFilledMultiColor() 2015-07-12 10:52:20 -06:00
6520b6c458 ImDrawList: added AddRectFilledMultiColor() helper + minor optimisation. 2015-07-12 10:48:06 -06:00
7a0004eb86 Revert 2015-07-11 18:15:34 -06:00
d10d0343b2 Plot() function can take 0.0f for both scale_min/scale_max to calculate scale 2015-07-11 18:10:43 -06:00
e681937f66 Delete merging artefact that survived for a day 2015-07-11 08:41:11 -06:00
fd44b9440b Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-07-10 21:45:25 -06:00
b67593a4b1 Changed SameLine() parameters from int to float. 2015-07-10 19:36:34 -06:00
8094aa78d2 Fixed incorrect assert triggering when code steal ActiveID move user moving window by calling e.g. SetKeyboardFocusHere() 2015-07-10 18:54:26 -06:00
827ff970cd InputText: Added ImGuiInputTextFlags_AlwaysInsertMode flag 2015-07-10 18:47:55 -06:00
d2701727b9 InputText: added ImGuiInputTextFlags_NoHorizontalScroll flag. Added HasSelection() helper in ImGuiTextEditCallbackData as a clarification. 2015-07-10 18:17:46 -06:00
f2bed00d80 Examples: README 2015-07-09 08:39:44 -06:00
5ab23ab1c0 Allegro 5 example: removed public domain mark, MIT as the rest, with @bggd approval 2015-07-08 17:25:56 -06:00
398ef1a212 Comments 2015-07-08 17:10:14 -06:00
245cf36522 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-08 17:09:47 -06:00
890585cde8 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-08 17:08:51 -06:00
08b1dd1035 Version number 1.43 WIP
Bits
2015-07-08 17:08:37 -06:00
fec09e37ab Disable warnings, undo f4aae6b9ec (#265 #266) 2015-07-08 17:05:24 -06:00
7d45c84f21 Merge pull request #266 from Extrawurst/patch-4
Fix minor clang-x64 warnings (fixes #265)
2015-07-08 17:02:28 -06:00
f4aae6b9ec fix minor clang-x64 warnings
fixes #265
2015-07-09 00:00:28 +02:00
09e8c4ec11 AA branch: Re-added PrimVtx() + PrimWriteVtx, PrimWriteIdx for finer control (#133) 2015-07-08 14:03:27 -06:00
d81ba432ec New demo binaries 2015-07-08 13:22:34 -06:00
e5bea65582 Version number 1.42 2015-07-08 12:59:26 -06:00
2f574ef952 Allegro 5 example: converted for indexed rendering. 2015-07-08 12:55:40 -06:00
60dd221737 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-08 12:49:18 -06:00
bbaaab7537 Allegro 5 example: fixed uv coordinate of non-default texture. 2015-07-08 12:41:09 -06:00
4d2d0ce5cd Allegro 5 example: handling of hardware and software mouse cursor rendering. 2015-07-08 12:16:50 -06:00
8db229b96f Allegro 5 example: fixed key modifiers, keyboard input, clipping, added pagedown/pageup. 2015-07-08 12:04:13 -06:00
c58d61dfd1 Allegro 5 example: formatting, match other example structure, fixed mouse buttons. 2015-07-08 11:53:30 -06:00
489e28ec11 Allegro 5 example: main.cpp matches other examples. added window title. 2015-07-08 11:46:18 -06:00
1845ff4690 SDL example: tweaks (#233 #226) 2015-07-08 11:42:43 -06:00
19e3c1506f Allegro5 example: added example from https://github.com/bggd/a5imgui_example 2015-07-08 11:34:36 -06:00
e49977a913 SDL example: hasty readme. 2015-07-08 11:08:58 -06:00
d041ebc6d4 Merge branch '2015-03-antialiased-primitives' of https://github.com/ocornut/imgui into 2015-03-antialiased-primitives 2015-07-08 10:33:25 -06:00
b7e63c163c SDL example: update for indexed rendering. 2015-07-08 10:32:55 -06:00
b36ff2fec3 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-08 10:30:30 -06:00
12aba576fb Merge pull request #264 from joeld42/antialias-ios-fix
AA branch: iOS Example: update for API changes and index rendering
2015-07-08 10:29:39 -06:00
a14f6696a3 SDL example: more cleanup to match other examples (#233 #226) 2015-07-08 10:27:25 -06:00
22e099366f SDL example: further cleanup to match other examples (#233 #226) 2015-07-08 10:20:08 -06:00
4167528001 SDL example: moved event loop to main.cpp , adding page up/page down. (#226) 2015-07-08 10:10:54 -06:00
81cebb9c85 Simplified to not combine vert buffers like the opengl3 example 2015-07-08 09:01:10 -07:00
b7a2a6b23f SDL example: renamed folder, added in README 2015-07-08 09:49:32 -06:00
44c23e0eed Allowing DeltaTime==0.0f to not assert 2015-07-08 09:48:10 -06:00
b3ae2976c5 SDL example: tweaks and fixes. 2015-07-08 09:46:55 -06:00
046dbf502c Merge branch 'SampleSDL2' of https://github.com/CedricGuillemet/imgui into CedricGuillemet-SampleSDL2 2015-07-08 09:01:04 -06:00
e3b9a61883 Examples: OpenGL3: simplified code. Upload each vertex array separately. (cf #264) 2015-07-08 08:27:36 -06:00
ca042134ae Update ios example for API changes and index rendering 2015-07-07 23:43:27 -07:00
1cd391146d Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-07 21:48:28 -06:00
67d93156df Fixed clang/gcc warnings (#133) 2015-07-07 21:47:33 -06:00
5f039e7098 Merge branch 'ios_example_merge' 2015-07-07 21:39:05 -06:00
7d144eb899 iOS Example: Optimise PNG files size 2015-07-07 21:37:50 -06:00
fb27360ea8 iOS example: shallow tweaks and fixes (untested) 2015-07-07 21:35:09 -06:00
eee6dab226 iOS example working based on modified OpenGL3 example + Synergy 2015-07-07 21:17:48 -06:00
54c2665032 AA branch: undo d35c1a9e66, thickness is back but goes through non-AA path (#133) 2015-07-07 20:56:58 -06:00
439040bb25 AA branch: more comments on breaking changes (#133) 2015-07-07 20:30:46 -06:00
d03b046ef4 AA branch: Agressively renamed all fields of ImDrawList, ImDrawCmd, ImDrawData to match the rest of our coding convention (#133) 2015-07-07 20:17:07 -06:00
d35c1a9e66 AA branch: removed the 'thickness' parameter from ImDrawList::AddLine() 2015-07-07 18:34:29 -06:00
ac56e4e209 AA branch: API breaking change documentation 2015-07-07 18:31:41 -06:00
af7f35d7c2 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-07 18:22:18 -06:00
87ebe95fd6 Columns/ImDrawList: dispatch render of each column in a sub-draw list and merge on closure, saving draw calls (#125) 2015-07-07 18:19:01 -06:00
3e4841765d ImDrawList: winodw draw lists destructed properly on Shutdown() 2015-07-07 18:00:19 -06:00
f4fc008a2a Fixed ListBoxHeader() not honoring negative sizes the same way as BeginChild() or BeginChildFrame() (#263) 2015-07-07 16:53:09 -06:00
acf58c6223 More debug-build friendly ImVector<> use micro optimisations for the most bottle-neck bunchs 2015-07-07 13:54:06 -06:00
bfa7d86070 AA branch: further use of ImVector<> Data/Size 2015-07-07 12:58:36 -06:00
c3ced1bd71 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-07-07 12:42:29 -06:00
3869e10574 ImVector<> access to Size/Capacity/Data (#262) 2015-07-07 12:39:08 -06:00
25882c47a3 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	examples/directx11_example/imgui_impl_dx11.cpp
	examples/directx9_example/imgui_impl_dx9.cpp
	examples/opengl3_example/imgui_impl_glfw_gl3.cpp
	examples/opengl_example/imgui_impl_glfw.cpp
	imgui.cpp
2015-07-07 12:15:35 -06:00
502e360ee5 Removed the majority of size_t from the code. ImVector<> now uses int. (#262)
May trigger new compilation warnings?
2015-07-07 12:09:25 -06:00
aeae03f4ac Fixed minor zealous Clang warning (demo code intentionally uses strdup() to be copiable) 2015-07-07 12:05:15 -06:00
02dbcf5405 ImVector<> cannot be re-defined (#262) 2015-07-07 11:27:22 -06:00
4d42760c0b Metrics window: "Show clipping rectangles when hovering ImDrawList" enabled by default 2015-07-06 22:10:44 -06:00
de6dfe8c5d ImRect (internal) fixed ImVec4 constructor, argh (broken e7e2fcdd19) 2015-07-06 22:05:27 -06:00
92b61d2ee4 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-06 21:47:09 -06:00
b92396b46a Optimisation, removed the duplicate ClipRectStack in ImGuiWindow, storing single value 2015-07-06 21:46:12 -06:00
6a22835f63 AA branch: ImDrawList: rename commands to cmd_buffer
Not strictly necessary but while we're doing minor breakage let's do
them at all once.
2015-07-06 21:09:05 -06:00
e7e2fcdd19 ImRect (internal) made constructors more non-optimised compilation friendly 2015-07-06 20:59:01 -06:00
a17e47fe14 ImDrawList: fixed non-merged commands when equal clip rectangles are in the two first commands 2015-07-06 20:38:06 -06:00
5782c69c2a Metrics window: calculate bounding box of actual vertices when hovering a draw list. 2015-07-06 16:34:41 -06:00
9db4b35168 Fixed ImRect.Add(ImVec2&) which was broken and somehow unused 2015-07-06 11:13:05 -06:00
0ff2a6ff64 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-07-06 10:56:50 -06:00
d6987d1586 ImDrawList store pointer to their owner name for easier auditing/debugging. Metrics windows render clip rectangle when hovering. 2015-07-06 10:52:49 -06:00
c52cefa2c2 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-05 22:27:50 -06:00
0d5e6e125c Documentation (#133 #254) 2015-07-05 22:26:01 -06:00
0676efd37f AA branch: added ImDrawData::DeIndexAllBuffers() helper (#254) 2015-07-05 22:09:55 -06:00
b2b616be00 AA branch: ImDrawCmd idx_count -> elem_count 2015-07-05 22:09:15 -06:00
f3303fa84f AA branch: io.RenderDrawListsFn signature changed to take ImDrawData, neater and future proof breaking of the render API (#133 #254) 2015-07-05 22:03:46 -06:00
2633325b9f Comments 2015-07-05 21:55:24 -06:00
562aecdaa5 Removed obsolete GetDefaultFontData() function that would assert anyway (obsoleted 2015/01/11) 2015-07-05 20:56:01 -06:00
3fa4451936 PlotLines(), PlotHistogram(): fixed incorrect hovering test (would trigger tooltip when menu is open) 2015-07-05 20:47:25 -06:00
1c160adbba Comments 2015-07-05 20:38:18 -06:00
c9676554b9 MenuItem() can be activated on release (#245) 2015-07-05 20:27:06 -06:00
8b4a470e1d Examples: DirectX9: fixed size passed to vertex and index buffer Lock() + readjust default buffer sizes. 2015-07-05 19:24:26 -06:00
56553f33b8 AA branch: added style.AntiAliasedLines, style.AntiAliasedShapes (#133) 2015-07-05 19:09:53 -06:00
19e59421e5 AA branch: comments, inlining minor ops 2015-07-05 18:42:41 -06:00
46c440d186 AA branch: AddPolyline() stores normals on stack 2015-07-05 18:19:22 -06:00
c09af38804 AA branch: AddConvexPolyFilled() store normals on stack 2015-07-05 18:05:55 -06:00
a74ca9025f AA branch: oops, ImInvLengthSqr() is ImInvLength() 2015-07-05 17:37:55 -06:00
a8b5f77591 AA branch: AddPolyline(), AddConvexPolyFilled() a little more readable with more consistent naming 2015-07-05 17:36:07 -06:00
0292c82b9c AA branch: fix lower-right bound of frame outlines 2015-07-05 16:52:06 -06:00
2f21347803 CollapsingHeader() fixed label rendering outside in columns context where cliprect max isn't aligned with header 2015-07-05 16:37:49 -06:00
7959fbe992 AA branch: CollapsingHeader() rounding down half window padding 2015-07-05 16:35:41 -06:00
f04c2002d6 AA branch: fixed column offsets not always aligned to the pixel causing CollapsingHeader() border to incorrectly anti-alias
Fixing framed CollapsingHeader() inside columns, where
GetContentRegionMax() doesn't return pixel aligned rounded position.
2015-07-05 16:32:26 -06:00
0d7ca3da24 AA branch: AddLine() api adds the 0.5f offset (unsure about that yet) 2015-07-05 16:24:55 -06:00
18fa8e1c7e Fixed IsMouseDragging() (fix #260) 2015-07-04 16:46:30 -06:00
61e551e0ee AA branch: fixed warning 2015-07-04 13:41:51 -06:00
3b94c37efc AA branch: minor tweaks + disabled debug code that disable AA when holding Ctrl 2015-07-04 12:59:55 -06:00
f435e42561 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	examples/opengl_example/imgui_impl_glfw.cpp
2015-07-04 12:44:25 -06:00
d76bc3434e Added DragFloatRange2() DragIntRange2() helpers (#76) 2015-07-04 12:17:11 -06:00
a33810d652 Update README.md 2015-07-03 16:08:00 -06:00
e9b81dd5ab Comments 2015-07-03 15:32:10 -06:00
fd3c6067bf Add conditional #ifdef prior to imconfig.h to facilitate inclusion in build systems (#255) 2015-07-03 15:31:54 -06:00
7437b43b2d Fixed warnings for more pedantic settings (#258) 2015-07-03 08:15:56 -06:00
b69d7d9df3 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-02 21:47:48 -06:00
2f03511062 Added ImGuiKey_PageUp, ImGuiKey_PageDown for user. 2015-07-02 21:43:07 -06:00
6826ab3ffd Added GetKeyIndex() helper. 2015-07-02 21:32:29 -06:00
0f9e2f8173 Tweaked scrolling example code (#150) 2015-07-02 21:22:16 -06:00
42efc29def SetScrollFromCursorPos() -> SetScrollHere() (#150) final call ! 2015-07-02 21:03:15 -06:00
4eba6cd470 Added SetScrollY(), SetScrollFromPosY(). Renamed SetScrollPosHere() to SetScrollFromCursorPos(). (#150) 2015-07-02 20:53:45 -06:00
b54cb1c24c Merge branch 'master' of https://github.com/ocornut/imgui 2015-07-02 20:49:36 -06:00
b37a326163 Renamed GetScrollPosY() to GetScrollY(). (#150)
Necessary to reduce confusion along with other scrolling functions,
because positions (e.g. cursor position) are not equivalent to scrolling
amount.
2015-07-02 20:47:04 -06:00
5d59e965f6 Update README.md 2015-07-02 15:42:19 -06:00
7bd28d17ca Update README.md 2015-07-02 15:35:55 -06:00
531d0ce7ce Moving tooltips and popup chunks of imgui.h below widgets (#219) 2015-07-02 14:55:30 -06:00
0201fe6ed1 Comments 2015-07-02 14:49:38 -06:00
9bedcb5304 Added GetCursorStartPos() necessary for using scroll target relative to beginning of window content (#150) 2015-07-02 14:46:49 -06:00
1b01137c90 Fixed text baseline alignment of small button (no padding) after regular buttons
Currently being a coward and only doing it via the SmallButton() entry
point.
2015-07-02 12:44:48 -06:00
bbc22ac8ca Comments + remove trailing comma 2015-07-02 11:26:35 -06:00
90ec28f6de Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-07-02 10:23:21 -06:00
e0da1e0658 Split into CaptureKeyboardFromApp() / CaptureMouseFromApp() 2015-07-02 09:20:15 -06:00
77fad80e9f Added CaptureInputsFromApp() to manually enforce e.g. keyboard capturing 2015-07-02 09:10:31 -06:00
eaaab0120a Moved Inputs utilities to their own section in imgui.h + additional comments 2015-07-02 08:57:17 -06:00
fc7b562635 Added font links courtesy of twitter + instructions for fonts compressed in C array 2015-07-02 08:16:23 -06:00
57f70a29b2 Fixed a bug with TextUnformatted() clipping of long text (#257) 2015-07-02 07:42:29 -06:00
0e5b64ecd2 SetScrollPosHere() Minor hack for effective "scroll to top" to appear like user expect it (#150)
Compensate the difference between WindowPadding and ItemSpacing
2015-07-01 19:01:27 -06:00
824cf5ae85 Fixed window padding being reported incorrectly for child windows with borders when parent have no borders 2015-07-01 18:55:42 -06:00
3d7b596a40 SetScrollToPosHere() fixed imprecision + handling lower gap better for bottom alignment (#150) 2015-07-01 18:23:11 -06:00
49b7a8e61f Added scroll tracking example with SetScrollPosHere() (relate #150) 2015-07-01 18:01:43 -06:00
b74d8e4c87 SetScrollPosHere() takes a y centering ratio and can be used to aim the top or bottom of the window (relate #150) 2015-07-01 17:51:44 -06:00
067b7d909a Style: Added GrabRounding (works well with AA branch). Followup to #212 2015-06-30 15:02:59 -06:00
d3c0bfefb3 AA branch: render axis aligned rect bypassing the AA path 2015-06-30 14:51:25 -06:00
b30d08d63a AA branch: bits 2015-06-30 14:24:50 -06:00
c39372e7d5 Title bar uses TitleBgActive color even when window has popups/menus over (#253) 2015-06-30 13:52:00 -06:00
47826830af Adding TitleBgActive color - still issues with popups/menus (#253) 2015-06-30 13:40:13 -06:00
c71b183965 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-06-30 13:31:56 -06:00
1318e1b74c AA branch: remove unused functions. 2015-06-30 13:30:25 -06:00
4bb94a9e4d AA branch: more optimisations. 2015-06-30 13:27:35 -06:00
a8f0eb5ec6 AA branch: more optimisations. 2015-06-30 13:12:45 -06:00
bbdf36cd3a AA branch: minor optimisations, merging loops 2015-06-30 13:09:07 -06:00
c3040dee35 AA branch: more inline. 2015-06-30 12:55:14 -06:00
077285ae57 AA branch: tidying up, inline PathStroke PathFill 2015-06-30 12:51:52 -06:00
aaefe458df AA branch: cleanup 2015-06-30 12:44:03 -06:00
ebfe4637d4 Merge branch '2015-04-indexed-rendering' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
	imgui.h
2015-06-30 12:43:26 -06:00
d57ee2458c AA branch: ImDrawList: renaming of Path based functions so both code paths can cohabit with no confusion 2015-06-29 19:25:41 -06:00
5bf30bd6c4 AA branch: Minor optimisations for Debug builds 2015-06-29 19:23:57 -06:00
71e9f2a3dd Fixed warnings for 64-bits builds 2015-06-29 15:46:18 -06:00
43dcd6ef47 Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	imgui.cpp
2015-06-29 15:43:58 -06:00
0bf90770b0 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-06-29 15:40:38 -06:00
0e3198edc2 Tidying up - renamed FindBestWindowPos() to FindBesttPopupWindowPos() 2015-06-29 15:18:26 -06:00
af0de5f357 Tidying up - ImRect doesn't use ImVec2 operators (so we can expose it later) 2015-06-29 13:30:37 -06:00
882c7a8cef Tidying up - ShowUserGuide, ShowStyleEditor only uses public calls 2015-06-29 13:20:28 -06:00
039ebb79f4 Tidying up - renamed a few internal functions 2015-06-29 13:18:44 -06:00
8b392feba1 Tidying up - moved ImFontAtlas glyph ranges helpers outside of ImFont block 2015-06-29 12:36:24 -06:00
0783697f87 Minor tidying up 2015-06-29 10:39:17 -06:00
4ac21aaa12 Version number 1.42 wip + todo list entries 2015-06-26 20:48:53 -06:00
14f189b2f6 Merge pull request #250 from benvanik/patch-1
Fixing 64-bit compilation warning caused by implicit size_t->int cast
2015-06-26 20:23:32 -06:00
5cd1a01514 Fixing 64-bit compilation warning caused by implicit size_t->int cast 2015-06-26 18:49:45 -07:00
0b98d3eb26 Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	imgui.cpp
2015-06-21 20:01:25 -06:00
01cb0dc7f7 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
	imgui.h
2015-06-21 19:58:30 -06:00
b360c83e92 Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering 2015-06-14 20:29:10 -06:00
7d860a0181 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-06-14 20:28:19 -06:00
a76eea85c8 Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	imgui.cpp
2015-05-31 16:59:01 +01:00
ade7661b3f Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-05-31 16:57:43 +01:00
2acdafe4f2 imgui_impl_sdl and main sample 2015-05-25 09:40:58 +02:00
e3f2ad728a Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	examples/directx11_example/imgui_impl_dx11.cpp
2015-05-21 22:57:29 +01:00
cc3ed515ca Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-05-21 22:52:46 +01:00
e9b6e437eb Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	imgui.cpp
	imgui.h
2015-05-15 17:33:04 +01:00
1eafe86627 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-05-15 17:31:56 +01:00
f00662a5ad Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering 2015-05-02 22:20:48 +01:00
08fd6a7e7d Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-05-02 22:20:14 +01:00
94c4e9564d Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering 2015-04-19 23:00:14 +01:00
86d1abf3f6 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-04-19 22:59:53 +01:00
4f1acf0d4a Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	imgui.cpp
2015-04-17 08:42:36 +01:00
1847270a5f Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-04-17 08:41:16 +01:00
43cb4038c6 Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	examples/directx11_example/imgui_impl_dx11.cpp
	imgui.cpp
2015-04-14 09:51:28 +01:00
0bb89ccee2 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-04-14 09:49:04 +01:00
88725be381 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-04-11 18:13:43 +01:00
bff9a6b6e3 Added ImFontAtlas::AddFontFromCompressedTTF() helper + binary_to_compressed_c.cpp tool 2015-04-11 17:52:51 +01:00
c3a71f5472 AA branch: Minor optimisation merge + thickness for non-aa strokes. 2015-04-09 23:00:55 +01:00
dbc9b2ec9b Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
2015-04-09 22:56:13 +01:00
6bdb8719e2 Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering 2015-04-09 22:50:18 +01:00
e0cd947904 AA branch: Fixes. 2015-04-09 22:40:50 +01:00
1e69175403 AA branch: Test disabling aa at runtime for stroke and fill. 2015-04-09 22:31:26 +01:00
431e391ccd AA branch: fixed circles. 2015-04-09 21:51:33 +01:00
14ddb81f7a AA branch: remove code unnecessary for this branch. 2015-04-09 21:39:56 +01:00
39445cf23a Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
	imgui.h
2015-04-09 21:38:30 +01:00
7ab49f80ca Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering
Conflicts:
	examples/directx11_example/imgui_impl_dx11.cpp
	examples/opengl3_example/imgui_impl_glfw_gl3.cpp
2015-04-09 21:22:06 +01:00
1746b04065 Indexed rendering. Not in main branch because breaks rendering code too much. Will merge in trunk along with more major graphics changes lat 2015-04-09 21:05:35 +01:00
13fab08cdb Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-04-08 20:37:18 +01:00
323ae8326e Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-04-07 13:51:01 +01:00
6ba7a74191 AA branch: fix. 2015-03-30 23:57:29 +01:00
bb385fabd4 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-03-30 23:55:40 +01:00
26991bb2ec Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
	imgui.h
2015-03-26 22:09:35 +00:00
ff1040a38d Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-03-21 10:55:31 +00:00
d77082af00 Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-03-21 00:54:31 +00:00
282532a92a AA Branch: notes. 2015-03-19 17:04:50 +00:00
138e292c4b Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts:
	imgui.cpp
	imgui.h
2015-03-19 17:01:54 +00:00
2a04c2a7bb Fix warnings 2015-03-19 09:33:43 +00:00
ea720963cf Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-03-16 10:21:25 +00:00
378eee490b Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives 2015-03-09 18:06:39 +00:00
8dd3f854fe AA branch: fixed columns separators. 2015-03-07 00:32:52 +00:00
470a8499fe AA branch: fixed input cursor. 2015-03-07 00:28:10 +00:00
af1f41dc6a AA branch: disabled border shadow by default. 2015-03-07 00:26:53 +00:00
f5c2f8c60d AA branch: fixed separators, borders, input cursor. - not really sure about this. 2015-03-07 00:24:21 +00:00
cf1554ebb5 AA branch: fixed frame rounding clamping glitch. 2015-03-07 00:06:48 +00:00
2b032004a9 AA branch: Fixed resize grip to scale better with non-default window rounding settings. 2015-03-07 00:01:02 +00:00
d69df3065f AA primitives: using a single vector for storage and accessing via raw pointers. 2015-03-06 23:47:26 +00:00
8ca3dc8e41 Merge: First pass on AA rendered primitives from https://github.com/memononen/imgui 2015-03-06 23:39:38 +00:00
fdc8c0722f Compile fixes 2015-01-06 19:24:57 +02:00
91684a428b Merge upstream 2015-01-06 19:15:41 +02:00
d9757bb583 First pass on AA rendered primitives 2015-01-06 19:05:24 +02:00
83 changed files with 12601 additions and 6344 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
imgui.ini

View File

@ -5,60 +5,64 @@ ImGui
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) [![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies. It is based on an "immediate" graphical user interface paradigm which allows you to build user interfaces with ease.
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and self-contained (no external dependencies). It is based on an "immediate mode" graphical user interface paradigm which enables you to build user interfaces with ease.
ImGui is designed to enable fast iteration and allow programmers to create "content creation" or "debug" tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.
ImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.
ImGui is particularly suited to integration in 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
ImGui is self-contained within 6 files that you can easily copy and compile into your application/engine:
ImGui is self-contained within a few files that you can easily copy and compile into your application/engine:
- imgui.cpp
- imgui.h
- imgui_demo.cpp
- imgui_draw.cpp
- imgui_internal.h
- imconfig.h (empty by default, user-editable)
- stb_rect_pack.h
- stb_textedit.h
- stb_truetype.h
No specific build process is required. You can add the .cpp files to your project or #include them from an existing file.
Your code passes mouse/keyboard inputs and settings to ImGui (see example applications for more details). After ImGui is setup, you can use it like in this example:
![screenshot of sample code alongside its output with ImGui](/web/code_sample_01.png?raw=true)
![screenshot of sample code alongside its output with ImGui](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01.png)
ImGui outputs vertex buffers and simple command-lists that you can render in your application. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase.
ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, etc.
ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, etc.
Some of the features supported in some way by ImGui: window management (ordering, moving, resizing, collapsing, persistent settings), button, slider, dragging value, checkbox, radio button, text input (with selection, clipboard support, and standard keyboard controls), multiline text input, filtering text input, tree nodes, collapsing header, word-wrapping, utf-8 text, images, selectable items, vertical and horizontal scrolling, sub-window with independant scrolling/clipping, ttf font loading, basic styling, logging any ui output into text data (clipboard/tty/file), hovering, tooltips, popup windows, modal windows, menu bars, menu items, context menus, combo boxes, list box, plotting lines and histograms, resizable columns, keyboard tabbing, dragging, simple drawing api (anti-aliased, with stroking, convex fill), and low-level primitives to create custom widgets.
Demo
----
You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at the features of ImGui, you can download binaries of the demo app here.
- [imgui-demo-binaries-20150531.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20150531.zip) (Windows binaries, ImGui 1.40 WIP 2015/05/31, 4 executables, 432 KB)
You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at the features of ImGui, you can download Windows binaries of the demo app here.
- [imgui-demo-binaries-20150716.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20150716.zip) (Windows binaries, ImGui 1.43 WIP 2015/07/16, 4 executables, 475 KB)
Gallery
-------
![screenshot 1](/web/test_window_01.png?raw=true)
![screenshot 2](/web/test_window_02.png?raw=true)
![screenshot 3](/web/test_window_03.png?raw=true)
![screenshot 4](/web/test_window_04.png?raw=true)
![screenshot 5](/web/test_window_05_menus.png?raw=true)
![screenshot 6](/web/examples_03.png?raw=true)
![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_01.png)
![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_02.png)
![screenshot 3](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_03.png)
![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v140/test_window_05_menus.png)
![screenshot 4](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png)
![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/examples_04.png)
![screenshot 7](https://cloud.githubusercontent.com/assets/8225057/7903336/96f0fb7c-07d0-11e5-95d6-41c6a1595e5a.png)
![screenshot 8](/web/examples_02.png?raw=true)
ImGui can load TTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with:
```
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
io.Fonts->AddFontFromFileTTF("ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
```
For Microsoft IME, pass your HWND to enable IME positioning:
```
io.ImeWindowHandle = my_hwnd;
```
![Japanese screenshot](/web/code_sample_01_jp.png?raw=true)
![Japanese screenshot](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01_jp.png)
References
----------
@ -75,8 +79,9 @@ Frequently Asked Question
<b>Where is the documentation?</b>
- The documentation is at the top of imgui.cpp + effectively imgui.h.
- Example code is in the ImGui::ShowTestWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output.
- Standalone example applications using OpenGL/DirectX are provided in the examples/ folder.
- Example code is in imgui_demo.cpp and particularly the ImGui::ShowTestWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output.
- Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder.
- It obviously needs better documentation! Consider helping or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.
<b>How do you use ImGui on a platform that may not have a mouse or keyboard?</b>
@ -88,7 +93,9 @@ In your Render function, try translating your projection matrix by (0.5f,0.5f) o
<b>Can you create elaborate/serious tools with ImGui?</b>
Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. However note that ImGui is programmer centric and the immediate-mode GUI paradigm might requires a bit of adaptation before you can realize its full potential.
Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools).
ImGui is very programmer centric and the immediate-mode GUI paradigm might requires a bit of adaptation before you can realize its full potential. Many programmers have unfortunately been taught by their environment to make unnecessarily complicated things. ImGui is about making things that are simple, efficient and powerful.
<b>Is ImGui fast?</b>
@ -96,11 +103,11 @@ Down to the fundation of its visual design, ImGui is engineered to be fairly per
Mileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended).
![performance screenshot](/web/performance_01.png?raw=true)
![performance screenshot](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v138/performance_01.png)
This is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint.
If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - using helpers such as CalcListClipping() - in order to avoid submitting them to ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem.
If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - using helpers such as ImGuiListClipper - in order to avoid submitting them to ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem.
<b>Can you reskin the look of ImGui?</b>
@ -110,7 +117,7 @@ You can alter the look of the interface to some degree: changing colors, sizes,
ImGui takes advantage of a few C++ features for convenience but nothing anywhere Boost-insanity/quagmire. In particular, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience but could be removed.
Shall someone wants to use ImGui from another language, it should be possible to wrap ImGui to be used from a raw C API in the future.
Shall someone really need to use ImGui from another language, there is an unofficial but reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly. I would suggest using your target language functionality to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. It was really designed with C++ in mind and may not make the same amount of sense with another language.
Donate
------
@ -138,7 +145,7 @@ Special supporters:
- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Stefano Cristiano.
And:
- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly.
- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei.
And other supporters; thanks!

3
examples/.gitignore vendored
View File

@ -15,14 +15,17 @@ opengl_example/Debug/*
opengl_example/Release/*
opengl_example/ipch/*
opengl_example/x64/*
opengl_example/opengl_example
opengl3_example/Debug/*
opengl3_example/Release/*
opengl3_example/ipch/*
opengl3_example/x64/*
opengl3_example/opengl3_example
*.opensdf
*.sdf
*.suo
*.vcxproj.user
*.o
## Ini files
imgui.ini

View File

@ -1,19 +1,36 @@
Those are standalone ready-to-build applications to demonstrate ImGui.
Unfortunately in 2015 it is still a massive pain to create and maintain portable build files.
I choose to provide Visual Studio 10 .sln files and Makefile for Linux/OSX.
Please let me know if they don't work with your setup!
You can probably just import the .cpp files into your own system and figure out the linkage from there.
Binaries of some of those demos are available at http://www.miracleworld.net/imgui/binaries
TL;DR;
Refer to 'opengl_example' to understand how the library is setup, because it is the simplest one.
Copy the imgui_impl_xxx.cpp/.h files you need if you are using one of provided rendering/IO backends.
If using different or your own backend, copy opengl_example/imgui_impl_opengl.cpp/.h to get started.
ImGui is highly portable and only requires a few things to run:
- Providing mouse/keyboard inputs
- Load the font atlas texture into GPU memory
- Providing a render function to render indexed textured triangles
- Optional: clipboard support, mouse cursor supports, Windows IME support, etc.
So this is essentially what those examples are doing + the obligatory cruft for portability.
Unfortunately in 2015 it is still a massive pain to create and maintain portable build files using
external library like the ones we're using here to provide 3D rendering.
For most examples here I choose to provide Visual Studio 10 .sln files and Makefile for Linux/OSX.
Please let me know if they don't work with your setup!
You can probably just import the imgui_impl_xxx.cpp/.h files into your own codebase or compile those
directly with a command-line compiler.
opengl_example/
OpenGL example, using GLFW + fixed pipeline.
This is simple and should work for all OpenGL enabled applications.
Prefer following this example since it is the shortest one!
Prefer following this example to learn how ImGui works!
(You can use this code in a GL3/GL4 context but make sure you disable the programmable pipeline
by calling "glUseProgram(0)" before ImGui::Render.)
opengl3_example/
OpenGL exemple, using GLFW/GL3W + programmable pipeline.
This uses more modern calls and custom shaders.
I don't think there is an advantage using this over the simpler example, but it is provided for reference.
OpenGL example, using GLFW/GL3W + programmable pipeline.
This uses more modern OpenGL calls and custom shaders. It's more messy.
directx9_example/
DirectX9 example, Windows only.
@ -22,3 +39,13 @@ directx11_example/
DirectX11 example, Windows only.
This is quite long and tedious, because: DirectX11.
ios_example/
iOS example.
Using Synergy to access keyboard/mouse data from server computer.
Synergy keyboard integration is rather hacky.
sdl_opengl_example/
SDL2 + OpenGL example.
allegro5_example/
Allegro 5 example.

View File

@ -0,0 +1,16 @@
# How to Build
- On Ubuntu 14.04+
```bash
g++ -I ../imgui main.cpp imgui_impl_a5.cpp ../imgui/imgui*.cpp -lallegro -lallegro_primitives
```
- On Windows with Visual Studio's CLI
\<a5path\> is your allegro5 folder.
```
cl /MD /I <a5path\include> /I ..\imgui main.cpp imgui_impl_a5.cpp ..\imgui\imgui*.cpp /link /LIBPATH:<a5path\lib> allegro-5.0.10-monolith-md.lib user32.lib
```

View File

@ -0,0 +1,290 @@
// ImGui Allegro 5 bindings
// https://github.com/ocornut/imgui
// by @birthggd
#include <stdint.h> // uint64_t
#include <cstring> // memcpy
#include <imgui.h>
#include "imgui_impl_a5.h"
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#ifdef _WIN32
#include <allegro5/allegro_windows.h>
#endif
// Data
static ALLEGRO_DISPLAY* g_Display = NULL;
static ALLEGRO_BITMAP* g_Texture = NULL;
static double g_Time = 0.0;
static ALLEGRO_MOUSE_CURSOR* g_MouseCursorInvisible = NULL;
static ALLEGRO_VERTEX_DECL* g_VertexDecl = NULL;
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
struct ImDrawVertAllegro
{
ImVec2 pos;
ImVec2 uv;
ALLEGRO_COLOR col;
};
static void ImGui_ImplA5_RenderDrawLists(ImDrawData* draw_data)
{
int op, src, dst;
al_get_blender(&op, &src, &dst);
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
// FIXME-OPT: Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats
static ImVector<ImDrawVertAllegro> vertices;
vertices.resize(cmd_list->VtxBuffer.size());
for (int i = 0; i < cmd_list->VtxBuffer.size(); ++i)
{
const ImDrawVert &dv = cmd_list->VtxBuffer[i];
ImDrawVertAllegro v;
v.pos = dv.pos;
v.uv = dv.uv;
unsigned char *c = (unsigned char*)&dv.col;
v.col = al_map_rgba(c[0], c[1], c[2], c[3]);
vertices[i] = v;
}
// FIXME-OPT: Unfortunately Allegro doesn't support 16-bit vertices
static ImVector<int> indices;
indices.resize(cmd_list->IdxBuffer.size());
for (int i = 0; i < cmd_list->IdxBuffer.size(); ++i)
indices[i] = (int)cmd_list->IdxBuffer.Data[i];
int idx_offset = 0;
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->TextureId;
al_set_clipping_rectangle(pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z-pcmd->ClipRect.x, pcmd->ClipRect.w-pcmd->ClipRect.y);
al_draw_indexed_prim(&vertices[0], g_VertexDecl, texture, &indices[idx_offset], pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
}
idx_offset += pcmd->ElemCount;
}
}
// Restore modified state
al_set_blender(op, src, dst);
al_set_clipping_rectangle(0, 0, al_get_display_width(g_Display), al_get_display_height(g_Display));
}
bool Imgui_ImplA5_CreateDeviceObjects()
{
ImGuiIO &io = ImGui::GetIO();
// Build texture
unsigned char *pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Create texture
int flags = al_get_new_bitmap_flags();
int fmt = al_get_new_bitmap_format();
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP|ALLEGRO_MIN_LINEAR|ALLEGRO_MAG_LINEAR);
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
ALLEGRO_BITMAP* img = al_create_bitmap(width, height);
al_set_new_bitmap_flags(flags);
al_set_new_bitmap_format(fmt);
if (!img)
return false;
ALLEGRO_LOCKED_REGION *locked_img = al_lock_bitmap(img, al_get_bitmap_format(img), ALLEGRO_LOCK_WRITEONLY);
if (!locked_img)
{
al_destroy_bitmap(img);
return false;
}
memcpy(locked_img->data, pixels, sizeof(int)*width*height);
al_unlock_bitmap(img);
// Convert software texture to hardware texture.
ALLEGRO_BITMAP* cloned_img = al_clone_bitmap(img);
al_destroy_bitmap(img);
if (!cloned_img)
return false;
// Store our identifier
io.Fonts->TexID = (void*)cloned_img;
g_Texture = cloned_img;
// Cleanup (don't clear the input data if you want to append new fonts later)
io.Fonts->ClearInputData();
io.Fonts->ClearTexData();
// Create an invisible mouse cursor
// Because al_hide_mouse_cursor() seems to mess up with the actual inputs..
ALLEGRO_BITMAP* mouse_cursor = al_create_bitmap(8,8);
g_MouseCursorInvisible = al_create_mouse_cursor(mouse_cursor, 0, 0);
al_destroy_bitmap(mouse_cursor);
return true;
}
void ImGui_ImplA5_InvalidateDeviceObjects()
{
if (g_Texture)
{
al_destroy_bitmap(g_Texture);
ImGui::GetIO().Fonts->TexID = NULL;
g_Texture = NULL;
}
if (g_MouseCursorInvisible)
{
al_destroy_mouse_cursor(g_MouseCursorInvisible);
g_MouseCursorInvisible = NULL;
}
}
bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display)
{
g_Display = display;
// Create custom vertex declaration.
// Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats.
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
ALLEGRO_VERTEX_ELEMENT elems[] =
{
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, OFFSETOF(ImDrawVertAllegro, pos) },
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, OFFSETOF(ImDrawVertAllegro, uv) },
{ ALLEGRO_PRIM_COLOR_ATTR, 0, OFFSETOF(ImDrawVertAllegro, col) },
{ 0, 0, 0 }
};
g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
ImGuiIO& io = ImGui::GetIO();
io.KeyMap[ImGuiKey_Tab] = ALLEGRO_KEY_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = ALLEGRO_KEY_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = ALLEGRO_KEY_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = ALLEGRO_KEY_UP;
io.KeyMap[ImGuiKey_DownArrow] = ALLEGRO_KEY_DOWN;
io.KeyMap[ImGuiKey_PageUp] = ALLEGRO_KEY_PGUP;
io.KeyMap[ImGuiKey_PageDown] = ALLEGRO_KEY_PGDN;
io.KeyMap[ImGuiKey_Home] = ALLEGRO_KEY_HOME;
io.KeyMap[ImGuiKey_End] = ALLEGRO_KEY_END;
io.KeyMap[ImGuiKey_Delete] = ALLEGRO_KEY_DELETE;
io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER;
io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE;
io.KeyMap[ImGuiKey_A] = ALLEGRO_KEY_A;
io.KeyMap[ImGuiKey_C] = ALLEGRO_KEY_C;
io.KeyMap[ImGuiKey_V] = ALLEGRO_KEY_V;
io.KeyMap[ImGuiKey_X] = ALLEGRO_KEY_X;
io.KeyMap[ImGuiKey_Y] = ALLEGRO_KEY_Y;
io.KeyMap[ImGuiKey_Z] = ALLEGRO_KEY_Z;
io.RenderDrawListsFn = ImGui_ImplA5_RenderDrawLists;
#ifdef _WIN32
io.ImeWindowHandle = al_get_win_window_handle(g_Display);
#endif
return true;
}
void ImGui_ImplA5_Shutdown()
{
ImGui_ImplA5_InvalidateDeviceObjects();
ImGui::Shutdown();
}
bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev)
{
ImGuiIO &io = ImGui::GetIO();
switch (ev->type)
{
case ALLEGRO_EVENT_MOUSE_AXES:
io.MouseWheel += ev->mouse.dz;
return true;
case ALLEGRO_EVENT_KEY_CHAR:
if (ev->keyboard.display == g_Display)
if (ev->keyboard.unichar > 0 && ev->keyboard.unichar < 0x10000)
io.AddInputCharacter((unsigned short)ev->keyboard.unichar);
return true;
case ALLEGRO_EVENT_KEY_DOWN:
case ALLEGRO_EVENT_KEY_UP:
if (ev->keyboard.display == g_Display)
io.KeysDown[ev->keyboard.keycode] = (ev->type == ALLEGRO_EVENT_KEY_DOWN);
return true;
}
return false;
}
void ImGui_ImplA5_NewFrame()
{
if (!g_Texture)
Imgui_ImplA5_CreateDeviceObjects();
ImGuiIO &io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
int w, h;
w = al_get_display_width(g_Display);
h = al_get_display_height(g_Display);
io.DisplaySize = ImVec2((float)w, (float)h);
// Setup time step
double current_time = al_get_time();
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
g_Time = current_time;
// Setup inputs
ALLEGRO_KEYBOARD_STATE keys;
al_get_keyboard_state(&keys);
io.KeyCtrl = al_key_down(&keys, ALLEGRO_KEY_LCTRL) || al_key_down(&keys, ALLEGRO_KEY_RCTRL);
io.KeyShift = al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT);
io.KeyAlt = al_key_down(&keys, ALLEGRO_KEY_ALT) || al_key_down(&keys, ALLEGRO_KEY_ALTGR);
ALLEGRO_MOUSE_STATE mouse;
if (keys.display == g_Display)
{
al_get_mouse_state(&mouse);
io.MousePos = ImVec2((float)mouse.x, (float)mouse.y);
}
else
{
io.MousePos = ImVec2(-1, -1);
}
al_get_mouse_state(&mouse);
io.MouseDown[0] = mouse.buttons & (1 << 0);
io.MouseDown[1] = mouse.buttons & (1 << 1);
io.MouseDown[2] = mouse.buttons & (1 << 2);
// Hide OS mouse cursor if ImGui is drawing it
if (io.MouseDrawCursor)
{
al_set_mouse_cursor(g_Display, g_MouseCursorInvisible);
}
else
{
ALLEGRO_SYSTEM_MOUSE_CURSOR cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT;
switch (ImGui::GetMouseCursor())
{
case ImGuiMouseCursor_TextInput: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_EDIT; break;
case ImGuiMouseCursor_Move: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE; break;
case ImGuiMouseCursor_ResizeNS: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_N; break;
case ImGuiMouseCursor_ResizeEW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E; break;
case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break;
case ImGuiMouseCursor_ResizeNWSE: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break;
}
al_set_system_mouse_cursor(g_Display, cursor_id);
}
// Start the frame
ImGui::NewFrame();
}

View File

@ -0,0 +1,17 @@
// ImGui Allegro 5 bindings
// https://github.com/ocornut/imgui
// by @birthggd
#pragma once
struct ALLEGRO_DISPLAY;
union ALLEGRO_EVENT;
IMGUI_API bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display);
IMGUI_API void ImGui_ImplA5_Shutdown();
IMGUI_API void ImGui_ImplA5_NewFrame();
IMGUI_API bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT* event);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_API bool Imgui_ImplA5_CreateDeviceObjects();
IMGUI_API void ImGui_ImplA5_InvalidateDeviceObjects();

View File

@ -0,0 +1,105 @@
// ImGui - standalone example application for Allegro 5
#include <stdint.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#include <imgui.h>
#include "imgui_impl_a5.h"
int main(int, char**)
{
// Setup Allegro
al_init();
al_install_keyboard();
al_install_mouse();
al_init_primitives_addon();
al_set_new_display_flags(ALLEGRO_RESIZABLE);
ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
al_set_window_title(display, "ImGui Allegro 5 example");
ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue();
al_register_event_source(queue, al_get_display_event_source(display));
al_register_event_source(queue, al_get_keyboard_event_source());
al_register_event_source(queue, al_get_mouse_event_source());
// Setup ImGui binding
ImGui_ImplA5_Init(display);
// Load Fonts
// (see extra_fonts/README.txt for more details)
//ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
bool show_test_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154);
// Main loop
bool running = true;
while (running)
{
ALLEGRO_EVENT ev;
while (al_get_next_event(queue, &ev))
{
ImGui_ImplA5_ProcessEvent(&ev);
if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) running = false;
if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
{
ImGui_ImplA5_InvalidateDeviceObjects();
al_acknowledge_resize(display);
Imgui_ImplA5_CreateDeviceObjects();
}
}
ImGui_ImplA5_NewFrame();
// 1. Show a simple window
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
{
static float f;
ImGui::Text("Hello, world!");
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::ColorEdit3("clear color", (float*)&clear_color);
if (ImGui::Button("Test Window")) show_test_window ^= 1;
if (ImGui::Button("Another Window")) show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f/ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
}
// 2. Show another simple window, this time using an explicit Begin/End pair
if (show_another_window)
{
ImGui::SetNextWindowSize(ImVec2(200, 100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello");
ImGui::End();
}
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
if (show_test_window)
{
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
ImGui::ShowTestWindow(&show_test_window);
}
// Rendering
al_clear_to_color(al_map_rgba_f(clear_color.x, clear_color.y, clear_color.z, clear_color.w));
ImGui::Render();
al_flip_display();
}
// Cleanup
ImGui_ImplA5_Shutdown();
al_destroy_event_queue(queue);
al_destroy_display(display);
return 0;
}

View File

@ -140,10 +140,13 @@
<ItemGroup>
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="imgui_impl_dx11.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="imgui_impl_dx11.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>

View File

@ -18,6 +18,9 @@
<ClInclude Include="imgui_impl_dx11.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">
@ -29,5 +32,11 @@
<ClCompile Include="imgui_impl_dx11.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -18,6 +18,7 @@ static HWND g_hWnd = 0;
static ID3D11Device* g_pd3dDevice = NULL;
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
static ID3D11Buffer* g_pVB = NULL;
static ID3D11Buffer* g_pIB = NULL;
static ID3D10Blob * g_pVertexShaderBlob = NULL;
static ID3D11VertexShader* g_pVertexShader = NULL;
static ID3D11InputLayout* g_pInputLayout = NULL;
@ -28,7 +29,7 @@ static ID3D11SamplerState* g_pFontSampler = NULL;
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
static ID3D11RasterizerState* g_pRasterizerState = NULL;
static ID3D11BlendState* g_pBlendState = NULL;
static int VERTEX_BUFFER_SIZE = 30000; // TODO: Make vertex buffer smaller and grow dynamically as needed.
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
struct VERTEX_CONSTANT_BUFFER
{
@ -38,20 +39,55 @@ struct VERTEX_CONSTANT_BUFFER
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
static void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
{
// Copy and convert all vertices into a single contiguous buffer
D3D11_MAPPED_SUBRESOURCE mappedResource;
if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK)
return;
ImDrawVert* vtx_dst = (ImDrawVert*)mappedResource.pData;
for (int n = 0; n < cmd_lists_count; n++)
// Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{
const ImDrawList* cmd_list = cmd_lists[n];
memcpy(vtx_dst, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert));
vtx_dst += cmd_list->vtx_buffer.size();
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
return;
}
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
{
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D11_BUFFER_DESC bufferDesc;
memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0)
return;
}
// Copy and convert all vertices into a single contiguous buffer
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
return;
if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
vtx_dst += cmd_list->VtxBuffer.size();
idx_dst += cmd_list->IdxBuffer.size();
}
g_pd3dDeviceContext->Unmap(g_pVB, 0);
g_pd3dDeviceContext->Unmap(g_pIB, 0);
// Setup orthographic projection matrix into our constant buffer
{
@ -93,6 +129,7 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
unsigned int offset = 0;
g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout);
g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, DXGI_FORMAT_R16_UINT, 0);
g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0);
g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
@ -106,25 +143,27 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
// Render command lists
int vtx_offset = 0;
for (int n = 0; n < cmd_lists_count; n++)
int idx_offset = 0;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = cmd_lists[n];
for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
if (pcmd->user_callback)
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
pcmd->user_callback(cmd_list, pcmd);
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
const D3D11_RECT r = { (LONG)pcmd->clip_rect.x, (LONG)pcmd->clip_rect.y, (LONG)pcmd->clip_rect.z, (LONG)pcmd->clip_rect.w };
g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->texture_id);
const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId);
g_pd3dDeviceContext->RSSetScissorRects(1, &r);
g_pd3dDeviceContext->Draw(pcmd->vtx_count, vtx_offset);
g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
}
vtx_offset += pcmd->vtx_count;
idx_offset += pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.size();
}
// Restore modified state
@ -133,7 +172,7 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0);
}
LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGuiIO& io = ImGui::GetIO();
switch (msg)
@ -150,6 +189,12 @@ LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lPar
case WM_RBUTTONUP:
io.MouseDown[1] = false;
return true;
case WM_MBUTTONDOWN:
io.MouseDown[2] = true;
return true;
case WM_MBUTTONUP:
io.MouseDown[2] = false;
return true;
case WM_MOUSEWHEEL:
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return true;
@ -242,13 +287,13 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
{
if (!g_pd3dDevice)
return false;
if (g_pVB)
if (g_pFontSampler)
ImGui_ImplDX11_InvalidateDeviceObjects();
// Create the vertex shader
{
static const char* vertexShader =
"cbuffer vertexBuffer : register(c0) \
"cbuffer vertexBuffer : register(b0) \
{\
float4x4 ProjectionMatrix; \
};\
@ -355,19 +400,6 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
}
// Create the vertex buffer
{
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = VERTEX_BUFFER_SIZE * sizeof(ImDrawVert);
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
return false;
}
ImGui_ImplDX11_CreateFontsTexture();
return true;
@ -379,7 +411,8 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
if (g_pFontTextureView) { g_pFontTextureView->Release(); ImGui::GetIO().Fonts->TexID = 0; }
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = 0; }
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
@ -409,6 +442,8 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;

View File

@ -4,17 +4,17 @@
struct ID3D11Device;
struct ID3D11DeviceContext;
bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context);
void ImGui_ImplDX11_Shutdown();
void ImGui_ImplDX11_NewFrame();
IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context);
IMGUI_API void ImGui_ImplDX11_Shutdown();
IMGUI_API void ImGui_ImplDX11_NewFrame();
// Use if you want to reset your rendering device without losing ImGui state.
void ImGui_ImplDX11_InvalidateDeviceObjects();
bool ImGui_ImplDX11_CreateDeviceObjects();
IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects();
IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects();
// Handler for Win32 messages, update mouse/keyboard data.
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
/*
extern LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
*/

View File

@ -149,13 +149,22 @@ int main(int, char**)
// Setup ImGui binding
ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext);
// Load Fonts
// (see extra_fonts/README.txt for more details)
//ImGuiIO& io = ImGui::GetIO();
//ImFont* my_font0 = io.Fonts->AddFontDefault();
//ImFont* my_font1 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/Karla-Regular.ttf", 16.0f);
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
bool show_test_window = true;
bool show_another_window = false;

View File

@ -139,12 +139,15 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="imgui_impl_dx9.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="imgui_impl_dx9.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -19,6 +19,12 @@
<ClCompile Include="imgui_impl_dx9.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h">
@ -30,5 +36,8 @@
<ClInclude Include="imgui_impl_dx9.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -15,7 +15,9 @@ static INT64 g_Time = 0;
static INT64 g_TicksPerSecond = 0;
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
static int VERTEX_BUFFER_SIZE = 30000; // TODO: Make vertex buffer smaller and grow dynamically as needed.
static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
static LPDIRECT3DTEXTURE9 g_FontTexture = NULL;
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
struct CUSTOMVERTEX
{
@ -28,23 +30,36 @@ struct CUSTOMVERTEX
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
static void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
{
size_t total_vtx_count = 0;
for (int n = 0; n < cmd_lists_count; n++)
total_vtx_count += cmd_lists[n]->vtx_buffer.size();
if (total_vtx_count == 0)
return;
// Create and grow buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
return;
}
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
{
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0)
return;
}
// Copy and convert all vertices into a single contiguous buffer
CUSTOMVERTEX* vtx_dst;
if (g_pVB->Lock(0, (UINT)total_vtx_count, (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
ImDrawIdx* idx_dst;
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
return;
for (int n = 0; n < cmd_lists_count; n++)
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
return;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = cmd_lists[n];
const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0];
for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++)
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_src = &cmd_list->VtxBuffer[0];
for (int i = 0; i < cmd_list->VtxBuffer.size(); i++)
{
vtx_dst->pos.x = vtx_src->pos.x;
vtx_dst->pos.y = vtx_src->pos.y;
@ -55,9 +70,13 @@ static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_
vtx_dst++;
vtx_src++;
}
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
idx_dst += cmd_list->IdxBuffer.size();
}
g_pVB->Unlock();
g_pIB->Unlock();
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetIndices( g_pIB );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing
@ -83,36 +102,38 @@ static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_
// Setup orthographic projection matrix
D3DXMATRIXA16 mat;
D3DXMatrixIdentity(&mat);
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat);
D3DXMatrixOrthoOffCenterLH(&mat, 0.5f, ImGui::GetIO().DisplaySize.x+0.5f, ImGui::GetIO().DisplaySize.y+0.5f, 0.5f, -1.0f, +1.0f);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat);
g_pd3dDevice->SetTransform( D3DTS_WORLD, &mat );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &mat );
D3DXMatrixOrthoOffCenterLH( &mat, 0.5f, ImGui::GetIO().DisplaySize.x+0.5f, ImGui::GetIO().DisplaySize.y+0.5f, 0.5f, -1.0f, +1.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mat );
// Render command lists
int vtx_offset = 0;
for (int n = 0; n < cmd_lists_count; n++)
int idx_offset = 0;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = cmd_lists[n];
for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
if (pcmd->user_callback)
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
pcmd->user_callback(cmd_list, pcmd);
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
const RECT r = { (LONG)pcmd->clip_rect.x, (LONG)pcmd->clip_rect.y, (LONG)pcmd->clip_rect.z, (LONG)pcmd->clip_rect.w };
g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->texture_id );
g_pd3dDevice->SetScissorRect(&r);
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, vtx_offset, pcmd->vtx_count/3);
const RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->TextureId );
g_pd3dDevice->SetScissorRect( &r );
g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.size(), idx_offset, pcmd->ElemCount/3 );
}
vtx_offset += pcmd->vtx_count;
idx_offset += pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.size();
}
}
LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGuiIO& io = ImGui::GetIO();
switch (msg)
@ -129,6 +150,12 @@ LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lPara
case WM_RBUTTONUP:
io.MouseDown[1] = false;
return true;
case WM_MBUTTONDOWN:
io.MouseDown[2] = true;
return true;
case WM_MBUTTONUP:
io.MouseDown[2] = false;
return true;
case WM_MOUSEWHEEL:
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return true;
@ -169,6 +196,8 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
@ -196,7 +225,7 @@ void ImGui_ImplDX9_Shutdown()
g_hWnd = 0;
}
static void ImGui_ImplDX9_CreateFontsTexture()
static bool ImGui_ImplDX9_CreateFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
@ -206,39 +235,31 @@ static void ImGui_ImplDX9_CreateFontsTexture()
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height, &bytes_per_pixel);
// Create DX9 texture
LPDIRECT3DTEXTURE9 pTexture = NULL;
if (D3DXCreateTexture(g_pd3dDevice, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8, D3DPOOL_DEFAULT, &pTexture) < 0)
{
IM_ASSERT(0);
return;
}
g_FontTexture = NULL;
if (D3DXCreateTexture(g_pd3dDevice, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8, D3DPOOL_DEFAULT, &g_FontTexture) < 0)
return false;
D3DLOCKED_RECT tex_locked_rect;
if (pTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
{
IM_ASSERT(0);
return;
}
if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
return false;
for (int y = 0; y < height; y++)
memcpy((unsigned char *)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel));
pTexture->UnlockRect(0);
g_FontTexture->UnlockRect(0);
// Store our identifier
io.Fonts->TexID = (void *)pTexture;
io.Fonts->TexID = (void *)g_FontTexture;
// Cleanup (don't clear the input data if you want to append new fonts later)
io.Fonts->ClearInputData();
io.Fonts->ClearTexData();
return true;
}
bool ImGui_ImplDX9_CreateDeviceObjects()
{
if (!g_pd3dDevice)
return false;
if (g_pd3dDevice->CreateVertexBuffer(VERTEX_BUFFER_SIZE * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
if (!ImGui_ImplDX9_CreateFontsTexture())
return false;
ImGui_ImplDX9_CreateFontsTexture();
return true;
}
@ -251,6 +272,11 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
g_pVB->Release();
g_pVB = NULL;
}
if (g_pIB)
{
g_pIB->Release();
g_pIB = NULL;
}
if (LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)ImGui::GetIO().Fonts->TexID)
{
tex->Release();
@ -260,7 +286,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
void ImGui_ImplDX9_NewFrame()
{
if (!g_pVB)
if (!g_FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();
ImGuiIO& io = ImGui::GetIO();

View File

@ -3,17 +3,17 @@
struct IDirect3DDevice9;
bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device);
void ImGui_ImplDX9_Shutdown();
void ImGui_ImplDX9_NewFrame();
IMGUI_API bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device);
IMGUI_API void ImGui_ImplDX9_Shutdown();
IMGUI_API void ImGui_ImplDX9_NewFrame();
// Use if you want to reset your rendering device without losing ImGui state.
void ImGui_ImplDX9_InvalidateDeviceObjects();
bool ImGui_ImplDX9_CreateDeviceObjects();
IMGUI_API void ImGui_ImplDX9_InvalidateDeviceObjects();
IMGUI_API bool ImGui_ImplDX9_CreateDeviceObjects();
// Handler for Win32 messages, update mouse/keyboard data.
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
/*
extern LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
*/

View File

@ -73,16 +73,22 @@ int main(int, char**)
// Setup ImGui binding
ImGui_ImplDX9_Init(hwnd, g_pd3dDevice);
//ImGuiIO& io = ImGui::GetIO();
//ImFont* my_font0 = io.Fonts->AddFontDefault();
//ImFont* my_font1 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/Karla-Regular.ttf", 16.0f);
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
// Load Fonts
// (see extra_fonts/README.txt for more details)
//ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
bool show_test_window = true;
bool show_another_window = false;
@ -91,6 +97,8 @@ int main(int, char**)
// Main loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))

3
examples/ios_example/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.DS_Store
imguiex.xcodeproj/project.xcworkspace/
imguiex.xcodeproj/xcuserdata/

View File

@ -0,0 +1,35 @@
# iOS example
----
## Introduction
This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/).
Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active.
## How to Use
----
0. In Synergy, go to Preferences, and uncheck "Use SSL encryption"
0. Run the example app.
0. Tap the "servername" button in the corner
0. Enter the name or the IP of your synergy host
0. If you had previously connected to a server, you may need to kill and re-start the app.
----
## Notes and TODOs
Things that would be nice but I didn't get around to doing:
* iOS software keyboard not supported for text inputs
* iOS hardware (bluetooth) keyboards not supported
* Graceful disconnect/reconnect from uSynergy.
* Copy/Paste not well-supported
----
## C++ on iOS
ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension.
Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer.
In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly.

View File

@ -0,0 +1,373 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; };
197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; };
6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; };
6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; };
6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; };
6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; };
6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; };
6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; };
6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; };
6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; };
6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; };
6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; };
6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; };
6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; };
6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; };
6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = "<group>"; };
197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = "<group>"; };
6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = "<group>"; };
6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = "<group>"; };
6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; };
6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = "<group>"; };
6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = "<group>"; };
6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = "<group>"; };
6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = "<group>"; };
6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = "<group>"; };
6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = "<group>"; };
6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = "<group>"; };
6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = "<group>"; };
6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = "<group>"; };
6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = "<group>"; };
6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = "<group>"; };
6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
6D2FC5511B2E632000C130BA /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */,
6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
6D1E39141B35EEF10017B40F /* usynergy */ = {
isa = PBXGroup;
children = (
6D1E39151B35EEF10017B40F /* uSynergy.c */,
6D1E39161B35EEF10017B40F /* uSynergy.h */,
);
name = usynergy;
path = ../libs/usynergy;
sourceTree = "<group>";
};
6D2FC54B1B2E632000C130BA = {
isa = PBXGroup;
children = (
6D1E39141B35EEF10017B40F /* usynergy */,
6D2FC5841B2E648D00C130BA /* imgui */,
6D2FC5561B2E632000C130BA /* imguiex */,
6D2FC5551B2E632000C130BA /* Products */,
);
sourceTree = "<group>";
};
6D2FC5551B2E632000C130BA /* Products */ = {
isa = PBXGroup;
children = (
6D2FC5541B2E632000C130BA /* imguiex.app */,
);
name = Products;
sourceTree = "<group>";
};
6D2FC5561B2E632000C130BA /* imguiex */ = {
isa = PBXGroup;
children = (
6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */,
6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */,
197E1E881B89443600E3FE6A /* imgui_demo.cpp */,
6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */,
6D2FC58A1B2E6A5500C130BA /* debug_hud.h */,
6D2FC55B1B2E632000C130BA /* AppDelegate.h */,
6D2FC55C1B2E632000C130BA /* AppDelegate.m */,
6D2FC55E1B2E632000C130BA /* Shader.fsh */,
6D2FC5601B2E632000C130BA /* Shader.vsh */,
6D2FC5621B2E632000C130BA /* GameViewController.h */,
6D2FC5631B2E632000C130BA /* GameViewController.m */,
6D2FC5651B2E632000C130BA /* Main.storyboard */,
6D2FC5681B2E632000C130BA /* Images.xcassets */,
6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */,
6D2FC5571B2E632000C130BA /* Supporting Files */,
);
path = imguiex;
sourceTree = "<group>";
};
6D2FC5571B2E632000C130BA /* Supporting Files */ = {
isa = PBXGroup;
children = (
6D2FC5921B30774900C130BA /* SystemConfiguration.framework */,
6D2FC5901B30773F00C130BA /* CFNetwork.framework */,
6D2FC5581B2E632000C130BA /* Info.plist */,
6D2FC5591B2E632000C130BA /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
6D2FC5841B2E648D00C130BA /* imgui */ = {
isa = PBXGroup;
children = (
6D2FC5851B2E64AB00C130BA /* imconfig.h */,
197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */,
6D2FC5861B2E64AB00C130BA /* imgui.cpp */,
6D2FC5871B2E64AB00C130BA /* imgui.h */,
);
name = imgui;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
6D2FC5531B2E632000C130BA /* imguiex */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */;
buildPhases = (
6D2FC5501B2E632000C130BA /* Sources */,
6D2FC5511B2E632000C130BA /* Frameworks */,
6D2FC5521B2E632000C130BA /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = imguiex;
productName = imguiex;
productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
6D2FC54C1B2E632000C130BA /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0630;
ORGANIZATIONNAME = "Joel Davis";
TargetAttributes = {
6D2FC5531B2E632000C130BA = {
CreatedOnToolsVersion = 6.3.2;
};
};
};
buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 6D2FC54B1B2E632000C130BA;
productRefGroup = 6D2FC5551B2E632000C130BA /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
6D2FC5531B2E632000C130BA /* imguiex */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
6D2FC5521B2E632000C130BA /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */,
6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */,
6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */,
6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */,
6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
6D2FC5501B2E632000C130BA /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */,
6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */,
6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */,
6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */,
6D2FC55A1B2E632000C130BA /* main.m in Sources */,
6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */,
6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */,
197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */,
197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
6D2FC5651B2E632000C130BA /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
6D2FC5661B2E632000C130BA /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
6D2FC56B1B2E632000C130BA /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
6D2FC5791B2E632000C130BA /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6D2FC57A1B2E632000C130BA /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
6D2FC57C1B2E632000C130BA /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = imguiex/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
6D2FC57D1B2E632000C130BA /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = imguiex/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6D2FC5791B2E632000C130BA /* Debug */,
6D2FC57A1B2E632000C130BA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6D2FC57C1B2E632000C130BA /* Debug */,
6D2FC57D1B2E632000C130BA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 6D2FC54C1B2E632000C130BA /* Project object */;
}

View File

@ -0,0 +1,13 @@
//
// AppDelegate.h
// imguiex
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@ -0,0 +1,41 @@
//
// AppDelegate.m
// imguiex
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="imguiex" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BV1-FR-VrT">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
<!--Game View Controller-->
<scene sceneID="tXr-a1-R10">
<objects>
<viewController id="BV1-FR-VrT" customClass="GameViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="8aa-yV-Osq"/>
<viewControllerLayoutGuide type="bottom" id="qHh-Mt-9TT"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="3se-qz-xqx" customClass="GLKView">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="piS-r7-VWh">
<rect key="frame" x="16" y="550" width="136" height="30"/>
<state key="normal" title="servername">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="onServernameTapped:" destination="BV1-FR-VrT" eventType="touchUpInside" id="9sO-yv-0be"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="qHh-Mt-9TT" firstAttribute="top" secondItem="piS-r7-VWh" secondAttribute="bottom" constant="20" id="JxW-fj-qni"/>
<constraint firstItem="piS-r7-VWh" firstAttribute="leading" secondItem="3se-qz-xqx" secondAttribute="leadingMargin" constant="20" id="w5q-gx-tJj"/>
</constraints>
</view>
<connections>
<outlet property="btnServername" destination="piS-r7-VWh" id="9iV-ef-l6M"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="SZV-WD-TEh" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,12 @@
//
// GameViewController.h
// imguiex
// This is the OpenGL Example template from XCode, modified to support ImGui
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
@interface GameViewController : GLKViewController
@end

View File

@ -0,0 +1,481 @@
//
// GameViewController.m
// imguiex
//
#import "GameViewController.h"
#import <OpenGLES/ES2/glext.h>
#import "imgui_impl_ios.h"
#import "debug_hud.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#define SERVERNAME_KEY @"ServerName"
#define SERVERNAME_ALERT_TAG (10)
// Uniform index.
enum
{
UNIFORM_MODELVIEWPROJECTION_MATRIX,
UNIFORM_NORMAL_MATRIX,
UNIFORM_DIFFUSE_COLOR,
NUM_UNIFORMS
};
GLint uniforms[NUM_UNIFORMS];
// Attribute index.
enum
{
ATTRIB_VERTEX,
ATTRIB_NORMAL,
NUM_ATTRIBUTES
};
GLfloat gCubeVertexData[216] =
{
// Data layout for each line below is:
// positionX, positionY, positionZ, normalX, normalY, normalZ,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f
};
@interface GameViewController () <UIAlertViewDelegate>
{
GLuint _program;
GLKMatrix4 _modelViewProjectionMatrix;
GLKMatrix3 _normalMatrix;
float _rotation;
GLuint _vertexArray;
GLuint _vertexBuffer;
DebugHUD _hud;
}
@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;
@property (strong, nonatomic) ImGuiHelper *imgui;
@property (weak, nonatomic) IBOutlet UIButton *btnServername;
@property (strong, nonatomic) NSString *serverName;
- (IBAction)onServernameTapped:(id)sender;
- (void)setupGL;
- (void)tearDownGL;
- (BOOL)loadShaders;
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file;
- (BOOL)linkProgram:(GLuint)prog;
- (BOOL)validateProgram:(GLuint)prog;
@end
@implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!self.context) {
NSLog(@"Failed to create ES context");
}
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self setupGL];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ];
self.imgui = [[ImGuiHelper alloc] initWithView:self.view ];
if (self.serverName)
{
[self.btnServername setTitle:self.serverName forState:UIControlStateNormal];
[self.imgui connectServer: self.serverName ];
}
DebugHUD_InitDefaults( &_hud );
}
- (void)dealloc
{
[self tearDownGL];
if ([EAGLContext currentContext] == self.context) {
[EAGLContext setCurrentContext:nil];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if ([self isViewLoaded] && ([[self view] window] == nil)) {
self.view = nil;
[self tearDownGL];
if ([EAGLContext currentContext] == self.context) {
[EAGLContext setCurrentContext:nil];
}
self.context = nil;
}
// Dispose of any resources that can be recreated.
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (IBAction)onServernameTapped:(id)sender
{
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG))
{
// This is really janky. I usually just hardcode the servername since I'm building it anyway.
// If you want to properly handle updating the server, you'll want to tear down and recreate
// the usynergy stuff in connectServer
BOOL serverNameWasSet = self.serverName.length > 0;
NSString *serverName = [[alertView textFieldAtIndex:0] text];
if ([serverName length] > 0) {
self.serverName = serverName;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:serverName forKey:SERVERNAME_KEY ];
[userDefaults synchronize];
[self.btnServername setTitle:self.serverName forState:UIControlStateNormal];
// If we hadn't previously connected, try now
if (!serverNameWasSet) {
[self.imgui connectServer:self.serverName];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated"
message:@"Restart the app to connect the server"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
}
}
}
}
- (void)setupGL
{
[EAGLContext setCurrentContext:self.context];
[self loadShaders];
self.effect = [[GLKBaseEffect alloc] init];
self.effect.light0.enabled = GL_TRUE;
self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f);
glEnable(GL_DEPTH_TEST);
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindVertexArrayOES(0);
}
- (void)tearDownGL
{
[EAGLContext setCurrentContext:self.context];
glDeleteBuffers(1, &_vertexBuffer);
glDeleteVertexArraysOES(1, &_vertexArray);
self.effect = nil;
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
}
#pragma mark - GLKView and GLKViewController delegate methods
- (void)update
{
float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
self.effect.transform.projectionMatrix = projectionMatrix;
GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);
// Compute the model view matrix for the object rendered with GLKit
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
self.effect.transform.modelviewMatrix = modelViewMatrix;
// Compute the model view matrix for the object rendered with ES2
modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
_rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0));
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray);
// Render the object with GLKit
[self.effect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 36);
// Render the object again with ES2
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] );
glDrawArrays(GL_TRIANGLES, 0, 36);
[self.imgui newFrame];
// Now do our ImGUI UI
DebugHUD_DoInterface( &_hud );
self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f);
// Now render Imgui
[self.imgui render];
}
#pragma mark - OpenGL ES 2 shader compilation
- (BOOL)loadShaders
{
GLuint vertShader, fragShader;
NSString *vertShaderPathname, *fragShaderPathname;
// Create shader program.
_program = glCreateProgram();
// Create and compile vertex shader.
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
NSLog(@"Failed to compile vertex shader");
return NO;
}
// Create and compile fragment shader.
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
NSLog(@"Failed to compile fragment shader");
return NO;
}
// Attach vertex shader to program.
glAttachShader(_program, vertShader);
// Attach fragment shader to program.
glAttachShader(_program, fragShader);
// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(_program, GLKVertexAttribPosition, "position");
glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");
// Link program.
if (![self linkProgram:_program]) {
NSLog(@"Failed to link program: %d", _program);
if (vertShader) {
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader) {
glDeleteShader(fragShader);
fragShader = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
return NO;
}
// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");
uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor");
// Release vertex and fragment shaders.
if (vertShader) {
glDetachShader(_program, vertShader);
glDeleteShader(vertShader);
}
if (fragShader) {
glDetachShader(_program, fragShader);
glDeleteShader(fragShader);
}
return YES;
}
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
GLint status;
const GLchar *source;
source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
if (!source) {
NSLog(@"Failed to load vertex shader");
return NO;
}
*shader = glCreateShader(type);
glShaderSource(*shader, 1, &source, NULL);
glCompileShader(*shader);
#if defined(DEBUG)
GLint logLength;
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(*shader, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
}
#endif
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (status == 0) {
glDeleteShader(*shader);
return NO;
}
return YES;
}
- (BOOL)linkProgram:(GLuint)prog
{
GLint status;
glLinkProgram(prog);
#if defined(DEBUG)
GLint logLength;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program link log:\n%s", log);
free(log);
}
#endif
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status == 0) {
return NO;
}
return YES;
}
- (BOOL)validateProgram:(GLuint)prog
{
GLint logLength, status;
glValidateProgram(prog);
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
if (status == 0) {
return NO;
}
return YES;
}
@end

View File

@ -0,0 +1,72 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "icon_imgui_60@2x~iphone.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "icon_imgui_60@3x~iphone.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "icon_imgui_76~ipad.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "icon_imgui_76@2x~ipad.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.imgui.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,10 @@
//
// Shader.fsh
// imguiex
varying lowp vec4 colorVarying;
void main()
{
gl_FragColor = colorVarying;
}

View File

@ -0,0 +1,25 @@
//
// Shader.vsh
// imguiex
attribute vec4 position;
attribute vec3 normal;
varying lowp vec4 colorVarying;
uniform vec3 diffuseColor;
uniform mat4 modelViewProjectionMatrix;
uniform mat3 normalMatrix;
void main()
{
vec3 eyeNormal = normalize(normalMatrix * normal);
vec3 lightPosition = vec3(0.0, 0.0, 1.0);
float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition)));
vec3 colorLit = diffuseColor * nDotVP;
colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 );
gl_Position = modelViewProjectionMatrix * position;
}

View File

@ -0,0 +1,45 @@
//
// debug_hud.cpp
// imguiex
#include <stdio.h>
#include "debug_hud.h"
#include "imgui.h"
void DebugHUD_InitDefaults( DebugHUD *hud )
{
hud->show_test_window = true;
hud->show_example_window = true;
hud->rotation_speed = 15.0f;
hud->cubeColor1[0] = 0.4f;
hud->cubeColor1[1] = 0.4f;
hud->cubeColor1[2] = 1.0f;
hud->cubeColor1[3] = 1.0f;
hud->cubeColor2[0] = 1.0f;
hud->cubeColor2[1] = 0.4f;
hud->cubeColor2[2] = 0.4f;
hud->cubeColor2[3] = 1.0f;
}
void DebugHUD_DoInterface( DebugHUD *hud )
{
if (hud->show_test_window)
{
ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver );
ImGui::ShowTestWindow( &hud->show_test_window );
}
if (hud->show_example_window)
{
ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver );
ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver );
ImGui::Begin("Another Window", &hud->show_example_window);
ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1);
ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2);
ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f);
ImGui::End();
}
}

View File

@ -0,0 +1,25 @@
//
// debug_hud.h
// imguiex
#pragma once
typedef struct DebugHUD
{
bool show_test_window;
bool show_example_window;
float rotation_speed;
float cubeColor1[4];
float cubeColor2[4];
} DebugHUD;
#if __cplusplus
extern "C" {
#endif
void DebugHUD_InitDefaults( DebugHUD *hud );
void DebugHUD_DoInterface( DebugHUD *hud );
#if __cplusplus
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,22 @@
//
// imgui_impl_ios.h
// imguiex
//
// Joel Davis (joeld42@gmail.com)
//
#pragma once
#include <Foundation/Foundation.h>
#include <UIKit/UIKit.h>
@interface ImGuiHelper : NSObject
- (id) initWithView: (UIView *)view;
- (void)connectServer: (NSString*)serverName;
- (void)render;
- (void)newFrame;
@end

View File

@ -0,0 +1,801 @@
//
// imgui_impl_ios.cpp
// imguiex
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "imgui_impl_ios.h"
#include "imgui.h"
#include "uSynergy.h"
// From Carbon HIToolbox/Events.h
// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247
enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_S = 0x01,
kVK_ANSI_D = 0x02,
kVK_ANSI_F = 0x03,
kVK_ANSI_H = 0x04,
kVK_ANSI_G = 0x05,
kVK_ANSI_Z = 0x06,
kVK_ANSI_X = 0x07,
kVK_ANSI_C = 0x08,
kVK_ANSI_V = 0x09,
kVK_ANSI_B = 0x0B,
kVK_ANSI_Q = 0x0C,
kVK_ANSI_W = 0x0D,
kVK_ANSI_E = 0x0E,
kVK_ANSI_R = 0x0F,
kVK_ANSI_Y = 0x10,
kVK_ANSI_T = 0x11,
kVK_ANSI_1 = 0x12,
kVK_ANSI_2 = 0x13,
kVK_ANSI_3 = 0x14,
kVK_ANSI_4 = 0x15,
kVK_ANSI_6 = 0x16,
kVK_ANSI_5 = 0x17,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_9 = 0x19,
kVK_ANSI_7 = 0x1A,
kVK_ANSI_Minus = 0x1B,
kVK_ANSI_8 = 0x1C,
kVK_ANSI_0 = 0x1D,
kVK_ANSI_RightBracket = 0x1E,
kVK_ANSI_O = 0x1F,
kVK_ANSI_U = 0x20,
kVK_ANSI_LeftBracket = 0x21,
kVK_ANSI_I = 0x22,
kVK_ANSI_P = 0x23,
kVK_ANSI_L = 0x25,
kVK_ANSI_J = 0x26,
kVK_ANSI_Quote = 0x27,
kVK_ANSI_K = 0x28,
kVK_ANSI_Semicolon = 0x29,
kVK_ANSI_Backslash = 0x2A,
kVK_ANSI_Comma = 0x2B,
kVK_ANSI_Slash = 0x2C,
kVK_ANSI_N = 0x2D,
kVK_ANSI_M = 0x2E,
kVK_ANSI_Period = 0x2F,
kVK_ANSI_Grave = 0x32,
kVK_ANSI_KeypadDecimal = 0x41,
kVK_ANSI_KeypadMultiply = 0x43,
kVK_ANSI_KeypadPlus = 0x45,
kVK_ANSI_KeypadClear = 0x47,
kVK_ANSI_KeypadDivide = 0x4B,
kVK_ANSI_KeypadEnter = 0x4C,
kVK_ANSI_KeypadMinus = 0x4E,
kVK_ANSI_KeypadEquals = 0x51,
kVK_ANSI_Keypad0 = 0x52,
kVK_ANSI_Keypad1 = 0x53,
kVK_ANSI_Keypad2 = 0x54,
kVK_ANSI_Keypad3 = 0x55,
kVK_ANSI_Keypad4 = 0x56,
kVK_ANSI_Keypad5 = 0x57,
kVK_ANSI_Keypad6 = 0x58,
kVK_ANSI_Keypad7 = 0x59,
kVK_ANSI_Keypad8 = 0x5B,
kVK_ANSI_Keypad9 = 0x5C
};
/* keycodes for keys that are independent of keyboard layout*/
enum {
kVK_Return = 0x24,
kVK_Tab = 0x30,
kVK_Space = 0x31,
kVK_Delete = 0x33,
kVK_Escape = 0x35,
kVK_Command = 0x37,
kVK_Shift = 0x38,
kVK_CapsLock = 0x39,
kVK_Option = 0x3A,
kVK_Control = 0x3B,
kVK_RightShift = 0x3C,
kVK_RightOption = 0x3D,
kVK_RightControl = 0x3E,
kVK_Function = 0x3F,
kVK_F17 = 0x40,
kVK_VolumeUp = 0x48,
kVK_VolumeDown = 0x49,
kVK_Mute = 0x4A,
kVK_F18 = 0x4F,
kVK_F19 = 0x50,
kVK_F20 = 0x5A,
kVK_F5 = 0x60,
kVK_F6 = 0x61,
kVK_F7 = 0x62,
kVK_F3 = 0x63,
kVK_F8 = 0x64,
kVK_F9 = 0x65,
kVK_F11 = 0x67,
kVK_F13 = 0x69,
kVK_F16 = 0x6A,
kVK_F14 = 0x6B,
kVK_F10 = 0x6D,
kVK_F12 = 0x6F,
kVK_F15 = 0x71,
kVK_Help = 0x72,
kVK_Home = 0x73,
kVK_PageUp = 0x74,
kVK_ForwardDelete = 0x75,
kVK_F4 = 0x76,
kVK_End = 0x77,
kVK_F2 = 0x78,
kVK_PageDown = 0x79,
kVK_F1 = 0x7A,
kVK_LeftArrow = 0x7B,
kVK_RightArrow = 0x7C,
kVK_DownArrow = 0x7D,
kVK_UpArrow = 0x7E
};
static char g_keycodeCharUnshifted[256] = {};
static char g_keycodeCharShifted[256] = {};
//static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false };
static float g_mouseWheelX = 0.0f;
static float g_mouseWheelY = 0.0f;
static GLuint g_FontTexture = 0;
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
static size_t g_VboSize = 0;
static unsigned int g_VboHandle = 0, g_VaoHandle = 0;
static float g_displayScale;
static int usynergy_sockfd;
static bool g_synergyPtrActive = false;
static uint16_t g_mousePosX = 0;
static uint16_t g_mousePosY = 0;
static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data);
bool ImGui_ImplIOS_CreateDeviceObjects();
static NSString *g_serverName;
uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie)
{
// NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since
// uSynergy does not support SSL.
NSLog( @"Connect Func!");
struct addrinfo hints, *res;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
// get server address
getaddrinfo([g_serverName UTF8String], "24800", &hints, &res);
if (!res)
{
NSLog( @"Could not find server: %@", g_serverName );
return USYNERGY_FALSE;
}
// make a socket:
usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
// connect it to the address and port we passed in to getaddrinfo():
int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen);
if (!ret) {
NSLog( @"Connect suceeded...");
} else {
NSLog( @"Connect failed, %d", ret );
}
return USYNERGY_TRUE;
}
uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length)
{
// NSLog( @"Send Func" );
send( usynergy_sockfd, buffer, length, 0 );
return USYNERGY_TRUE;
}
uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength)
{
*outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 );
return USYNERGY_TRUE;
}
void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs)
{
usleep( timeMs * 1000 );
}
uint32_t ImGui_GetTimeFunc()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000);
}
void ImGui_TraceFunc(uSynergyCookie cookie, const char *text)
{
puts(text);
}
void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active)
{
g_synergyPtrActive = active;
// printf( "Synergy: screen activate %s\n", active?"YES":"NO" );
}
void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY,
uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle)
{
// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY );
uSynergyContext *ctx = (uSynergyContext*)cookie;
g_mousePosX = x;
g_mousePosY = y;
g_mouseWheelX = wheelX;
g_mouseWheelY = wheelY;
g_MousePressed[0] = buttonLeft;
g_MousePressed[1] = buttonMiddle;
g_MousePressed[2] = buttonRight;
ctx->m_mouseWheelX = 0;
ctx->m_mouseWheelY = 0;
}
void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key,
uint16_t modifiers, uSynergyBool down, uSynergyBool repeat)
{
int scanCode = key-1;
// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false");
ImGuiIO& io = ImGui::GetIO();
io.KeysDown[key] = down;
io.KeyShift = modifiers & USYNERGY_MODIFIER_SHIFT;
io.KeyCtrl = modifiers & USYNERGY_MODIFIER_CTRL;
io.KeyAlt = modifiers & USYNERGY_MODIFIER_ALT;
// Add this as keyboard input
if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL))
{
// If this key maps to a character input, apply it
int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode];
io.AddInputCharacter((unsigned short)charForKeycode);
}
}
void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY)
{
printf("Synergy: joystick callback TODO\n");
}
void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size)
{
printf("Synergy: clipboard callback TODO\n" );
}
@interface ImGuiHelper ()
{
BOOL _mouseDown;
BOOL _mouseTapped;
CGPoint _touchPos;
uSynergyContext _synergyCtx;
dispatch_queue_t _synergyQueue;
}
@property (nonatomic, weak) UIView *view;
@property (nonatomic, strong) NSString *serverName;
@end
@implementation ImGuiHelper
- (id) initWithView: (UIView *)view
{
self = [super init];
if (self)
{
self.view = view;
[self setupImGuiHooks];
}
return self;
}
- (void)setupKeymaps
{
// The keyboard mapping is a big headache. I tried for a while to find a better way to do this,
// but this was the best I could come up with. There are some device independent API's available
// to convert scan codes to unicode characters, but these are only available on mac and not
// on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do
// this or any way to get the character codes out of usynergy.
g_keycodeCharUnshifted[ kVK_ANSI_A ]='a';
g_keycodeCharUnshifted[ kVK_ANSI_S ]='s';
g_keycodeCharUnshifted[ kVK_ANSI_D ]='d';
g_keycodeCharUnshifted[ kVK_ANSI_F ]='f';
g_keycodeCharUnshifted[ kVK_ANSI_H ]='h';
g_keycodeCharUnshifted[ kVK_ANSI_G ]='g';
g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z';
g_keycodeCharUnshifted[ kVK_ANSI_X ]='x';
g_keycodeCharUnshifted[ kVK_ANSI_C ]='c';
g_keycodeCharUnshifted[ kVK_ANSI_V ]='v';
g_keycodeCharUnshifted[ kVK_ANSI_B ]='b';
g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q';
g_keycodeCharUnshifted[ kVK_ANSI_W ]='w';
g_keycodeCharUnshifted[ kVK_ANSI_E ]='e';
g_keycodeCharUnshifted[ kVK_ANSI_R ]='r';
g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y';
g_keycodeCharUnshifted[ kVK_ANSI_T ]='t';
g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1';
g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2';
g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3';
g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4';
g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6';
g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5';
g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='=';
g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9';
g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7';
g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-';
g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8';
g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0';
g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']';
g_keycodeCharUnshifted[ kVK_ANSI_O ]='o';
g_keycodeCharUnshifted[ kVK_ANSI_U ]='u';
g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='[';
g_keycodeCharUnshifted[ kVK_ANSI_I ]='i';
g_keycodeCharUnshifted[ kVK_ANSI_P ]='p';
g_keycodeCharUnshifted[ kVK_ANSI_L ]='l';
g_keycodeCharUnshifted[ kVK_ANSI_J ]='j';
g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\'';
g_keycodeCharUnshifted[ kVK_ANSI_K ]='k';
g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';';
g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\';
g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=',';
g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/';
g_keycodeCharUnshifted[ kVK_ANSI_N ]='n';
g_keycodeCharUnshifted[ kVK_ANSI_M ]='m';
g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.';
g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`';
g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.';
g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*';
g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+';
g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/';
g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n';
g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-';
g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='=';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8';
g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9';
g_keycodeCharUnshifted[ kVK_Space ]=' ';
g_keycodeCharShifted[ kVK_ANSI_A ]='A';
g_keycodeCharShifted[ kVK_ANSI_S ]='S';
g_keycodeCharShifted[ kVK_ANSI_D ]='D';
g_keycodeCharShifted[ kVK_ANSI_F ]='F';
g_keycodeCharShifted[ kVK_ANSI_H ]='H';
g_keycodeCharShifted[ kVK_ANSI_G ]='G';
g_keycodeCharShifted[ kVK_ANSI_Z ]='Z';
g_keycodeCharShifted[ kVK_ANSI_X ]='X';
g_keycodeCharShifted[ kVK_ANSI_C ]='C';
g_keycodeCharShifted[ kVK_ANSI_V ]='V';
g_keycodeCharShifted[ kVK_ANSI_B ]='B';
g_keycodeCharShifted[ kVK_ANSI_Q ]='Q';
g_keycodeCharShifted[ kVK_ANSI_W ]='W';
g_keycodeCharShifted[ kVK_ANSI_E ]='E';
g_keycodeCharShifted[ kVK_ANSI_R ]='R';
g_keycodeCharShifted[ kVK_ANSI_Y ]='Y';
g_keycodeCharShifted[ kVK_ANSI_T ]='T';
g_keycodeCharShifted[ kVK_ANSI_1 ]='!';
g_keycodeCharShifted[ kVK_ANSI_2 ]='@';
g_keycodeCharShifted[ kVK_ANSI_3 ]='#';
g_keycodeCharShifted[ kVK_ANSI_4 ]='$';
g_keycodeCharShifted[ kVK_ANSI_6 ]='^';
g_keycodeCharShifted[ kVK_ANSI_5 ]='%';
g_keycodeCharShifted[ kVK_ANSI_Equal ]='+';
g_keycodeCharShifted[ kVK_ANSI_9 ]='(';
g_keycodeCharShifted[ kVK_ANSI_7 ]='&';
g_keycodeCharShifted[ kVK_ANSI_Minus ]='_';
g_keycodeCharShifted[ kVK_ANSI_8 ]='*';
g_keycodeCharShifted[ kVK_ANSI_0 ]=')';
g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}';
g_keycodeCharShifted[ kVK_ANSI_O ]='O';
g_keycodeCharShifted[ kVK_ANSI_U ]='U';
g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{';
g_keycodeCharShifted[ kVK_ANSI_I ]='I';
g_keycodeCharShifted[ kVK_ANSI_P ]='P';
g_keycodeCharShifted[ kVK_ANSI_L ]='L';
g_keycodeCharShifted[ kVK_ANSI_J ]='J';
g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"';
g_keycodeCharShifted[ kVK_ANSI_K ]='K';
g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':';
g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|';
g_keycodeCharShifted[ kVK_ANSI_Comma ]='<';
g_keycodeCharShifted[ kVK_ANSI_Slash ]='?';
g_keycodeCharShifted[ kVK_ANSI_N ]='N';
g_keycodeCharShifted[ kVK_ANSI_M ]='M';
g_keycodeCharShifted[ kVK_ANSI_Period ]='>';
g_keycodeCharShifted[ kVK_ANSI_Grave ]='~';
g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.';
g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*';
g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+';
g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/';
g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n';
g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-';
g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='=';
g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0';
g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1';
g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2';
g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3';
g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4';
g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5';
g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6';
g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7';
g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8';
g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9';
g_keycodeCharShifted[ kVK_Space ]=' ';
}
- (void)setupImGuiHooks
{
ImGuiIO &io = ImGui::GetIO();
[self setupKeymaps];
// Account for retina display for glScissor
g_displayScale = [[UIScreen mainScreen] scale];
ImGuiStyle &style = ImGui::GetStyle();
style.TouchExtraPadding = ImVec2( 4.0, 4.0 );
io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists;
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ];
[self.view addGestureRecognizer:panRecognizer];
UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)];
[self.view addGestureRecognizer:tapRecoginzer];
// Fill out the Synergy key map
// (for some reason synergy scan codes are off by 1)
io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1;
io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1;
io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1;
io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1;
io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1;
io.KeyMap[ImGuiKey_Home] = kVK_Home+1;
io.KeyMap[ImGuiKey_End] = kVK_End+1;
io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1;
io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1;
io.KeyMap[ImGuiKey_Enter] = kVK_Return+1;
io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1;
io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1;
io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1;
io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1;
io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1;
io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1;
io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1;
}
- (void)connectServer: (NSString*)serverName
{
self.serverName = serverName;
g_serverName = serverName;
// Init synergy
NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];
uSynergyInit( &_synergyCtx );
_synergyCtx.m_clientName = strdup( [bundleName UTF8String] );
_synergyCtx.m_clientWidth = self.view.bounds.size.width;
_synergyCtx.m_clientHeight = self.view.bounds.size.height;
_synergyCtx.m_connectFunc = ImGui_ConnectFunc;
_synergyCtx.m_sendFunc = ImGui_SendFunc;
_synergyCtx.m_receiveFunc = ImGui_RecvFunc;
_synergyCtx.m_sleepFunc = ImGui_SleepFunc;
_synergyCtx.m_traceFunc = ImGui_TraceFunc;
_synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc;
_synergyCtx.m_traceFunc = ImGui_TraceFunc;
_synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback;
_synergyCtx.m_mouseCallback = ImGui_MouseCallback;
_synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback;
_synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx;
// Create a background thread for synergy
_synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL );
dispatch_async( _synergyQueue, ^{
while (1) {
uSynergyUpdate( &_synergyCtx );
}
});
}
- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer
{
if ((recognizer.state == UIGestureRecognizerStateBegan) ||
(recognizer.state == UIGestureRecognizerStateChanged))
{
_mouseDown = YES;
_touchPos = [recognizer locationInView:self.view];
}
else
{
_mouseDown = NO;
_touchPos = CGPointMake( -1, -1 );
}
}
- (void)viewDidTap: (UITapGestureRecognizer*)recognizer
{
_touchPos = [recognizer locationInView:self.view];
_mouseTapped = YES;
}
- (void)render
{
ImGui::Render();
}
- (void)newFrame
{
ImGuiIO& io = ImGui::GetIO();
ImGuiStyle &style = ImGui::GetStyle();
if (!g_FontTexture)
{
ImGui_ImplIOS_CreateDeviceObjects();
}
io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height );
io.MouseDrawCursor = g_synergyPtrActive;
if (g_synergyPtrActive)
{
style.TouchExtraPadding = ImVec2( 0.0, 0.0 );
io.MousePos = ImVec2( g_mousePosX, g_mousePosY );
for (int i=0; i < 3; i++)
{
io.MouseDown[i] = g_MousePressed[i];
}
// This is an arbitrary scaling factor that works for me. Not sure what units these
// mousewheel values from synergy are supposed to be in
io.MouseWheel = g_mouseWheelY / 500.0;
}
else
{
// Synergy not active, use touch events
style.TouchExtraPadding = ImVec2( 4.0, 4.0 );
io.MousePos = ImVec2(_touchPos.x, _touchPos.y );
if ((_mouseDown) || (_mouseTapped))
{
io.MouseDown[0] = true;
_mouseTapped = NO;
}
else
{
io.MouseDown[0] = false;
}
}
ImGui::NewFrame();
}
@end
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES
static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data)
{
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
GLint last_program, last_texture;
glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glActiveTexture(GL_TEXTURE0);
// Setup orthographic projection matrix
const float width = ImGui::GetIO().DisplaySize.x;
const float height = ImGui::GetIO().DisplaySize.y;
const float ortho_projection[4][4] =
{
{ 2.0f/width, 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/-height, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f },
};
glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
glBindVertexArray(g_VaoHandle);
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
ImDrawList* cmd_list = draw_data->CmdLists[n];
ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert);
if (g_VboSize < needed_vtx_size)
{
// Grow our buffer if needed
g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW);
}
unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
if (!vtx_data)
continue;
memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
glUnmapBuffer(GL_ARRAY_BUFFER);
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++)
{
if (pcmd->UserCallback)
{
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glScissor((int)(pcmd->ClipRect.x * g_displayScale),
(int)((height - pcmd->ClipRect.w) * g_displayScale),
(int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale),
(int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale));
glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer );
}
idx_buffer += pcmd->ElemCount;
}
}
// Restore modified state
glBindVertexArray(0);
glBindBuffer( GL_ARRAY_BUFFER, 0);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glUseProgram(last_program);
glDisable(GL_SCISSOR_TEST);
glBindTexture(GL_TEXTURE_2D, last_texture);
}
void ImGui_ImplIOS_CreateFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader.
glGenTextures(1, &g_FontTexture);
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
// Cleanup (don't clear the input data if you want to append new fonts later)
io.Fonts->ClearInputData();
io.Fonts->ClearTexData();
}
bool ImGui_ImplIOS_CreateDeviceObjects()
{
const GLchar *vertex_shader =
"uniform mat4 ProjMtx;\n"
"attribute highp vec2 Position;\n"
"attribute highp vec2 UV;\n"
"attribute highp vec4 Color;\n"
"varying vec2 Frag_UV;\n"
"varying vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n";
const GLchar* fragment_shader =
"uniform sampler2D Texture;\n"
"varying highp vec2 Frag_UV;\n"
"varying highp vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n"
"}\n";
g_ShaderHandle = glCreateProgram();
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_VertHandle, 1, &vertex_shader, 0);
glShaderSource(g_FragHandle, 1, &fragment_shader, 0);
glCompileShader(g_VertHandle);
#if defined(DEBUG)
GLint logLength;
glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log);
NSLog(@"VERTEX Shader compile log:\n%s", log);
free(log);
}
#endif
glCompileShader(g_FragHandle);
#if defined(DEBUG)
glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log);
NSLog(@"FRAGMENT Shader compile log:\n%s", log);
free(log);
}
#endif
glAttachShader(g_ShaderHandle, g_VertHandle);
glAttachShader(g_ShaderHandle, g_FragHandle);
glLinkProgram(g_ShaderHandle);
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
glGenBuffers(1, &g_VboHandle);
glGenVertexArrays(1, &g_VaoHandle);
glBindVertexArray(g_VaoHandle);
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glEnableVertexAttribArray(g_AttribLocationPosition);
glEnableVertexAttribArray(g_AttribLocationUV);
glEnableVertexAttribArray(g_AttribLocationColor);
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
#undef OFFSETOF
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ImGui_ImplIOS_CreateFontsTexture();
return true;
}

View File

@ -0,0 +1,13 @@
//
// main.m
// imguiex
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@ -0,0 +1,636 @@
/*
uSynergy client -- Implementation for the embedded Synergy client library
version 1.0.0, July 7th, 2012
Copyright (c) 2012 Alex Evans
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "uSynergy.h"
#include <stdio.h>
#include <string.h>
//---------------------------------------------------------------------------------------------------------------------
// Internal helpers
//---------------------------------------------------------------------------------------------------------------------
/**
@brief Read 16 bit integer in network byte order and convert to native byte order
**/
static int16_t sNetToNative16(const unsigned char *value)
{
#ifdef USYNERGY_LITTLE_ENDIAN
return value[1] | (value[0] << 8);
#else
return value[0] | (value[1] << 8);
#endif
}
/**
@brief Read 32 bit integer in network byte order and convert to native byte order
**/
static int32_t sNetToNative32(const unsigned char *value)
{
#ifdef USYNERGY_LITTLE_ENDIAN
return value[3] | (value[2] << 8) | (value[1] << 16) | (value[0] << 24);
#else
return value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
#endif
}
/**
@brief Trace text to client
**/
static void sTrace(uSynergyContext *context, const char* text)
{
// Don't trace if we don't have a trace function
if (context->m_traceFunc != 0L)
context->m_traceFunc(context->m_cookie, text);
}
/**
@brief Add string to reply packet
**/
static void sAddString(uSynergyContext *context, const char *string)
{
size_t len = strlen(string);
memcpy(context->m_replyCur, string, len);
context->m_replyCur += len;
}
/**
@brief Add uint8 to reply packet
**/
static void sAddUInt8(uSynergyContext *context, uint8_t value)
{
*context->m_replyCur++ = value;
}
/**
@brief Add uint16 to reply packet
**/
static void sAddUInt16(uSynergyContext *context, uint16_t value)
{
uint8_t *reply = context->m_replyCur;
*reply++ = (uint8_t)(value >> 8);
*reply++ = (uint8_t)value;
context->m_replyCur = reply;
}
/**
@brief Add uint32 to reply packet
**/
static void sAddUInt32(uSynergyContext *context, uint32_t value)
{
uint8_t *reply = context->m_replyCur;
*reply++ = (uint8_t)(value >> 24);
*reply++ = (uint8_t)(value >> 16);
*reply++ = (uint8_t)(value >> 8);
*reply++ = (uint8_t)value;
context->m_replyCur = reply;
}
/**
@brief Send reply packet
**/
static uSynergyBool sSendReply(uSynergyContext *context)
{
// Set header size
uint8_t *reply_buf = context->m_replyBuffer;
uint32_t reply_len = (uint32_t)(context->m_replyCur - reply_buf); /* Total size of reply */
uint32_t body_len = reply_len - 4; /* Size of body */
uSynergyBool ret;
reply_buf[0] = (uint8_t)(body_len >> 24);
reply_buf[1] = (uint8_t)(body_len >> 16);
reply_buf[2] = (uint8_t)(body_len >> 8);
reply_buf[3] = (uint8_t)body_len;
// Send reply
ret = context->m_sendFunc(context->m_cookie, context->m_replyBuffer, reply_len);
// Reset reply buffer write pointer
context->m_replyCur = context->m_replyBuffer+4;
return ret;
}
/**
@brief Call mouse callback after a mouse event
**/
static void sSendMouseCallback(uSynergyContext *context)
{
// Skip if no callback is installed
if (context->m_mouseCallback == 0L)
return;
// Send callback
context->m_mouseCallback(context->m_cookie, context->m_mouseX, context->m_mouseY, context->m_mouseWheelX,
context->m_mouseWheelY, context->m_mouseButtonLeft, context->m_mouseButtonRight, context->m_mouseButtonMiddle);
}
/**
@brief Send keyboard callback when a key has been pressed or released
**/
static void sSendKeyboardCallback(uSynergyContext *context, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat)
{
// Skip if no callback is installed
if (context->m_keyboardCallback == 0L)
return;
// Send callback
context->m_keyboardCallback(context->m_cookie, key, modifiers, down, repeat);
}
/**
@brief Send joystick callback
**/
static void sSendJoystickCallback(uSynergyContext *context, uint8_t joyNum)
{
int8_t *sticks;
// Skip if no callback is installed
if (context->m_joystickCallback == 0L)
return;
// Send callback
sticks = context->m_joystickSticks[joyNum];
context->m_joystickCallback(context->m_cookie, joyNum, context->m_joystickButtons[joyNum], sticks[0], sticks[1], sticks[2], sticks[3]);
}
/**
@brief Parse a single client message, update state, send callbacks and send replies
**/
#define USYNERGY_IS_PACKET(pkt_id) memcmp(message+4, pkt_id, 4)==0
static void sProcessMessage(uSynergyContext *context, const uint8_t *message)
{
// We have a packet!
if (memcmp(message+4, "Synergy", 7)==0)
{
// Welcome message
// kMsgHello = "Synergy%2i%2i"
// kMsgHelloBack = "Synergy%2i%2i%s"
sAddString(context, "Synergy");
sAddUInt16(context, USYNERGY_PROTOCOL_MAJOR);
sAddUInt16(context, USYNERGY_PROTOCOL_MINOR);
sAddUInt32(context, (uint32_t)strlen(context->m_clientName));
sAddString(context, context->m_clientName);
if (!sSendReply(context))
{
// Send reply failed, let's try to reconnect
sTrace(context, "SendReply failed, trying to reconnect in a second");
context->m_connected = USYNERGY_FALSE;
context->m_sleepFunc(context->m_cookie, 1000);
}
else
{
// Let's assume we're connected
char buffer[256+1];
sprintf(buffer, "Connected as client \"%s\"", context->m_clientName);
sTrace(context, buffer);
context->m_hasReceivedHello = USYNERGY_TRUE;
}
return;
}
else if (USYNERGY_IS_PACKET("QINF"))
{
// Screen info. Reply with DINF
// kMsgQInfo = "QINF"
// kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i"
uint16_t x = 0, y = 0, warp = 0;
sAddString(context, "DINF");
sAddUInt16(context, x);
sAddUInt16(context, y);
sAddUInt16(context, context->m_clientWidth);
sAddUInt16(context, context->m_clientHeight);
sAddUInt16(context, warp);
sAddUInt16(context, 0); // mx?
sAddUInt16(context, 0); // my?
sSendReply(context);
return;
}
else if (USYNERGY_IS_PACKET("CIAK"))
{
// Do nothing?
// kMsgCInfoAck = "CIAK"
return;
}
else if (USYNERGY_IS_PACKET("CROP"))
{
// Do nothing?
// kMsgCResetOptions = "CROP"
return;
}
else if (USYNERGY_IS_PACKET("CINN"))
{
// Screen enter. Reply with CNOP
// kMsgCEnter = "CINN%2i%2i%4i%2i"
// Obtain the Synergy sequence number
context->m_sequenceNumber = sNetToNative32(message + 12);
context->m_isCaptured = USYNERGY_TRUE;
// Call callback
if (context->m_screenActiveCallback != 0L)
context->m_screenActiveCallback(context->m_cookie, USYNERGY_TRUE);
}
else if (USYNERGY_IS_PACKET("COUT"))
{
// Screen leave
// kMsgCLeave = "COUT"
context->m_isCaptured = USYNERGY_FALSE;
// Call callback
if (context->m_screenActiveCallback != 0L)
context->m_screenActiveCallback(context->m_cookie, USYNERGY_FALSE);
}
else if (USYNERGY_IS_PACKET("DMDN"))
{
// Mouse down
// kMsgDMouseDown = "DMDN%1i"
char btn = message[8]-1;
if (btn==2)
context->m_mouseButtonRight = USYNERGY_TRUE;
else if (btn==1)
context->m_mouseButtonMiddle = USYNERGY_TRUE;
else
context->m_mouseButtonLeft = USYNERGY_TRUE;
sSendMouseCallback(context);
}
else if (USYNERGY_IS_PACKET("DMUP"))
{
// Mouse up
// kMsgDMouseUp = "DMUP%1i"
char btn = message[8]-1;
if (btn==2)
context->m_mouseButtonRight = USYNERGY_FALSE;
else if (btn==1)
context->m_mouseButtonMiddle = USYNERGY_FALSE;
else
context->m_mouseButtonLeft = USYNERGY_FALSE;
sSendMouseCallback(context);
}
else if (USYNERGY_IS_PACKET("DMMV"))
{
// Mouse move. Reply with CNOP
// kMsgDMouseMove = "DMMV%2i%2i"
context->m_mouseX = sNetToNative16(message+8);
context->m_mouseY = sNetToNative16(message+10);
sSendMouseCallback(context);
}
else if (USYNERGY_IS_PACKET("DMWM"))
{
// Mouse wheel
// kMsgDMouseWheel = "DMWM%2i%2i"
// kMsgDMouseWheel1_0 = "DMWM%2i"
context->m_mouseWheelX += sNetToNative16(message+8);
context->m_mouseWheelY += sNetToNative16(message+10);
sSendMouseCallback(context);
}
else if (USYNERGY_IS_PACKET("DKDN"))
{
// Key down
// kMsgDKeyDown = "DKDN%2i%2i%2i"
// kMsgDKeyDown1_0 = "DKDN%2i%2i"
//uint16_t id = sNetToNative16(message+8);
uint16_t mod = sNetToNative16(message+10);
uint16_t key = sNetToNative16(message+12);
sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_FALSE);
}
else if (USYNERGY_IS_PACKET("DKRP"))
{
// Key repeat
// kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"
// kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"
uint16_t mod = sNetToNative16(message+10);
// uint16_t count = sNetToNative16(message+12);
uint16_t key = sNetToNative16(message+14);
sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_TRUE);
}
else if (USYNERGY_IS_PACKET("DKUP"))
{
// Key up
// kMsgDKeyUp = "DKUP%2i%2i%2i"
// kMsgDKeyUp1_0 = "DKUP%2i%2i"
//uint16 id=Endian::sNetToNative(sbuf[4]);
uint16_t mod = sNetToNative16(message+10);
uint16_t key = sNetToNative16(message+12);
sSendKeyboardCallback(context, key, mod, USYNERGY_FALSE, USYNERGY_FALSE);
}
else if (USYNERGY_IS_PACKET("DGBT"))
{
// Joystick buttons
// kMsgDGameButtons = "DGBT%1i%2i";
uint8_t joy_num = message[8];
if (joy_num<USYNERGY_NUM_JOYSTICKS)
{
// Copy button state, then send callback
context->m_joystickButtons[joy_num] = (message[9] << 8) | message[10];
sSendJoystickCallback(context, joy_num);
}
}
else if (USYNERGY_IS_PACKET("DGST"))
{
// Joystick sticks
// kMsgDGameSticks = "DGST%1i%1i%1i%1i%1i";
uint8_t joy_num = message[8];
if (joy_num<USYNERGY_NUM_JOYSTICKS)
{
// Copy stick state, then send callback
memcpy(context->m_joystickSticks[joy_num], message+9, 4);
sSendJoystickCallback(context, joy_num);
}
}
else if (USYNERGY_IS_PACKET("DSOP"))
{
// Set options
// kMsgDSetOptions = "DSOP%4I"
}
else if (USYNERGY_IS_PACKET("CALV"))
{
// Keepalive, reply with CALV and then CNOP
// kMsgCKeepAlive = "CALV"
sAddString(context, "CALV");
sSendReply(context);
// now reply with CNOP
}
else if (USYNERGY_IS_PACKET("DCLP"))
{
// Clipboard message
// kMsgDClipboard = "DCLP%1i%4i%s"
//
// The clipboard message contains:
// 1 uint32: The size of the message
// 4 chars: The identifier ("DCLP")
// 1 uint8: The clipboard index
// 1 uint32: The sequence number. It's zero, because this message is always coming from the server?
// 1 uint32: The total size of the remaining 'string' (as per the Synergy %s string format (which is 1 uint32 for size followed by a char buffer (not necessarily null terminated)).
// 1 uint32: The number of formats present in the message
// And then 'number of formats' times the following:
// 1 uint32: The format of the clipboard data
// 1 uint32: The size n of the clipboard data
// n uint8: The clipboard data
const uint8_t * parse_msg = message+17;
uint32_t num_formats = sNetToNative32(parse_msg);
parse_msg += 4;
for (; num_formats; num_formats--)
{
// Parse clipboard format header
uint32_t format = sNetToNative32(parse_msg);
uint32_t size = sNetToNative32(parse_msg+4);
parse_msg += 8;
// Call callback
if (context->m_clipboardCallback)
context->m_clipboardCallback(context->m_cookie, format, parse_msg, size);
parse_msg += size;
}
}
else
{
// Unknown packet, could be any of these
// kMsgCNoop = "CNOP"
// kMsgCClose = "CBYE"
// kMsgCClipboard = "CCLP%1i%4i"
// kMsgCScreenSaver = "CSEC%1i"
// kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"
// kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"
// kMsgDMouseRelMove = "DMRM%2i%2i"
// kMsgEIncompatible = "EICV%2i%2i"
// kMsgEBusy = "EBSY"
// kMsgEUnknown = "EUNK"
// kMsgEBad = "EBAD"
char buffer[64];
sprintf(buffer, "Unknown packet '%c%c%c%c'", message[4], message[5], message[6], message[7]);
sTrace(context, buffer);
return;
}
// Reply with CNOP maybe?
sAddString(context, "CNOP");
sSendReply(context);
}
#undef USYNERGY_IS_PACKET
/**
@brief Mark context as being disconnected
**/
static void sSetDisconnected(uSynergyContext *context)
{
context->m_connected = USYNERGY_FALSE;
context->m_hasReceivedHello = USYNERGY_FALSE;
context->m_isCaptured = USYNERGY_FALSE;
context->m_replyCur = context->m_replyBuffer + 4;
context->m_sequenceNumber = 0;
}
/**
@brief Update a connected context
**/
static void sUpdateContext(uSynergyContext *context)
{
/* Receive data (blocking) */
int receive_size = USYNERGY_RECEIVE_BUFFER_SIZE - context->m_receiveOfs;
int num_received = 0;
int packlen = 0;
if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer + context->m_receiveOfs, receive_size, &num_received) == USYNERGY_FALSE)
{
/* Receive failed, let's try to reconnect */
char buffer[128];
sprintf(buffer, "Receive failed (%d bytes asked, %d bytes received), trying to reconnect in a second", receive_size, num_received);
sTrace(context, buffer);
sSetDisconnected(context);
context->m_sleepFunc(context->m_cookie, 1000);
return;
}
context->m_receiveOfs += num_received;
/* If we didn't receive any data then we're probably still polling to get connected and
therefore not getting any data back. To avoid overloading the system with a Synergy
thread that would hammer on polling, we let it rest for a bit if there's no data. */
if (num_received == 0)
context->m_sleepFunc(context->m_cookie, 500);
/* Check for timeouts */
if (context->m_hasReceivedHello)
{
uint32_t cur_time = context->m_getTimeFunc();
if (num_received == 0)
{
/* Timeout after 2 secs of inactivity (we received no CALV) */
if ((cur_time - context->m_lastMessageTime) > USYNERGY_IDLE_TIMEOUT)
sSetDisconnected(context);
}
else
context->m_lastMessageTime = cur_time;
}
/* Eat packets */
for (;;)
{
/* Grab packet length and bail out if the packet goes beyond the end of the buffer */
packlen = sNetToNative32(context->m_receiveBuffer);
if (packlen+4 > context->m_receiveOfs)
break;
/* Process message */
sProcessMessage(context, context->m_receiveBuffer);
/* Move packet to front of buffer */
memmove(context->m_receiveBuffer, context->m_receiveBuffer+packlen+4, context->m_receiveOfs-packlen-4);
context->m_receiveOfs -= packlen+4;
}
/* Throw away over-sized packets */
if (packlen > USYNERGY_RECEIVE_BUFFER_SIZE)
{
/* Oversized packet, ditch tail end */
char buffer[128];
sprintf(buffer, "Oversized packet: '%c%c%c%c' (length %d)", context->m_receiveBuffer[4], context->m_receiveBuffer[5], context->m_receiveBuffer[6], context->m_receiveBuffer[7], packlen);
sTrace(context, buffer);
num_received = context->m_receiveOfs-4; // 4 bytes for the size field
while (num_received != packlen)
{
int buffer_left = packlen - num_received;
int to_receive = buffer_left < USYNERGY_RECEIVE_BUFFER_SIZE ? buffer_left : USYNERGY_RECEIVE_BUFFER_SIZE;
int ditch_received = 0;
if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer, to_receive, &ditch_received) == USYNERGY_FALSE)
{
/* Receive failed, let's try to reconnect */
sTrace(context, "Receive failed, trying to reconnect in a second");
sSetDisconnected(context);
context->m_sleepFunc(context->m_cookie, 1000);
break;
}
else
{
num_received += ditch_received;
}
}
context->m_receiveOfs = 0;
}
}
//---------------------------------------------------------------------------------------------------------------------
// Public interface
//---------------------------------------------------------------------------------------------------------------------
/**
@brief Initialize uSynergy context
**/
void uSynergyInit(uSynergyContext *context)
{
/* Zero memory */
memset(context, 0, sizeof(uSynergyContext));
/* Initialize to default state */
sSetDisconnected(context);
}
/**
@brief Update uSynergy
**/
void uSynergyUpdate(uSynergyContext *context)
{
if (context->m_connected)
{
/* Update context, receive data, call callbacks */
sUpdateContext(context);
}
else
{
/* Try to connect */
if (context->m_connectFunc(context->m_cookie))
context->m_connected = USYNERGY_TRUE;
}
}
/**
@brief Send clipboard data
**/
void uSynergySendClipboard(uSynergyContext *context, const char *text)
{
// Calculate maximum size that will fit in a reply packet
uint32_t overhead_size = 4 + /* Message size */
4 + /* Message ID */
1 + /* Clipboard index */
4 + /* Sequence number */
4 + /* Rest of message size (because it's a Synergy string from here on) */
4 + /* Number of clipboard formats */
4 + /* Clipboard format */
4; /* Clipboard data length */
uint32_t max_length = USYNERGY_REPLY_BUFFER_SIZE - overhead_size;
// Clip text to max length
uint32_t text_length = (uint32_t)strlen(text);
if (text_length > max_length)
{
char buffer[128];
sprintf(buffer, "Clipboard buffer too small, clipboard truncated at %d characters", max_length);
sTrace(context, buffer);
text_length = max_length;
}
// Assemble packet
sAddString(context, "DCLP");
sAddUInt8(context, 0); /* Clipboard index */
sAddUInt32(context, context->m_sequenceNumber);
sAddUInt32(context, 4+4+4+text_length); /* Rest of message size: numFormats, format, length, data */
sAddUInt32(context, 1); /* Number of formats (only text for now) */
sAddUInt32(context, USYNERGY_CLIPBOARD_FORMAT_TEXT);
sAddUInt32(context, text_length);
sAddString(context, text);
sSendReply(context);
}

View File

@ -0,0 +1,420 @@
/*
uSynergy client -- Interface for the embedded Synergy client library
version 1.0.0, July 7th, 2012
Copyright (C) 2012 Synergy Si Ltd.
Copyright (c) 2012 Alex Evans
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
//---------------------------------------------------------------------------------------------------------------------
// Configuration
//---------------------------------------------------------------------------------------------------------------------
/**
@brief Determine endianness
**/
#if defined(USYNERGY_LITTLE_ENDIAN) && defined(USYNERGY_BIG_ENDIAN)
/* Ambiguous: both endians specified */
#error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN"
#elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN)
/* Attempt to auto detect */
#if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN)
#define USYNERGY_LITTLE_ENDIAN
#elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN)
#define USYNERGY_BIG_ENDIAN
#else
#error "Can't detect endian-nes, please defined either USYNERGY_LITTLE_ENDIAN or USYNERGY_BIG_ENDIAN";
#endif
#else
/* User-specified endian-nes, nothing to do for us */
#endif
//---------------------------------------------------------------------------------------------------------------------
// Types and Constants
//---------------------------------------------------------------------------------------------------------------------
/**
@brief Boolean type
**/
typedef int uSynergyBool;
#define USYNERGY_FALSE 0 /* False value */
#define USYNERGY_TRUE 1 /* True value */
/**
@brief User context type
The uSynergyCookie type is an opaque type that is used by uSynergy to communicate to the client. It is passed along to
callback functions as context.
**/
typedef struct { int ignored; } * uSynergyCookie;
/**
@brief Clipboard types
**/
enum uSynergyClipboardFormat
{
USYNERGY_CLIPBOARD_FORMAT_TEXT = 0, /* Text format, UTF-8, newline is LF */
USYNERGY_CLIPBOARD_FORMAT_BITMAP = 1, /* Bitmap format, BMP 24/32bpp, BI_RGB */
USYNERGY_CLIPBOARD_FORMAT_HTML = 2, /* HTML format, HTML fragment, UTF-8, newline is LF */
};
/**
@brief Constants and limits
**/
#define USYNERGY_NUM_JOYSTICKS 4 /* Maximum number of supported joysticks */
#define USYNERGY_PROTOCOL_MAJOR 1 /* Major protocol version */
#define USYNERGY_PROTOCOL_MINOR 4 /* Minor protocol version */
#define USYNERGY_IDLE_TIMEOUT 2000 /* Timeout in milliseconds before reconnecting */
#define USYNERGY_TRACE_BUFFER_SIZE 1024 /* Maximum length of traced message */
#define USYNERGY_REPLY_BUFFER_SIZE 1024 /* Maximum size of a reply packet */
#define USYNERGY_RECEIVE_BUFFER_SIZE 4096 /* Maximum size of an incoming packet */
/**
@brief Keyboard constants
**/
#define USYNERGY_MODIFIER_SHIFT 0x0001 /* Shift key modifier */
#define USYNERGY_MODIFIER_CTRL 0x0002 /* Ctrl key modifier */
#define USYNERGY_MODIFIER_ALT 0x0004 /* Alt key modifier */
#define USYNERGY_MODIFIER_META 0x0008 /* Meta key modifier */
#define USYNERGY_MODIFIER_WIN 0x0010 /* Windows key modifier */
#define USYNERGY_MODIFIER_ALT_GR 0x0020 /* AltGr key modifier */
#define USYNERGY_MODIFIER_LEVEL5LOCK 0x0040 /* Level5Lock key modifier */
#define USYNERGY_MODIFIER_CAPSLOCK 0x1000 /* CapsLock key modifier */
#define USYNERGY_MODIFIER_NUMLOCK 0x2000 /* NumLock key modifier */
#define USYNERGY_MODIFIER_SCROLLOCK 0x4000 /* ScrollLock key modifier */
//---------------------------------------------------------------------------------------------------------------------
// Functions and Callbacks
//---------------------------------------------------------------------------------------------------------------------
/**
@brief Connect function
This function is called when uSynergy needs to connect to the host. It doesn't imply a network implementation or
destination address, that must all be handled on the user side. The function should return USYNERGY_TRUE if a
connection was established or USYNERGY_FALSE if it could not connect.
When network errors occur (e.g. uSynergySend or uSynergyReceive fail) then the connect call will be called again
so the implementation of the function must close any old connections and clean up resources before retrying.
@param cookie Cookie supplied in the Synergy context
**/
typedef uSynergyBool (*uSynergyConnectFunc)(uSynergyCookie cookie);
/**
@brief Send function
This function is called when uSynergy needs to send something over the default connection. It should return
USYNERGY_TRUE if sending succeeded and USYNERGY_FALSE otherwise. This function should block until the send
operation is completed.
@param cookie Cookie supplied in the Synergy context
@param buffer Address of buffer to send
@param length Length of buffer to send
**/
typedef uSynergyBool (*uSynergySendFunc)(uSynergyCookie cookie, const uint8_t *buffer, int length);
/**
@brief Receive function
This function is called when uSynergy needs to receive data from the default connection. It should return
USYNERGY_TRUE if receiving data succeeded and USYNERGY_FALSE otherwise. This function should block until data
has been received and wait for data to become available. If @a outLength is set to 0 upon completion it is
assumed that the connection is alive, but still in a connecting state and needs time to settle.
@param cookie Cookie supplied in the Synergy context
@param buffer Address of buffer to receive data into
@param maxLength Maximum amount of bytes to write into the receive buffer
@param outLength Address of integer that receives the actual amount of bytes written into @a buffer
**/
typedef uSynergyBool (*uSynergyReceiveFunc)(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength);
/**
@brief Thread sleep function
This function is called when uSynergy wants to suspend operation for a while before retrying an operation. It
is mostly used when a socket times out or disconnect occurs to prevent uSynergy from continuously hammering a
network connection in case the network is down.
@param cookie Cookie supplied in the Synergy context
@param timeMs Time to sleep the current thread (in milliseconds)
**/
typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs);
/**
@brief Get time function
This function is called when uSynergy needs to know the current time. This is used to determine when timeouts
have occured. The time base should be a cyclic millisecond time value.
@returns Time value in milliseconds
**/
typedef uint32_t (*uSynergyGetTimeFunc)();
/**
@brief Trace function
This function is called when uSynergy wants to trace something. It is optional to show these messages, but they
are often useful when debugging. uSynergy only traces major events like connecting and disconnecting. Usually
only a single trace is shown when the connection is established and no more trace are called.
@param cookie Cookie supplied in the Synergy context
@param text Text to be traced
**/
typedef void (*uSynergyTraceFunc)(uSynergyCookie cookie, const char *text);
/**
@brief Screen active callback
This callback is called when Synergy makes the screen active or inactive. This
callback is usually sent when the mouse enters or leaves the screen.
@param cookie Cookie supplied in the Synergy context
@param active Activation flag, 1 if the screen has become active, 0 if the screen has become inactive
**/
typedef void (*uSynergyScreenActiveCallback)(uSynergyCookie cookie, uSynergyBool active);
/**
@brief Mouse callback
This callback is called when a mouse events happens. The mouse X and Y position,
wheel and button state is communicated in the message. It's up to the user to
interpret if this is a mouse up, down, double-click or other message.
@param cookie Cookie supplied in the Synergy context
@param x Mouse X position
@param y Mouse Y position
@param wheelX Mouse wheel X position
@param wheelY Mouse wheel Y position
@param buttonLeft Left button pressed status, 0 for released, 1 for pressed
@param buttonMiddle Middle button pressed status, 0 for released, 1 for pressed
@param buttonRight Right button pressed status, 0 for released, 1 for pressed
**/
typedef void (*uSynergyMouseCallback)(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle);
/**
@brief Key event callback
This callback is called when a key is pressed or released.
@param cookie Cookie supplied in the Synergy context
@param key Key code of key that was pressed or released
@param modifiers Status of modifier keys (alt, shift, etc.)
@param down Down or up status, 1 is key is pressed down, 0 if key is released (up)
@param repeat Repeat flag, 1 if the key is down because the key is repeating, 0 if the key is initially pressed by the user
**/
typedef void (*uSynergyKeyboardCallback)(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat);
/**
@brief Joystick event callback
This callback is called when a joystick stick or button changes. It is possible that multiple callbacks are
fired when different sticks or buttons change as these are individual messages in the packet stream. Each
callback will contain all the valid state for the different axes and buttons. The last callback received will
represent the most current joystick state.
@param cookie Cookie supplied in the Synergy context
@param joyNum Joystick number, always in the range [0 ... USYNERGY_NUM_JOYSTICKS>
@param buttons Button pressed mask
@param leftStickX Left stick X position, in range [-127 ... 127]
@param leftStickY Left stick Y position, in range [-127 ... 127]
@param rightStickX Right stick X position, in range [-127 ... 127]
@param rightStickY Right stick Y position, in range [-127 ... 127]
**/
typedef void (*uSynergyJoystickCallback)(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY);
/**
@brief Clipboard event callback
This callback is called when something is placed on the clipboard. Multiple callbacks may be fired for
multiple clipboard formats if they are supported. The data provided is read-only and may not be modified
by the application.
@param cookie Cookie supplied in the Synergy context
@param format Clipboard format
@param data Memory area containing the clipboard raw data
@param size Size of clipboard data
**/
typedef void (*uSynergyClipboardCallback)(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size);
//---------------------------------------------------------------------------------------------------------------------
// Context
//---------------------------------------------------------------------------------------------------------------------
/**
@brief uSynergy context
**/
typedef struct
{
/* Mandatory configuration data, filled in by client */
uSynergyConnectFunc m_connectFunc; /* Connect function */
uSynergySendFunc m_sendFunc; /* Send data function */
uSynergyReceiveFunc m_receiveFunc; /* Receive data function */
uSynergySleepFunc m_sleepFunc; /* Thread sleep function */
uSynergyGetTimeFunc m_getTimeFunc; /* Get current time function */
const char* m_clientName; /* Name of Synergy Screen / Client */
uint16_t m_clientWidth; /* Width of screen */
uint16_t m_clientHeight; /* Height of screen */
/* Optional configuration data, filled in by client */
uSynergyCookie m_cookie; /* Cookie pointer passed to callback functions (can be NULL) */
uSynergyTraceFunc m_traceFunc; /* Function for tracing status (can be NULL) */
uSynergyScreenActiveCallback m_screenActiveCallback; /* Callback for entering and leaving screen */
uSynergyMouseCallback m_mouseCallback; /* Callback for mouse events */
uSynergyKeyboardCallback m_keyboardCallback; /* Callback for keyboard events */
uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */
uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */
/* State data, used internall by client, initialized by uSynergyInit() */
uSynergyBool m_connected; /* Is our socket connected? */
uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */
uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */
uint32_t m_lastMessageTime; /* Time at which last message was received */
uint32_t m_sequenceNumber; /* Packet sequence number */
uint8_t m_receiveBuffer[USYNERGY_RECEIVE_BUFFER_SIZE]; /* Receive buffer */
int m_receiveOfs; /* Receive buffer offset */
uint8_t m_replyBuffer[USYNERGY_REPLY_BUFFER_SIZE]; /* Reply buffer */
uint8_t* m_replyCur; /* Write offset into reply buffer */
uint16_t m_mouseX; /* Mouse X position */
uint16_t m_mouseY; /* Mouse Y position */
int16_t m_mouseWheelX; /* Mouse wheel X position */
int16_t m_mouseWheelY; /* Mouse wheel Y position */
uSynergyBool m_mouseButtonLeft; /* Mouse left button */
uSynergyBool m_mouseButtonRight; /* Mouse right button */
uSynergyBool m_mouseButtonMiddle; /* Mouse middle button */
int8_t m_joystickSticks[USYNERGY_NUM_JOYSTICKS][4]; /* Joystick stick position in 2 axes for 2 sticks */
uint16_t m_joystickButtons[USYNERGY_NUM_JOYSTICKS]; /* Joystick button state */
} uSynergyContext;
//---------------------------------------------------------------------------------------------------------------------
// Interface
//---------------------------------------------------------------------------------------------------------------------
/**
@brief Initialize uSynergy context
This function initializes @a context for use. Call this function directly after
creating the context, before filling in any configuration data in it. Not calling
this function will cause undefined behavior.
@param context Context to be initialized
**/
extern void uSynergyInit(uSynergyContext *context);
/**
@brief Update uSynergy
This function updates uSynergy and does the bulk of the work. It does connection management,
receiving data, reconnecting after errors or timeouts and so on. It assumes that networking
operations are blocking and it can suspend the current thread if it needs to wait. It is
best practice to call uSynergyUpdate from a background thread so it is responsive.
Because uSynergy relies mostly on blocking calls it will mostly stay in thread sleep state
waiting for system mutexes and won't eat much memory.
uSynergyUpdate doesn't do any memory allocations or have any side effects beyond those of
the callbacks it calls.
@param context Context to be updated
**/
extern void uSynergyUpdate(uSynergyContext *context);
/**
@brief Send clipboard data
This function sets new clipboard data and sends it to the server. Use this function if
your client cuts or copies data onto the clipboard that it needs to share with the
server.
Currently there is only support for plaintext, but HTML and image data could be
supported with some effort.
@param context Context to send clipboard data to
@param text Text to set to the clipboard
**/
extern void uSynergySendClipboard(uSynergyContext *context, const char *text);
#ifdef __cplusplus
};
#endif

View File

@ -10,8 +10,9 @@
#CXX = g++
EXE = opengl3_example
OBJS = main.o imgui_impl_glfw_gl3.o
OBJS += ../../imgui.o
OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o
OBJS += ../libs/gl3w/GL/gl3w.o
UNAME_S := $(shell uname -s)
@ -22,7 +23,7 @@ ifeq ($(UNAME_S), Linux) #LINUX
LIBS = `pkg-config --static --libs glfw3`
CXXFLAGS = -I../../ -I../libs/gl3w `pkg-config --cflags glfw3`
CXXFLAGS += -Wall
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)
endif
@ -33,7 +34,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
LIBS += -lglfw3
CXXFLAGS = -I../../ -I../libs/gl3w -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include
CXXFLAGS += -Wall
CXXFLAGS += -Wall -Wformat
# CXXFLAGS += -D__APPLE__
CFLAGS = $(CXXFLAGS)
endif
@ -41,12 +42,12 @@ endif
.cpp.o:
$(CXX) $(CXXFLAGS) -c -o $@ $<
all:imgui_example
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
imgui_example:$(OBJS)
$(CXX) -o imgui_example $(OBJS) $(CXXFLAGS) $(LIBS)
$(EXE): $(OBJS)
$(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS)
clean:
rm $(OBJS)
rm $(EXE) $(OBJS)

View File

@ -7,7 +7,7 @@
// GL3W/GLFW
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
#ifdef _MSC_VER
#ifdef _WIN32
#undef APIENTRY
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
@ -23,21 +23,22 @@ static GLuint g_FontTexture = 0;
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
static size_t g_VboSize = 0;
static unsigned int g_VboHandle = 0, g_VaoHandle = 0;
static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0;
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
{
if (cmd_lists_count == 0)
return;
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
GLint last_program, last_texture;
// Backup GL state
GLint last_program, last_texture, last_array_buffer, last_element_array_buffer, last_vertex_array;
glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -46,74 +47,58 @@ static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawList** const cmd_lists, int
glEnable(GL_SCISSOR_TEST);
glActiveTexture(GL_TEXTURE0);
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
ImGuiIO& io = ImGui::GetIO();
float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Setup orthographic projection matrix
const float width = ImGui::GetIO().DisplaySize.x;
const float height = ImGui::GetIO().DisplaySize.y;
const float ortho_projection[4][4] =
{
{ 2.0f/width, 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/-height, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f },
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{-1.0f, 1.0f, 0.0f, 1.0f },
};
glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
// Grow our buffer according to what we need
size_t total_vtx_count = 0;
for (int n = 0; n < cmd_lists_count; n++)
total_vtx_count += cmd_lists[n]->vtx_buffer.size();
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
size_t needed_vtx_size = total_vtx_count * sizeof(ImDrawVert);
if (g_VboSize < needed_vtx_size)
{
g_VboSize = needed_vtx_size + 5000 * sizeof(ImDrawVert); // Grow buffer
glBufferData(GL_ARRAY_BUFFER, g_VboSize, NULL, GL_STREAM_DRAW);
}
// Copy and convert all vertices into a single contiguous buffer
unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
if (!buffer_data)
return;
for (int n = 0; n < cmd_lists_count; n++)
{
const ImDrawList* cmd_list = cmd_lists[n];
memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert));
buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert);
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(g_VaoHandle);
int cmd_offset = 0;
for (int n = 0; n < cmd_lists_count; n++)
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = cmd_lists[n];
int vtx_offset = cmd_offset;
const ImDrawCmd* pcmd_end = cmd_list->commands.end();
for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++)
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawIdx* idx_buffer_offset = 0;
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.size() * sizeof(ImDrawVert), (GLvoid*)&cmd_list->VtxBuffer.front(), GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx), (GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW);
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++)
{
if (pcmd->user_callback)
if (pcmd->UserCallback)
{
pcmd->user_callback(cmd_list, pcmd);
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->texture_id);
glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer_offset);
}
vtx_offset += pcmd->vtx_count;
idx_buffer_offset += pcmd->ElemCount;
}
cmd_offset = vtx_offset;
}
// Restore modified state
glBindVertexArray(0);
// Restore modified GL state
glUseProgram(last_program);
glDisable(GL_SCISSOR_TEST);
glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
glBindVertexArray(last_vertex_array);
glDisable(GL_SCISSOR_TEST);
}
static const char* ImGui_ImplGlfwGL3_GetClipboardText()
@ -182,6 +167,12 @@ void ImGui_ImplGlfwGL3_CreateFontsTexture()
bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
{
// Backup GL state
GLint last_texture, last_array_buffer, last_vertex_array;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
const GLchar *vertex_shader =
"#version 330\n"
"uniform mat4 ProjMtx;\n"
@ -226,6 +217,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
glGenBuffers(1, &g_VboHandle);
glGenBuffers(1, &g_ElementsHandle);
glGenVertexArrays(1, &g_VaoHandle);
glBindVertexArray(g_VaoHandle);
@ -239,11 +231,14 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
#undef OFFSETOF
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ImGui_ImplGlfwGL3_CreateFontsTexture();
// Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
glBindVertexArray(last_vertex_array);
return true;
}
@ -257,6 +252,8 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks)
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
@ -273,7 +270,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks)
io.RenderDrawListsFn = ImGui_ImplGlfwGL3_RenderDrawLists;
io.SetClipboardTextFn = ImGui_ImplGlfwGL3_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplGlfwGL3_GetClipboardText;
#ifdef _MSC_VER
#ifdef _WIN32
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
#endif
@ -292,8 +289,8 @@ void ImGui_ImplGlfwGL3_Shutdown()
{
if (g_VaoHandle) glDeleteVertexArrays(1, &g_VaoHandle);
if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle);
g_VaoHandle = 0;
g_VboHandle = 0;
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
g_VaoHandle = g_VboHandle = g_ElementsHandle = 0;
glDetachShader(g_ShaderHandle, g_VertHandle);
glDeleteShader(g_VertHandle);
@ -327,7 +324,8 @@ void ImGui_ImplGlfwGL3_NewFrame()
int display_w, display_h;
glfwGetWindowSize(g_Window, &w, &h);
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)display_w, (float)display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
// Setup time step
double current_time = glfwGetTime();
@ -340,9 +338,7 @@ void ImGui_ImplGlfwGL3_NewFrame()
{
double mouse_x, mouse_y;
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels
mouse_y *= (float)display_h / h;
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
}
else
{

View File

@ -3,18 +3,18 @@
struct GLFWwindow;
bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks);
void ImGui_ImplGlfwGL3_Shutdown();
void ImGui_ImplGlfwGL3_NewFrame();
IMGUI_API bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks);
IMGUI_API void ImGui_ImplGlfwGL3_Shutdown();
IMGUI_API void ImGui_ImplGlfwGL3_NewFrame();
// Use if you want to reset your rendering device without losing ImGui state.
void ImGui_ImplGlfwGL3_InvalidateDeviceObjects();
bool ImGui_ImplGlfwGL3_CreateDeviceObjects();
IMGUI_API void ImGui_ImplGlfwGL3_InvalidateDeviceObjects();
IMGUI_API bool ImGui_ImplGlfwGL3_CreateDeviceObjects();
// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization)
// Provided here if you want to chain callbacks.
// You can also handle inputs yourself and use those as a reference.
void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_API void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_API void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_API void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_API void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c);

View File

@ -29,13 +29,22 @@ int main(int, char**)
// Setup ImGui binding
ImGui_ImplGlfwGL3_Init(window, true);
// Load Fonts
// (see extra_fonts/README.txt for more details)
//ImGuiIO& io = ImGui::GetIO();
//ImFont* my_font0 = io.Fonts->AddFontDefault();
//ImFont* my_font1 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/Karla-Regular.ttf", 16.0f);
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
bool show_test_window = true;
bool show_another_window = false;
@ -44,7 +53,6 @@ int main(int, char**)
// Main loop
while (!glfwWindowShouldClose(window))
{
ImGuiIO& io = ImGui::GetIO();
glfwPollEvents();
ImGui_ImplGlfwGL3_NewFrame();
@ -77,7 +85,9 @@ int main(int, char**)
}
// Rendering
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render();

View File

@ -149,6 +149,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="..\libs\gl3w\GL\gl3w.c" />
<ClCompile Include="imgui_impl_glfw_gl3.cpp" />
<ClCompile Include="main.cpp" />
@ -156,6 +158,7 @@
<ItemGroup>
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="..\libs\gl3w\GL\gl3w.h" />
<ClInclude Include="..\libs\gl3w\GL\glcorearb.h" />
<ClInclude Include="imgui_impl_glfw_gl3.h" />

View File

@ -25,6 +25,12 @@
<ClCompile Include="..\libs\gl3w\GL\gl3w.c">
<Filter>gl3w</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h">
@ -42,5 +48,8 @@
<ClInclude Include="..\libs\gl3w\GL\glcorearb.h">
<Filter>gl3w</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -10,8 +10,9 @@
#CXX = g++
EXE = opengl_example
OBJS = main.o imgui_impl_glfw.o
OBJS += ../../imgui.o
OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o
UNAME_S := $(shell uname -s)
@ -21,7 +22,7 @@ ifeq ($(UNAME_S), Linux) #LINUX
LIBS = `pkg-config --static --libs glfw3`
CXXFLAGS = -I../../ `pkg-config --cflags glfw3`
CXXFLAGS += -Wall
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)
endif
@ -32,7 +33,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
LIBS += -lglfw3
CXXFLAGS = -I../../ -I/usr/local/include
CXXFLAGS += -Wall
CXXFLAGS += -Wall -Wformat
# CXXFLAGS += -D__APPLE__
CFLAGS = $(CXXFLAGS)
endif
@ -40,12 +41,12 @@ endif
.cpp.o:
$(CXX) $(CXXFLAGS) -c -o $@ $<
all:imgui_example
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
imgui_example:$(OBJS)
$(CXX) -o imgui_example $(OBJS) $(CXXFLAGS) $(LIBS)
$(EXE): $(OBJS)
$(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS)
clean:
rm $(OBJS)
rm $(EXE) $(OBJS)

View File

@ -6,7 +6,7 @@
// GLFW
#include <GLFW/glfw3.h>
#ifdef _MSC_VER
#ifdef _WIN32
#undef APIENTRY
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
@ -23,14 +23,13 @@ static GLuint g_FontTexture = 0;
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
static void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
{
if (cmd_lists_count == 0)
return;
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer.
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -43,42 +42,45 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
glEnable(GL_TEXTURE_2D);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
ImGuiIO& io = ImGui::GetIO();
float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Setup orthographic projection matrix
const float width = ImGui::GetIO().DisplaySize.x;
const float height = ImGui::GetIO().DisplaySize.y;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// Render command lists
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
for (int n = 0; n < cmd_lists_count; n++)
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = cmd_lists[n];
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->vtx_buffer.front();
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos)));
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv)));
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col)));
int vtx_offset = 0;
for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
if (pcmd->user_callback)
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
pcmd->user_callback(cmd_list, pcmd);
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->texture_id);
glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer);
}
vtx_offset += pcmd->vtx_count;
idx_buffer += pcmd->ElemCount;
}
}
#undef OFFSETOF
@ -87,7 +89,7 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, last_texture);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
@ -147,6 +149,8 @@ bool ImGui_ImplGlfw_CreateDeviceObjects()
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
// Create texture
GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGenTextures(1, &g_FontTexture);
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -159,6 +163,7 @@ bool ImGui_ImplGlfw_CreateDeviceObjects()
// Cleanup (don't clear the input data if you want to append new fonts later)
io.Fonts->ClearInputData();
io.Fonts->ClearTexData();
glBindTexture(GL_TEXTURE_2D, last_texture);
return true;
}
@ -183,6 +188,8 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks)
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
@ -199,7 +206,7 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks)
io.RenderDrawListsFn = ImGui_ImplGlfw_RenderDrawLists;
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
#ifdef _MSC_VER
#ifdef _WIN32
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
#endif
@ -232,7 +239,8 @@ void ImGui_ImplGlfw_NewFrame()
int display_w, display_h;
glfwGetWindowSize(g_Window, &w, &h);
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)display_w, (float)display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
// Setup time step
double current_time = glfwGetTime();
@ -245,9 +253,7 @@ void ImGui_ImplGlfw_NewFrame()
{
double mouse_x, mouse_y;
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels
mouse_y *= (float)display_h / h;
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
}
else
{

View File

@ -3,18 +3,18 @@
struct GLFWwindow;
bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks);
void ImGui_ImplGlfw_Shutdown();
void ImGui_ImplGlfw_NewFrame();
IMGUI_API bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks);
IMGUI_API void ImGui_ImplGlfw_Shutdown();
IMGUI_API void ImGui_ImplGlfw_NewFrame();
// Use if you want to reset your rendering device without losing ImGui state.
void ImGui_ImplGlfw_InvalidateDeviceObjects();
bool ImGui_ImplGlfw_CreateDeviceObjects();
IMGUI_API void ImGui_ImplGlfw_InvalidateDeviceObjects();
IMGUI_API bool ImGui_ImplGlfw_CreateDeviceObjects();
// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization)
// Provided here if you want to chain callbacks.
// You can also handle inputs yourself and use those as a reference.
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_API void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);

View File

@ -21,13 +21,22 @@ int main(int, char**)
// Setup ImGui binding
ImGui_ImplGlfw_Init(window, true);
// Load Fonts
// (see extra_fonts/README.txt for more details)
//ImGuiIO& io = ImGui::GetIO();
//ImFont* my_font0 = io.Fonts->AddFontDefault();
//ImFont* my_font1 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/Karla-Regular.ttf", 16.0f);
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
bool show_test_window = true;
bool show_another_window = false;
@ -68,7 +77,9 @@ int main(int, char**)
}
// Rendering
glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render();

View File

@ -149,12 +149,15 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="imgui_impl_glfw.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="imgui_impl_glfw.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -19,6 +19,12 @@
<ClCompile Include="imgui_impl_glfw.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h">
@ -30,5 +36,8 @@
<ClInclude Include="imgui_impl_glfw.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,23 @@
# How to Build
- On Windows with Visual Studio's CLI
\<sdl2path\> is your SDL2 folder.
```
cl /MD /I <sdl2path\include> /I ..\.. main.cpp imgui_impl_sdl.cpp ..\..\imgui*.cpp /link /LIBPATH:<sdl2path\lib> SDL2.lib SDL2main.lib
```
- On Linux and similar Unixes
```
c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -o sdl2example
```
- On Mac OS X
```
brew install sdl2
c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -o sdl2example
```

View File

@ -0,0 +1,257 @@
// ImGui SDL2 binding with OpenGL
// https://github.com/ocornut/imgui
#include <SDL.h>
#include <SDL_syswm.h>
#include <SDL_opengl.h>
#include <imgui.h>
#include "imgui_impl_sdl.h"
// Data
static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
static GLuint g_FontTexture = 0;
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
static void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
{
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer.
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
// Setup orthographic projection matrix
const float width = ImGui::GetIO().DisplaySize.x;
const float height = ImGui::GetIO().DisplaySize.y;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// Render command lists
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos)));
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv)));
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col)));
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glScissor((int)pcmd->ClipRect.x, (int)(height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer);
}
idx_buffer += pcmd->ElemCount;
}
}
#undef OFFSETOF
// Restore modified state
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, 0);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
static const char* ImGui_ImplSdl_GetClipboardText()
{
return SDL_GetClipboardText();
}
static void ImGui_ImplSdl_SetClipboardText(const char* text)
{
SDL_SetClipboardText(text);
}
bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
switch (event->type)
{
case SDL_MOUSEWHEEL:
{
if (event->wheel.y > 0)
g_MouseWheel = 1;
if (event->wheel.y < 0)
g_MouseWheel = -1;
return true;
}
case SDL_MOUSEBUTTONDOWN:
{
if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
return true;
}
case SDL_TEXTINPUT:
{
ImGuiIO& io = ImGui::GetIO();
io.AddInputCharactersUTF8(event->text.text);
return true;
}
case SDL_KEYDOWN:
case SDL_KEYUP:
{
int key = event->key.keysym.sym & ~SDLK_SCANCODE_MASK;
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
return true;
}
}
return false;
}
bool ImGui_ImplSdl_CreateDeviceObjects()
{
ImGuiIO& io = ImGui::GetIO();
// Build texture
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
// Create texture
glGenTextures(1, &g_FontTexture);
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
// Cleanup (don't clear the input data if you want to append new fonts later)
io.Fonts->ClearInputData();
io.Fonts->ClearTexData();
return true;
}
void ImGui_ImplSdl_InvalidateDeviceObjects()
{
if (g_FontTexture)
{
glDeleteTextures(1, &g_FontTexture);
ImGui::GetIO().Fonts->TexID = 0;
g_FontTexture = 0;
}
}
bool ImGui_ImplSdl_Init(SDL_Window *window)
{
ImGuiIO& io = ImGui::GetIO();
io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN;
io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE;
io.KeyMap[ImGuiKey_A] = SDLK_a;
io.KeyMap[ImGuiKey_C] = SDLK_c;
io.KeyMap[ImGuiKey_V] = SDLK_v;
io.KeyMap[ImGuiKey_X] = SDLK_x;
io.KeyMap[ImGuiKey_Y] = SDLK_y;
io.KeyMap[ImGuiKey_Z] = SDLK_z;
io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists;
io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText;
#ifdef _WIN32
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo);
io.ImeWindowHandle = wmInfo.info.win.window;
#endif
return true;
}
void ImGui_ImplSdl_Shutdown()
{
ImGui_ImplSdl_InvalidateDeviceObjects();
ImGui::Shutdown();
}
void ImGui_ImplSdl_NewFrame(SDL_Window *window)
{
if (!g_FontTexture)
ImGui_ImplSdl_CreateDeviceObjects();
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
int w, h;
SDL_GetWindowSize(window, &w, &h);
io.DisplaySize = ImVec2((float)w, (float)h);
// Setup time step
Uint32 time = SDL_GetTicks();
double current_time = time / 1000.0;
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
g_Time = current_time;
// Setup inputs
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
int mx, my;
Uint32 mouseMask = SDL_GetMouseState(&mx, &my);
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS)
io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
else
io.MousePos = ImVec2(-1,-1);
io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
io.MouseWheel = g_MouseWheel;
g_MouseWheel = 0.0f;
// Hide OS mouse cursor if ImGui is drawing it
SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1);
// Start the frame
ImGui::NewFrame();
}

View File

@ -0,0 +1,14 @@
// ImGui SDL2 binding with OpenGL
// https://github.com/ocornut/imgui
struct SDL_Window;
typedef union SDL_Event SDL_Event;
IMGUI_API bool ImGui_ImplSdl_Init(SDL_Window *window);
IMGUI_API void ImGui_ImplSdl_Shutdown();
IMGUI_API void ImGui_ImplSdl_NewFrame(SDL_Window *window);
IMGUI_API bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_API void ImGui_ImplSdl_InvalidateDeviceObjects();
IMGUI_API bool ImGui_ImplSdl_CreateDeviceObjects();

View File

@ -0,0 +1,108 @@
// ImGui - standalone example application for SDL2 + OpenGL
#include <imgui.h>
#include "imgui_impl_sdl.h"
#include <stdio.h>
#include <SDL.h>
#include <SDL_opengl.h>
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
}
// Setup window
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
SDL_GLContext glcontext = SDL_GL_CreateContext(window);
// Setup ImGui binding
ImGui_ImplSdl_Init(window);
// Load Fonts
// (see extra_fonts/README.txt for more details)
//ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
bool show_test_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154);
// Main loop
bool done = false;
while (!done)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSdl_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
}
ImGui_ImplSdl_NewFrame(window);
// 1. Show a simple window
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
{
static float f = 0.0f;
ImGui::Text("Hello, world!");
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::ColorEdit3("clear color", (float*)&clear_color);
if (ImGui::Button("Test Window")) show_test_window ^= 1;
if (ImGui::Button("Another Window")) show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
}
// 2. Show another simple window, this time using an explicit Begin/End pair
if (show_another_window)
{
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello");
ImGui::End();
}
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
if (show_test_window)
{
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
ImGui::ShowTestWindow(&show_test_window);
}
// Rendering
glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render();
SDL_GL_SwapWindow(window);
}
// Cleanup
ImGui_ImplSdl_Shutdown();
SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

Binary file not shown.

View File

@ -3,9 +3,75 @@
Those are only provided as a convenience, you can load your own .TTF files.
---------------------------------
INCLUDED FONTS
LOADING INSTRUCTIONS
---------------------------------
Load default font with:
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();
Load .TTF file with:
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
Detailed options:
ImFontConfig config;
config.OversampleH = 3;
config.OversampleV = 3;
config.GlyphExtraSpacing.x = 1.0f;
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
Combine two fonts into one:
// Load main font
io.Fonts->AddFontDefault();
// Add character ranges and merge into main font
ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges);
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config, io.Fonts->GetGlyphRangesJapanese());
Add a fourth parameter to bake specific font ranges only:
// Basic Latin, Extended Latin
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault());
// Include full set of about 21000 CJK Unified Ideographs
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
// Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChinese());
Offset font vertically by altering the io.Font->DisplayOffset value:
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
font->DisplayOffset.y += 1; // Render 1 pixel down
---------------------------------
EMBED A FONT IN SOURCE CODE
---------------------------------
Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array. Then load the font with:
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
Or
ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
---------------------------------
INCLUDED FONT FILES
---------------------------------
Cousine-Regular.ttf
Digitized data copyright (c) 2010 Google Corporation.
Licensed under the SIL Open Font License, Version 1.1
DroidSans.ttf
Copyright (c) Steve Matteson
Apache License, version 2.0
@ -26,36 +92,28 @@
SIL OPEN FONT LICENSE Version 1.1
---------------------------------
OTHER FONTS
LINKS
---------------------------------
For Japanese:
Typefaces for source code beautification
https://github.com/chrissimpkins/codeface
M+ fonts by Coji Morishita are free and include most useful Kanjis you would need.
mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html
Programmation fonts
http://s9w.github.io/font_compare/
Proggy Programming Fonts
http://upperbounds.net
For Japanese, Chinese, Korean:
You can use Arial Unicode or other Unicode fonts provided with Windows (not sure of their license).
Other suggestions?
Inconsolata
http://www.levien.com/type/myfonts/inconsolata.html
---------------------------------
LOADING INSTRUCTIONS
---------------------------------
Adobe Source Code Pro: Monospaced font family for user interface and coding environments
https://github.com/adobe-fonts/source-code-pro
Load .TTF file with:
Monospace/Fixed Width Programmer's Fonts
http://www.lowing.org/fonts/
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels);
Add a third parameter to bake specific font ranges:
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, io.Fonts->GetGlyphRangesDefault()); // Basic Latin, Extended Latin
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, io.Fonts->GetGlyphRangesJapanese()); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, io.Fonts->GetGlyphRangesChinese()); // Include full set of about 21000 CJK Unified Ideographs
Offset font by altering the io.Font->DisplayOffset value:
ImFont* font = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels);
font->DisplayOffset.y += 1; // Render 1 pixel down
(Japanese) M+ fonts by Coji Morishita are free and include most useful Kanjis you would need.
http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html
Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing).

View File

@ -1,8 +1,10 @@
// ImGui - binary_to_compressed_c.cpp
// Helper tool to turn a file into a C array.
// The data is first compressed with stb_compress() to reduce source code size a little.
// The data is first compressed with stb_compress() to reduce source code size.
// Then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex)
// (If we used 32-bits constants it would require take 11 bytes of source code to encode 4 bytes.)
// Useful if you want to embed fonts into your code.
// Note that the output array is likely to be bigger than the binary file..
// Note that even with compression, the output array is likely to be bigger than the binary file..
// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
#define _CRT_SECURE_NO_WARNINGS
@ -11,28 +13,44 @@
#include <stdlib.h>
#include <assert.h>
const int COLUMNS = 12;
// stb_compress* from stb.h - declaration
typedef unsigned int stb_uint;
typedef unsigned char stb_uchar;
stb_uint stb_compress(stb_uchar *out,stb_uchar *in,stb_uint len);
static bool binary_to_compressed_c(const char* filename, const char* symbol);
static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding);
int main(int argc, char** argv)
{
if (argc < 3)
{
printf("Syntax: %s <inputfile> <symbolname>\n", argv[0]);
printf("Syntax: %s [-base85] <inputfile> <symbolname>\n", argv[0]);
return 0;
}
binary_to_compressed_c(argv[1], argv[2]);
int argn = 1;
bool use_base85_encoding = false;
if (argv[argn][0] == '-')
{
if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; }
else
{
printf("Unknown argument: '%s'\n", argv[argn]);
return 1;
}
}
binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding);
return 1;
}
bool binary_to_compressed_c(const char* filename, const char* symbol)
char Encode85Byte(unsigned int x)
{
x = (x % 85) + 35;
return (x>='\\') ? x+1 : x;
}
bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding)
{
// Read file
FILE* f = fopen(filename, "rb");
@ -50,22 +68,38 @@ bool binary_to_compressed_c(const char* filename, const char* symbol)
int compressed_sz = stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz);
memset(compressed + compressed_sz, 0, maxlen - compressed_sz);
// Output
// Output as Base85 encoded
FILE* out = stdout;
fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
fprintf(out, "// Exported using binary_to_compressed_c\n");
fprintf(out, "static const unsigned int %s_compressed_size = %d;\n", symbol, (int)compressed_sz);
fprintf(out, "static const unsigned int %s_compressed_data[%d/4] =\n{", symbol, (int)((compressed_sz+3)/4)*4);
int column = 0;
for (int i = 0; i < compressed_sz; i += 4)
fprintf(out, "// Exported using binary_to_compressed_c.cpp\n");
if (use_base85_encoding)
{
unsigned int d = *(unsigned int*)(compressed + i);
if ((column++ % COLUMNS) == 0)
fprintf(out, "\n 0x%08x, ", d);
else
fprintf(out, "0x%08x, ", d);
fprintf(out, "static const char %s_compressed_data_base85[%d+1] =\n \"", symbol, (int)((compressed_sz+3)/4)*5);
int column = 0;
for (int i = 0; i < compressed_sz; i += 4)
{
unsigned int d = *(unsigned int*)(compressed + i);
fprintf(out, "%c%c%c%c%c", Encode85Byte(d), Encode85Byte(d/85), Encode85Byte(d/7225), Encode85Byte(d/614125), Encode85Byte(d/52200625));
if ((i % 112) == 112-4)
fprintf(out, "\"\n \"");
}
fprintf(out, "\";\n\n");
}
else
{
fprintf(out, "static const unsigned int %s_compressed_size = %d;\n", symbol, (int)compressed_sz);
fprintf(out, "static const unsigned int %s_compressed_data[%d/4] =\n{", symbol, (int)((compressed_sz+3)/4)*4);
int column = 0;
for (int i = 0; i < compressed_sz; i += 4)
{
unsigned int d = *(unsigned int*)(compressed + i);
if ((column++ % 12) == 0)
fprintf(out, "\n 0x%08x, ", d);
else
fprintf(out, "0x%08x, ", d);
}
fprintf(out, "\n};\n\n");
}
fprintf(out, "\n};\n\n");
// Cleanup
delete[] data;

View File

@ -6,11 +6,6 @@
#pragma once
//---- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h
//#include <vector>
//#define ImVector std::vector
//#define ImVector MyVector
//---- Define assertion handler. Defaults to calling assert().
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
@ -35,7 +30,7 @@
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//---- Implement STB libraries in a namespace to avoid conflicts
//#define IMGUI_STB_NAMESPACE ImStb
//#define IMGUI_STB_NAMESPACE ImGuiStb
//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
/*

7599
imgui.cpp

File diff suppressed because it is too large Load Diff

550
imgui.h

File diff suppressed because it is too large Load Diff

2188
imgui_demo.cpp Normal file

File diff suppressed because it is too large Load Diff

2196
imgui_draw.cpp Normal file

File diff suppressed because it is too large Load Diff

684
imgui_internal.h Normal file
View File

@ -0,0 +1,684 @@
// ImGui library v1.45 WIP
// Internals
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
// Implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators)
// #define IMGUI_DEFINE_MATH_OPERATORS
#pragma once
#ifndef IMGUI_VERSION
#error Must include imgui.h before imgui_internal.h
#endif
#include <stdio.h> // FILE*
#include <math.h> // sqrtf()
//-----------------------------------------------------------------------------
// Forward Declarations
//-----------------------------------------------------------------------------
struct ImRect;
struct ImGuiColMod;
struct ImGuiStyleMod;
struct ImGuiGroupData;
struct ImGuiSimpleColumns;
struct ImGuiDrawContext;
struct ImGuiTextEditState;
struct ImGuiIniData;
struct ImGuiMouseCursorData;
struct ImGuiPopupRef;
struct ImGuiState;
struct ImGuiWindow;
typedef int ImGuiLayoutType; // enum ImGuiLayoutType_
typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_
typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_
//-------------------------------------------------------------------------
// STB libraries
//-------------------------------------------------------------------------
namespace ImGuiStb
{
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#endif
#undef STB_TEXTEDIT_STRING
#undef STB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_STRING ImGuiTextEditState
#define STB_TEXTEDIT_CHARTYPE ImWchar
#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f
#include "stb_textedit.h"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
} // namespace ImGuiStb
//-----------------------------------------------------------------------------
// Context
//-----------------------------------------------------------------------------
extern ImGuiState* GImGui;
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
#define IM_PI 3.14159265358979323846f
// Helpers: UTF-8 <> wchar
int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count
int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points
// Helpers: Misc
ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings
bool ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, int* out_file_size = NULL, int padding_bytes = 0);
bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c);
static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; }
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
// Helpers: String
int ImStricmp(const char* str1, const char* str2);
int ImStrnicmp(const char* str1, const char* str2, int count);
char* ImStrdup(const char* str);
int ImStrlenW(const ImWchar* str);
const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
int ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_PRINTFARGS(3);
int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args);
// Helpers: Math
// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined)
#ifdef IMGUI_DEFINE_MATH_OPERATORS
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); }
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }
static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }
static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-lhs.w); }
#endif
static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; }
static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); }
static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); }
static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); }
static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; }
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; }
static inline ImVec2 ImRound(ImVec2 v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
enum ImGuiButtonFlags_
{
ImGuiButtonFlags_Repeat = 1 << 0,
ImGuiButtonFlags_PressedOnClick = 1 << 1, // return pressed on click only (default requires click+release)
ImGuiButtonFlags_PressedOnRelease = 1 << 2, // return pressed on release only (default requires click+release)
ImGuiButtonFlags_FlattenChilds = 1 << 3,
ImGuiButtonFlags_DontClosePopups = 1 << 4,
ImGuiButtonFlags_Disabled = 1 << 5,
ImGuiButtonFlags_AlignTextBaseLine = 1 << 6
};
enum ImGuiTreeNodeFlags_
{
ImGuiTreeNodeFlags_DefaultOpen = 1 << 0,
ImGuiTreeNodeFlags_NoAutoExpandOnLog = 1 << 1
};
enum ImGuiSelectableFlagsPrivate_
{
// NB: need to be in sync with last value of ImGuiSelectableFlags_
ImGuiSelectableFlags_Menu = 1 << 2,
ImGuiSelectableFlags_MenuItem = 1 << 3,
ImGuiSelectableFlags_Disabled = 1 << 4,
ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 5
};
// FIXME: this is in development, not exposed/functional as a generic feature yet.
enum ImGuiLayoutType_
{
ImGuiLayoutType_Vertical,
ImGuiLayoutType_Horizontal
};
enum ImGuiPlotType
{
ImGuiPlotType_Lines,
ImGuiPlotType_Histogram
};
enum ImGuiDataType
{
ImGuiDataType_Int,
ImGuiDataType_Float
};
// 2D axis aligned bounding-box
// NB: we can't rely on ImVec2 math operators being available here
struct ImRect
{
ImVec2 Min; // Upper-left
ImVec2 Max; // Lower-right
ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {}
ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }
ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); }
float GetWidth() const { return Max.x-Min.x; }
float GetHeight() const { return Max.y-Min.y; }
ImVec2 GetTL() const { return Min; }
ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); }
ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); }
ImVec2 GetBR() const { return Max; }
bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; }
void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; }
void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
void Round() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const
{
if (!on_edge && Contains(p))
return p;
if (p.x > Max.x) p.x = Max.x;
else if (p.x < Min.x) p.x = Min.x;
if (p.y > Max.y) p.y = Max.y;
else if (p.y < Min.y) p.y = Min.y;
return p;
}
};
// Stacked color modifier, backup of modified data so we can restore it
struct ImGuiColMod
{
ImGuiCol Col;
ImVec4 PreviousValue;
};
// Stacked style modifier, backup of modified data so we can restore it
struct ImGuiStyleMod
{
ImGuiStyleVar Var;
ImVec2 PreviousValue;
};
// Stacked data for BeginGroup()/EndGroup()
struct ImGuiGroupData
{
ImVec2 BackupCursorPos;
ImVec2 BackupCursorMaxPos;
float BackupColumnsStartX;
float BackupCurrentLineHeight;
float BackupCurrentLineTextBaseOffset;
float BackupLogLinePosY;
bool AdvanceCursor;
};
// Simple column measurement currently used for MenuItem() only. This is very short-sighted for now and not a generic helper.
struct ImGuiSimpleColumns
{
int Count;
float Spacing;
float Width, NextWidth;
float Pos[8], NextWidths[8];
ImGuiSimpleColumns();
void Update(int count, float spacing, bool clear);
float DeclColumns(float w0, float w1, float w2);
float CalcExtraSpace(float avail_w);
};
// Internal state of the currently focused/edited text input box
struct ImGuiTextEditState
{
ImGuiID Id; // widget id owning the text state
ImVector<ImWchar> Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
ImVector<char> InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
ImVector<char> TempTextBuffer;
int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
int BufSizeA; // end-user buffer size
float ScrollX;
ImGuiStb::STB_TexteditState StbState;
float CursorAnim;
bool CursorFollow;
ImVec2 InputCursorScreenPos; // Cursor position in screen space to be used by IME callback.
bool SelectedAllMouseLock;
ImGuiTextEditState() { memset(this, 0, sizeof(*this)); }
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; }
void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
void OnKeyPressed(int key);
};
// Data saved in imgui.ini file
struct ImGuiIniData
{
char* Name;
ImGuiID ID;
ImVec2 Pos;
ImVec2 Size;
bool Collapsed;
};
// Mouse cursor data (used when io.MouseDrawCursor is set)
struct ImGuiMouseCursorData
{
ImGuiMouseCursor Type;
ImVec2 HotOffset;
ImVec2 Size;
ImVec2 TexUvMin[2];
ImVec2 TexUvMax[2];
};
// Storage for current popup stack
struct ImGuiPopupRef
{
ImGuiID PopupID; // Set on OpenPopup()
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
ImGuiWindow* ParentWindow; // Set on OpenPopup()
ImGuiID ParentMenuSet; // Set on OpenPopup()
ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupID = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
};
// Main state for ImGui
struct ImGuiState
{
bool Initialized;
ImGuiIO IO;
ImGuiStyle Style;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize()
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters.
ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvForWhite
float Time;
int FrameCount;
int FrameCountRendered;
ImVector<ImGuiWindow*> Windows;
ImVector<ImGuiWindow*> WindowsSortBuffer;
ImGuiWindow* CurrentWindow; // Being drawn into
ImVector<ImGuiWindow*> CurrentWindowStack;
ImGuiWindow* FocusedWindow; // Will catch keyboard inputs
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
ImGuiID HoveredId; // Hovered widget
ImGuiID HoveredIdPreviousFrame;
ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdPreviousFrame;
bool ActiveIdIsAlive;
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
bool ActiveIdIsFocusedOnly; // Set only by active widget. Denote focus but no active interaction
ImGuiWindow* ActiveIdWindow;
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window.
ImVector<ImGuiIniData> Settings; // .ini Settings
float SettingsDirtyTimer; // Save .ini settinngs on disk when time reaches zero
int DisableHideTextAfterDoubleHash;
ImVector<ImGuiColMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
ImVector<ImGuiPopupRef> OpenedPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupRef> CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame)
// Storage for SetNexWindow** and SetNextTreeNode*** functions
ImVec2 SetNextWindowPosVal;
ImVec2 SetNextWindowSizeVal;
ImVec2 SetNextWindowContentSizeVal;
bool SetNextWindowCollapsedVal;
ImGuiSetCond SetNextWindowPosCond;
ImGuiSetCond SetNextWindowSizeCond;
ImGuiSetCond SetNextWindowContentSizeCond;
ImGuiSetCond SetNextWindowCollapsedCond;
bool SetNextWindowFocus;
bool SetNextTreeNodeOpenedVal;
ImGuiSetCond SetNextTreeNodeOpenedCond;
// Render
ImVector<ImDrawList*> RenderDrawLists[3];
float ModalWindowDarkeningRatio;
ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays
ImGuiMouseCursor MouseCursor;
ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_];
// Widget state
ImGuiTextEditState InputTextState;
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode
ImVec2 ActiveClickDeltaToCenter;
float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings
ImVec2 DragLastMouseDelta;
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
float DragSpeedScaleSlow;
float DragSpeedScaleFast;
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
char Tooltip[1024];
char* PrivateClipboard; // If no custom clipboard handler is defined
// Logging
bool LogEnabled;
FILE* LogFile; // If != NULL log to stdout/ file
ImGuiTextBuffer* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
int LogStartDepth;
int LogAutoExpandMaxDepth;
// Misc
float FramerateSecPerFrame[120]; // calculate estimate of framerate for user
int FramerateSecPerFrameIdx;
float FramerateSecPerFrameAccum;
bool CaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags
bool CaptureKeyboardNextFrame;
char TempBuffer[1024*3+1]; // temporary text buffer
ImGuiState()
{
Initialized = false;
Font = NULL;
FontSize = FontBaseSize = 0.0f;
FontTexUvWhitePixel = ImVec2(0.0f, 0.0f);
Time = 0.0f;
FrameCount = 0;
FrameCountRendered = -1;
CurrentWindow = NULL;
FocusedWindow = NULL;
HoveredWindow = NULL;
HoveredRootWindow = NULL;
HoveredId = 0;
HoveredIdPreviousFrame = 0;
ActiveId = 0;
ActiveIdPreviousFrame = 0;
ActiveIdIsAlive = false;
ActiveIdIsJustActivated = false;
ActiveIdIsFocusedOnly = false;
ActiveIdWindow = NULL;
MovedWindow = NULL;
SettingsDirtyTimer = 0.0f;
DisableHideTextAfterDoubleHash = 0;
SetNextWindowPosVal = ImVec2(0.0f, 0.0f);
SetNextWindowSizeVal = ImVec2(0.0f, 0.0f);
SetNextWindowCollapsedVal = false;
SetNextWindowPosCond = 0;
SetNextWindowSizeCond = 0;
SetNextWindowCollapsedCond = 0;
SetNextWindowFocus = false;
SetNextTreeNodeOpenedVal = false;
SetNextTreeNodeOpenedCond = 0;
ScalarAsInputTextId = 0;
ActiveClickDeltaToCenter = ImVec2(0.0f, 0.0f);
DragCurrentValue = 0.0f;
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
DragSpeedDefaultRatio = 0.01f;
DragSpeedScaleSlow = 0.01f;
DragSpeedScaleFast = 10.0f;
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
memset(Tooltip, 0, sizeof(Tooltip));
PrivateClipboard = NULL;
ModalWindowDarkeningRatio = 0.0f;
OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
MouseCursor = ImGuiMouseCursor_Arrow;
LogEnabled = false;
LogFile = NULL;
LogClipboard = NULL;
LogStartDepth = 0;
LogAutoExpandMaxDepth = 2;
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
FramerateSecPerFrameIdx = 0;
FramerateSecPerFrameAccum = 0.0f;
CaptureMouseNextFrame = CaptureKeyboardNextFrame = false;
}
};
// Transient per-window data, reset at the beginning of the frame
// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered.
struct ImGuiDrawContext
{
ImVec2 CursorPos;
ImVec2 CursorPosPrevLine;
ImVec2 CursorStartPos;
ImVec2 CursorMaxPos; // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at the end of the frame
float CurrentLineHeight;
float CurrentLineTextBaseOffset;
float PrevLineHeight;
float PrevLineTextBaseOffset;
float LogLinePosY;
int TreeDepth;
ImGuiID LastItemID;
ImRect LastItemRect;
bool LastItemHoveredAndUsable;
bool LastItemHoveredRect;
bool MenuBarAppending;
float MenuBarOffsetX;
ImVector<ImGuiWindow*> ChildWindows;
ImGuiStorage* StateStorage;
ImGuiLayoutType LayoutType;
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
bool ButtonRepeat; // == ButtonRepeatStack.back() [empty == false]
bool AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true]
float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
ImVector<bool> ButtonRepeatStack;
ImVector<bool> AllowKeyboardFocusStack;
ImVector<float> ItemWidthStack;
ImVector<float> TextWrapPosStack;
ImVector<ImGuiGroupData>GroupStack;
ImGuiColorEditMode ColorEditMode;
int StackSizesBackup[6]; // Store size of various stacks for asserting
float ColumnsStartX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
int ColumnsCurrent;
int ColumnsCount;
ImVec2 ColumnsStartPos;
float ColumnsCellMinY;
float ColumnsCellMaxY;
bool ColumnsShowBorders;
ImGuiID ColumnsSetID;
ImVector<float> ColumnsOffsetsT; // Columns offset normalized 0.0 (far left) -> 1.0 (far right)
ImGuiDrawContext()
{
CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f);
CurrentLineHeight = PrevLineHeight = 0.0f;
CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
LogLinePosY = -1.0f;
TreeDepth = 0;
LastItemID = 0;
LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f);
LastItemHoveredAndUsable = LastItemHoveredRect = false;
MenuBarAppending = false;
MenuBarOffsetX = 0.0f;
StateStorage = NULL;
LayoutType = ImGuiLayoutType_Vertical;
ItemWidth = 0.0f;
ButtonRepeat = false;
AllowKeyboardFocus = true;
TextWrapPos = -1.0f;
ColorEditMode = ImGuiColorEditMode_RGB;
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
ColumnsStartX = 0.0f;
ColumnsOffsetX = 0.0f;
ColumnsCurrent = 0;
ColumnsCount = 1;
ColumnsStartPos = ImVec2(0.0f, 0.0f);
ColumnsCellMinY = ColumnsCellMaxY = 0.0f;
ColumnsShowBorders = true;
ColumnsSetID = 0;
}
};
// Windows data
struct ImGuiWindow
{
char* Name;
ImGuiID ID;
ImGuiWindowFlags Flags;
ImVec2 PosFloat;
ImVec2 Pos; // Position rounded-up to nearest pixel
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
ImVec2 SizeFull; // Size when non collapsed
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame
ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize()
ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect
ImGuiID MoveID; // == window->GetID("#MOVE")
ImVec2 Scroll;
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
bool ScrollbarX, ScrollbarY;
ImVec2 ScrollbarSizes; //
bool Active; // Set to true on Begin()
bool WasActive;
bool Accessed; // Set to true when any widget access the current window
bool Collapsed; // Set when collapsing window to become only title-bar
bool SkipItems; // == Visible && !Collapsed
int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
ImGuiID PopupID; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
int AutoFitFramesX, AutoFitFramesY;
bool AutoFitOnlyGrows;
int AutoPosLastDirection;
int HiddenFrames;
int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag.
int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag.
int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag.
bool SetWindowPosCenterWanted;
ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
ImRect ClippedWindowRect; // = ClipRect just after setup in Begin()
int LastFrameDrawn;
float ItemWidthDefault;
ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items
ImGuiStorage StateStorage;
float FontWindowScale; // Scale multiplier per-window
ImDrawList* DrawList;
ImGuiWindow* RootWindow;
ImGuiWindow* RootNonPopupWindow;
// Focus
int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
int FocusIdxAllRequestCurrent; // Item being requested for focus
int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus
int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)
int FocusIdxTabRequestNext; // "
public:
ImGuiWindow(const char* name);
~ImGuiWindow();
ImGuiID GetID(const char* str, const char* str_end = NULL);
ImGuiID GetID(const void* ptr);
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; }
float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; }
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; }
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
ImU32 Color(ImGuiCol idx, float a=1.f) const { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * a; return ImGui::ColorConvertFloat4ToU32(c); }
ImU32 Color(const ImVec4& col) const { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); }
};
//-----------------------------------------------------------------------------
// Internal API
// No guarantee of forward compatibility here.
//-----------------------------------------------------------------------------
namespace ImGui
{
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiState& g = *GImGui; return g.CurrentWindow; } // If this ever crash it means that ImGui::NewFrame() has never been called (which is illegal). We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
inline ImGuiWindow* GetCurrentWindow() { ImGuiState& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }
IMGUI_API ImGuiWindow* GetParentWindow();
IMGUI_API void FocusWindow(ImGuiWindow* window);
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void KeepAliveID(ImGuiID id);
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id);
IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged);
IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false);
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop = true); // Return true if focus is requested
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
// NB: All position are in absolute pixels coordinates (not window coordinates)
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL);
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
IMGUI_API void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false);
IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col);
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, ImGuiButtonFlags flags = 0);
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal);
IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power);
IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format);
IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power);
IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power);
IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format);
IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags);
IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags);
IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags);
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision);
IMGUI_API bool TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);
IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value);
IMGUI_API float RoundScalar(float value, int decimal_precision);
} // namespace ImGuiP

View File

@ -1,3 +1,6 @@
// [ImGui] this is a slightly modified version of stb_truetype.h 1.4
// [ImGui] we made a fix for using the END key on multi-line text edit, see https://github.com/ocornut/imgui/issues/275
// stb_textedit.h - v1.4 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools
//
@ -957,6 +960,8 @@ retry:
stb_textedit_move_to_first(state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
state->cursor = find.first_char + find.length;
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
state->cursor--;
state->has_preferred_x = 0;
break;
}
@ -977,6 +982,8 @@ retry:
stb_textedit_prep_selection_at_cursor(state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
state->cursor = state->select_end = find.first_char + find.length;
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
state->cursor = state->select_end = state->cursor - 1;
state->has_preferred_x = 0;
break;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB