Compare commits
160 Commits
Author | SHA1 | Date | |
---|---|---|---|
7751ce0a69 | |||
9bb95db68a | |||
0a8acf241c | |||
c388c7e6eb | |||
088df3d1ba | |||
09fae1c209 | |||
016dbb7472 | |||
6ec65c46aa | |||
0fa3d6e25f | |||
f898e658bb | |||
22fe7f23b1 | |||
b756510f21 | |||
b6ac371496 | |||
81b9480413 | |||
b9d9f62ae3 | |||
4b94454fb4 | |||
b86505bf2f | |||
df1c056c88 | |||
eb1b9d4521 | |||
d35ceb793e | |||
a61b92f362 | |||
51bbe1d961 | |||
e4d4dae3bf | |||
bd3c53754d | |||
a1162ac001 | |||
618a42acf8 | |||
3cd1b8a37b | |||
746951691a | |||
8eafb373f7 | |||
fec4232c79 | |||
85672fec2e | |||
d5ed586d70 | |||
d58a029285 | |||
6e039c8b7d | |||
05a42ba3a6 | |||
da2ccf0a78 | |||
3e647d86aa | |||
0e0cd5e705 | |||
8d32fcb7d4 | |||
4ea2af7ea5 | |||
3773fb4117 | |||
24028911e3 | |||
3fd68c3a31 | |||
1cf4b313e2 | |||
2e85dce1ee | |||
62d233aaab | |||
3cdb4fa456 | |||
7439df0ba1 | |||
ad42787543 | |||
91059da1a5 | |||
b420a51541 | |||
c07ab1b56a | |||
22a9555a99 | |||
25080d53e5 | |||
43448d9c89 | |||
e20077fbd0 | |||
2c677c45c7 | |||
3b339efeb2 | |||
8fc50f5ed3 | |||
dd5d251273 | |||
2fb63b6068 | |||
cd3d027df0 | |||
7adad71042 | |||
88c33ecc29 | |||
1f63e01cc6 | |||
bd26de0628 | |||
5a9639b423 | |||
b90d0c558d | |||
51f8e33eb4 | |||
80dd1e1065 | |||
5f6b261c9b | |||
681ac5f777 | |||
0d344e1f03 | |||
d2b43f31e3 | |||
d17a586738 | |||
710b9b68b1 | |||
29ba288ea0 | |||
addfa75eb0 | |||
882072cf30 | |||
7bd507d266 | |||
1ff104641a | |||
3b8d1ec207 | |||
e9e1fd2b3c | |||
6062d18cf9 | |||
05f0993616 | |||
6dd2b13220 | |||
5864c45fe3 | |||
4bc3642bdb | |||
a3f32381c4 | |||
67f17a644c | |||
e807d97089 | |||
23d156908d | |||
42d4b4be6a | |||
efc473df98 | |||
bbda899801 | |||
a17885f470 | |||
7de89e0da3 | |||
7c61822d26 | |||
ca027e1754 | |||
c5dacee3a7 | |||
d6f6afabb3 | |||
76a39ad224 | |||
aa7fc37b37 | |||
c13c2449bb | |||
c2cb727ac9 | |||
47fd8431c1 | |||
926f7bfcc5 | |||
f6414f2011 | |||
931a4c5b49 | |||
c32221fa20 | |||
a165954a69 | |||
ddf8b280e9 | |||
969b1e0563 | |||
6e15b71663 | |||
ef628a0a9d | |||
df5a06f119 | |||
e9b697698a | |||
5240013c90 | |||
1956703c42 | |||
f5dbb0a973 | |||
ade21a1ad5 | |||
868ba05a13 | |||
152878571e | |||
fa0aa5ace6 | |||
6267905a17 | |||
1509b8f634 | |||
2bc6346b48 | |||
9169b2911c | |||
a4b96445e8 | |||
6c11d7623e | |||
6d6ee4e1f1 | |||
f33eb89018 | |||
e9b0a61f48 | |||
a8d3b045b7 | |||
a830037eab | |||
309ff44579 | |||
f30d23a502 | |||
a905505cca | |||
46eee0cee4 | |||
29863b55ef | |||
530f103dfe | |||
7a3e6aa38d | |||
cda3aecc6a | |||
b6d1d85d86 | |||
9a426faf4f | |||
b0d5600ffb | |||
c52a54ef43 | |||
cc9d63b46a | |||
d3ad5ce475 | |||
cb3d503941 | |||
ddc7f8b0b0 | |||
57ac561ecb | |||
2573ffb6fc | |||
c938affcac | |||
a1e176fb07 | |||
901e9890d4 | |||
f4ee74b312 | |||
64e5c2f127 | |||
e2655d104e | |||
e3001fb986 |
53
README.md
@ -1,16 +1,19 @@
|
||||
ImGui
|
||||
=====
|
||||
|
||||
ImGui is a bloat-free graphical user interface library for C++. It is portable, renderer agnostic and carries minimal amount of dependencies (only 3 files are needed). It is based on an "immediate" graphical user interface paradigm which allows you to build simple 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 carries minimal amount of dependencies (only 3 files are needed). It is based on an "immediate" graphical user interface paradigm which allows you to build user interfaces with ease.
|
||||
|
||||
ImGui is designed to allow programmers to create "content creation" or "debug" tools (as opposed to tools for the average end-user). It favors simplicity and thus lacks certain features normally found in more high-level libraries, such as string localisation.
|
||||
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
|
||||
|
||||
After ImGui is setup in your application, you can use it like in this example:
|
||||
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.
|
||||
|
||||
After ImGui is setup in your engine, you can use it like in this example:
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
Gallery
|
||||
-------
|
||||
@ -20,14 +23,54 @@ Gallery
|
||||

|
||||

|
||||
|
||||
UTF-8 is supported for text display and input. Here using M+ font to display Japanese:
|
||||
|
||||

