|
@@ -109,43 +109,33 @@
|
|
|
GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
|
|
|
|
|
|
- Run and study the examples and demo to get acquainted with the library.
|
|
|
- - Add the Dear ImGui source files to your projects, using your preferred build system.
|
|
|
+ - Add the Dear ImGui source files to your projects or using your preferred build system.
|
|
|
It is recommended you build the .cpp files as part of your project and not as a library.
|
|
|
- You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types.
|
|
|
- You may be able to grab and copy a ready made imgui_impl_*** file from the examples/ folder.
|
|
|
- When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
|
|
|
+ - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide.
|
|
|
+ Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render"
|
|
|
+ phases of your own application. All rendering informatioe are stored into command-lists that you will retrieve after calling ImGui::Render().
|
|
|
+ - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code.
|
|
|
|
|
|
- - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize
|
|
|
- (application resolution). Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic
|
|
|
- integration you don't need to worry about it all.
|
|
|
- - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory.
|
|
|
- - Every frame:
|
|
|
- - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.)
|
|
|
- - Call ImGui::NewFrame() to begin the frame
|
|
|
- - You can use any ImGui function you want between NewFrame() and Render()
|
|
|
- - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler.
|
|
|
- (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwise some features will break)
|
|
|
- - All rendering information are stored into command-lists until ImGui::Render() is called.
|
|
|
- - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide.
|
|
|
- - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases
|
|
|
- of your own application.
|
|
|
- - Refer to the examples applications in the examples/ folder for instruction on how to setup your code.
|
|
|
- - A minimal application skeleton may be:
|
|
|
+ THIS IS HOW A SIMPLE APPLICATION MAY LOOK LIKE
|
|
|
|
|
|
// Application init
|
|
|
+ // Create a context
|
|
|
ImGui::CreateContext();
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
- io.DisplaySize.x = 1920.0f;
|
|
|
- io.DisplaySize.y = 1280.0f;
|
|
|
- // TODO: Fill others settings of the io structure later.
|
|
|
+ // TODO: Fill optional settings of the io structure later.
|
|
|
+ // TODO: Load fonts if you don't want to use the default font.
|
|
|
|
|
|
- // Load texture atlas (there is a default font so you don't need to care about choosing a font yet)
|
|
|
- unsigned char* pixels;
|
|
|
+ // Build and load the texture atlas into a texture
|
|
|
+ unsigned char* pixels = NULL;
|
|
|
int width, height;
|
|
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
|
|
- // TODO: At this points you've got the texture data and you need to upload that your your graphic system:
|
|
|
- MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA)
|
|
|
- // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'. This will be passed back to your via the renderer.
|
|
|
+ // At this point you've got the texture data and you need to upload that your your graphic system:
|
|
|
+ MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
|
|
|
+ // Store your texture pointer/identifier (in whatever formatyour engine uses) in 'io.Fonts->TexID'.
|
|
|
+ // This will be passed back to your via the renderer. Read FAQ for details about ImTextureID.
|
|
|
io.Fonts->TexID = (void*)texture;
|
|
|
|
|
|
// Application main loop
|
|
@@ -154,18 +144,24 @@
|
|
|
// Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.)
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
io.DeltaTime = 1.0f/60.0f;
|
|
|
- io.MousePos = mouse_pos;
|
|
|
- io.MouseDown[0] = mouse_button_0;
|
|
|
- io.MouseDown[1] = mouse_button_1;
|
|
|
+ io.DisplaySize.x = 1920.0f;
|
|
|
+ io.DisplaySize.y = 1280.0f;
|
|
|
+ io.MousePos = my_mouse_pos;
|
|
|
+ io.MouseDown[0] = my_mouse_buttons[0];
|
|
|
+ io.MouseDown[1] = my_mouse_buttons[1];
|
|
|
|
|
|
// Call NewFrame(), after this point you can use ImGui::* functions anytime
|
|
|
+ // (So you want to try calling Newframe() as early as you can in your mainloop to be able to use imgui everywhere)
|
|
|
ImGui::NewFrame();
|
|
|
|
|
|
// Most of your application code here
|
|
|
+ ImGui::Text("Hello, world!");
|
|
|
MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
|
|
|
MyGameRender(); // may use any ImGui functions as well!
|
|
|
|
|
|
- // Render & swap video buffers
|
|
|
+ // Render imgui, swap buffers
|
|
|
+ // (You want to try calling EndFrame/Render as late as you can, to be able to use imgui in your own game rendering code)
|
|
|
+ ImGui::EndFrame();
|
|
|
ImGui::Render();
|
|
|
MyImGuiRenderFunction(ImGui::GetDrawData());
|
|
|
SwapBuffers();
|
|
@@ -174,13 +170,13 @@
|
|
|
// Shutdown
|
|
|
ImGui::DestroyContext();
|
|
|
|
|
|
+ THIS HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE
|
|
|
|
|
|
- - A minimal render function skeleton may be:
|
|
|
-
|
|
|
- void void MyRenderFunction(ImDrawData* draw_data)
|
|
|
+ void void MyImGuiRenderFunction(ImDrawData* draw_data)
|
|
|
{
|
|
|
// TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
|
|
|
- // TODO: Setup viewport, orthographic projection matrix
|
|
|
+ // TODO: Setup viewport using draw_data->DisplaySize
|
|
|
+ // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
|
|
|
// TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
|
|
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
|
{
|
|
@@ -199,10 +195,16 @@
|
|
|
// The vast majority of draw calls with use the imgui texture atlas, which value you have set yourself during initialization.
|
|
|
MyEngineBindTexture(pcmd->TextureId);
|
|
|
|
|
|
- // We are using scissoring to clip some objects. All low-level graphics API supports it.
|
|
|
- // If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
|
|
|
- // (some elements visible outside their bounds) but you can fix that once everywhere else works!
|
|
|
- MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
|
|
+ // We are using scissoring to clip some objects. All low-level graphics API should supports it.
|
|
|
+ // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
|
|
|
+ // (some elements visible outside their bounds) but you can fix that once everywhere else works!
|
|
|
+ // - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize)
|
|
|
+ // In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize.
|
|
|
+ // However, in the interest of supporting multi-viewport applications in the future, always subtract draw_data->DisplayPos from
|
|
|
+ // clipping bounds to convert them to your viewport space.
|
|
|
+ // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
|
|
|
+ ImVec2 pos = draw_data->DisplayPos;
|
|
|
+ MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y));
|
|
|
|
|
|
// Render 'pcmd->ElemCount/3' indexed triangles.
|
|
|
// By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits if your engine doesn't support 16-bits indices.
|