|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
The Immediate Mode GUI paradigm may at first appear unusual to some users. This is mainly because "Retained Mode" GUIs have been so widespread and predominant. The following links can give you a better understanding about how Immediate Mode GUIs works.
|
||||
- [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html).
|
||||
- [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf).
|
||||
- [Jari Komppa's tutorial on building an ImGui library](http://iki.fi/sol/imgui/).
|
||||
- [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861).
|
||||
|
||||
Frequently Asked Question
|
||||
-------------------------
|
||||
<b>How do you use ImGui on a platform that may not have a mouse and keyboard?</b>
|
||||
|
||||
I recommend using [Synergy](http://synergy-project.org). With the uSynergy.c micro client running you can seamlessly use your PC input devices from a video game console or a tablet. ImGui was also designed to function with touch inputs if you increase the padding of widgets to compensate for the lack of precision of touch devices, but it is recommended you use a mouse to allow optimising for screen real-estate.
|
||||
|
||||
<b>I integrated ImGui in my engine and the text or lines are blurry..</b>
|
||||
|
||||
- Try adjusting ImGui::GetIO().PixelCenterOffset to 0.0f or 0.5f.
|
||||
- In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
|
||||
|
||||
<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. There's no reason you cannot, and 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.
|
||||
|
||||
<b>Can you reskin the look of ImGui?</b>
|
||||
|
||||
Yes, you can alter the look of the interface to some degree: changing colors, sizes and padding, font. However, as ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. The example below uses modified settings to create a more compact UI with different colors:
|
||||
|
||||

|
||||
|
||||
<b>Can you develop features xxxx for ImGui?</b>
|
||||
|
||||
Please use GitHub 'Issues' facilities to suggest and discuss improvements. If you are company and would like specific non-trivial features to be implemented, I am available for hire to work on or with ImGui. Donations are also welcome to support further work on the library.
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
Developed by [Omar Cornut](http://www.miracleworld.net). The library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com).
|
||||
|
||||
Embeds [proggy_clean](http://www.proggyfonts.net/) font by Tristan Grimmer (also MIT license).
|
||||
Embeds [proggy_clean](http://upperbounds.net) font by Tristan Grimmer (MIT license).
|
||||
Embeds [M+ fonts](http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html) font by Coji Morishita (free software license).
|
||||
|
||||
Inspiration, feedback, and testing: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Matt Willis. Thanks!
|
||||
Inspiration, feedback, and testing: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Thanks!
|
||||
|
||||
License
|
||||
-------
|
||||
|
@ -46,7 +46,7 @@
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;user32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;imm32.lib;user32.lib</AdditionalDependencies>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
</Link>
|
||||
@ -64,7 +64,7 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;user32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;imm32.lib;user32.lib</AdditionalDependencies>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
</Link>
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <windows.h>
|
||||
#include <imm.h>
|
||||
#include <mmsystem.h>
|
||||
#include <d3dx9.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
@ -20,7 +21,10 @@ struct CUSTOMVERTEX
|
||||
};
|
||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer)
|
||||
// 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)
|
||||
// - try adjusting ImGui::GetIO().PixelCenterOffset to 0.5f or 0.375f
|
||||
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
{
|
||||
size_t total_vtx_count = 0;
|
||||
@ -79,95 +83,25 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
||||
D3DXMatrixIdentity(&mat);
|
||||
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat);
|
||||
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat);
|
||||
D3DXMatrixOrthoOffCenterLH(&mat, 0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
||||
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++)
|
||||
{
|
||||
// Setup stack of clipping rectangles
|
||||
int clip_rect_buf_offset = 0;
|
||||
ImVector<ImVec4> clip_rect_stack;
|
||||
clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999));
|
||||
|
||||
// Render command list
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
const ImDrawCmd* pcmd_end = cmd_list->commands.end();
|
||||
for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++)
|
||||
{
|
||||
switch (pcmd->cmd_type)
|
||||
{
|
||||
case ImDrawCmdType_DrawTriangleList:
|
||||
{
|
||||
const ImVec4& clip_rect = clip_rect_stack.back();
|
||||
const RECT r = { (LONG)clip_rect.x, (LONG)clip_rect.y, (LONG)clip_rect.z, (LONG)clip_rect.w };
|
||||
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->SetScissorRect(&r);
|
||||
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, vtx_offset, pcmd->vtx_count/3);
|
||||
vtx_offset += pcmd->vtx_count;
|
||||
}
|
||||
break;
|
||||
|
||||
case ImDrawCmdType_PushClipRect:
|
||||
clip_rect_stack.push_back(cmd_list->clip_rect_buffer[clip_rect_buf_offset++]);
|
||||
break;
|
||||
|
||||
case ImDrawCmdType_PopClipRect:
|
||||
clip_rect_stack.pop_back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get text data in Win32 clipboard
|
||||
static const char* ImImpl_GetClipboardTextFn()
|
||||
{
|
||||
static char* buf_local = NULL;
|
||||
if (buf_local)
|
||||
{
|
||||
free(buf_local);
|
||||
buf_local = NULL;
|
||||
}
|
||||
|
||||
if (!OpenClipboard(NULL))
|
||||
return NULL;
|
||||
|
||||
HANDLE buf_handle = GetClipboardData(CF_TEXT);
|
||||
if (buf_handle == NULL)
|
||||
return NULL;
|
||||
|
||||
if (char* buf_global = (char*)GlobalLock(buf_handle))
|
||||
buf_local = strdup(buf_global);
|
||||
GlobalUnlock(buf_handle);
|
||||
CloseClipboard();
|
||||
|
||||
return buf_local;
|
||||
}
|
||||
|
||||
// Set text data in Win32 clipboard
|
||||
static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end)
|
||||
{
|
||||
if (!OpenClipboard(NULL))
|
||||
return;
|
||||
|
||||
if (!text_end)
|
||||
text_end = text + strlen(text);
|
||||
|
||||
const int buf_length = (text_end - text) + 1;
|
||||
HGLOBAL buf_handle = GlobalAlloc(GMEM_MOVEABLE, buf_length * sizeof(char));
|
||||
if (buf_handle == NULL)
|
||||
return;
|
||||
|
||||
char* buf_global = (char *)GlobalLock(buf_handle);
|
||||
memcpy(buf_global, text, text_end - text);
|
||||
buf_global[text_end - text] = 0;
|
||||
GlobalUnlock(buf_handle);
|
||||
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_TEXT, buf_handle);
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
HRESULT InitD3D(HWND hWnd)
|
||||
{
|
||||
@ -230,8 +164,8 @@ LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return true;
|
||||
case WM_CHAR:
|
||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||
if (wParam > 1 && wParam < 256)
|
||||
io.AddInputCharacter((char)wParam);
|
||||
if (wParam > 0 && wParam < 0x10000)
|
||||
io.AddInputCharacter((unsigned short)wParam);
|
||||
return true;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
@ -243,6 +177,19 @@ LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
// Notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed)
|
||||
static void ImImpl_ImeSetInputScreenPosFn(int x, int y)
|
||||
{
|
||||
if (HIMC himc = ImmGetContext(hWnd))
|
||||
{
|
||||
COMPOSITIONFORM cf;
|
||||
cf.ptCurrentPos.x = x;
|
||||
cf.ptCurrentPos.y = y;
|
||||
cf.dwStyle = CFS_FORCE_POSITION;
|
||||
ImmSetCompositionWindow(himc, &cf);
|
||||
}
|
||||
}
|
||||
|
||||
void InitImGui()
|
||||
{
|
||||
RECT rect;
|
||||
@ -271,8 +218,7 @@ void InitImGui()
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
|
||||
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
||||
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
||||
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
||||
io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn;
|
||||
|
||||
// Create the vertex buffer
|
||||
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||
@ -292,6 +238,35 @@ void InitImGui()
|
||||
}
|
||||
}
|
||||
|
||||
INT64 ticks_per_second = 0;
|
||||
INT64 time = 0;
|
||||
|
||||
void UpdateImGui()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup timestep
|
||||
INT64 current_time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - time) / ticks_per_second;
|
||||
time = current_time;
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse position, buttons, wheel from the window message callback)
|
||||
BYTE keystate[256];
|
||||
GetKeyboardState(keystate);
|
||||
for (int i = 0; i < 256; i++)
|
||||
io.KeysDown[i] = (keystate[i] & 0x80) != 0;
|
||||
io.KeyCtrl = (keystate[VK_CONTROL] & 0x80) != 0;
|
||||
io.KeyShift = (keystate[VK_SHIFT] & 0x80) != 0;
|
||||
// io.MousePos : filled by WM_MOUSEMOVE event
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
{
|
||||
// Register the window class
|
||||
@ -301,15 +276,20 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
// Create the application's window
|
||||
hWnd = CreateWindow(L"ImGui Example", L"ImGui DirectX9 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
|
||||
|
||||
INT64 ticks_per_second, time;
|
||||
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second))
|
||||
return 1;
|
||||
if (!QueryPerformanceCounter((LARGE_INTEGER *)&time))
|
||||
return 1;
|
||||
|
||||
// Initialize Direct3D
|
||||
if (InitD3D(hWnd) >= 0)
|
||||
if (InitD3D(hWnd) < 0)
|
||||
{
|
||||
if (g_pVB)
|
||||
g_pVB->Release();
|
||||
UnregisterClass(L"ImGui Example", wc.hInstance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Show the window
|
||||
ShowWindow(hWnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hWnd);
|
||||
@ -328,24 +308,10 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1) ImGui start frame, setup time delta & inputs
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
INT64 current_time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - time) / ticks_per_second;
|
||||
time = current_time;
|
||||
BYTE keystate[256];
|
||||
GetKeyboardState(keystate);
|
||||
for (int i = 0; i < 256; i++)
|
||||
io.KeysDown[i] = (keystate[i] & 0x80) != 0;
|
||||
io.KeyCtrl = (keystate[VK_CONTROL] & 0x80) != 0;
|
||||
io.KeyShift = (keystate[VK_SHIFT] & 0x80) != 0;
|
||||
// io.MousePos : filled by WM_MOUSEMOVE event
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
ImGui::NewFrame();
|
||||
UpdateImGui();
|
||||
|
||||
// 2) ImGui usage
|
||||
// Create a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
static bool show_test_window = true;
|
||||
static bool show_another_window = false;
|
||||
static float f;
|
||||
@ -359,19 +325,21 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
static int ms_per_frame_idx = 0;
|
||||
static float ms_per_frame_accum = 0.0f;
|
||||
ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame[ms_per_frame_idx] = io.DeltaTime * 1000.0f;
|
||||
ms_per_frame[ms_per_frame_idx] = ImGui::GetIO().DeltaTime * 1000.0f;
|
||||
ms_per_frame_accum += ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame_idx = (ms_per_frame_idx + 1) % 120;
|
||||
const float ms_per_frame_avg = ms_per_frame_accum / 120;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg);
|
||||
|
||||
// Show the ImGui test window
|
||||
// Most of user example code is in ImGui::ShowTestWindow()
|
||||
if (show_test_window)
|
||||
{
|
||||
// More example code in ShowTestWindow()
|
||||
ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
// Show another simple window
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
@ -379,15 +347,13 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3) Rendering
|
||||
// Clear frame buffer
|
||||
// Rendering
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
||||
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0);
|
||||
if (g_pd3dDevice->BeginScene() >= 0)
|
||||
{
|
||||
// Render ImGui
|
||||
ImGui::Render();
|
||||
g_pd3dDevice->EndScene();
|
||||
}
|
||||
@ -395,7 +361,6 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
}
|
||||
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
|
||||
if (g_pVB)
|
||||
g_pVB->Release();
|
||||
|
53
examples/opengl_example/Makefile
Normal file
@ -0,0 +1,53 @@
|
||||
#
|
||||
# Cross Platform Make file
|
||||
#
|
||||
# Compatible with Ubuntu 14.04.1 and Mac OS X
|
||||
#
|
||||
#
|
||||
# if you using Mac OS X:
|
||||
# You should install glew via homebrew
|
||||
# brew install glew
|
||||
# Also you'll need glfw
|
||||
# http://www.glfw.org
|
||||
#
|
||||
|
||||
CXX = g++
|
||||
|
||||
OBJS = main.o
|
||||
OBJS += ../../imgui.o
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
|
||||
ifeq ($(UNAME_S), Linux) #LINUX
|
||||
ECHO_MESSAGE = "Linux"
|
||||
CXXFLAGS = -I../../ `pkg-config --cflags glfw3`
|
||||
LIBS = `pkg-config --static --libs glfw3` -lGLEW
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_S), Darwin) #APPLE
|
||||
ECHO_MESSAGE = "Mac OS X"
|
||||
|
||||
LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
|
||||
LIBS += -L/usr/local/Cellar/glew/1.10.0/lib -L/usr/local/lib
|
||||
LIBS += -lglew -lglfw3
|
||||
|
||||
CXXFLAGS = -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include
|
||||
CXXFLAGS += -I../../
|
||||
|
||||
# CXXFLAGS += -D__APPLE__
|
||||
|
||||
endif
|
||||
|
||||
.cpp.o:
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
all:imgui_example
|
||||
@echo Build complete for $(ECHO_MESSAGE)
|
||||
|
||||
imgui_example:$(OBJS)
|
||||
$(CXX) -o imgui_example $(OBJS) $(CXXFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm $(OBJS)
|
||||
|
@ -1,158 +1,110 @@
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||
#include <Windows.h>
|
||||
#include <Imm.h>
|
||||
#endif
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h" // for .png loading
|
||||
#include "../../imgui.h"
|
||||
|
||||
// glew & glfw
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WGL
|
||||
#include <GLFW/glfw3native.h>
|
||||
#endif
|
||||
|
||||
static GLFWwindow* window;
|
||||
static GLuint vbo;
|
||||
static GLuint vao;
|
||||
static GLuint vertexShader;
|
||||
static GLuint fragmentShader;
|
||||
static GLuint shaderProgram;
|
||||
static GLuint fontTex;
|
||||
static ImVec2 mousePosScale(1.0f, 1.0f);
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer)
|
||||
// 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)
|
||||
// - try adjusting ImGui::GetIO().PixelCenterOffset to 0.5f or 0.375f
|
||||
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
{
|
||||
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)
|
||||
if (cmd_lists_count == 0)
|
||||
return;
|
||||
|
||||
// Copy all vertices into a single contiguous GL buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBindVertexArray(vao);
|
||||
glBufferData(GL_ARRAY_BUFFER, total_vtx_count * sizeof(ImDrawVert), NULL, GL_STREAM_DRAW);
|
||||
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);
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing
|
||||
// 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.
|
||||
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);
|
||||
|
||||
// Bind texture and enable our shader
|
||||
// Setup texture
|
||||
glBindTexture(GL_TEXTURE_2D, fontTex);
|
||||
glUseProgram(shaderProgram);
|
||||
const GLint uniMVP = glGetUniformLocation(shaderProgram, "MVP");
|
||||
const GLint uniClipRect = glGetUniformLocation(shaderProgram, "ClipRect");
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
const float height = ImGui::GetIO().DisplaySize.y;
|
||||
const float mvp[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 },
|
||||
};
|
||||
glUniformMatrix4fv(uniMVP, 1, GL_FALSE, &mvp[0][0]);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
{
|
||||
// Setup stack of clipping rectangles
|
||||
int clip_rect_buf_offset = 0;
|
||||
ImVector<ImVec4> clip_rect_stack;
|
||||
clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999));
|
||||
|
||||
// Render command list
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
const unsigned char* vtx_buffer = (const unsigned char*)cmd_list->vtx_buffer.begin();
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer+8));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer+16));
|
||||
|
||||
int vtx_offset = 0;
|
||||
const ImDrawCmd* pcmd_end = cmd_list->commands.end();
|
||||
for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++)
|
||||
{
|
||||
switch (pcmd->cmd_type)
|
||||
{
|
||||
case ImDrawCmdType_DrawTriangleList:
|
||||
glUniform4fv(uniClipRect, 1, (float*)&clip_rect_stack.back());
|
||||
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);
|
||||
vtx_offset += pcmd->vtx_count;
|
||||
break;
|
||||
|
||||
case ImDrawCmdType_PushClipRect:
|
||||
clip_rect_stack.push_back(cmd_list->clip_rect_buffer[clip_rect_buf_offset++]);
|
||||
break;
|
||||
|
||||
case ImDrawCmdType_PopClipRect:
|
||||
clip_rect_stack.pop_back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
// Cleanup GL state
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
// NB: ImGui already provide OS clipboard support for Windows so this isn't needed if you are using Windows only.
|
||||
static const char* ImImpl_GetClipboardTextFn()
|
||||
{
|
||||
return glfwGetClipboardString(window);
|
||||
}
|
||||
|
||||
static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end)
|
||||
static void ImImpl_SetClipboardTextFn(const char* text)
|
||||
{
|
||||
if (!text_end)
|
||||
text_end = text + strlen(text);
|
||||
|
||||
// Add a zero-terminator because glfw function doesn't take a size
|
||||
char* buf = (char*)malloc(text_end - text + 1);
|
||||
memcpy(buf, text, text_end-text);
|
||||
buf[text_end-text] = '\0';
|
||||
glfwSetClipboardString(window, buf);
|
||||
free(buf);
|
||||
glfwSetClipboardString(window, text);
|
||||
}
|
||||
|
||||
// Shader sources
|
||||
const GLchar* vertexSource =
|
||||
"#version 150 core\n"
|
||||
"uniform mat4 MVP;"
|
||||
"in vec2 i_pos;"
|
||||
"in vec2 i_uv;"
|
||||
"in vec4 i_col;"
|
||||
"out vec4 col;"
|
||||
"out vec2 pixel_pos;"
|
||||
"out vec2 uv;"
|
||||
"void main() {"
|
||||
" col = i_col;"
|
||||
" pixel_pos = i_pos;"
|
||||
" uv = i_uv;"
|
||||
" gl_Position = MVP * vec4(i_pos.x, i_pos.y, 0.0f, 1.0f);"
|
||||
"}";
|
||||
|
||||
const GLchar* fragmentSource =
|
||||
"#version 150 core\n"
|
||||
"uniform sampler2D Tex;"
|
||||
"uniform vec4 ClipRect;"
|
||||
"in vec4 col;"
|
||||
"in vec2 pixel_pos;"
|
||||
"in vec2 uv;"
|
||||
"out vec4 o_col;"
|
||||
"void main() {"
|
||||
" o_col = texture(Tex, uv) * col;"
|
||||
//" if (pixel_pos.x < ClipRect.x || pixel_pos.y < ClipRect.y || pixel_pos.x > ClipRect.z || pixel_pos.y > ClipRect.w) discard;" // Clipping: using discard
|
||||
//" if (step(ClipRect.x,pixel_pos.x) * step(ClipRect.y,pixel_pos.y) * step(pixel_pos.x,ClipRect.z) * step(pixel_pos.y,ClipRect.w) < 1.0f) discard;" // Clipping: using discard and step
|
||||
" o_col.w *= (step(ClipRect.x,pixel_pos.x) * step(ClipRect.y,pixel_pos.y) * step(pixel_pos.x,ClipRect.z) * step(pixel_pos.y,ClipRect.w));" // Clipping: branch-less, set alpha 0.0f
|
||||
"}";
|
||||
#ifdef _MSC_VER
|
||||
// Notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed)
|
||||
static void ImImpl_ImeSetInputScreenPosFn(int x, int y)
|
||||
{
|
||||
HWND hwnd = glfwGetWin32Window(window);
|
||||
if (HIMC himc = ImmGetContext(hwnd))
|
||||
{
|
||||
COMPOSITIONFORM cf;
|
||||
cf.ptCurrentPos.x = x;
|
||||
cf.ptCurrentPos.y = y;
|
||||
cf.dwStyle = CFS_FORCE_POSITION;
|
||||
ImmSetCompositionWindow(himc, &cf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// GLFW callbacks to get events
|
||||
static void glfw_error_callback(int error, const char* description)
|
||||
@ -160,10 +112,10 @@ static void glfw_error_callback(int error, const char* description)
|
||||
fputs(description, stderr);
|
||||
}
|
||||
|
||||
static float mouse_wheel = 0.0f;
|
||||
static void glfw_scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
mouse_wheel = (float)yoffset;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseWheel = (yoffset != 0.0f) ? yoffset > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1
|
||||
}
|
||||
|
||||
static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
@ -179,8 +131,8 @@ static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int act
|
||||
|
||||
static void glfw_char_callback(GLFWwindow* window, unsigned int c)
|
||||
{
|
||||
if (c > 0 && c <= 255)
|
||||
ImGui::GetIO().AddInputCharacter((char)c);
|
||||
if (c > 0 && c < 0x10000)
|
||||
ImGui::GetIO().AddInputCharacter((unsigned short)c);
|
||||
}
|
||||
|
||||
// OpenGL code based on http://open.gl tutorials
|
||||
@ -191,38 +143,30 @@ void InitGL()
|
||||
if (!glfwInit())
|
||||
exit(1);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
glfwWindowHint(GLFW_REFRESH_RATE, 60);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
window = glfwCreateWindow(1280, 720, "ImGui OpenGL example", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
glfwSetKeyCallback(window, glfw_key_callback);
|
||||
glfwSetScrollCallback(window, glfw_scroll_callback);
|
||||
glfwSetCharCallback(window, glfw_char_callback);
|
||||
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// After calling glewInit() our GL error state may be GL_INVALID_ENUM
|
||||
const GLenum err = glGetError();
|
||||
(void)err;
|
||||
IM_ASSERT(err == GL_NO_ERROR || err == GL_INVALID_ENUM);
|
||||
}
|
||||
|
||||
void InitImGui()
|
||||
{
|
||||
int w, h;
|
||||
int fb_w, fb_h;
|
||||
glfwGetWindowSize(window, &w, &h);
|
||||
glfwGetFramebufferSize(window, &fb_w, &fb_h);
|
||||
mousePosScale.x = (float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates.
|
||||
mousePosScale.y = (float)fb_h / h;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2((float)w, (float)h); // Display size, in pixels. For clamping windows positions.
|
||||
io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); // Display size, in pixels. For clamping windows positions.
|
||||
io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable)
|
||||
io.PixelCenterOffset = 0.5f; // Align OpenGL texels
|
||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime.
|
||||
io.PixelCenterOffset = 0.0f; // Align OpenGL texels
|
||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||
@ -243,62 +187,9 @@ void InitImGui()
|
||||
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
||||
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
||||
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
||||
|
||||
// Setup graphics backend
|
||||
GLint status = GL_TRUE;
|
||||
GLenum err = GL_NO_ERROR;
|
||||
err = glGetError(); IM_ASSERT(err == GL_NO_ERROR);
|
||||
|
||||
// Create and compile the vertex shader
|
||||
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexSource, NULL);
|
||||
glCompileShader(vertexShader);
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE)
|
||||
{
|
||||
char buffer[512];
|
||||
glGetShaderInfoLog(vertexShader, 1024, NULL, buffer);
|
||||
printf("%s", buffer);
|
||||
IM_ASSERT(status == GL_TRUE);
|
||||
}
|
||||
|
||||
// Create and compile the fragment shader
|
||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
|
||||
glCompileShader(fragmentShader);
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
|
||||
IM_ASSERT(status == GL_TRUE);
|
||||
|
||||
// Link the vertex and fragment shader into a shader program
|
||||
shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
glBindFragDataLocation(shaderProgram, 0, "o_col");
|
||||
glLinkProgram(shaderProgram);
|
||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &status);
|
||||
IM_ASSERT(status == GL_TRUE);
|
||||
|
||||
// Create Vertex Buffer Objects & Vertex Array Objects
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
GLint posAttrib = glGetAttribLocation(shaderProgram, "i_pos");
|
||||
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), 0);
|
||||
glEnableVertexAttribArray(posAttrib);
|
||||
|
||||
GLint uvAttrib = glGetAttribLocation(shaderProgram, "i_uv");
|
||||
glEnableVertexAttribArray(uvAttrib);
|
||||
glVertexAttribPointer(uvAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (void*)(2*sizeof(float)));
|
||||
|
||||
GLint colAttrib = glGetAttribLocation(shaderProgram, "i_col");
|
||||
glVertexAttribPointer(colAttrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (void*)(4*sizeof(float)));
|
||||
glEnableVertexAttribArray(colAttrib);
|
||||
err = glGetError(); IM_ASSERT(err == GL_NO_ERROR);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
#ifdef _MSC_VER
|
||||
io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn;
|
||||
#endif
|
||||
|
||||
// Load font texture
|
||||
glGenTextures(1, &fontTex);
|
||||
@ -306,53 +197,75 @@ void InitImGui()
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
#if 1
|
||||
// Default font (embedded in code)
|
||||
const void* png_data;
|
||||
unsigned int png_size;
|
||||
ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
|
||||
int tex_x, tex_y, tex_comp;
|
||||
void* tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 0);
|
||||
IM_ASSERT(tex_data != NULL);
|
||||
#else
|
||||
// Custom font from filesystem
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromFile("../../extra_fonts/mplus-2m-medium_18.fnt");
|
||||
IM_ASSERT(io.Font->IsLoaded());
|
||||
|
||||
int tex_x, tex_y, tex_comp;
|
||||
void* tex_data = stbi_load("../../extra_fonts/mplus-2m-medium_18.png", &tex_x, &tex_y, &tex_comp, 0);
|
||||
IM_ASSERT(tex_data != NULL);
|
||||
|
||||
// Automatically find white pixel from the texture we just loaded
|
||||
// (io.FontTexUvForWhite needs to contains UV coordinates pointing to a white pixel in order to render solid objects)
|
||||
for (int tex_data_off = 0; tex_data_off < tex_x*tex_y; tex_data_off++)
|
||||
if (((unsigned int*)tex_data)[tex_data_off] == 0xffffffff)
|
||||
{
|
||||
io.FontTexUvForWhite = ImVec2((float)(tex_data_off % tex_x)/(tex_x), (float)(tex_data_off / tex_x)/(tex_y));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
|
||||
stbi_image_free(tex_data);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
void UpdateImGui()
|
||||
{
|
||||
ImGui::Shutdown();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
glDeleteProgram(shaderProgram);
|
||||
glDeleteShader(fragmentShader);
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
// Setup timestep
|
||||
static double time = 0.0f;
|
||||
const double current_time = glfwGetTime();
|
||||
io.DeltaTime = (float)(current_time - time);
|
||||
time = current_time;
|
||||
|
||||
glfwTerminate();
|
||||
// Setup inputs
|
||||
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(window, &mouse_x, &mouse_y);
|
||||
io.MousePos = ImVec2((float)mouse_x * mousePosScale.x, (float)mouse_y * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
io.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0;
|
||||
io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0;
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
// Application code
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
InitGL();
|
||||
InitImGui();
|
||||
|
||||
double time = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseWheel = 0;
|
||||
glfwPollEvents();
|
||||
UpdateImGui();
|
||||
|
||||
// 1) ImGui start frame, setup time delta & inputs
|
||||
const double current_time = glfwGetTime();
|
||||
io.DeltaTime = (float)(current_time - time);
|
||||
time = current_time;
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(window, &mouse_x, &mouse_y);
|
||||
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.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0;
|
||||
io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0;
|
||||
io.MouseWheel = (mouse_wheel != 0) ? mouse_wheel > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1
|
||||
mouse_wheel = 0.0f;
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 2) ImGui usage
|
||||
// Create a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
static bool show_test_window = true;
|
||||
static bool show_another_window = false;
|
||||
static float f;
|
||||
@ -366,19 +279,21 @@ int main(int argc, char** argv)
|
||||
static int ms_per_frame_idx = 0;
|
||||
static float ms_per_frame_accum = 0.0f;
|
||||
ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame[ms_per_frame_idx] = io.DeltaTime * 1000.0f;
|
||||
ms_per_frame[ms_per_frame_idx] = ImGui::GetIO().DeltaTime * 1000.0f;
|
||||
ms_per_frame_accum += ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame_idx = (ms_per_frame_idx + 1) % 120;
|
||||
const float ms_per_frame_avg = ms_per_frame_accum / 120;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg);
|
||||
|
||||
// Show the ImGui test window
|
||||
// Most of user example code is in ImGui::ShowTestWindow()
|
||||
if (show_test_window)
|
||||
{
|
||||
// More example code in ShowTestWindow()
|
||||
ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
// Show another simple window
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
@ -386,14 +301,15 @@ int main(int argc, char** argv)
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3) Rendering
|
||||
// Rendering
|
||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||
glClearColor(0.8f, 0.6f, 0.6f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui::Render();
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
Shutdown();
|
||||
ImGui::Shutdown();
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\glfw\lib-msvc100;$(SolutionDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>opengl32.lib;imm32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>NotSet</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -63,7 +63,7 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\glfw\lib-msvc100;$(SolutionDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>opengl32.lib;imm32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>NotSet</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* stb_image - v1.43 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
||||
/* stb_image - v1.46 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
||||
when you control the images you're loading
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
avoid problematic images and only need the trivial interface
|
||||
|
||||
JPEG baseline (no JPEG progressive)
|
||||
PNG 8-bit-per-channel only
|
||||
PNG 1/2/4/8-bit-per-channel (16 bpc not supported)
|
||||
|
||||
TGA (not sure what subset, if a subset)
|
||||
BMP non-1bpp, non-RLE
|
||||
@ -28,11 +28,15 @@
|
||||
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
|
||||
|
||||
Latest revisions:
|
||||
1.xx (2014-09-26) 1/2/4-bit PNG support (both grayscale and paletted)
|
||||
1.46 (2014-08-26) fix broken tRNS chunk in non-paletted PNG
|
||||
1.45 (2014-08-16) workaround MSVC-ARM internal compiler error by wrapping malloc
|
||||
1.44 (2014-08-07) warnings
|
||||
1.43 (2014-07-15) fix MSVC-only bug in 1.42
|
||||
1.42 (2014-07-09) no _CRT_SECURE_NO_WARNINGS; error-path fixes; STBI_ASSERT
|
||||
1.41 (2014-06-25) fix search&replace that messed up comments/error messages
|
||||
1.40 (2014-06-22) gcc warning
|
||||
1.39 (2014-06-15) TGA optimization fix, multiple BMP fixes
|
||||
1.39 (2014-06-15) TGA optimization bugfix, multiple BMP fixes
|
||||
1.38 (2014-06-06) suppress MSVC run-time warnings, fix accidental rename of 'skip'
|
||||
1.37 (2014-06-04) remove duplicate typedef
|
||||
1.36 (2014-06-03) converted to header file, allow reading incorrect iphoned-images without iphone flag
|
||||
@ -60,17 +64,19 @@
|
||||
James "moose2000" Brown (iPhone PNG) David Woo
|
||||
Ben "Disch" Wenger (io callbacks) Roy Eltham
|
||||
Martin "SpartanJ" Golini Luke Graham
|
||||
Thomas Ruf
|
||||
Omar Cornut (1/2/4-bit png) Thomas Ruf
|
||||
John Bartholomew
|
||||
Optimizations & bugfixes Ken Hamada
|
||||
Fabian "ryg" Giesen Cort Stratton
|
||||
Arseny Kapoulkine Blazej Dariusz Roszkowski
|
||||
Thibault Reuille
|
||||
If your name should be here but Paul Du Bois
|
||||
isn't, let Sean know. Guillaume George
|
||||
Paul Du Bois
|
||||
Guillaume George
|
||||
Jerry Jansson
|
||||
Hayaki Saito
|
||||
Johan Duparc
|
||||
If your name should be here but Hayaki Saito
|
||||
isn't, let Sean know. Johan Duparc
|
||||
Ronny Chevalier
|
||||
Michal Cichon
|
||||
*/
|
||||
|
||||
#ifndef STBI_INCLUDE_STB_IMAGE_H
|
||||
@ -525,6 +531,11 @@ static int stbi__err(const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *stbi__malloc(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
// stbi__err - error
|
||||
// stbi__errpf - error returning pointer to float
|
||||
// stbi__errpuc - error returning pointer to unsigned char
|
||||
@ -577,11 +588,11 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp
|
||||
FILE *stbi__fopen(char const *filename, char const *mode)
|
||||
{
|
||||
FILE *f;
|
||||
#if _MSC_VER >= 1400
|
||||
if (0 != fopen_s(&f, filename, "rb"))
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
if (0 != fopen_s(&f, filename, mode))
|
||||
f=0;
|
||||
#else
|
||||
f = fopen(filename, "rb");
|
||||
f = fopen(filename, mode);
|
||||
#endif
|
||||
return f;
|
||||
}
|
||||
@ -756,7 +767,7 @@ static void stbi__refill_buffer(stbi__context *s)
|
||||
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
|
||||
if (n == 0) {
|
||||
// at end of file, treat same as if from memory, but need to handle case
|
||||
// where s->img_buffer isn't pointing to safe memory, stbi__err.g. 0-byte file
|
||||
// where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
|
||||
s->read_from_callbacks = 0;
|
||||
s->img_buffer = s->buffer_start;
|
||||
s->img_buffer_end = s->buffer_start+1;
|
||||
@ -854,7 +865,7 @@ static stbi__uint32 stbi__get32le(stbi__context *s)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// generic converter from built-in img_n to req_comp
|
||||
// individual types do this automatically as much as possible (stbi__err.g. jpeg
|
||||
// individual types do this automatically as much as possible (e.g. jpeg
|
||||
// does all cases internally since it needs to colorspace convert anyway,
|
||||
// and it never has alpha, so very few cases ). png can automatically
|
||||
// interleave an alpha=255 channel, but falls back to this for other cases
|
||||
@ -875,7 +886,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
||||
if (req_comp == img_n) return data;
|
||||
STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
|
||||
|
||||
good = (unsigned char *) malloc(req_comp * x * y);
|
||||
good = (unsigned char *) stbi__malloc(req_comp * x * y);
|
||||
if (good == NULL) {
|
||||
free(data);
|
||||
return stbi__errpuc("outofmem", "Out of memory");
|
||||
@ -915,7 +926,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
||||
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
|
||||
{
|
||||
int i,k,n;
|
||||
float *output = (float *) malloc(x * y * comp * sizeof(float));
|
||||
float *output = (float *) stbi__malloc(x * y * comp * sizeof(float));
|
||||
if (output == NULL) { free(data); return stbi__errpf("outofmem", "Out of memory"); }
|
||||
// compute number of non-alpha components
|
||||
if (comp & 1) n = comp; else n = comp-1;
|
||||
@ -933,7 +944,7 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
|
||||
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp)
|
||||
{
|
||||
int i,k,n;
|
||||
stbi_uc *output = (stbi_uc *) malloc(x * y * comp);
|
||||
stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp);
|
||||
if (output == NULL) { free(data); return stbi__errpuc("outofmem", "Out of memory"); }
|
||||
// compute number of non-alpha components
|
||||
if (comp & 1) n = comp; else n = comp-1;
|
||||
@ -1601,16 +1612,16 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
||||
z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
|
||||
|
||||
for (i=0; i < s->img_n; ++i) {
|
||||
// number of effective pixels (stbi__err.g. for non-interleaved MCU)
|
||||
// number of effective pixels (e.g. for non-interleaved MCU)
|
||||
z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;
|
||||
z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;
|
||||
// to simplify generation, we'll allocate enough memory to decode
|
||||
// the bogus oversized data from using interleaved MCUs and their
|
||||
// big blocks (stbi__err.g. a 16x16 iMCU on an image of width 33); we won't
|
||||
// big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
|
||||
// discard the extra data until colorspace conversion
|
||||
z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
|
||||
z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
|
||||
z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15);
|
||||
z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15);
|
||||
if (z->img_comp[i].raw_data == NULL) {
|
||||
for(--i; i >= 0; --i) {
|
||||
free(z->img_comp[i].raw_data);
|
||||
@ -1626,7 +1637,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// use comparisons since in some cases we handle more than one case (stbi__err.g. stbi__SOF)
|
||||
// use comparisons since in some cases we handle more than one case (e.g. stbi__SOF)
|
||||
#define stbi__DNL(x) ((x) == 0xdc)
|
||||
#define stbi__SOI(x) ((x) == 0xd8)
|
||||
#define stbi__EOI(x) ((x) == 0xd9)
|
||||
@ -1875,7 +1886,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
||||
|
||||
// allocate line buffer big enough for upsampling off the edges
|
||||
// with upsample factor of 4
|
||||
z->img_comp[k].linebuf = (stbi_uc *) malloc(z->s->img_x + 3);
|
||||
z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3);
|
||||
if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
|
||||
|
||||
r->hs = z->img_h_max / z->img_comp[k].h;
|
||||
@ -1893,7 +1904,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
||||
}
|
||||
|
||||
// can't error after this so, this is safe
|
||||
output = (stbi_uc *) malloc(n * z->s->img_x * z->s->img_y + 1);
|
||||
output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1);
|
||||
if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
|
||||
|
||||
// now go ahead and resample
|
||||
@ -2015,7 +2026,7 @@ stbi_inline static int stbi__bit_reverse(int v, int bits)
|
||||
{
|
||||
STBI_ASSERT(bits <= 16);
|
||||
// to bit reverse n bits, reverse 16 and shift
|
||||
// stbi__err.g. 11 bits, bit reverse and shift away 5
|
||||
// e.g. 11 bits, bit reverse and shift away 5
|
||||
return stbi__bitreverse16(v) >> (16-bits);
|
||||
}
|
||||
|
||||
@ -2338,7 +2349,7 @@ static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse
|
||||
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
|
||||
{
|
||||
stbi__zbuf a;
|
||||
char *p = (char *) malloc(initial_size);
|
||||
char *p = (char *) stbi__malloc(initial_size);
|
||||
if (p == NULL) return NULL;
|
||||
a.zbuffer = (stbi_uc *) buffer;
|
||||
a.zbuffer_end = (stbi_uc *) buffer + len;
|
||||
@ -2359,7 +2370,7 @@ STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
|
||||
STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
|
||||
{
|
||||
stbi__zbuf a;
|
||||
char *p = (char *) malloc(initial_size);
|
||||
char *p = (char *) stbi__malloc(initial_size);
|
||||
if (p == NULL) return NULL;
|
||||
a.zbuffer = (stbi_uc *) buffer;
|
||||
a.zbuffer_end = (stbi_uc *) buffer + len;
|
||||
@ -2386,7 +2397,7 @@ STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer
|
||||
STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
|
||||
{
|
||||
stbi__zbuf a;
|
||||
char *p = (char *) malloc(16384);
|
||||
char *p = (char *) stbi__malloc(16384);
|
||||
if (p == NULL) return NULL;
|
||||
a.zbuffer = (stbi_uc *) buffer;
|
||||
a.zbuffer_end = (stbi_uc *) buffer+len;
|
||||
@ -2477,89 +2488,144 @@ static int stbi__paeth(int a, int b, int c)
|
||||
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
|
||||
|
||||
// create the png data from post-deflated data
|
||||
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y)
|
||||
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
|
||||
{
|
||||
stbi__context *s = a->s;
|
||||
stbi__uint32 i,j,stride = x*out_n;
|
||||
stbi__uint32 img_len;
|
||||
int k;
|
||||
int img_n = s->img_n; // copy it into a local for later
|
||||
stbi_uc* line8 = NULL; // point into raw when depth==8 else temporary local buffer
|
||||
|
||||
STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
|
||||
a->out = (stbi_uc *) malloc(x * y * out_n);
|
||||
a->out = (stbi_uc *) stbi__malloc(x * y * out_n);
|
||||
if (!a->out) return stbi__err("outofmem", "Out of memory");
|
||||
|
||||
img_len = ((((img_n * x * depth) + 7) >> 3) + 1) * y;
|
||||
if (s->img_x == x && s->img_y == y) {
|
||||
if (raw_len != (img_n * x + 1) * y) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
} else { // interlaced:
|
||||
if (raw_len < (img_n * x + 1) * y) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
}
|
||||
|
||||
if (depth != 8) {
|
||||
line8 = (stbi_uc *) stbi__malloc((x+7) * out_n); // allocate buffer for one scanline
|
||||
if (!line8) return stbi__err("outofmem", "Out of memory");
|
||||
}
|
||||
|
||||
for (j=0; j < y; ++j) {
|
||||
stbi_uc *in;
|
||||
stbi_uc *cur = a->out + stride*j;
|
||||
stbi_uc *prior = cur - stride;
|
||||
int filter = *raw++;
|
||||
if (filter > 4) return stbi__err("invalid filter","Corrupt PNG");
|
||||
if (filter > 4) {
|
||||
if (depth != 8) free(line8);
|
||||
return stbi__err("invalid filter","Corrupt PNG");
|
||||
}
|
||||
|
||||
if (depth == 8) {
|
||||
in = raw;
|
||||
raw += x*img_n;
|
||||
}
|
||||
else {
|
||||
// unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
|
||||
// png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
|
||||
in = line8;
|
||||
stbi_uc* decode_out = line8;
|
||||
stbi_uc scale = (color == 0) ? 0xFF/((1<<depth)-1) : 1; // scale grayscale values to 0..255 range
|
||||
if (depth == 4) {
|
||||
for (k=x*img_n; k >= 1; k-=2, raw++) {
|
||||
*decode_out++ = scale * ((*raw >> 4) );
|
||||
*decode_out++ = scale * ((*raw ) & 0x0f);
|
||||
}
|
||||
} else if (depth == 2) {
|
||||
for (k=x*img_n; k >= 1; k-=4, raw++) {
|
||||
*decode_out++ = scale * ((*raw >> 6) );
|
||||
*decode_out++ = scale * ((*raw >> 4) & 0x03);
|
||||
*decode_out++ = scale * ((*raw >> 2) & 0x03);
|
||||
*decode_out++ = scale * ((*raw ) & 0x03);
|
||||
}
|
||||
} else if (depth == 1) {
|
||||
for (k=x*img_n; k >= 1; k-=8, raw++) {
|
||||
*decode_out++ = scale * ((*raw >> 7) );
|
||||
*decode_out++ = scale * ((*raw >> 6) & 0x01);
|
||||
*decode_out++ = scale * ((*raw >> 5) & 0x01);
|
||||
*decode_out++ = scale * ((*raw >> 4) & 0x01);
|
||||
*decode_out++ = scale * ((*raw >> 3) & 0x01);
|
||||
*decode_out++ = scale * ((*raw >> 2) & 0x01);
|
||||
*decode_out++ = scale * ((*raw >> 1) & 0x01);
|
||||
*decode_out++ = scale * ((*raw ) & 0x01);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if first row, use special filter that doesn't sample previous row
|
||||
if (j == 0) filter = first_row_filter[filter];
|
||||
|
||||
// handle first pixel explicitly
|
||||
for (k=0; k < img_n; ++k) {
|
||||
switch (filter) {
|
||||
case STBI__F_none : cur[k] = raw[k]; break;
|
||||
case STBI__F_sub : cur[k] = raw[k]; break;
|
||||
case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
||||
case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
|
||||
case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
|
||||
case STBI__F_avg_first : cur[k] = raw[k]; break;
|
||||
case STBI__F_paeth_first: cur[k] = raw[k]; break;
|
||||
case STBI__F_none : cur[k] = in[k]; break;
|
||||
case STBI__F_sub : cur[k] = in[k]; break;
|
||||
case STBI__F_up : cur[k] = STBI__BYTECAST(in[k] + prior[k]); break;
|
||||
case STBI__F_avg : cur[k] = STBI__BYTECAST(in[k] + (prior[k]>>1)); break;
|
||||
case STBI__F_paeth : cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(0,prior[k],0)); break;
|
||||
case STBI__F_avg_first : cur[k] = in[k]; break;
|
||||
case STBI__F_paeth_first: cur[k] = in[k]; break;
|
||||
}
|
||||
}
|
||||
if (img_n != out_n) cur[img_n] = 255;
|
||||
raw += img_n;
|
||||
in += img_n;
|
||||
cur += out_n;
|
||||
prior += out_n;
|
||||
// this is a little gross, so that we don't switch per-pixel or per-component
|
||||
if (img_n == out_n) {
|
||||
#define CASE(f) \
|
||||
case f: \
|
||||
for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \
|
||||
for (i=x-1; i >= 1; --i, in+=img_n,cur+=img_n,prior+=img_n) \
|
||||
for (k=0; k < img_n; ++k)
|
||||
switch (filter) {
|
||||
CASE(STBI__F_none) cur[k] = raw[k]; break;
|
||||
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-img_n]); break;
|
||||
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
||||
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-img_n])>>1)); break;
|
||||
CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-img_n],prior[k],prior[k-img_n])); break;
|
||||
CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-img_n] >> 1)); break;
|
||||
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-img_n],0,0)); break;
|
||||
CASE(STBI__F_none) cur[k] = in[k]; break;
|
||||
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(in[k] + cur[k-img_n]); break;
|
||||
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(in[k] + prior[k]); break;
|
||||
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(in[k] + ((prior[k] + cur[k-img_n])>>1)); break;
|
||||
CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-img_n],prior[k],prior[k-img_n])); break;
|
||||
CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(in[k] + (cur[k-img_n] >> 1)); break;
|
||||
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-img_n],0,0)); break;
|
||||
}
|
||||
#undef CASE
|
||||
} else {
|
||||
STBI_ASSERT(img_n+1 == out_n);
|
||||
#define CASE(f) \
|
||||
case f: \
|
||||
for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \
|
||||
for (i=x-1; i >= 1; --i, cur[img_n]=255,in+=img_n,cur+=out_n,prior+=out_n) \
|
||||
for (k=0; k < img_n; ++k)
|
||||
switch (filter) {
|
||||
CASE(STBI__F_none) cur[k] = raw[k]; break;
|
||||
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break;
|
||||
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
||||
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break;
|
||||
CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break;
|
||||
CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break;
|
||||
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break;
|
||||
CASE(STBI__F_none) cur[k] = in[k]; break;
|
||||
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(in[k] + cur[k-out_n]); break;
|
||||
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(in[k] + prior[k]); break;
|
||||
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(in[k] + ((prior[k] + cur[k-out_n])>>1)); break;
|
||||
CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break;
|
||||
CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(in[k] + (cur[k-out_n] >> 1)); break;
|
||||
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-out_n],0,0)); break;
|
||||
}
|
||||
#undef CASE
|
||||
}
|
||||
}
|
||||
|
||||
if (depth != 8) free(line8);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, int interlaced)
|
||||
static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, int depth, int color, int interlaced)
|
||||
{
|
||||
stbi_uc *final;
|
||||
int p;
|
||||
if (!interlaced)
|
||||
return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y);
|
||||
return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y, depth, color);
|
||||
|
||||
// de-interlacing
|
||||
final = (stbi_uc *) malloc(a->s->img_x * a->s->img_y * out_n);
|
||||
final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n);
|
||||
for (p=0; p < 7; ++p) {
|
||||
int xorig[] = { 0,4,0,2,0,1,0 };
|
||||
int yorig[] = { 0,0,4,0,2,0,1 };
|
||||
@ -2570,7 +2636,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_l
|
||||
x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
|
||||
y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
|
||||
if (x && y) {
|
||||
if (!stbi__create_png_image_raw(a, raw, raw_len, out_n, x, y)) {
|
||||
stbi__uint32 img_len = ((((out_n * x * depth) + 7) >> 3) + 1) * y;
|
||||
if (!stbi__create_png_image_raw(a, raw, raw_len, out_n, x, y, depth, color)) {
|
||||
free(final);
|
||||
return 0;
|
||||
}
|
||||
@ -2579,8 +2646,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_l
|
||||
memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n,
|
||||
a->out + (j*x+i)*out_n, out_n);
|
||||
free(a->out);
|
||||
raw += (x*out_n+1)*y;
|
||||
raw_len -= (x*out_n+1)*y;
|
||||
raw += img_len;
|
||||
raw_len -= img_len;
|
||||
}
|
||||
}
|
||||
a->out = final;
|
||||
@ -2618,7 +2685,7 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
|
||||
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
|
||||
stbi_uc *p, *temp_out, *orig = a->out;
|
||||
|
||||
p = (stbi_uc *) malloc(pixel_count * pal_img_n);
|
||||
p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n);
|
||||
if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
||||
|
||||
// between here and free(out) below, exitting would leak
|
||||
@ -2710,7 +2777,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
||||
stbi_uc palette[1024], pal_img_n=0;
|
||||
stbi_uc has_trans=0, tc[3];
|
||||
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
|
||||
int first=1,k,interlace=0, is_iphone=0;
|
||||
int first=1,k,interlace=0, color=0, depth=0, is_iphone=0;
|
||||
stbi__context *s = z->s;
|
||||
|
||||
z->expanded = NULL;
|
||||
@ -2729,13 +2796,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
||||
stbi__skip(s, c.length);
|
||||
break;
|
||||
case PNG_TYPE('I','H','D','R'): {
|
||||
int depth,color,comp,filter;
|
||||
int comp,filter;
|
||||
if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
|
||||
first = 0;
|
||||
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
|
||||
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
||||
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
||||
depth = stbi__get8(s); if (depth != 8) return stbi__err("8bit only","PNG not supported: 8-bit only");
|
||||
depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only");
|
||||
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
|
||||
if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
|
||||
comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");
|
||||
@ -2819,7 +2886,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
||||
s->img_out_n = s->img_n+1;
|
||||
else
|
||||
s->img_out_n = s->img_n;
|
||||
if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0;
|
||||
if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0;
|
||||
if (has_trans)
|
||||
if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
|
||||
if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
|
||||
@ -2872,7 +2939,7 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
|
||||
}
|
||||
*x = p->s->img_x;
|
||||
*y = p->s->img_y;
|
||||
if (n) *n = p->s->img_n;
|
||||
if (n) *n = p->s->img_out_n;
|
||||
}
|
||||
free(p->out); p->out = NULL;
|
||||
free(p->expanded); p->expanded = NULL;
|
||||
@ -3074,7 +3141,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
||||
target = req_comp;
|
||||
else
|
||||
target = s->img_n; // if they want monochrome, we'll post-convert
|
||||
out = (stbi_uc *) malloc(target * s->img_x * s->img_y);
|
||||
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y);
|
||||
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
||||
if (bpp < 16) {
|
||||
int z=0;
|
||||
@ -3303,7 +3370,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
||||
*y = tga_height;
|
||||
if (comp) *comp = tga_comp;
|
||||
|
||||
tga_data = (unsigned char*)malloc( tga_width * tga_height * tga_comp );
|
||||
tga_data = (unsigned char*)stbi__malloc( tga_width * tga_height * tga_comp );
|
||||
if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
|
||||
|
||||
// skip to the data's starting position (offset usually = 0)
|
||||
@ -3322,7 +3389,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
||||
// any data to skip? (offset usually = 0)
|
||||
stbi__skip(s, tga_palette_start );
|
||||
// load the palette
|
||||
tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 );
|
||||
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 );
|
||||
if (!tga_palette) {
|
||||
free(tga_data);
|
||||
return stbi__errpuc("outofmem", "Out of memory");
|
||||
@ -3513,7 +3580,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
|
||||
return stbi__errpuc("bad compression", "PSD has an unknown compression format");
|
||||
|
||||
// Create the destination image.
|
||||
out = (stbi_uc *) malloc(4 * w*h);
|
||||
out = (stbi_uc *) stbi__malloc(4 * w*h);
|
||||
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
||||
pixelCount = w*h;
|
||||
|
||||
@ -3798,7 +3865,7 @@ static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int re
|
||||
stbi__get16be(s); //skip `pad'
|
||||
|
||||
// intermediate buffer is RGBA
|
||||
result = (stbi_uc *) malloc(x*y*4);
|
||||
result = (stbi_uc *) stbi__malloc(x*y*4);
|
||||
memset(result, 0xff, x*y*4);
|
||||
|
||||
if (!stbi__pic_load_core(s,x,y,comp, result)) {
|
||||
@ -4049,14 +4116,14 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
|
||||
|
||||
if (g->out == 0) {
|
||||
if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
|
||||
g->out = (stbi_uc *) malloc(4 * g->w * g->h);
|
||||
g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
|
||||
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
|
||||
stbi__fill_gif_background(g);
|
||||
} else {
|
||||
// animated-gif-only path
|
||||
if (((g->eflags & 0x1C) >> 2) == 3) {
|
||||
old_out = g->out;
|
||||
g->out = (stbi_uc *) malloc(4 * g->w * g->h);
|
||||
g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
|
||||
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
|
||||
memcpy(g->out, old_out, g->w*g->h*4);
|
||||
}
|
||||
@ -4279,7 +4346,7 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
||||
if (req_comp == 0) req_comp = 3;
|
||||
|
||||
// Read data
|
||||
hdr_data = (float *) malloc(height * width * req_comp * sizeof(float));
|
||||
hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float));
|
||||
|
||||
// Load image data
|
||||
// image data is stored as some number of sca
|
||||
@ -4318,7 +4385,7 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
||||
len <<= 8;
|
||||
len |= stbi__get8(s);
|
||||
if (len != width) { free(hdr_data); free(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
|
||||
if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4);
|
||||
if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4);
|
||||
|
||||
for (k = 0; k < 4; ++k) {
|
||||
i = 0;
|
||||
@ -4555,6 +4622,12 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
|
||||
|
||||
/*
|
||||
revision history:
|
||||
1.46 (2014-08-26)
|
||||
fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG
|
||||
1.45 (2014-08-16)
|
||||
fix MSVC-ARM internal compiler error by wrapping malloc
|
||||
1.44 (2014-08-07)
|
||||
various warning fixes from Ronny Chevalier
|
||||
1.43 (2014-07-15)
|
||||
fix MSVC-only compiler problem in code changed in 1.42
|
||||
1.42 (2014-07-09)
|
||||
|
BIN
extra_fonts/ProggyClean.zip
Normal file
BIN
extra_fonts/ProggySmall.zip
Normal file
100
extra_fonts/README.txt
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
Extra fonts for ImGui.
|
||||
THOSE FONTS ARE OPTIONAL.
|
||||
|
||||
ImGui embeds a copy of 'proggy_clean' that you can use without any external files.
|
||||
Export your own font with bmfont (www.angelcode.com/products/bmfont).
|
||||
|
||||
bmfont reads fonts (.ttf, .fon, etc.) and output a .fnt file and a texture file, e.g:
|
||||
|
||||
proggy_clean.fon --> [bmfont] ---> proggy_clean_13.fnt
|
||||
proggy_clean_13.png
|
||||
|
||||
If you need a free font that supports chinese/japanese characters, you can use the M+ fonts.
|
||||
TTF and sources are availables at http://mplus-fonts.sourceforge.jp/mplus-outline-fonts.
|
||||
This directory include some of the M+ fonts converted by bmfont.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Configure bmfont:
|
||||
|
||||
- Export .fnt as Binary
|
||||
- Output .png, 32-bits (or whatever is suitable for your loader/renderer)
|
||||
- Tip: uncheck "Render from TrueType outline" and "Font Smoothing" for best result with non-anti-aliased type fonts.
|
||||
But you can experiment with other settings if you want anti-aliased fonts.
|
||||
- Tip: use pngout.exe (http://advsys.net/ken/utils.htm) to further reduce the file size of .png files
|
||||
All files in this folder have been optimised with pngout.exe
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
(A) Use font data embedded in ImGui
|
||||
|
||||
// Access embedded font data
|
||||
const void* fnt_data; // pointer to FNT data
|
||||
unsigned fnt_size; // size of FNT data
|
||||
const void* png_data; // pointer to PNG data
|
||||
unsigned int png_size; // size of PNG data
|
||||
ImGui::GetDefaultFontData(&fnt_data, &fnt_size, &png_data, &png_size);
|
||||
|
||||
1. Load the .FNT data from 'fnt_data' (NB: this is done for you by default if you don't do anything)
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromMemory(fnt_data, fnt_size);
|
||||
|
||||
2. Load the .PNG data from 'png_data' into a texture
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
(B) Use fonts from external files
|
||||
|
||||
You need to set io.FontTexUvForWhite to UV coordinates pointing to a white pixel in the texture.
|
||||
You can either locate a white pixel manually or use code at runtime to find or write one.
|
||||
The OpenGL example include sample code to find a white pixel given an uncompressed 32-bits texture:
|
||||
|
||||
// Automatically find white pixel from the texture we just loaded
|
||||
// (io.FontTexUvForWhite needs to contains UV coordinates pointing to a white pixel in order to render solid objects)
|
||||
for (int tex_data_off = 0; tex_data_off < tex_x*tex_y; tex_data_off++)
|
||||
if (((unsigned int*)tex_data)[tex_data_off] == 0xffffffff)
|
||||
{
|
||||
io.FontTexUvForWhite = ImVec2((float)(tex_data_off % tex_x)/(tex_x), (float)(tex_data_off / tex_x)/(tex_y));
|
||||
break;
|
||||
}
|
||||
|
||||
1. Load the .FNT data, e.g.
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// proggy_clean_13 [default]
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromFile("proggy_clean_13.fnt");
|
||||
IM_ASSERT(io.Font->IsLoaded());
|
||||
io.FontTexUvForWhite = ImVec2(0.0f/256.0f,0.0f/128);
|
||||
io.FontYOffset = +1;
|
||||
|
||||
// proggy_small_12
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromFile("proggy_small_12.fnt");
|
||||
IM_ASSERT(io.Font->IsLoaded());
|
||||
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
||||
io.FontYOffset = +2;
|
||||
|
||||
// proggy_small_14
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromFile("proggy_small_14.fnt");
|
||||
IM_ASSERT(io.Font->IsLoaded());
|
||||
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
||||
io.FontYOffset = +3;
|
||||
|
||||
// courier_new_16
|
||||
io.Font->LoadFromFile("courier_new_16.fnt");
|
||||
io.FontTexUvForWhite = ImVec2(1.0f/256.0f,4.0f/128);
|
||||
|
||||
// courier_new_18
|
||||
io.Font->LoadFromFile("courier_new_18.fnt");
|
||||
io.FontTexUvForWhite = ImVec2(4.0f/256.0f,5.0f/256);
|
||||
|
||||
|
||||
2. Load the matching .PNG data into a texture
|
||||
|
||||
//-----------------------------------------------------------------------------
|
BIN
extra_fonts/courier_new_16.fnt
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
extra_fonts/courier_new_16.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
extra_fonts/courier_new_18.fnt
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
extra_fonts/courier_new_18.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
extra_fonts/mplus-2m-medium_18.fnt
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
extra_fonts/mplus-2m-medium_18.png
Normal file
After Width: | Height: | Size: 284 KiB |
BIN
extra_fonts/proggy_clean_13.fnt
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
extra_fonts/proggy_clean_13.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
extra_fonts/proggy_small_12.fnt
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
extra_fonts/proggy_small_12.png
Normal file
After Width: | Height: | Size: 949 B |
BIN
extra_fonts/proggy_small_14.fnt
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
extra_fonts/proggy_small_14.png
Normal file
After Width: | Height: | Size: 949 B |
24
imconfig.h
@ -1,18 +1,26 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER IMPLEMENTATION
|
||||
// This file contains compile-time options for ImGui.
|
||||
// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO().
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//----- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h
|
||||
//---- 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. Default to calling assert().
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
|
||||
//----- Define implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||
//---- Don't implement default clipboard handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
|
||||
|
||||
//---- Include imgui_user.cpp at the end of imgui.cpp so you can include code that extends ImGui using its private data/functions.
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_CPP
|
||||
|
||||
//---- Define implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||
@ -23,12 +31,14 @@
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
|
||||
//----- Freely implement extra functions within the ImGui:: namespace.
|
||||
//----- e.g. you can create variants of the ImGui::Value() helper for your low-level math types.
|
||||
//---- Freely implement extra functions within the ImGui:: namespace.
|
||||
//---- Declare helpers or widgets implemented in imgui_user.cpp or elsewhere, so end-user doesn't need to include multiple files.
|
||||
//---- e.g. you can create variants of the ImGui::Value() helper for your low-level math types.
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void Value(const char* prefix, cosnt MyVec2& v, const char* float_format = NULL);
|
||||
void Value(const char* prefix, cosnt MyVec4& v, const char* float_format = NULL);
|
||||
void Value(const char* prefix, const MyVec2& v, const char* float_format = NULL);
|
||||
void Value(const char* prefix, const MyVec4& v, const char* float_format = NULL);
|
||||
};
|
||||
*/
|
||||
|
||||
|
305
imgui.h
@ -1,4 +1,4 @@
|
||||
// ImGui library
|
||||
// ImGui library v1.13
|
||||
// See .cpp file for commentary.
|
||||
// See ImGui::ShowTestWindow() for sample code.
|
||||
// Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
|
||||
@ -17,7 +17,8 @@ struct ImGuiWindow;
|
||||
#include "imconfig.h"
|
||||
#include <float.h> // FLT_MAX
|
||||
#include <stdarg.h> // va_list
|
||||
#include <stdlib.h> // NULL
|
||||
#include <stddef.h> // ptrdiff_t
|
||||
#include <stdlib.h> // NULL, malloc
|
||||
|
||||
#ifndef IM_ASSERT
|
||||
#include <assert.h>
|
||||
@ -25,12 +26,13 @@ struct ImGuiWindow;
|
||||
#endif
|
||||
|
||||
typedef unsigned int ImU32;
|
||||
typedef unsigned short ImWchar;
|
||||
typedef ImU32 ImGuiID;
|
||||
typedef int ImGuiCol; // enum ImGuiCol_
|
||||
typedef int ImGuiKey; // enum ImGuiKey_
|
||||
typedef int ImGuiColorEditMode; // enum ImGuiColorEditMode_
|
||||
typedef ImU32 ImGuiWindowFlags; // enum ImGuiWindowFlags_
|
||||
typedef ImU32 ImGuiInputTextFlags; // enum ImGuiInputTextFlags_
|
||||
typedef int ImGuiWindowFlags; // enum ImGuiWindowFlags_
|
||||
typedef int ImGuiInputTextFlags; // enum ImGuiInputTextFlags_
|
||||
typedef ImBitmapFont* ImFont;
|
||||
|
||||
struct ImVec2
|
||||
@ -55,59 +57,68 @@ struct ImVec4
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace ImGui
|
||||
{
|
||||
// Proxy functions to access the MemAllocFn/MemFreeFn/MemReallocFn pointers in ImGui::GetIO(). The only reason they exist here is to allow ImVector<> to compile inline.
|
||||
void* MemAlloc(size_t sz);
|
||||
void MemFree(void* ptr);
|
||||
void* MemRealloc(void* ptr, size_t sz);
|
||||
};
|
||||
|
||||
// std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug).
|
||||
// this implementation does NOT call c++ constructors! we don't need them! also only provide the minimum functionalities we need.
|
||||
// Use '#define ImVector std::vector' if you want to use the STL type or your own type.
|
||||
// Our implementation does NOT call c++ constructors! because the data types we use don't need them (but that could be added as well). Only provide the minimum functionalities we need.
|
||||
#ifndef ImVector
|
||||
template<typename T>
|
||||
class ImVector
|
||||
{
|
||||
private:
|
||||
size_t _size;
|
||||
size_t _capacity;
|
||||
T* _data;
|
||||
size_t Size;
|
||||
size_t Capacity;
|
||||
T* Data;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
|
||||
ImVector() { _size = _capacity = 0; _data = NULL; }
|
||||
~ImVector() { if (_data) free(_data); }
|
||||
ImVector() { Size = Capacity = 0; Data = NULL; }
|
||||
~ImVector() { if (Data) ImGui::MemFree(Data); }
|
||||
|
||||
inline bool empty() const { return _size == 0; }
|
||||
inline size_t size() const { return _size; }
|
||||
inline size_t capacity() const { return _capacity; }
|
||||
inline bool empty() const { return Size == 0; }
|
||||
inline size_t size() const { return Size; }
|
||||
inline size_t capacity() const { return Capacity; }
|
||||
|
||||
inline value_type& at(size_t i) { IM_ASSERT(i < _size); return _data[i]; }
|
||||
inline const value_type& at(size_t i) const { IM_ASSERT(i < _size); return _data[i]; }
|
||||
inline value_type& operator[](size_t i) { IM_ASSERT(i < _size); return _data[i]; }
|
||||
inline const value_type& operator[](size_t i) const { IM_ASSERT(i < _size); return _data[i]; }
|
||||
inline value_type& at(size_t i) { IM_ASSERT(i < Size); return Data[i]; }
|
||||
inline const value_type& at(size_t i) const { IM_ASSERT(i < Size); return Data[i]; }
|
||||
inline value_type& operator[](size_t i) { IM_ASSERT(i < Size); return Data[i]; }
|
||||
inline const value_type& operator[](size_t i) const { IM_ASSERT(i < Size); return Data[i]; }
|
||||
|
||||
inline void clear() { if (_data) { _size = _capacity = 0; free(_data); _data = NULL; } }
|
||||
inline iterator begin() { return _data; }
|
||||
inline const iterator begin() const { return _data; }
|
||||
inline iterator end() { return _data + _size; }
|
||||
inline const iterator end() const { return _data + _size; }
|
||||
inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
|
||||
inline iterator begin() { return Data; }
|
||||
inline const_iterator begin() const { return Data; }
|
||||
inline iterator end() { return Data + Size; }
|
||||
inline const_iterator end() const { return Data + Size; }
|
||||
inline value_type& front() { return at(0); }
|
||||
inline const value_type& front() const { return at(0); }
|
||||
inline value_type& back() { IM_ASSERT(_size > 0); return at(_size-1); }
|
||||
inline const value_type& back() const { IM_ASSERT(_size > 0); return at(_size-1); }
|
||||
inline void swap(ImVector<T>& rhs) { const size_t rhs_size = rhs._size; rhs._size = _size; _size = rhs_size; const size_t rhs_cap = rhs._capacity; rhs._capacity = _capacity; _capacity = rhs_cap; value_type* rhs_data = rhs._data; rhs._data = _data; _data = rhs_data; }
|
||||
inline value_type& back() { IM_ASSERT(Size > 0); return at(Size-1); }
|
||||
inline const value_type& back() const { IM_ASSERT(Size > 0); return at(Size-1); }
|
||||
inline void swap(ImVector<T>& rhs) { const size_t rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; const size_t rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
|
||||
|
||||
inline void reserve(size_t new_capacity) { _data = (value_type*)realloc(_data, new_capacity * sizeof(value_type)); _capacity = new_capacity; }
|
||||
inline void resize(size_t new_size) { if (new_size > _capacity) reserve(new_size); _size = new_size; }
|
||||
inline void reserve(size_t new_capacity) { Data = (value_type*)ImGui::MemRealloc(Data, new_capacity * sizeof(value_type)); Capacity = new_capacity; }
|
||||
inline void resize(size_t new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; }
|
||||
|
||||
inline void push_back(const value_type& v) { if (_size == _capacity) reserve(_capacity ? _capacity * 2 : 4); _data[_size++] = v; }
|
||||
inline void pop_back() { IM_ASSERT(_size > 0); _size--; }
|
||||
inline void push_back(const value_type& v) { if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); Data[Size++] = v; }
|
||||
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
|
||||
|
||||
inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const int off = it - begin(); memmove(_data + off, _data + off + 1, (_size - off - 1) * sizeof(value_type)); _size--; return _data + off; }
|
||||
inline void insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const int off = it - begin(); if (_size == _capacity) reserve(_capacity ? _capacity * 2 : 4); if (off < (int)_size) memmove(_data + off + 1, _data + off, (_size - off) * sizeof(value_type)); _data[off] = v; _size++; }
|
||||
inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const ptrdiff_t off = it - begin(); memmove(Data + off, Data + off + 1, (Size - off - 1) * sizeof(value_type)); Size--; return Data + off; }
|
||||
inline void insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - off) * sizeof(value_type)); Data[off] = v; Size++; }
|
||||
};
|
||||
#endif // #ifndef ImVector
|
||||
|
||||
// Helpers at bottom of the file:
|
||||
// - if (IMGUI_ONCE_UPON_A_FRAME) // Execute a block of code once per frame only
|
||||
// - struct ImGuiTextFilter // Parse and apply text filter. In format "aaaaa[,bbbb][,ccccc]"
|
||||
// - struct ImGuiTextFilter // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
|
||||
// - struct ImGuiTextBuffer // Text buffer for logging/accumulating text
|
||||
// - struct ImGuiStorage // Custom key value storage (if you need to alter open/close states manually)
|
||||
// - struct ImDrawList // Draw command list
|
||||
@ -133,24 +144,31 @@ namespace ImGui
|
||||
void BeginChild(const char* str_id, ImVec2 size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0);
|
||||
void EndChild();
|
||||
bool GetWindowIsFocused();
|
||||
float GetWindowWidth();
|
||||
ImVec2 GetWindowPos(); // you should rarely need/care about the window position, but it can be useful if you want to use your own drawing
|
||||
void SetWindowPos(ImVec2 pos); // unchecked
|
||||
ImVec2 GetWindowSize();
|
||||
float GetWindowWidth();
|
||||
ImVec2 GetWindowPos(); // you should rarely need/care about the window position, but it can be useful if you want to use your own drawing.
|
||||
void SetWindowPos(const ImVec2& pos); // set current window pos.
|
||||
ImVec2 GetWindowContentRegionMin();
|
||||
ImVec2 GetWindowContentRegionMax();
|
||||
ImDrawList* GetWindowDrawList();
|
||||
void SetFontScale(float scale);
|
||||
void SetScrollPosHere();
|
||||
void SetTreeStateStorage(ImGuiStorage* tree);
|
||||
ImDrawList* GetWindowDrawList(); // get rendering command-list if you want to append your own draw primitives.
|
||||
void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontBaseScale if you want to scale all windows together.
|
||||
void SetScrollPosHere(); // adjust scrolling position to center into the current cursor position.
|
||||
void SetTreeStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it).
|
||||
ImGuiStorage* GetTreeStateStorage();
|
||||
void PushItemWidth(float item_width);
|
||||
void PopItemWidth();
|
||||
float GetItemWidth();
|
||||
void PushAllowKeyboardFocus(bool v);
|
||||
void PopAllowKeyboardFocus();
|
||||
void PushStyleColor(ImGuiCol idx, ImVec4 col);
|
||||
void PushStyleColor(ImGuiCol idx, const ImVec4& col);
|
||||
void PopStyleColor();
|
||||
|
||||
// Tooltip
|
||||
void SetTooltip(const char* fmt, ...); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). last call wins.
|
||||
void SetTooltipV(const char* fmt, va_list args);
|
||||
void BeginTooltip(); // use to create full-featured tooltip windows that aren't just text.
|
||||
void EndTooltip();
|
||||
|
||||
// Layout
|
||||
void Separator(); // horizontal line
|
||||
void SameLine(int column_x = 0, int spacing_w = -1); // call between widgets to layout them horizontally
|
||||
@ -160,9 +178,12 @@ namespace ImGui
|
||||
float GetColumnOffset(int column_index = -1);
|
||||
void SetColumnOffset(int column_index, float offset);
|
||||
float GetColumnWidth(int column_index = -1);
|
||||
ImVec2 GetCursorPos(); // cursor position relative to window position
|
||||
void SetCursorPos(ImVec2 p);
|
||||
void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match higher widgets.
|
||||
ImVec2 GetCursorPos(); // cursor position is relative to window position
|
||||
void SetCursorPos(const ImVec2& pos); // "
|
||||
void SetCursorPosX(float x); // "
|
||||
void SetCursorPosY(float y); // "
|
||||
ImVec2 GetCursorScreenPos(); // cursor position in screen space
|
||||
void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match subsequent (bigger) widgets.
|
||||
float GetTextLineSpacing();
|
||||
float GetTextLineHeight();
|
||||
|
||||
@ -175,26 +196,34 @@ namespace ImGui
|
||||
// Widgets
|
||||
void Text(const char* fmt, ...);
|
||||
void TextV(const char* fmt, va_list args);
|
||||
void TextColored(const ImVec4& col, const char* fmt, ...); // shortcut to doing PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
|
||||
void TextColoredV(const ImVec4& col, const char* fmt, va_list args);
|
||||
void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done to any bounded stack buffer, better for long chunks of text.
|
||||
void LabelText(const char* label, const char* fmt, ...);
|
||||
void LabelTextV(const char* label, const char* fmt, va_list args);
|
||||
void BulletText(const char* fmt, ...);
|
||||
void BulletTextV(const char* fmt, va_list args);
|
||||
bool Button(const char* label, ImVec2 size = ImVec2(0,0), bool repeat_when_held = false);
|
||||
bool SmallButton(const char* label);
|
||||
bool CollapsingHeader(const char* label, const char* str_id = NULL, const bool display_frame = true, const bool default_open = false);
|
||||
bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
|
||||
bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders.
|
||||
bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
|
||||
bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
|
||||
bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
|
||||
bool SliderAngle(const char* label, float* v, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); // *v in radians
|
||||
bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = "%.0f");
|
||||
void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0));
|
||||
void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0));
|
||||
void Checkbox(const char* label, bool* v);
|
||||
void CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
|
||||
void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float));
|
||||
void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float));
|
||||
bool Checkbox(const char* label, bool* v);
|
||||
bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
|
||||
bool RadioButton(const char* label, bool active);
|
||||
bool RadioButton(const char* label, int* v, int v_button);
|
||||
bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1);
|
||||
bool InputFloat3(const char* label, float v[3], int decimal_precision = -1);
|
||||
bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100);
|
||||
bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0);
|
||||
bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0);
|
||||
bool InputFloat2(const char* label, float v[2], int decimal_precision = -1);
|
||||
bool InputFloat3(const char* label, float v[3], int decimal_precision = -1);
|
||||
bool InputFloat4(const char* label, float v[4], int decimal_precision = -1);
|
||||
bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0);
|
||||
bool Combo(const char* label, int* current_item, const char** items, int items_count, int popup_height_items = 7);
|
||||
bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_height_items = 7); // Separate items with \0, end item-list with \0\0
|
||||
bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_height_items = 7);
|
||||
@ -202,10 +231,12 @@ namespace ImGui
|
||||
bool ColorEdit3(const char* label, float col[3]);
|
||||
bool ColorEdit4(const char* label, float col[4], bool show_alpha = true);
|
||||
void ColorEditMode(ImGuiColorEditMode mode);
|
||||
bool TreeNode(const char* str_label_id); // if returning 'true' the user is responsible for calling TreePop
|
||||
bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop
|
||||
bool TreeNode(const char* str_id, const char* fmt, ...); // "
|
||||
bool TreeNode(const void* ptr_id, const char* fmt, ...); // "
|
||||
void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layout purpose
|
||||
bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // "
|
||||
bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // "
|
||||
void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose
|
||||
void TreePush(const void* ptr_id = NULL); // "
|
||||
void TreePop();
|
||||
void OpenNextNode(bool open); // force open/close the next TreeNode or CollapsingHeader
|
||||
@ -221,22 +252,29 @@ namespace ImGui
|
||||
|
||||
// Logging
|
||||
void LogButtons();
|
||||
void LogToTTY(int max_depth);
|
||||
void LogToFile(int max_depth, const char* filename);
|
||||
void LogToClipboard(int max_depth);
|
||||
void LogToTTY(int max_depth = -1);
|
||||
void LogToFile(int max_depth = -1, const char* filename = NULL);
|
||||
void LogToClipboard(int max_depth = -1);
|
||||
|
||||
// Utilities
|
||||
void SetTooltip(const char* fmt, ...); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). (currently no contention handling, last call win)
|
||||
void SetNewWindowDefaultPos(ImVec2 pos); // set position of window that do
|
||||
void SetNewWindowDefaultPos(const ImVec2& pos); // set position of window that do
|
||||
bool IsHovered(); // was the last item active area hovered by mouse?
|
||||
bool IsClipped(ImVec2 item_size); // to perform coarse clipping on user's side (as an optimisation)
|
||||
ImVec2 GetItemBoxMin(); // get bounding box of last item
|
||||
ImVec2 GetItemBoxMax(); // get bounding box of last item
|
||||
bool IsClipped(const ImVec2& item_size); // to perform coarse clipping on user's side (as an optimisation)
|
||||
bool IsKeyPressed(int key_index, bool repeat = true); // key_index into the keys_down[512] array, imgui doesn't know the semantic of each entry
|
||||
bool IsMouseClicked(int button, bool repeat = false);
|
||||
ImVec2 GetMousePos();
|
||||
bool IsMouseDoubleClicked(int button);
|
||||
bool IsMouseHoveringWindow(); // is mouse hovering current window ("window" in API names always refer to current window)
|
||||
bool IsMouseHoveringAnyWindow(); // is mouse hovering any active imgui window
|
||||
bool IsMouseHoveringBox(const ImVec2& box_min, const ImVec2& box_max); // is mouse hovering given bounding box
|
||||
bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window
|
||||
ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
|
||||
float GetTime();
|
||||
int GetFrameCount();
|
||||
const char* GetStyleColorName(ImGuiCol idx);
|
||||
void GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const void** png_data, unsigned int* png_size);
|
||||
ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, const bool hide_text_after_hash = true);
|
||||
|
||||
}; // namespace ImGui
|
||||
|
||||
@ -260,10 +298,11 @@ enum ImGuiWindowFlags_
|
||||
enum ImGuiInputTextFlags_
|
||||
{
|
||||
// Default: 0
|
||||
ImGuiInputTextFlags_CharsDecimal = 1 << 0,
|
||||
ImGuiInputTextFlags_CharsHexadecimal = 1 << 1,
|
||||
ImGuiInputTextFlags_AutoSelectAll = 1 << 2,
|
||||
ImGuiInputTextFlags_AlignCenter = 1 << 3,
|
||||
ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/
|
||||
ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef
|
||||
ImGuiInputTextFlags_AutoSelectAll = 1 << 2, // Select entire text when first taking focus
|
||||
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 3, // Return 'true' when Enter is pressed (as opposed to when the value was modified)
|
||||
//ImGuiInputTextFlags_AlignCenter = 1 << 3,
|
||||
};
|
||||
|
||||
// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array
|
||||
@ -339,21 +378,21 @@ enum ImGuiColorEditMode_
|
||||
ImGuiColorEditMode_HEX = 2,
|
||||
};
|
||||
|
||||
// See constructor for comments of individual fields.
|
||||
struct ImGuiStyle
|
||||
{
|
||||
ImVec2 WindowPadding;
|
||||
ImVec2 WindowMinSize;
|
||||
ImVec2 FramePadding;
|
||||
ImVec2 ItemSpacing;
|
||||
ImVec2 ItemInnerSpacing;
|
||||
ImVec2 TouchExtraPadding;
|
||||
ImVec2 AutoFitPadding;
|
||||
float WindowFillAlphaDefault;
|
||||
float WindowRounding;
|
||||
float TreeNodeSpacing;
|
||||
float ColumnsMinSpacing;
|
||||
float ScrollBarWidth;
|
||||
float Alpha; // Global alpha applies to everything in ImGui
|
||||
ImVec2 WindowPadding; // Padding within a window
|
||||
ImVec2 WindowMinSize; // Minimum window size
|
||||
ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets)
|
||||
ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines
|
||||
ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
|
||||
ImVec2 TouchExtraPadding; // Expand bounding box for touch-based system where touch position is not accurate enough (unnecessary for mouse inputs). Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget running. So dont grow this too much!
|
||||
ImVec2 AutoFitPadding; // Extra space after auto-fit (double-clicking on resize grip)
|
||||
float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin()
|
||||
float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
|
||||
float TreeNodeSpacing; // Horizontal spacing when entering a tree node
|
||||
float ColumnsMinSpacing; // Minimum horizontal spacing between two columns
|
||||
float ScrollBarWidth; // Width of the vertical scroll bar
|
||||
ImVec4 Colors[ImGuiCol_COUNT];
|
||||
|
||||
ImGuiStyle();
|
||||
@ -363,7 +402,10 @@ struct ImGuiStyle
|
||||
// Read 'Programmer guide' section in .cpp file for general usage.
|
||||
struct ImGuiIO
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
// Settings (fill once) // Default value:
|
||||
//------------------------------------------------------------------
|
||||
|
||||
ImVec2 DisplaySize; // <unset> // Display size, in pixels. For clamping windows positions.
|
||||
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
|
||||
float IniSavingRate; // = 5.0f // Maximum time between saving .ini file, in seconds. Set to a negative value to disable .ini saving.
|
||||
@ -373,39 +415,67 @@ struct ImGuiIO
|
||||
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
|
||||
int KeyMap[ImGuiKey_COUNT]; // <unset> // Map of indices into the KeysDown[512] entries array
|
||||
ImFont Font; // <auto> // Gets passed to text functions. Typedef ImFont to the type you want (ImBitmapFont* or your own font).
|
||||
float FontHeight; // <auto> // Default font height, must be the vertical distance between two lines of text, aka == CalcTextSize(" ").y
|
||||
bool FontAllowScaling; // = false // Set to allow scaling text with CTRL+Wheel.
|
||||
float PixelCenterOffset; // = 0.5f // Set to 0.0f for DirectX <= 9, 0.5f for Direct3D >= 10 and OpenGL.
|
||||
float FontYOffset; // = 0.0f // Offset font rendering by xx pixels in Y axis.
|
||||
ImVec2 FontTexUvForWhite; // = (0.0f,0.0f) // Font texture must have a white pixel at this UV coordinate. Adjust if you are using custom texture.
|
||||
float FontBaseScale; // = 1.0f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()
|
||||
bool FontAllowUserScaling; // = false // Set to allow scaling text with CTRL+Wheel.
|
||||
ImWchar FontFallbackGlyph; // = '?' // Replacement glyph is one isn't found.
|
||||
float PixelCenterOffset; // = 0.0f // Try to set to 0.5f or 0.375f if rendering is blurry
|
||||
|
||||
// Settings - Functions (fill once)
|
||||
void (*RenderDrawListsFn)(ImDrawList** const draw_lists, int count); // Required
|
||||
const char* (*GetClipboardTextFn)(); // Required for clipboard support
|
||||
void (*SetClipboardTextFn)(const char* text, const char* text_end); // Required for clipboard support (nb- the string is *NOT* zero-terminated at 'text_end')
|
||||
//------------------------------------------------------------------
|
||||
// User Functions
|
||||
//------------------------------------------------------------------
|
||||
|
||||
// REQUIRED: rendering function.
|
||||
// See example code if you are unsure of how to implement this.
|
||||
void (*RenderDrawListsFn)(ImDrawList** const draw_lists, int count);
|
||||
|
||||
// Optional: access OS clipboard (default to use native Win32 clipboard on Windows, otherwise use a ImGui private clipboard)
|
||||
// Override to access OS clipboard on other architectures.
|
||||
const char* (*GetClipboardTextFn)();
|
||||
void (*SetClipboardTextFn)(const char* text);
|
||||
|
||||
// Optional: override memory allocations (default to posix malloc/realloc/free)
|
||||
void* (*MemAllocFn)(size_t sz);
|
||||
void* (*MemReallocFn)(void* ptr, size_t sz);
|
||||
void (*MemFreeFn)(void* ptr);
|
||||
|
||||
// Optional: notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed)
|
||||
void (*ImeSetInputScreenPosFn)(int x, int y);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Input - Fill before calling NewFrame()
|
||||
//------------------------------------------------------------------
|
||||
|
||||
ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
bool MouseDown[2]; // Mouse buttons
|
||||
bool MouseDown[5]; // Mouse buttons. ImGui itself only uses button 0 (left button) but you can use others as storage for convenience.
|
||||
int MouseWheel; // Mouse wheel: -1,0,+1
|
||||
bool KeyCtrl; // Keyboard modifier pressed: Control
|
||||
bool KeyShift; // Keyboard modifier pressed: Shift
|
||||
bool KeysDown[512]; // Keyboard keys that are pressed (in whatever order user naturally has access to keyboard data)
|
||||
char InputCharacters[16]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
|
||||
|
||||
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
|
||||
bool WantCaptureMouse; // ImGui is using your mouse input (= window is being hovered or widget is active).
|
||||
bool WantCaptureKeyboard; // imGui is using your keyboard input (= widget is active).
|
||||
ImWchar InputCharacters[16]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
|
||||
|
||||
// Function
|
||||
void AddInputCharacter(char c); // Helper to add a new character into InputCharacters[]
|
||||
void AddInputCharacter(ImWchar); // Helper to add a new character into InputCharacters[]
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
|
||||
//------------------------------------------------------------------
|
||||
|
||||
bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input)
|
||||
bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// [Internal] ImGui will maintain those fields for you
|
||||
//------------------------------------------------------------------
|
||||
|
||||
ImVec2 MousePosPrev;
|
||||
ImVec2 MouseDelta;
|
||||
bool MouseClicked[2];
|
||||
ImVec2 MouseClickedPos[2];
|
||||
float MouseClickedTime[2];
|
||||
bool MouseDoubleClicked[2];
|
||||
float MouseDownTime[2];
|
||||
bool MouseClicked[5];
|
||||
ImVec2 MouseClickedPos[5];
|
||||
float MouseClickedTime[5];
|
||||
bool MouseDoubleClicked[5];
|
||||
float MouseDownTime[5];
|
||||
float KeysDownTime[512];
|
||||
|
||||
ImGuiIO();
|
||||
@ -427,7 +497,7 @@ private:
|
||||
bool TryIsNewFrame() const { const int current_frame = ImGui::GetFrameCount(); if (LastFrame == current_frame) return false; LastFrame = current_frame; return true; }
|
||||
};
|
||||
|
||||
// Helper: Parse and apply text filter. In format "aaaaa[,bbbb][,ccccc]"
|
||||
// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
|
||||
struct ImGuiTextFilter
|
||||
{
|
||||
struct TextRange
|
||||
@ -441,7 +511,7 @@ struct ImGuiTextFilter
|
||||
const char* end() const { return e; }
|
||||
bool empty() const { return b == e; }
|
||||
char front() const { return *b; }
|
||||
static bool isblank(char c) { return c == ' ' && c == '\t'; }
|
||||
static bool isblank(char c) { return c == ' ' || c == '\t'; }
|
||||
void trim_blanks() { while (b < e && isblank(*b)) b++; while (e > b && isblank(*(e-1))) e--; }
|
||||
void split(char separator, ImVector<TextRange>& out);
|
||||
};
|
||||
@ -469,7 +539,7 @@ struct ImGuiTextBuffer
|
||||
size_t size() const { return Buf.size()-1; }
|
||||
bool empty() { return Buf.empty(); }
|
||||
void clear() { Buf.clear(); Buf.push_back(0); }
|
||||
void Append(const char* fmt, ...);
|
||||
void append(const char* fmt, ...);
|
||||
};
|
||||
|
||||
// Helper: Key->value storage
|
||||
@ -496,25 +566,12 @@ struct ImGuiStorage
|
||||
// Hold a series of drawing commands. The user provide a renderer for ImDrawList
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
enum ImDrawCmdType
|
||||
{
|
||||
ImDrawCmdType_DrawTriangleList,
|
||||
ImDrawCmdType_PushClipRect,
|
||||
ImDrawCmdType_PopClipRect,
|
||||
};
|
||||
|
||||
// sizeof() == 4
|
||||
struct ImDrawCmd
|
||||
{
|
||||
ImDrawCmdType cmd_type : 16;
|
||||
unsigned int vtx_count : 16;
|
||||
ImDrawCmd(ImDrawCmdType _cmd_type = ImDrawCmdType_DrawTriangleList, unsigned int _vtx_count = 0) { cmd_type = _cmd_type; vtx_count = _vtx_count; }
|
||||
unsigned int vtx_count;
|
||||
ImVec4 clip_rect;
|
||||
};
|
||||
|
||||
#ifndef IMDRAW_TEX_UV_FOR_WHITE
|
||||
#define IMDRAW_TEX_UV_FOR_WHITE ImVec2(0,0)
|
||||
#endif
|
||||
|
||||
// sizeof() == 20
|
||||
struct ImDrawVert
|
||||
{
|
||||
@ -527,18 +584,20 @@ struct ImDrawVert
|
||||
// User is responsible for providing a renderer for this in ImGuiIO::RenderDrawListFn
|
||||
struct ImDrawList
|
||||
{
|
||||
ImVector<ImDrawCmd> commands;
|
||||
// This is what you have to render
|
||||
ImVector<ImDrawCmd> commands; // commands
|
||||
ImVector<ImDrawVert> vtx_buffer; // each command consume ImDrawCmd::vtx_count of those
|
||||
ImVector<ImVec4> clip_rect_buffer; // each PushClipRect command consume 1 of those
|
||||
ImVector<ImVec4> clip_rect_stack_; // [internal] clip rect stack while building the command-list (so text command can perform clipping early on)
|
||||
ImDrawVert* vtx_write_; // [internal] point within vtx_buffer after each add command. allow us to use less [] and .resize on the vector (often slow on windows/debug)
|
||||
|
||||
// [Internal to ImGui]
|
||||
ImVector<ImVec4> clip_rect_stack; // [internal] clip rect stack while building the command-list (so text command can perform clipping early on)
|
||||
ImDrawVert* vtx_write; // [internal] point within vtx_buffer after each add command (to avoid using the ImVector<> operators too much)
|
||||
|
||||
ImDrawList() { Clear(); }
|
||||
|
||||
void Clear();
|
||||
void PushClipRect(const ImVec4& clip_rect);
|
||||
void PopClipRect();
|
||||
void AddCommand(ImDrawCmdType cmd_type, int vtx_count);
|
||||
void ReserveVertices(unsigned int vtx_count);
|
||||
void AddVtx(const ImVec2& pos, ImU32 col);
|
||||
void AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col);
|
||||
|
||||
@ -607,7 +666,7 @@ struct ImBitmapFont
|
||||
#pragma pack(pop)
|
||||
|
||||
unsigned char* Data; // Raw data, content of .fnt file
|
||||
int DataSize; //
|
||||
size_t DataSize; //
|
||||
bool DataOwned; //
|
||||
const FntInfo* Info; // (point into raw data)
|
||||
const FntCommon* Common; // (point into raw data)
|
||||
@ -622,13 +681,15 @@ struct ImBitmapFont
|
||||
ImBitmapFont();
|
||||
~ImBitmapFont() { Clear(); }
|
||||
|
||||
bool LoadFromMemory(const void* data, int data_size);
|
||||
bool LoadFromMemory(const void* data, size_t data_size);
|
||||
bool LoadFromFile(const char* filename);
|
||||
void Clear();
|
||||
void BuildLookupTable();
|
||||
const FntGlyph * FindGlyph(unsigned short c) const;
|
||||
float GetFontSize() const { return (float)Info->FontSize; }
|
||||
bool IsLoaded() const { return Info != NULL && Common != NULL && Glyphs != NULL; }
|
||||
|
||||
ImVec2 CalcTextSize(float size, float max_width, const char* text_begin, const char* text_end, const char** remaining = NULL) const;
|
||||
ImVec2 CalcTextSizeA(float size, float max_width, const char* text_begin, const char* text_end, const char** remaining = NULL) const; // utf8
|
||||
ImVec2 CalcTextSizeW(float size, float max_width, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL) const; // wchar
|
||||
void RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, ImDrawVert*& out_vertices) const;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
// stb_textedit.h - v1.3 - public domain - Sean Barrett
|
||||
// stb_textedit.h - v1.4 - public domain - Sean Barrett
|
||||
// Development of this library was sponsored by RAD Game Tools
|
||||
//
|
||||
// This C header file implements the guts of a multi-line text-editing
|
||||
@ -30,8 +30,9 @@
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.3 (2013-06-19) fix mouse clicking to round to nearest char boundary
|
||||
// 1.2 (2013-05-27) fix some RAD types that had crept into the new code
|
||||
// 1.4 (2014-08-17) fix signed/unsigned warnings
|
||||
// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
|
||||
// 1.2 (2014-05-27) fix some RAD types that had crept into the new code
|
||||
// 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE )
|
||||
// 1.0 (2012-07-26) improve documentation, initial public release
|
||||
// 0.3 (2012-02-24) bugfixes, single-line mode; insert mode
|
||||
@ -41,7 +42,7 @@
|
||||
// ADDITIONAL CONTRIBUTORS
|
||||
//
|
||||
// Ulf Winklemann: move-by-word in 1.1
|
||||
// Scott Graham: mouse selectiom bugfix in 1.3
|
||||
// Scott Graham: mouse selection bugfix in 1.3
|
||||
//
|
||||
// USAGE
|
||||
//
|
||||
@ -445,7 +446,7 @@ static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
|
||||
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
||||
static void stb_text_makeundo_insert(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
||||
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
|
||||
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
|
||||
|
||||
typedef struct
|
||||
@ -649,7 +650,7 @@ static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
|
||||
stb_textedit_delete_selection(str,state);
|
||||
// try to insert the characters
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
|
||||
stb_text_makeundo_insert(str, state, state->cursor, len);
|
||||
stb_text_makeundo_insert(state, state->cursor, len);
|
||||
state->cursor += len;
|
||||
state->has_preferred_x = 0;
|
||||
return 1;
|
||||
@ -684,7 +685,7 @@ retry:
|
||||
} else {
|
||||
stb_textedit_delete_selection(str,state); // implicity clamps
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
||||
stb_text_makeundo_insert(str, state, state->cursor, 1);
|
||||
stb_text_makeundo_insert(state, state->cursor, 1);
|
||||
++state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
}
|
||||
@ -1007,13 +1008,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
||||
int n = state->undo_rec[0].insert_length, i;
|
||||
// delete n characters from all other records
|
||||
state->undo_char_point = state->undo_char_point - (short) n; // vsnet05
|
||||
memmove(state->undo_char, state->undo_char + n, state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE));
|
||||
memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
for (i=0; i < state->undo_point; ++i)
|
||||
if (state->undo_rec[i].char_storage >= 0)
|
||||
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it
|
||||
}
|
||||
--state->undo_point;
|
||||
memmove(state->undo_rec, state->undo_rec+1, state->undo_point*sizeof(state->undo_rec[0]));
|
||||
memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1031,13 +1032,13 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
||||
int n = state->undo_rec[k].insert_length, i;
|
||||
// delete n characters from all other records
|
||||
state->redo_char_point = state->redo_char_point + (short) n; // vsnet05
|
||||
memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE));
|
||||
memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
for (i=state->redo_point; i < k; ++i)
|
||||
if (state->undo_rec[i].char_storage >= 0)
|
||||
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
|
||||
}
|
||||
++state->redo_point;
|
||||
memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]));
|
||||
memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1203,7 +1204,7 @@ static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
s->redo_point++;
|
||||
}
|
||||
|
||||
static void stb_text_makeundo_insert(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
|
||||
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)
|
||||
{
|
||||
stb_text_createundo(&state->undostate, where, 0, length);
|
||||
}
|
||||
|
BIN
web/skinning_sample_01.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
web/utf8_sample_01.png
Normal file
After Width: | Height: | Size: 5.4 KiB |