mirror of
https://github.com/aap/librw.git
synced 2024-11-25 05:05:42 +00:00
implemented dear imgui for librw
This commit is contained in:
parent
d522a47120
commit
578c5f81fb
10
premake5.lua
10
premake5.lua
@ -96,6 +96,7 @@ end
|
||||
|
||||
function skeleton()
|
||||
files { "skeleton/*.cpp", "skeleton/*.h" }
|
||||
files { "skeleton/imgui/*.cpp", "skeleton/imgui/*.h" }
|
||||
includedirs { "skeleton" }
|
||||
end
|
||||
|
||||
@ -132,6 +133,15 @@ project "clumpview"
|
||||
removeplatforms { "*null" }
|
||||
removeplatforms { "ps2" } -- for now
|
||||
|
||||
project "imguitest"
|
||||
kind "WindowedApp"
|
||||
characterset ("MBCS")
|
||||
skeltool("imguitest")
|
||||
files { "tools/imguitest/imgui/*.cpp" }
|
||||
flags { "WinMain" }
|
||||
removeplatforms { "*null" }
|
||||
removeplatforms { "ps2" }
|
||||
|
||||
project "ps2test"
|
||||
kind "ConsoleApp"
|
||||
targetdir (Bindir)
|
||||
|
@ -149,6 +149,12 @@ keypress(GLFWwindow *window, int key, int scancode, int action, int mods)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
charinput(GLFWwindow *window, unsigned int c)
|
||||
{
|
||||
EventHandler(CHARINPUT, (void*)c);
|
||||
}
|
||||
|
||||
static void
|
||||
resize(GLFWwindow *window, int w, int h)
|
||||
{
|
||||
@ -160,6 +166,46 @@ resize(GLFWwindow *window, int w, int h)
|
||||
EventHandler(RESIZE, &r);
|
||||
}
|
||||
|
||||
static void
|
||||
mousemove(GLFWwindow *window, double x, double y)
|
||||
{
|
||||
sk::MouseState ms;
|
||||
ms.posx = x;
|
||||
ms.posy = y;
|
||||
EventHandler(MOUSEMOVE, &ms);
|
||||
}
|
||||
|
||||
static void
|
||||
mousebtn(GLFWwindow *window, int button, int action, int mods)
|
||||
{
|
||||
static int buttons = 0;
|
||||
sk::MouseState ms;
|
||||
|
||||
switch(button){
|
||||
case GLFW_MOUSE_BUTTON_LEFT:
|
||||
if(action == GLFW_PRESS)
|
||||
buttons |= 1;
|
||||
else
|
||||
buttons &= ~1;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_MIDDLE:
|
||||
if(action == GLFW_PRESS)
|
||||
buttons |= 2;
|
||||
else
|
||||
buttons &= ~2;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_RIGHT:
|
||||
if(action == GLFW_PRESS)
|
||||
buttons |= 4;
|
||||
else
|
||||
buttons &= ~4;
|
||||
break;
|
||||
}
|
||||
|
||||
ms.buttons = buttons;
|
||||
EventHandler(MOUSEBTN, &ms);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
@ -179,7 +225,10 @@ main(int argc, char *argv[])
|
||||
|
||||
initkeymap();
|
||||
glfwSetKeyCallback(window, keypress);
|
||||
glfwSetCharCallback(window, charinput);
|
||||
glfwSetWindowSizeCallback(window, resize);
|
||||
glfwSetCursorPosCallback(window, mousemove);
|
||||
glfwSetMouseButtonCallback(window, mousebtn);
|
||||
|
||||
float lastTime = glfwGetTime()*1000;
|
||||
while(!sk::globals.quit && !glfwWindowShouldClose(window)){
|
||||
@ -196,4 +245,15 @@ main(int argc, char *argv[])
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace sk {
|
||||
|
||||
void
|
||||
SetMousePosition(int x, int y)
|
||||
{
|
||||
glfwSetCursorPos(*engineStartParams.window, (double)x, (double)y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
21
skeleton/imgui/LICENSE.txt
Normal file
21
skeleton/imgui/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2017 Omar Cornut and ImGui contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
61
skeleton/imgui/imconfig.h
Normal file
61
skeleton/imgui/imconfig.h
Normal file
@ -0,0 +1,61 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 assertion handler. Defaults to calling assert().
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
|
||||
//#define IMGUI_API __declspec( dllexport )
|
||||
//#define IMGUI_API __declspec( dllimport )
|
||||
|
||||
//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
|
||||
//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
|
||||
|
||||
//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
|
||||
//---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp to learn why.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS
|
||||
|
||||
//---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself.
|
||||
//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
|
||||
|
||||
//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends)
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Implement STB libraries in a namespace to avoid linkage conflicts
|
||||
//#define IMGUI_STB_NAMESPACE ImGuiStb
|
||||
|
||||
//---- Define constructor and 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; } \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
|
||||
//---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices
|
||||
//#define ImDrawIdx unsigned int
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||
//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers.
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL);
|
||||
}
|
||||
*/
|
||||
|
11739
skeleton/imgui/imgui.cpp
Normal file
11739
skeleton/imgui/imgui.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1684
skeleton/imgui/imgui.h
Normal file
1684
skeleton/imgui/imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
3068
skeleton/imgui/imgui_demo.cpp
Normal file
3068
skeleton/imgui/imgui_demo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2906
skeleton/imgui/imgui_draw.cpp
Normal file
2906
skeleton/imgui/imgui_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
203
skeleton/imgui/imgui_impl_rw.cpp
Normal file
203
skeleton/imgui/imgui_impl_rw.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
#include <rw.h>
|
||||
#include <skeleton.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui_impl_rw.h"
|
||||
|
||||
using namespace rw::RWDEVICE;
|
||||
|
||||
static rw::Texture *g_FontTexture;
|
||||
static Im2DVertex *g_vertbuf;
|
||||
static int g_vertbufSize;
|
||||
|
||||
void
|
||||
ImGui_ImplRW_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
// minimized
|
||||
if (io.DisplaySize.x <= 0.0f || io.DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
if(g_vertbuf == nil || g_vertbufSize < draw_data->TotalVtxCount){
|
||||
if(g_vertbuf){
|
||||
rwFree(g_vertbuf);
|
||||
g_vertbuf = nil;
|
||||
}
|
||||
g_vertbufSize = draw_data->TotalVtxCount + 5000;
|
||||
g_vertbuf = rwNewT(Im2DVertex, g_vertbufSize, 0);
|
||||
}
|
||||
|
||||
rw::Camera *cam = (rw::Camera*)rw::engine->currentCamera;
|
||||
Im2DVertex *vtx_dst = g_vertbuf;
|
||||
for(int n = 0; n < draw_data->CmdListsCount; n++){
|
||||
const ImDrawList *cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert *vtx_src = cmd_list->VtxBuffer.Data;
|
||||
for(int i = 0; i < cmd_list->VtxBuffer.Size; i++){
|
||||
vtx_dst[i].setScreenX(vtx_src[i].pos.x);
|
||||
vtx_dst[i].setScreenY(vtx_src[i].pos.y);
|
||||
vtx_dst[i].setScreenZ(rw::im2d::GetNearZ());
|
||||
vtx_dst[i].setCameraZ(cam->nearPlane);
|
||||
vtx_dst[i].setRecipCameraZ(1.0f/cam->nearPlane);
|
||||
vtx_dst[i].setColor(vtx_src[i].col&0xFF, vtx_src[i].col>>8 & 0xFF, vtx_src[i].col>>16 & 0xFF, vtx_src[i].col>>24 & 0xFF);
|
||||
vtx_dst[i].setU(vtx_src[i].uv.x);
|
||||
vtx_dst[i].setV(vtx_src[i].uv.y);
|
||||
}
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
rw::SetRenderState(rw::VERTEXALPHA, 1);
|
||||
rw::SetRenderState(rw::SRCBLEND, rw::BLENDSRCALPHA);
|
||||
rw::SetRenderState(rw::DESTBLEND, rw::BLENDINVSRCALPHA);
|
||||
rw::SetRenderState(rw::ZTESTENABLE, 0);
|
||||
|
||||
int vtx_offset = 0;
|
||||
for(int n = 0; n < draw_data->CmdListsCount; n++){
|
||||
const ImDrawList *cmd_list = draw_data->CmdLists[n];
|
||||
int idx_offset = 0;
|
||||
for(int i = 0; i < cmd_list->CmdBuffer.Size; i++){
|
||||
const ImDrawCmd *pcmd = &cmd_list->CmdBuffer[i];
|
||||
if(pcmd->UserCallback)
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
else{
|
||||
rw::engine->imtexture = (rw::Texture*)pcmd->TextureId;
|
||||
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST,
|
||||
g_vertbuf+vtx_offset, cmd_list->VtxBuffer.Size,
|
||||
cmd_list->IdxBuffer.Data+idx_offset, pcmd->ElemCount);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ImGui_ImplRW_Init(void)
|
||||
{
|
||||
using namespace sk;
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
io.KeyMap[ImGuiKey_Tab] = KEY_TAB;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = KEY_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = KEY_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = KEY_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = KEY_PGUP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = KEY_PGDN;
|
||||
io.KeyMap[ImGuiKey_Home] = KEY_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = KEY_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = KEY_DEL;
|
||||
io.KeyMap[ImGuiKey_Backspace] = KEY_BACKSP;
|
||||
io.KeyMap[ImGuiKey_Enter] = KEY_ENTER;
|
||||
io.KeyMap[ImGuiKey_Escape] = KEY_ESC;
|
||||
io.KeyMap[ImGuiKey_A] = 'A';
|
||||
io.KeyMap[ImGuiKey_C] = 'C';
|
||||
io.KeyMap[ImGuiKey_V] = 'V';
|
||||
io.KeyMap[ImGuiKey_X] = 'X';
|
||||
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
|
||||
io.RenderDrawListsFn = ImGui_ImplRW_RenderDrawLists;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ImGui_ImplRW_Shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
ImGui_ImplRW_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
unsigned char *pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, nil);
|
||||
|
||||
rw::Image *image;
|
||||
image = rw::Image::create(width, height, 32);
|
||||
image->allocate();
|
||||
for(int y = 0; y < height; y++)
|
||||
memcpy(image->pixels + image->stride*y, pixels + width*4* y, width*4);
|
||||
g_FontTexture = rw::Texture::create(rw::Raster::createFromImage(image));
|
||||
image->destroy();
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void*)g_FontTexture;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ImGui_ImplRW_CreateDeviceObjects()
|
||||
{
|
||||
// if(!g_pd3dDevice)
|
||||
// return false;
|
||||
if(!ImGui_ImplRW_CreateFontsTexture())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ImGui_ImplRW_NewFrame(float timeDelta)
|
||||
{
|
||||
if(!g_FontTexture)
|
||||
ImGui_ImplRW_CreateDeviceObjects();
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
io.DisplaySize = ImVec2(sk::globals.width, sk::globals.height);
|
||||
io.DeltaTime = timeDelta;
|
||||
|
||||
io.KeyCtrl = false; //io.KeysDown[sk::KEY_LCTRL] || io.KeysDown[sk::KEY_RCTRL];
|
||||
io.KeyShift = false; //io.KeysDown[sk::KEY_LSHIFT] || io.KeysDown[sk::KEY_RSHIFT];
|
||||
io.KeyAlt = false; //io.KeysDown[sk::KEY_LALT] || io.KeysDown[sk::KEY_RALT];
|
||||
io.KeySuper = false;
|
||||
|
||||
if(io.WantMoveMouse)
|
||||
sk::SetMousePosition(io.MousePos.x, io.MousePos.y);
|
||||
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
sk::EventStatus
|
||||
ImGuiEventHandler(sk::Event e, void *param)
|
||||
{
|
||||
using namespace sk;
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
MouseState *ms;
|
||||
uint c;
|
||||
|
||||
switch(e){
|
||||
case KEYDOWN:
|
||||
c = *(int*)param;
|
||||
if(c < 256)
|
||||
io.KeysDown[c] = 1;
|
||||
return EVENTPROCESSED;
|
||||
case KEYUP:
|
||||
c = *(int*)param;
|
||||
if(c < 256)
|
||||
io.KeysDown[c] = 0;
|
||||
return EVENTPROCESSED;
|
||||
case CHARINPUT:
|
||||
c = (uint)param;
|
||||
io.AddInputCharacter((unsigned short)c);
|
||||
return EVENTPROCESSED;
|
||||
case MOUSEMOVE:
|
||||
ms = (MouseState*)param;
|
||||
io.MousePos.x = ms->posx;
|
||||
io.MousePos.y = ms->posy;
|
||||
return EVENTPROCESSED;
|
||||
case MOUSEBTN:
|
||||
ms = (MouseState*)param;
|
||||
io.MouseDown[0] = !!(ms->buttons & 1);
|
||||
io.MouseDown[2] = !!(ms->buttons & 2);
|
||||
io.MouseDown[1] = !!(ms->buttons & 4);
|
||||
return EVENTPROCESSED;
|
||||
}
|
||||
return EVENTPROCESSED;
|
||||
}
|
4
skeleton/imgui/imgui_impl_rw.h
Normal file
4
skeleton/imgui/imgui_impl_rw.h
Normal file
@ -0,0 +1,4 @@
|
||||
IMGUI_API bool ImGui_ImplRW_Init(void);
|
||||
IMGUI_API void ImGui_ImplRW_Shutdown(void);
|
||||
IMGUI_API void ImGui_ImplRW_NewFrame(float timeDelta);
|
||||
sk::EventStatus ImGuiEventHandler(sk::Event e, void *param);
|
985
skeleton/imgui/imgui_internal.h
Normal file
985
skeleton/imgui/imgui_internal.h
Normal file
@ -0,0 +1,985 @@
|
||||
// dear imgui, v1.54 WIP
|
||||
// (internals)
|
||||
|
||||
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
|
||||
// Set:
|
||||
// #define IMGUI_DEFINE_MATH_OPERATORS
|
||||
// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators)
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef IMGUI_VERSION
|
||||
#error Must include imgui.h before imgui_internal.h
|
||||
#endif
|
||||
|
||||
#include <stdio.h> // FILE*
|
||||
#include <math.h> // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward Declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ImRect;
|
||||
struct ImGuiColMod;
|
||||
struct ImGuiStyleMod;
|
||||
struct ImGuiGroupData;
|
||||
struct ImGuiSimpleColumns;
|
||||
struct ImGuiDrawContext;
|
||||
struct ImGuiTextEditState;
|
||||
struct ImGuiMouseCursorData;
|
||||
struct ImGuiPopupRef;
|
||||
struct ImGuiWindow;
|
||||
struct ImGuiWindowSettings;
|
||||
|
||||
typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_
|
||||
typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_
|
||||
typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_
|
||||
typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_
|
||||
typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// STB libraries
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
namespace ImGuiStb
|
||||
{
|
||||
|
||||
#undef STB_TEXTEDIT_STRING
|
||||
#undef STB_TEXTEDIT_CHARTYPE
|
||||
#define STB_TEXTEDIT_STRING ImGuiTextEditState
|
||||
#define STB_TEXTEDIT_CHARTYPE ImWchar
|
||||
#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f
|
||||
#include "stb_textedit.h"
|
||||
|
||||
} // namespace ImGuiStb
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Context
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef GImGui
|
||||
extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointer
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define IM_PI 3.14159265358979323846f
|
||||
#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM))
|
||||
|
||||
// Helpers: UTF-8 <> wchar
|
||||
IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
|
||||
IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count
|
||||
IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
|
||||
IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
|
||||
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points
|
||||
|
||||
// Helpers: Misc
|
||||
IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings
|
||||
IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0);
|
||||
IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode);
|
||||
static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; }
|
||||
static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; }
|
||||
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
|
||||
|
||||
// Helpers: Geometry
|
||||
IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);
|
||||
IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
|
||||
IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
|
||||
IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);
|
||||
|
||||
// Helpers: String
|
||||
IMGUI_API int ImStricmp(const char* str1, const char* str2);
|
||||
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count);
|
||||
IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count);
|
||||
IMGUI_API char* ImStrdup(const char* str);
|
||||
IMGUI_API char* ImStrchrRange(const char* str_begin, const char* str_end, char c);
|
||||
IMGUI_API int ImStrlenW(const ImWchar* str);
|
||||
IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
|
||||
IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
|
||||
IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3);
|
||||
IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3);
|
||||
|
||||
// Helpers: Math
|
||||
// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined)
|
||||
#ifdef IMGUI_DEFINE_MATH_OPERATORS
|
||||
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
|
||||
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); }
|
||||
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
|
||||
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
|
||||
static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }
|
||||
static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }
|
||||
static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
|
||||
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
|
||||
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
||||
static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
||||
static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w); }
|
||||
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); }
|
||||
static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); }
|
||||
#endif
|
||||
|
||||
static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
|
||||
static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||
static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
|
||||
static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||
static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); }
|
||||
static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); }
|
||||
static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
|
||||
static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
|
||||
static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); }
|
||||
static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
|
||||
static inline void ImSwap(int& a, int& b) { int tmp = a; a = b; b = tmp; }
|
||||
static inline void ImSwap(float& a, float& b) { float tmp = a; a = b; b = tmp; }
|
||||
static inline int ImLerp(int a, int b, float t) { return (int)(a + (b - a) * t); }
|
||||
static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; }
|
||||
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); }
|
||||
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
|
||||
static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); }
|
||||
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
|
||||
static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
|
||||
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; }
|
||||
static inline float ImFloor(float f) { return (float)(int)f; }
|
||||
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
|
||||
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
|
||||
static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
||||
|
||||
// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
|
||||
// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
|
||||
struct ImNewPlacementDummy {};
|
||||
inline void* operator new(size_t, ImNewPlacementDummy, void* ptr) { return ptr; }
|
||||
inline void operator delete(void*, ImNewPlacementDummy, void*) {} // This is only required so we can use the symetrical new()
|
||||
#define IM_PLACEMENT_NEW(_PTR) new(ImNewPlacementDummy(), _PTR)
|
||||
#define IM_NEW(_TYPE) new(ImNewPlacementDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE
|
||||
template <typename T> void IM_DELETE(T*& p) { if (p) { p->~T(); ImGui::MemFree(p); p = NULL; } }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Internal Drag and Drop payload types. String starting with '_' are reserved for Dear ImGui.
|
||||
#define IMGUI_PAYLOAD_TYPE_DOCKABLE "_IMDOCK" // ImGuiWindow* // [Internal] Docking/tabs
|
||||
|
||||
enum ImGuiButtonFlags_
|
||||
{
|
||||
ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat
|
||||
ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // return true on click + release on same item [DEFAULT if no PressedOn* flag is set]
|
||||
ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release)
|
||||
ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release)
|
||||
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release)
|
||||
ImGuiButtonFlags_FlattenChildren = 1 << 5, // allow interactions even if a child window is overlapping
|
||||
ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap()
|
||||
ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED]
|
||||
ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions
|
||||
ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
|
||||
ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable interaction if a key modifier is held
|
||||
ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
|
||||
ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12 // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
|
||||
};
|
||||
|
||||
enum ImGuiSliderFlags_
|
||||
{
|
||||
ImGuiSliderFlags_Vertical = 1 << 0
|
||||
};
|
||||
|
||||
enum ImGuiColumnsFlags_
|
||||
{
|
||||
// Default: 0
|
||||
ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers
|
||||
ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers
|
||||
ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns
|
||||
ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window
|
||||
ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove.
|
||||
};
|
||||
|
||||
enum ImGuiSelectableFlagsPrivate_
|
||||
{
|
||||
// NB: need to be in sync with last value of ImGuiSelectableFlags_
|
||||
ImGuiSelectableFlags_Menu = 1 << 3, // -> PressedOnClick
|
||||
ImGuiSelectableFlags_MenuItem = 1 << 4, // -> PressedOnRelease
|
||||
ImGuiSelectableFlags_Disabled = 1 << 5,
|
||||
ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6
|
||||
};
|
||||
|
||||
enum ImGuiSeparatorFlags_
|
||||
{
|
||||
ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
|
||||
ImGuiSeparatorFlags_Vertical = 1 << 1
|
||||
};
|
||||
|
||||
// FIXME: this is in development, not exposed/functional as a generic feature yet.
|
||||
enum ImGuiLayoutType_
|
||||
{
|
||||
ImGuiLayoutType_Vertical,
|
||||
ImGuiLayoutType_Horizontal
|
||||
};
|
||||
|
||||
enum ImGuiAxis
|
||||
{
|
||||
ImGuiAxis_None = -1,
|
||||
ImGuiAxis_X = 0,
|
||||
ImGuiAxis_Y = 1
|
||||
};
|
||||
|
||||
enum ImGuiPlotType
|
||||
{
|
||||
ImGuiPlotType_Lines,
|
||||
ImGuiPlotType_Histogram
|
||||
};
|
||||
|
||||
enum ImGuiDataType
|
||||
{
|
||||
ImGuiDataType_Int,
|
||||
ImGuiDataType_Float,
|
||||
ImGuiDataType_Float2
|
||||
};
|
||||
|
||||
enum ImGuiDir
|
||||
{
|
||||
ImGuiDir_None = -1,
|
||||
ImGuiDir_Left = 0,
|
||||
ImGuiDir_Right = 1,
|
||||
ImGuiDir_Up = 2,
|
||||
ImGuiDir_Down = 3,
|
||||
ImGuiDir_Count_
|
||||
};
|
||||
|
||||
// 2D axis aligned bounding-box
|
||||
// NB: we can't rely on ImVec2 math operators being available here
|
||||
struct IMGUI_API ImRect
|
||||
{
|
||||
ImVec2 Min; // Upper-left
|
||||
ImVec2 Max; // Lower-right
|
||||
|
||||
ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {}
|
||||
ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
|
||||
ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
|
||||
ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
|
||||
|
||||
ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }
|
||||
ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); }
|
||||
float GetWidth() const { return Max.x-Min.x; }
|
||||
float GetHeight() const { return Max.y-Min.y; }
|
||||
ImVec2 GetTL() const { return Min; } // Top-left
|
||||
ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right
|
||||
ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left
|
||||
ImVec2 GetBR() const { return Max; } // Bottom-right
|
||||
bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
|
||||
bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }
|
||||
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
|
||||
void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; }
|
||||
void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }
|
||||
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
|
||||
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
|
||||
void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; }
|
||||
void ClipWith(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
|
||||
void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
|
||||
void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); }
|
||||
bool IsFinite() const { return Min.x != FLT_MAX; }
|
||||
ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const
|
||||
{
|
||||
if (!on_edge && Contains(p))
|
||||
return p;
|
||||
if (p.x > Max.x) p.x = Max.x;
|
||||
else if (p.x < Min.x) p.x = Min.x;
|
||||
if (p.y > Max.y) p.y = Max.y;
|
||||
else if (p.y < Min.y) p.y = Min.y;
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
// Stacked color modifier, backup of modified data so we can restore it
|
||||
struct ImGuiColMod
|
||||
{
|
||||
ImGuiCol Col;
|
||||
ImVec4 BackupValue;
|
||||
};
|
||||
|
||||
// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.
|
||||
struct ImGuiStyleMod
|
||||
{
|
||||
ImGuiStyleVar VarIdx;
|
||||
union { int BackupInt[2]; float BackupFloat[2]; };
|
||||
ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; }
|
||||
ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; }
|
||||
ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }
|
||||
};
|
||||
|
||||
// Stacked data for BeginGroup()/EndGroup()
|
||||
struct ImGuiGroupData
|
||||
{
|
||||
ImVec2 BackupCursorPos;
|
||||
ImVec2 BackupCursorMaxPos;
|
||||
float BackupIndentX;
|
||||
float BackupGroupOffsetX;
|
||||
float BackupCurrentLineHeight;
|
||||
float BackupCurrentLineTextBaseOffset;
|
||||
float BackupLogLinePosY;
|
||||
bool BackupActiveIdIsAlive;
|
||||
bool AdvanceCursor;
|
||||
};
|
||||
|
||||
// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper.
|
||||
struct IMGUI_API ImGuiSimpleColumns
|
||||
{
|
||||
int Count;
|
||||
float Spacing;
|
||||
float Width, NextWidth;
|
||||
float Pos[8], NextWidths[8];
|
||||
|
||||
ImGuiSimpleColumns();
|
||||
void Update(int count, float spacing, bool clear);
|
||||
float DeclColumns(float w0, float w1, float w2);
|
||||
float CalcExtraSpace(float avail_w);
|
||||
};
|
||||
|
||||
// Internal state of the currently focused/edited text input box
|
||||
struct IMGUI_API ImGuiTextEditState
|
||||
{
|
||||
ImGuiID Id; // widget id owning the text state
|
||||
ImVector<ImWchar> Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
|
||||
ImVector<char> InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
|
||||
ImVector<char> TempTextBuffer;
|
||||
int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
|
||||
int BufSizeA; // end-user buffer size
|
||||
float ScrollX;
|
||||
ImGuiStb::STB_TexteditState StbState;
|
||||
float CursorAnim;
|
||||
bool CursorFollow;
|
||||
bool SelectedAllMouseLock;
|
||||
|
||||
ImGuiTextEditState() { memset(this, 0, sizeof(*this)); }
|
||||
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
|
||||
void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); }
|
||||
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
|
||||
void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; }
|
||||
void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
|
||||
void OnKeyPressed(int key);
|
||||
};
|
||||
|
||||
// Data saved in imgui.ini file
|
||||
struct ImGuiWindowSettings
|
||||
{
|
||||
char* Name;
|
||||
ImGuiID Id;
|
||||
ImVec2 Pos;
|
||||
ImVec2 Size;
|
||||
bool Collapsed;
|
||||
|
||||
ImGuiWindowSettings() { Name = NULL; Id = 0; Pos = Size = ImVec2(0,0); Collapsed = false; }
|
||||
};
|
||||
|
||||
struct ImGuiSettingsHandler
|
||||
{
|
||||
const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']'
|
||||
ImGuiID TypeHash; // == ImHash(TypeName, 0, 0)
|
||||
void* (*ReadOpenFn)(ImGuiContext& ctx, const char* name);
|
||||
void (*ReadLineFn)(ImGuiContext& ctx, void* entry, const char* line);
|
||||
void (*WriteAllFn)(ImGuiContext& ctx, ImGuiTextBuffer* out_buf);
|
||||
};
|
||||
|
||||
// Mouse cursor data (used when io.MouseDrawCursor is set)
|
||||
struct ImGuiMouseCursorData
|
||||
{
|
||||
ImGuiMouseCursor Type;
|
||||
ImVec2 HotOffset;
|
||||
ImVec2 Size;
|
||||
ImVec2 TexUvMin[2];
|
||||
ImVec2 TexUvMax[2];
|
||||
};
|
||||
|
||||
// Storage for current popup stack
|
||||
struct ImGuiPopupRef
|
||||
{
|
||||
ImGuiID PopupId; // Set on OpenPopup()
|
||||
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
|
||||
ImGuiWindow* ParentWindow; // Set on OpenPopup()
|
||||
ImGuiID ParentMenuSet; // Set on OpenPopup()
|
||||
ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup
|
||||
|
||||
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
|
||||
};
|
||||
|
||||
struct ImGuiColumnData
|
||||
{
|
||||
float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
|
||||
float OffsetNormBeforeResize;
|
||||
ImGuiColumnsFlags Flags; // Not exposed
|
||||
ImRect ClipRect;
|
||||
|
||||
ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; Flags = 0; }
|
||||
};
|
||||
|
||||
struct ImGuiColumnsSet
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImGuiColumnsFlags Flags;
|
||||
bool IsFirstFrame;
|
||||
bool IsBeingResized;
|
||||
int Current;
|
||||
int Count;
|
||||
float MinX, MaxX;
|
||||
float StartPosY;
|
||||
float StartMaxPosX; // Backup of CursorMaxPos
|
||||
float CellMinY, CellMaxY;
|
||||
ImVector<ImGuiColumnData> Columns;
|
||||
|
||||
ImGuiColumnsSet() { Clear(); }
|
||||
void Clear()
|
||||
{
|
||||
ID = 0;
|
||||
Flags = 0;
|
||||
IsFirstFrame = false;
|
||||
IsBeingResized = false;
|
||||
Current = 0;
|
||||
Count = 1;
|
||||
MinX = MaxX = 0.0f;
|
||||
StartPosY = 0.0f;
|
||||
StartMaxPosX = 0.0f;
|
||||
CellMinY = CellMaxY = 0.0f;
|
||||
Columns.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct ImDrawListSharedData
|
||||
{
|
||||
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
|
||||
ImFont* Font; // Current/default font (optional, for simplified AddText overload)
|
||||
float FontSize; // Current/default font size (optional, for simplified AddText overload)
|
||||
float CurveTessellationTol;
|
||||
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
|
||||
|
||||
// Const data
|
||||
// FIXME: Bake rounded corners fill/borders in atlas
|
||||
ImVec2 CircleVtx12[12];
|
||||
|
||||
ImDrawListSharedData();
|
||||
};
|
||||
|
||||
// Main state for ImGui
|
||||
struct ImGuiContext
|
||||
{
|
||||
bool Initialized;
|
||||
ImGuiIO IO;
|
||||
ImGuiStyle Style;
|
||||
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
|
||||
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
|
||||
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
|
||||
ImDrawListSharedData DrawListSharedData;
|
||||
|
||||
float Time;
|
||||
int FrameCount;
|
||||
int FrameCountEnded;
|
||||
int FrameCountRendered;
|
||||
ImVector<ImGuiWindow*> Windows;
|
||||
ImVector<ImGuiWindow*> WindowsSortBuffer;
|
||||
ImVector<ImGuiWindow*> CurrentWindowStack;
|
||||
ImGuiStorage WindowsById;
|
||||
int WindowsActiveCount;
|
||||
ImGuiWindow* CurrentWindow; // Being drawn into
|
||||
ImGuiWindow* NavWindow; // Nav/focused window for navigation
|
||||
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
|
||||
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
|
||||
ImGuiID HoveredId; // Hovered widget
|
||||
bool HoveredIdAllowOverlap;
|
||||
ImGuiID HoveredIdPreviousFrame;
|
||||
float HoveredIdTimer;
|
||||
ImGuiID ActiveId; // Active widget
|
||||
ImGuiID ActiveIdPreviousFrame;
|
||||
float ActiveIdTimer;
|
||||
bool ActiveIdIsAlive; // Active widget has been seen this frame
|
||||
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
|
||||
bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
|
||||
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
|
||||
ImGuiWindow* ActiveIdWindow;
|
||||
ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window.
|
||||
ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId
|
||||
ImVector<ImGuiColMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
|
||||
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
|
||||
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
|
||||
ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent)
|
||||
ImVector<ImGuiPopupRef> CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame)
|
||||
|
||||
// Storage for SetNexWindow** and SetNextTreeNode*** functions
|
||||
ImVec2 SetNextWindowPosVal;
|
||||
ImVec2 SetNextWindowPosPivot;
|
||||
ImVec2 SetNextWindowSizeVal;
|
||||
ImVec2 SetNextWindowContentSizeVal;
|
||||
bool SetNextWindowCollapsedVal;
|
||||
ImGuiCond SetNextWindowPosCond;
|
||||
ImGuiCond SetNextWindowSizeCond;
|
||||
ImGuiCond SetNextWindowContentSizeCond;
|
||||
ImGuiCond SetNextWindowCollapsedCond;
|
||||
ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true
|
||||
ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback;
|
||||
void* SetNextWindowSizeConstraintCallbackUserData;
|
||||
bool SetNextWindowSizeConstraint;
|
||||
bool SetNextWindowFocus;
|
||||
bool SetNextTreeNodeOpenVal;
|
||||
ImGuiCond SetNextTreeNodeOpenCond;
|
||||
|
||||
// Render
|
||||
ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user
|
||||
ImVector<ImDrawList*> RenderDrawLists[3];
|
||||
float ModalWindowDarkeningRatio;
|
||||
ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays
|
||||
ImGuiMouseCursor MouseCursor;
|
||||
ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_];
|
||||
|
||||
// Drag and Drop
|
||||
bool DragDropActive;
|
||||
ImGuiDragDropFlags DragDropSourceFlags;
|
||||
int DragDropMouseButton;
|
||||
ImGuiPayload DragDropPayload;
|
||||
ImRect DragDropTargetRect;
|
||||
ImGuiID DragDropTargetId;
|
||||
float DragDropAcceptIdCurrRectSurface;
|
||||
ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload)
|
||||
ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets)
|
||||
int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source
|
||||
ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly
|
||||
unsigned char DragDropPayloadBufLocal[8];
|
||||
|
||||
// Widget state
|
||||
ImGuiTextEditState InputTextState;
|
||||
ImFont InputTextPasswordFont;
|
||||
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
|
||||
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
|
||||
ImVec4 ColorPickerRef;
|
||||
float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings
|
||||
ImVec2 DragLastMouseDelta;
|
||||
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
|
||||
float DragSpeedScaleSlow;
|
||||
float DragSpeedScaleFast;
|
||||
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
|
||||
int TooltipOverrideCount;
|
||||
ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
|
||||
ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor
|
||||
|
||||
// Settings
|
||||
float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero
|
||||
ImVector<ImGuiWindowSettings> SettingsWindows; // .ini settings for ImGuiWindow
|
||||
ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
|
||||
|
||||
// Logging
|
||||
bool LogEnabled;
|
||||
FILE* LogFile; // If != NULL log to stdout/ file
|
||||
ImGuiTextBuffer* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
|
||||
int LogStartDepth;
|
||||
int LogAutoExpandMaxDepth;
|
||||
|
||||
// Misc
|
||||
float FramerateSecPerFrame[120]; // calculate estimate of framerate for user
|
||||
int FramerateSecPerFrameIdx;
|
||||
float FramerateSecPerFrameAccum;
|
||||
int WantCaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags
|
||||
int WantCaptureKeyboardNextFrame;
|
||||
int WantTextInputNextFrame;
|
||||
char TempBuffer[1024*3+1]; // temporary text buffer
|
||||
|
||||
ImGuiContext() : OverlayDrawList(NULL)
|
||||
{
|
||||
Initialized = false;
|
||||
Font = NULL;
|
||||
FontSize = FontBaseSize = 0.0f;
|
||||
|
||||
Time = 0.0f;
|
||||
FrameCount = 0;
|
||||
FrameCountEnded = FrameCountRendered = -1;
|
||||
WindowsActiveCount = 0;
|
||||
CurrentWindow = NULL;
|
||||
NavWindow = NULL;
|
||||
HoveredWindow = NULL;
|
||||
HoveredRootWindow = NULL;
|
||||
HoveredId = 0;
|
||||
HoveredIdAllowOverlap = false;
|
||||
HoveredIdPreviousFrame = 0;
|
||||
HoveredIdTimer = 0.0f;
|
||||
ActiveId = 0;
|
||||
ActiveIdPreviousFrame = 0;
|
||||
ActiveIdTimer = 0.0f;
|
||||
ActiveIdIsAlive = false;
|
||||
ActiveIdIsJustActivated = false;
|
||||
ActiveIdAllowOverlap = false;
|
||||
ActiveIdClickOffset = ImVec2(-1,-1);
|
||||
ActiveIdWindow = NULL;
|
||||
MovingWindow = NULL;
|
||||
MovingWindowMoveId = 0;
|
||||
|
||||
SetNextWindowPosVal = ImVec2(0.0f, 0.0f);
|
||||
SetNextWindowSizeVal = ImVec2(0.0f, 0.0f);
|
||||
SetNextWindowCollapsedVal = false;
|
||||
SetNextWindowPosCond = 0;
|
||||
SetNextWindowSizeCond = 0;
|
||||
SetNextWindowContentSizeCond = 0;
|
||||
SetNextWindowCollapsedCond = 0;
|
||||
SetNextWindowSizeConstraintRect = ImRect();
|
||||
SetNextWindowSizeConstraintCallback = NULL;
|
||||
SetNextWindowSizeConstraintCallbackUserData = NULL;
|
||||
SetNextWindowSizeConstraint = false;
|
||||
SetNextWindowFocus = false;
|
||||
SetNextTreeNodeOpenVal = false;
|
||||
SetNextTreeNodeOpenCond = 0;
|
||||
|
||||
DragDropActive = false;
|
||||
DragDropSourceFlags = 0;
|
||||
DragDropMouseButton = -1;
|
||||
DragDropTargetId = 0;
|
||||
DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
|
||||
DragDropAcceptFrameCount = -1;
|
||||
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
|
||||
|
||||
ScalarAsInputTextId = 0;
|
||||
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
|
||||
DragCurrentValue = 0.0f;
|
||||
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
|
||||
DragSpeedDefaultRatio = 1.0f / 100.0f;
|
||||
DragSpeedScaleSlow = 1.0f / 100.0f;
|
||||
DragSpeedScaleFast = 10.0f;
|
||||
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
|
||||
TooltipOverrideCount = 0;
|
||||
OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f);
|
||||
|
||||
ModalWindowDarkeningRatio = 0.0f;
|
||||
OverlayDrawList._Data = &DrawListSharedData;
|
||||
OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
|
||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||
memset(MouseCursorData, 0, sizeof(MouseCursorData));
|
||||
|
||||
SettingsDirtyTimer = 0.0f;
|
||||
|
||||
LogEnabled = false;
|
||||
LogFile = NULL;
|
||||
LogClipboard = NULL;
|
||||
LogStartDepth = 0;
|
||||
LogAutoExpandMaxDepth = 2;
|
||||
|
||||
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
|
||||
FramerateSecPerFrameIdx = 0;
|
||||
FramerateSecPerFrameAccum = 0.0f;
|
||||
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
|
||||
memset(TempBuffer, 0, sizeof(TempBuffer));
|
||||
}
|
||||
};
|
||||
|
||||
// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin().
|
||||
enum ImGuiItemFlags_
|
||||
{
|
||||
ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true
|
||||
ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.
|
||||
ImGuiItemFlags_Disabled = 1 << 2, // false // FIXME-WIP: Disable interactions but doesn't affect visuals. Should be: grey out and disable interactions with widgets that affect data + view widgets (WIP)
|
||||
//ImGuiItemFlags_NoNav = 1 << 3, // false
|
||||
//ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false
|
||||
ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window
|
||||
ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus
|
||||
};
|
||||
|
||||
// Transient per-window data, reset at the beginning of the frame
|
||||
// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered.
|
||||
struct IMGUI_API ImGuiDrawContext
|
||||
{
|
||||
ImVec2 CursorPos;
|
||||
ImVec2 CursorPosPrevLine;
|
||||
ImVec2 CursorStartPos;
|
||||
ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Turned into window->SizeContents at the beginning of next frame
|
||||
float CurrentLineHeight;
|
||||
float CurrentLineTextBaseOffset;
|
||||
float PrevLineHeight;
|
||||
float PrevLineTextBaseOffset;
|
||||
float LogLinePosY;
|
||||
int TreeDepth;
|
||||
ImGuiID LastItemId;
|
||||
ImRect LastItemRect;
|
||||
bool LastItemRectHoveredRect;
|
||||
bool MenuBarAppending;
|
||||
float MenuBarOffsetX;
|
||||
ImVector<ImGuiWindow*> ChildWindows;
|
||||
ImGuiStorage* StateStorage;
|
||||
ImGuiLayoutType LayoutType;
|
||||
|
||||
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
|
||||
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
|
||||
float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
|
||||
float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
|
||||
ImVector<ImGuiItemFlags>ItemFlagsStack;
|
||||
ImVector<float> ItemWidthStack;
|
||||
ImVector<float> TextWrapPosStack;
|
||||
ImVector<ImGuiGroupData>GroupStack;
|
||||
int StackSizesBackup[6]; // Store size of various stacks for asserting
|
||||
|
||||
float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
|
||||
float GroupOffsetX;
|
||||
float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
|
||||
ImGuiColumnsSet* ColumnsSet; // Current columns set
|
||||
|
||||
ImGuiDrawContext()
|
||||
{
|
||||
CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f);
|
||||
CurrentLineHeight = PrevLineHeight = 0.0f;
|
||||
CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
|
||||
LogLinePosY = -1.0f;
|
||||
TreeDepth = 0;
|
||||
LastItemId = 0;
|
||||
LastItemRect = ImRect();
|
||||
LastItemRectHoveredRect = false;
|
||||
MenuBarAppending = false;
|
||||
MenuBarOffsetX = 0.0f;
|
||||
StateStorage = NULL;
|
||||
LayoutType = ImGuiLayoutType_Vertical;
|
||||
ItemWidth = 0.0f;
|
||||
ItemFlags = ImGuiItemFlags_Default_;
|
||||
TextWrapPos = -1.0f;
|
||||
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
|
||||
|
||||
IndentX = 0.0f;
|
||||
GroupOffsetX = 0.0f;
|
||||
ColumnsOffsetX = 0.0f;
|
||||
ColumnsSet = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// Windows data
|
||||
struct IMGUI_API ImGuiWindow
|
||||
{
|
||||
char* Name;
|
||||
ImGuiID ID; // == ImHash(Name)
|
||||
ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_
|
||||
ImVec2 PosFloat;
|
||||
ImVec2 Pos; // Position rounded-up to nearest pixel
|
||||
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
|
||||
ImVec2 SizeFull; // Size when non collapsed
|
||||
ImVec2 SizeFullAtLastBegin; // Copy of SizeFull at the end of Begin. This is the reference value we'll use on the next frame to decide if we need scrollbars.
|
||||
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. Include decoration, window title, border, menu, etc.
|
||||
ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize()
|
||||
ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis
|
||||
ImVec2 WindowPadding; // Window padding at the time of begin.
|
||||
float WindowRounding; // Window rounding at the time of begin.
|
||||
float WindowBorderSize; // Window border size at the time of begin.
|
||||
ImGuiID MoveId; // == window->GetID("#MOVE")
|
||||
ImVec2 Scroll;
|
||||
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
|
||||
ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
|
||||
bool ScrollbarX, ScrollbarY;
|
||||
ImVec2 ScrollbarSizes;
|
||||
bool Active; // Set to true on Begin()
|
||||
bool WasActive;
|
||||
bool WriteAccessed; // Set to true when any widget access the current window
|
||||
bool Collapsed; // Set when collapsing window to become only title-bar
|
||||
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
|
||||
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
|
||||
bool CloseButton; // Set when the window has a close button (p_open != NULL)
|
||||
int BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0.
|
||||
int BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues.
|
||||
int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
|
||||
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
|
||||
int AutoFitFramesX, AutoFitFramesY;
|
||||
bool AutoFitOnlyGrows;
|
||||
int AutoFitChildAxises;
|
||||
ImGuiDir AutoPosLastDirection;
|
||||
int HiddenFrames;
|
||||
ImGuiCond SetWindowPosAllowFlags; // store condition flags for next SetWindowPos() call.
|
||||
ImGuiCond SetWindowSizeAllowFlags; // store condition flags for next SetWindowSize() call.
|
||||
ImGuiCond SetWindowCollapsedAllowFlags; // store condition flags for next SetWindowCollapsed() call.
|
||||
ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size)
|
||||
ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right.
|
||||
|
||||
ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame
|
||||
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
|
||||
ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
|
||||
ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window.
|
||||
ImRect InnerRect;
|
||||
int LastFrameActive;
|
||||
float ItemWidthDefault;
|
||||
ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items
|
||||
ImGuiStorage StateStorage;
|
||||
ImVector<ImGuiColumnsSet> ColumnsStorage;
|
||||
float FontWindowScale; // Scale multiplier per-window
|
||||
ImDrawList* DrawList;
|
||||
ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL.
|
||||
ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window.
|
||||
ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
||||
|
||||
// Navigation / Focus
|
||||
int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
|
||||
int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
|
||||
int FocusIdxAllRequestCurrent; // Item being requested for focus
|
||||
int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus
|
||||
int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)
|
||||
int FocusIdxTabRequestNext; // "
|
||||
|
||||
public:
|
||||
ImGuiWindow(ImGuiContext* context, const char* name);
|
||||
~ImGuiWindow();
|
||||
|
||||
ImGuiID GetID(const char* str, const char* str_end = NULL);
|
||||
ImGuiID GetID(const void* ptr);
|
||||
ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
|
||||
ImGuiID GetIDFromRectangle(const ImRect& r_abs);
|
||||
|
||||
// We don't use g.FontSize because the window may be != g.CurrentWidow.
|
||||
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
|
||||
float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; }
|
||||
float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; }
|
||||
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
|
||||
float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; }
|
||||
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
|
||||
};
|
||||
|
||||
// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data.
|
||||
struct ImGuiItemHoveredDataBackup
|
||||
{
|
||||
ImGuiID LastItemId;
|
||||
ImRect LastItemRect;
|
||||
bool LastItemRectHoveredRect;
|
||||
|
||||
ImGuiItemHoveredDataBackup() { Backup(); }
|
||||
void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; }
|
||||
void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Internal API
|
||||
// No guarantee of forward compatibility here.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace ImGui
|
||||
{
|
||||
// We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
|
||||
// If this ever crash because g.CurrentWindow is NULL it means that either
|
||||
// - ImGui::NewFrame() has never been called, which is illegal.
|
||||
// - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
|
||||
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
|
||||
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
|
||||
IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
|
||||
IMGUI_API void FocusWindow(ImGuiWindow* window);
|
||||
IMGUI_API void BringWindowToFront(ImGuiWindow* window);
|
||||
IMGUI_API void BringWindowToBack(ImGuiWindow* window);
|
||||
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
|
||||
|
||||
IMGUI_API void Initialize();
|
||||
|
||||
IMGUI_API void MarkIniSettingsDirty();
|
||||
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(ImGuiID type_id);
|
||||
IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);
|
||||
|
||||
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
||||
IMGUI_API void ClearActiveID();
|
||||
IMGUI_API void SetHoveredID(ImGuiID id);
|
||||
IMGUI_API void KeepAliveID(ImGuiID id);
|
||||
|
||||
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
|
||||
IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
|
||||
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id);
|
||||
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
|
||||
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
|
||||
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested
|
||||
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
|
||||
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
|
||||
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
|
||||
IMGUI_API void PushMultiItemsWidths(int components, float width_full = 0.0f);
|
||||
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
|
||||
IMGUI_API void PopItemFlag();
|
||||
|
||||
IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing);
|
||||
IMGUI_API void ClosePopup(ImGuiID id);
|
||||
IMGUI_API bool IsPopupOpen(ImGuiID id);
|
||||
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
|
||||
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true);
|
||||
|
||||
IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate);
|
||||
|
||||
IMGUI_API void Scrollbar(ImGuiLayoutType direction);
|
||||
IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout.
|
||||
IMGUI_API bool SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f);
|
||||
|
||||
IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id);
|
||||
IMGUI_API void ClearDragDrop();
|
||||
IMGUI_API bool IsDragDropPayloadBeingAccepted();
|
||||
|
||||
// FIXME-WIP: New Columns API
|
||||
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
|
||||
IMGUI_API void EndColumns(); // close columns
|
||||
IMGUI_API void PushColumnClipRect(int column_index = -1);
|
||||
|
||||
// NB: All position are in absolute pixels coordinates (never using window coordinates internally)
|
||||
// AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT.
|
||||
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
|
||||
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
||||
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);
|
||||
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
|
||||
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0);
|
||||
IMGUI_API void RenderTriangle(ImVec2 pos, ImGuiDir dir, float scale = 1.0f);
|
||||
IMGUI_API void RenderBullet(ImVec2 pos);
|
||||
IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz);
|
||||
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
|
||||
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
|
||||
|
||||
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius);
|
||||
IMGUI_API bool ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFlags flags = 0);
|
||||
|
||||
IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power);
|
||||
IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format);
|
||||
|
||||
IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power);
|
||||
IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power);
|
||||
IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format);
|
||||
|
||||
IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);
|
||||
IMGUI_API bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags);
|
||||
IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags);
|
||||
IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags);
|
||||
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision);
|
||||
|
||||
IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);
|
||||
IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags);
|
||||
|
||||
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
|
||||
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
|
||||
IMGUI_API void TreePushRawID(ImGuiID id);
|
||||
|
||||
IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);
|
||||
|
||||
IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value);
|
||||
IMGUI_API float RoundScalar(float value, int decimal_precision);
|
||||
|
||||
// Shade functions
|
||||
IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1);
|
||||
IMGUI_API void ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x);
|
||||
IMGUI_API void ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp);
|
||||
|
||||
} // namespace ImGui
|
||||
|
||||
// ImFontAtlas internals
|
||||
IMGUI_API bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent);
|
||||
IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc);
|
||||
IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
|
||||
IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);
|
||||
IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
583
skeleton/imgui/stb_rect_pack.h
Normal file
583
skeleton/imgui/stb_rect_pack.h
Normal file
@ -0,0 +1,583 @@
|
||||
// stb_rect_pack.h - v0.10 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Not necessarily the awesomest packing method, but better than
|
||||
// the totally naive one in stb_truetype (which is primarily what
|
||||
// this is meant to replace).
|
||||
//
|
||||
// Has only had a few tests run, may have issues.
|
||||
//
|
||||
// More docs to come.
|
||||
//
|
||||
// No memory allocations; uses qsort() and assert() from stdlib.
|
||||
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
|
||||
//
|
||||
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||
//
|
||||
// Please note: better rectangle packers are welcome! Please
|
||||
// implement them to the same API, but with a different init
|
||||
// function.
|
||||
//
|
||||
// Credits
|
||||
//
|
||||
// Library
|
||||
// Sean Barrett
|
||||
// Minor features
|
||||
// Martins Mozeiko
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
// 0.09 (2016-08-27) fix compiler warnings
|
||||
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||
// 0.01: initial release
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// This software is dual-licensed to the public domain and under the following
|
||||
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||
// publish, and distribute this file as you see fit.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// INCLUDE SECTION
|
||||
//
|
||||
|
||||
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||
|
||||
#define STB_RECT_PACK_VERSION 1
|
||||
|
||||
#ifdef STBRP_STATIC
|
||||
#define STBRP_DEF static
|
||||
#else
|
||||
#define STBRP_DEF extern
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct stbrp_context stbrp_context;
|
||||
typedef struct stbrp_node stbrp_node;
|
||||
typedef struct stbrp_rect stbrp_rect;
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
typedef int stbrp_coord;
|
||||
#else
|
||||
typedef unsigned short stbrp_coord;
|
||||
#endif
|
||||
|
||||
STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||
// are 'num_rects' many of them.
|
||||
//
|
||||
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||
// have the 'was_packed' flag set to 0.
|
||||
//
|
||||
// You should not try to access the 'rects' array from another thread
|
||||
// while this function is running, as the function temporarily reorders
|
||||
// the array while it executes.
|
||||
//
|
||||
// To pack into another rectangle, you need to call stbrp_init_target
|
||||
// again. To continue packing into the same rectangle, you can call
|
||||
// this function again. Calling this multiple times with multiple rect
|
||||
// arrays will probably produce worse packing results than calling it
|
||||
// a single time with the full rectangle array, but the option is
|
||||
// available.
|
||||
|
||||
struct stbrp_rect
|
||||
{
|
||||
// reserved for your use:
|
||||
int id;
|
||||
|
||||
// input:
|
||||
stbrp_coord w, h;
|
||||
|
||||
// output:
|
||||
stbrp_coord x, y;
|
||||
int was_packed; // non-zero if valid packing
|
||||
|
||||
}; // 16 bytes, nominally
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||
// Initialize a rectangle packer to:
|
||||
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||
//
|
||||
// You must call this function every time you start packing into a new target.
|
||||
//
|
||||
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||
// the call (or calls) finish.
|
||||
//
|
||||
// Note: to guarantee best results, either:
|
||||
// 1. make sure 'num_nodes' >= 'width'
|
||||
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||
//
|
||||
// If you don't do either of the above things, widths will be quantized to multiples
|
||||
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||
//
|
||||
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||
// may run out of temporary storage and be unable to pack some rectangles.
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||
// Optionally call this function after init but before doing any packing to
|
||||
// change the handling of the out-of-temp-memory scenario, described above.
|
||||
// If you call init again, this will be reset to the default (false).
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||
// Optionally select which packing heuristic the library should use. Different
|
||||
// heuristics will produce better/worse results for different data sets.
|
||||
// If you call init again, this will be reset to the default.
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP_HEURISTIC_Skyline_default=0,
|
||||
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// the details of the following structures don't matter to you, but they must
|
||||
// be visible so you can handle the memory allocations for them
|
||||
|
||||
struct stbrp_node
|
||||
{
|
||||
stbrp_coord x,y;
|
||||
stbrp_node *next;
|
||||
};
|
||||
|
||||
struct stbrp_context
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int align;
|
||||
int init_mode;
|
||||
int heuristic;
|
||||
int num_nodes;
|
||||
stbrp_node *active_head;
|
||||
stbrp_node *free_head;
|
||||
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPLEMENTATION SECTION
|
||||
//
|
||||
|
||||
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||
#ifndef STBRP_SORT
|
||||
#include <stdlib.h>
|
||||
#define STBRP_SORT qsort
|
||||
#endif
|
||||
|
||||
#ifndef STBRP_ASSERT
|
||||
#include <assert.h>
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP__INIT_skyline = 1
|
||||
};
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||
{
|
||||
switch (context->init_mode) {
|
||||
case STBRP__INIT_skyline:
|
||||
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||
context->heuristic = heuristic;
|
||||
break;
|
||||
default:
|
||||
STBRP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||
{
|
||||
if (allow_out_of_mem)
|
||||
// if it's ok to run out of memory, then don't bother aligning them;
|
||||
// this gives better packing, but may fail due to OOM (even though
|
||||
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||
context->align = 1;
|
||||
else {
|
||||
// if it's not ok to run out of memory, then quantize the widths
|
||||
// so that num_nodes is always enough nodes.
|
||||
//
|
||||
// I.e. num_nodes * align >= width
|
||||
// align >= width / num_nodes
|
||||
// align = ceil(width/num_nodes)
|
||||
|
||||
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||
{
|
||||
int i;
|
||||
#ifndef STBRP_LARGE_RECTS
|
||||
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
|
||||
#endif
|
||||
|
||||
for (i=0; i < num_nodes-1; ++i)
|
||||
nodes[i].next = &nodes[i+1];
|
||||
nodes[i].next = NULL;
|
||||
context->init_mode = STBRP__INIT_skyline;
|
||||
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||
context->free_head = &nodes[0];
|
||||
context->active_head = &context->extra[0];
|
||||
context->width = width;
|
||||
context->height = height;
|
||||
context->num_nodes = num_nodes;
|
||||
stbrp_setup_allow_out_of_mem(context, 0);
|
||||
|
||||
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||
context->extra[0].x = 0;
|
||||
context->extra[0].y = 0;
|
||||
context->extra[0].next = &context->extra[1];
|
||||
context->extra[1].x = (stbrp_coord) width;
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
context->extra[1].y = (1<<30);
|
||||
#else
|
||||
context->extra[1].y = 65535;
|
||||
#endif
|
||||
context->extra[1].next = NULL;
|
||||
}
|
||||
|
||||
// find minimum y position if it starts at x1
|
||||
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||
{
|
||||
stbrp_node *node = first;
|
||||
int x1 = x0 + width;
|
||||
int min_y, visited_width, waste_area;
|
||||
|
||||
STBRP__NOTUSED(c);
|
||||
|
||||
STBRP_ASSERT(first->x <= x0);
|
||||
|
||||
#if 0
|
||||
// skip in case we're past the node
|
||||
while (node->next->x <= x0)
|
||||
++node;
|
||||
#else
|
||||
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||
#endif
|
||||
|
||||
STBRP_ASSERT(node->x <= x0);
|
||||
|
||||
min_y = 0;
|
||||
waste_area = 0;
|
||||
visited_width = 0;
|
||||
while (node->x < x1) {
|
||||
if (node->y > min_y) {
|
||||
// raise min_y higher.
|
||||
// we've accounted for all waste up to min_y,
|
||||
// but we'll now add more waste for everything we've visted
|
||||
waste_area += visited_width * (node->y - min_y);
|
||||
min_y = node->y;
|
||||
// the first time through, visited_width might be reduced
|
||||
if (node->x < x0)
|
||||
visited_width += node->next->x - x0;
|
||||
else
|
||||
visited_width += node->next->x - node->x;
|
||||
} else {
|
||||
// add waste area
|
||||
int under_width = node->next->x - node->x;
|
||||
if (under_width + visited_width > width)
|
||||
under_width = width - visited_width;
|
||||
waste_area += under_width * (min_y - node->y);
|
||||
visited_width += under_width;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
*pwaste = waste_area;
|
||||
return min_y;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x,y;
|
||||
stbrp_node **prev_link;
|
||||
} stbrp__findresult;
|
||||
|
||||
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||
{
|
||||
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||
stbrp__findresult fr;
|
||||
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||
|
||||
// align to multiple of c->align
|
||||
width = (width + c->align - 1);
|
||||
width -= width % c->align;
|
||||
STBRP_ASSERT(width % c->align == 0);
|
||||
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
while (node->x + width <= c->width) {
|
||||
int y,waste;
|
||||
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||
// bottom left
|
||||
if (y < best_y) {
|
||||
best_y = y;
|
||||
best = prev;
|
||||
}
|
||||
} else {
|
||||
// best-fit
|
||||
if (y + height <= c->height) {
|
||||
// can only use it if it first vertically
|
||||
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||
|
||||
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||
//
|
||||
// e.g, if fitting
|
||||
//
|
||||
// ____________________
|
||||
// |____________________|
|
||||
//
|
||||
// into
|
||||
//
|
||||
// | |
|
||||
// | ____________|
|
||||
// |____________|
|
||||
//
|
||||
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||
//
|
||||
// This makes BF take about 2x the time
|
||||
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||
tail = c->active_head;
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
// find first node that's admissible
|
||||
while (tail->x < width)
|
||||
tail = tail->next;
|
||||
while (tail) {
|
||||
int xpos = tail->x - width;
|
||||
int y,waste;
|
||||
STBRP_ASSERT(xpos >= 0);
|
||||
// find the left position that matches this
|
||||
while (node->next->x <= xpos) {
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||
if (y + height < c->height) {
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
STBRP_ASSERT(y <= best_y);
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
tail = tail->next;
|
||||
}
|
||||
}
|
||||
|
||||
fr.prev_link = best;
|
||||
fr.x = best_x;
|
||||
fr.y = best_y;
|
||||
return fr;
|
||||
}
|
||||
|
||||
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||
{
|
||||
// find best position according to heuristic
|
||||
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||
stbrp_node *node, *cur;
|
||||
|
||||
// bail if:
|
||||
// 1. it failed
|
||||
// 2. the best node doesn't fit (we don't always check this)
|
||||
// 3. we're out of memory
|
||||
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||
res.prev_link = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
// on success, create new node
|
||||
node = context->free_head;
|
||||
node->x = (stbrp_coord) res.x;
|
||||
node->y = (stbrp_coord) (res.y + height);
|
||||
|
||||
context->free_head = node->next;
|
||||
|
||||
// insert the new node into the right starting point, and
|
||||
// let 'cur' point to the remaining nodes needing to be
|
||||
// stiched back in
|
||||
|
||||
cur = *res.prev_link;
|
||||
if (cur->x < res.x) {
|
||||
// preserve the existing one, so start testing with the next one
|
||||
stbrp_node *next = cur->next;
|
||||
cur->next = node;
|
||||
cur = next;
|
||||
} else {
|
||||
*res.prev_link = node;
|
||||
}
|
||||
|
||||
// from here, traverse cur and free the nodes, until we get to one
|
||||
// that shouldn't be freed
|
||||
while (cur->next && cur->next->x <= res.x + width) {
|
||||
stbrp_node *next = cur->next;
|
||||
// move the current node to the free list
|
||||
cur->next = context->free_head;
|
||||
context->free_head = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
// stitch the list back in
|
||||
node->next = cur;
|
||||
|
||||
if (cur->x < res.x + width)
|
||||
cur->x = (stbrp_coord) (res.x + width);
|
||||
|
||||
#ifdef _DEBUG
|
||||
cur = context->active_head;
|
||||
while (cur->x < context->width) {
|
||||
STBRP_ASSERT(cur->x < cur->next->x);
|
||||
cur = cur->next;
|
||||
}
|
||||
STBRP_ASSERT(cur->next == NULL);
|
||||
|
||||
{
|
||||
stbrp_node *L1 = NULL, *L2 = NULL;
|
||||
int count=0;
|
||||
cur = context->active_head;
|
||||
while (cur) {
|
||||
L1 = cur;
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
cur = context->free_head;
|
||||
while (cur) {
|
||||
L2 = cur;
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
STBRP_ASSERT(count == context->num_nodes+2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->h > q->h)
|
||||
return -1;
|
||||
if (p->h < q->h)
|
||||
return 1;
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
static int rect_width_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->w > q->w)
|
||||
return -1;
|
||||
if (p->w < q->w)
|
||||
return 1;
|
||||
return (p->h > q->h) ? -1 : (p->h < q->h);
|
||||
}
|
||||
|
||||
static int rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
#define STBRP__MAXVAL 0xffffffff
|
||||
#else
|
||||
#define STBRP__MAXVAL 0xffff
|
||||
#endif
|
||||
|
||||
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i;
|
||||
|
||||
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = i;
|
||||
#ifndef STBRP_LARGE_RECTS
|
||||
STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);
|
||||
#endif
|
||||
}
|
||||
|
||||
// sort according to heuristic
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||
} else {
|
||||
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||
if (fr.prev_link) {
|
||||
rects[i].x = (stbrp_coord) fr.x;
|
||||
rects[i].y = (stbrp_coord) fr.y;
|
||||
} else {
|
||||
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unsort
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||
|
||||
// set was_packed flags
|
||||
for (i=0; i < num_rects; ++i)
|
||||
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||
}
|
||||
#endif
|
1322
skeleton/imgui/stb_textedit.h
Normal file
1322
skeleton/imgui/stb_textedit.h
Normal file
File diff suppressed because it is too large
Load Diff
4018
skeleton/imgui/stb_truetype.h
Normal file
4018
skeleton/imgui/stb_truetype.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -69,6 +69,9 @@ enum Event
|
||||
PLUGINATTACH,
|
||||
KEYDOWN,
|
||||
KEYUP,
|
||||
CHARINPUT,
|
||||
MOUSEMOVE,
|
||||
MOUSEBTN,
|
||||
RESIZE,
|
||||
IDLE,
|
||||
QUIT
|
||||
@ -83,6 +86,13 @@ struct Globals
|
||||
};
|
||||
extern Globals globals;
|
||||
|
||||
// Argument to mouse events
|
||||
struct MouseState
|
||||
{
|
||||
int posx, posy;
|
||||
int buttons; // bits 0-2 are left, middle, right button down
|
||||
};
|
||||
|
||||
struct Args
|
||||
{
|
||||
int argc;
|
||||
@ -94,8 +104,12 @@ bool InitRW(void);
|
||||
void TerminateRW(void);
|
||||
Camera *CameraCreate(int32 width, int32 height, bool32 z);
|
||||
void CameraSize(Camera *cam, Rect *r);
|
||||
void SetMousePosition(int x, int y);
|
||||
EventStatus EventHandler(Event e, void *param);
|
||||
|
||||
}
|
||||
|
||||
sk::EventStatus AppEventHandler(sk::Event e, void *param);
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/imgui_impl_rw.h"
|
||||
|
@ -64,7 +64,9 @@ LRESULT CALLBACK
|
||||
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static int resizing = 0;
|
||||
static int buttons = 0;
|
||||
|
||||
MouseState ms;
|
||||
switch(msg){
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
@ -100,6 +102,35 @@ WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
KeyUp(keymap[wParam]);
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
if(wParam > 0 && wParam < 0x10000)
|
||||
EventHandler(CHARINPUT, (void*)wParam);
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
POINTS p = MAKEPOINTS(lParam);
|
||||
ms.posx = p.x;
|
||||
ms.posy = p.y;
|
||||
EventHandler(MOUSEMOVE, &ms);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
buttons |= 1; goto mbtn;
|
||||
case WM_LBUTTONUP:
|
||||
buttons &= ~1; goto mbtn;
|
||||
case WM_MBUTTONDOWN:
|
||||
buttons |= 2; goto mbtn;
|
||||
case WM_MBUTTONUP:
|
||||
buttons &= ~2; goto mbtn;
|
||||
case WM_RBUTTONDOWN:
|
||||
buttons |= 4; goto mbtn;
|
||||
case WM_RBUTTONUP:
|
||||
buttons &= ~4;
|
||||
mbtn:
|
||||
ms.buttons = buttons;
|
||||
EventHandler(MOUSEBTN, &ms);
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
rw::Rect r;
|
||||
r.x = 0;
|
||||
@ -181,12 +212,19 @@ int WINAPI
|
||||
WinMain(HINSTANCE instance, HINSTANCE,
|
||||
PSTR cmdLine, int showCmd)
|
||||
{
|
||||
/*
|
||||
|
||||
AllocConsole();
|
||||
freopen("CONIN$", "r", stdin);
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
*/
|
||||
|
||||
INT64 ticks;
|
||||
INT64 ticksPerSecond;
|
||||
if(!QueryPerformanceFrequency((LARGE_INTEGER*)&ticksPerSecond))
|
||||
return 0;
|
||||
if(!QueryPerformanceCounter((LARGE_INTEGER*)&ticks))
|
||||
return 0;
|
||||
|
||||
args.argc = __argc;
|
||||
args.argv = __argv;
|
||||
if(EventHandler(INITIALIZE, nil) == EVENTERROR)
|
||||
@ -205,21 +243,35 @@ WinMain(HINSTANCE instance, HINSTANCE,
|
||||
if(EventHandler(RWINITIALIZE, nil) == EVENTERROR)
|
||||
return 0;
|
||||
|
||||
float lastTime = (float)GetTickCount();
|
||||
INT64 lastTicks;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&lastTicks);
|
||||
running = true;
|
||||
while((pollEvents(), running) && !globals.quit){
|
||||
float currTime = (float)GetTickCount();
|
||||
float timeDelta = (currTime - lastTime)*0.001f;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
|
||||
float timeDelta = (float)(ticks - lastTicks)/ticksPerSecond;
|
||||
|
||||
EventHandler(IDLE, &timeDelta);
|
||||
|
||||
lastTime = currTime;
|
||||
lastTicks = ticks;
|
||||
}
|
||||
|
||||
EventHandler(RWTERMINATE, nil);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace sk {
|
||||
|
||||
void
|
||||
SetMousePosition(int x, int y)
|
||||
{
|
||||
POINT pos = { x, y };
|
||||
ClientToScreen(engineStartParams.window, &pos);
|
||||
SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef RW_OPENGL
|
||||
|
@ -479,11 +479,27 @@ Camera::streamGetSize(void)
|
||||
s_plglist.streamGetSize(this);
|
||||
}
|
||||
|
||||
// Assumes horizontal FOV for 4:3, but we convert to vertical FOV
|
||||
void
|
||||
Camera::setFOV(float32 fov, float32 ratio)
|
||||
Camera::setFOV(float32 hfov, float32 ratio)
|
||||
{
|
||||
V2d v;
|
||||
float32 a = tan(fov*3.14159f/360.0f);
|
||||
float w, h;
|
||||
|
||||
w = this->frameBuffer->width;
|
||||
h = this->frameBuffer->height;
|
||||
if(w < 1 || h < 1){
|
||||
w = 1;
|
||||
h = 1;
|
||||
}
|
||||
hfov = hfov*3.14159f/360.0f; // deg to rad
|
||||
|
||||
float ar1 = 4.0/3.0;
|
||||
float ar2 = w/h;
|
||||
float vfov = atan(tan(hfov/2) / ar1) *2;
|
||||
hfov = atan(tan(vfov/2) * ar2) *2;
|
||||
|
||||
float32 a = tan(hfov);
|
||||
v.set(a, a/ratio);
|
||||
this->setViewWindow(&v);
|
||||
v.set(0.0f, 0.0f);
|
||||
|
@ -28,8 +28,8 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
|
||||
int lighting = !!(geo->flags & rw::Geometry::LIGHT);
|
||||
if(lighting)
|
||||
d3d::lightingCB();
|
||||
else
|
||||
return;
|
||||
// else
|
||||
// return;
|
||||
|
||||
d3d::setRenderState(D3DRS_LIGHTING, lighting);
|
||||
|
||||
@ -45,6 +45,13 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
|
||||
InstanceData *inst = header->inst;
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
d3d::setTexture(0, inst->material->texture);
|
||||
d3d::setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
d3d::setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||||
d3d::setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
|
||||
d3d::setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
d3d::setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
|
||||
d3d::setTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
|
||||
|
||||
d3d::setMaterial(inst->material);
|
||||
|
||||
d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
|
||||
|
@ -84,6 +84,12 @@ setRenderState(uint32 state, uint32 value)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
getRenderState(uint32 state, uint32 *value)
|
||||
{
|
||||
*value = stateCache[state].value;
|
||||
}
|
||||
|
||||
void
|
||||
setTextureStageState(uint32 stage, uint32 type, uint32 value)
|
||||
{
|
||||
@ -98,6 +104,12 @@ setTextureStageState(uint32 stage, uint32 type, uint32 value)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
getTextureStageState(uint32 stage, uint32 type, uint32 *value)
|
||||
{
|
||||
*value = textureStageStateCache[type][stage].value;
|
||||
}
|
||||
|
||||
void
|
||||
flushCache(void)
|
||||
{
|
||||
@ -135,6 +147,12 @@ setSamplerState(uint32 stage, uint32 type, uint32 value)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
getSamplerState(uint32 stage, uint32 type, uint32 *value)
|
||||
{
|
||||
*value = d3dSamplerStates[type][stage];
|
||||
}
|
||||
|
||||
// Bring D3D device in accordance with saved render states (after a reset)
|
||||
static void
|
||||
resetD3d9Device(void)
|
||||
@ -480,7 +498,8 @@ clearCamera(Camera *cam, RGBA *col, uint32 mode)
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
d3dpp.Flags = 0;
|
||||
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
||||
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
// TODO: check result
|
||||
d3d::d3ddevice->Reset(&d3dpp);
|
||||
d3d9Globals.presentWidth = r.right;
|
||||
@ -548,7 +567,8 @@ openD3D(EngineStartParams *params)
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
d3dpp.Flags = 0;
|
||||
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
||||
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
|
||||
IDirect3DDevice9 *dev;
|
||||
hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, win,
|
||||
|
@ -77,6 +77,13 @@ im2DRenderIndexedPrimitive(PrimitiveType primType,
|
||||
d3ddevice->SetIndices(im2dindbuf);
|
||||
d3ddevice->SetVertexDeclaration(im2ddecl);
|
||||
d3d::setTexture(0, engine->imtexture);
|
||||
setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||||
setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
setTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
|
||||
|
||||
d3d::flushCache();
|
||||
|
||||
uint32 primCount = 0;
|
||||
|
@ -143,8 +143,11 @@ void registerNativeRaster(void);
|
||||
// Rendering
|
||||
|
||||
void setRenderState(uint32 state, uint32 value);
|
||||
void getRenderState(uint32 state, uint32 *value);
|
||||
void setTextureStageState(uint32 stage, uint32 type, uint32 value);
|
||||
void getTextureStageState(uint32 stage, uint32 type, uint32 *value);
|
||||
void setSamplerState(uint32 stage, uint32 type, uint32 value);
|
||||
void getSamplerState(uint32 stage, uint32 type, uint32 *value);
|
||||
void flushCache(void);
|
||||
|
||||
void setTexture(uint32 stage, Texture *tex);
|
||||
|
@ -1595,6 +1595,7 @@ readNativeTexture(Stream *stream)
|
||||
goto fail;
|
||||
}
|
||||
stream->read(&streamExt, 0x40);
|
||||
/*
|
||||
printf("%X %X %X %X %X %016llX %X %X %016llX %016llX %X %X %X %X\n",
|
||||
streamExt.width,
|
||||
streamExt.height,
|
||||
@ -1610,7 +1611,7 @@ streamExt.pixelSize,
|
||||
streamExt.paletteSize,
|
||||
streamExt.totalSize,
|
||||
streamExt.mipmapVal);
|
||||
|
||||
*/
|
||||
noNewStyleRasters = streamExt.type < 2;
|
||||
rw::version = version;
|
||||
raster = Raster::create(streamExt.width, streamExt.height,
|
||||
|
@ -683,6 +683,7 @@ struct TexDictionary
|
||||
void destroy(void);
|
||||
int32 count(void) { return this->textures.count(); }
|
||||
void add(Texture *t);
|
||||
void addFront(Texture *t);
|
||||
Texture *find(const char *name);
|
||||
static TexDictionary *streamRead(Stream *stream);
|
||||
void streamWrite(Stream *stream);
|
||||
|
@ -113,6 +113,15 @@ TexDictionary::add(Texture *t)
|
||||
this->textures.append(&t->inDict);
|
||||
}
|
||||
|
||||
void
|
||||
TexDictionary::addFront(Texture *t)
|
||||
{
|
||||
if(t->dict)
|
||||
t->inDict.remove();
|
||||
t->dict = this;
|
||||
this->textures.add(&t->inDict);
|
||||
}
|
||||
|
||||
Texture*
|
||||
TexDictionary::find(const char *name)
|
||||
{
|
||||
|
169
tools/imguitest/main.cpp
Normal file
169
tools/imguitest/main.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#include <rw.h>
|
||||
#include <skeleton.h>
|
||||
#include <assert.h>
|
||||
|
||||
rw::V3d zero = { 0.0f, 0.0f, 0.0f };
|
||||
struct SceneGlobals {
|
||||
rw::World *world;
|
||||
rw::Camera *camera;
|
||||
} Scene;
|
||||
rw::EngineStartParams engineStartParams;
|
||||
|
||||
void
|
||||
Init(void)
|
||||
{
|
||||
sk::globals.windowtitle = "ImGui test";
|
||||
sk::globals.width = 1280;
|
||||
sk::globals.height = 800;
|
||||
sk::globals.quit = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
attachPlugins(void)
|
||||
{
|
||||
rw::ps2::registerPDSPlugin(40);
|
||||
rw::ps2::registerPluginPDSPipes();
|
||||
|
||||
rw::registerMeshPlugin();
|
||||
rw::registerNativeDataPlugin();
|
||||
rw::registerAtomicRightsPlugin();
|
||||
rw::registerMaterialRightsPlugin();
|
||||
rw::xbox::registerVertexFormatPlugin();
|
||||
rw::registerSkinPlugin();
|
||||
rw::registerUserDataPlugin();
|
||||
rw::registerHAnimPlugin();
|
||||
rw::registerMatFXPlugin();
|
||||
rw::registerUVAnimPlugin();
|
||||
rw::ps2::registerADCPlugin();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
InitRW(void)
|
||||
{
|
||||
// rw::platform = rw::PLATFORM_D3D8;
|
||||
if(!sk::InitRW())
|
||||
return false;
|
||||
|
||||
Scene.world = rw::World::create();
|
||||
|
||||
rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT);
|
||||
ambient->setColor(0.2f, 0.2f, 0.2f);
|
||||
Scene.world->addLight(ambient);
|
||||
|
||||
rw::V3d xaxis = { 1.0f, 0.0f, 0.0f };
|
||||
rw::Light *direct = rw::Light::create(rw::Light::DIRECTIONAL);
|
||||
direct->setColor(0.8f, 0.8f, 0.8f);
|
||||
direct->setFrame(rw::Frame::create());
|
||||
direct->getFrame()->rotate(&xaxis, 180.0f, rw::COMBINEREPLACE);
|
||||
Scene.world->addLight(direct);
|
||||
|
||||
Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
|
||||
Scene.world->addCamera(Scene.camera);
|
||||
|
||||
ImGui_ImplRW_Init();
|
||||
ImGui::StyleColorsClassic();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Draw(float timeDelta)
|
||||
{
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
rw::RGBA clearcol = { clear_color.x*255, clear_color.y*255, clear_color.z*255, clear_color.w*255 };
|
||||
Scene.camera->clear(&clearcol, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
|
||||
Scene.camera->beginUpdate();
|
||||
|
||||
ImGui_ImplRW_NewFrame(timeDelta);
|
||||
|
||||
// 1. Show a simple window.
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
|
||||
{
|
||||
static float f = 0.0f;
|
||||
ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
|
||||
if(ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
|
||||
show_demo_window ^= 1;
|
||||
if(ImGui::Button("Another Window"))
|
||||
show_another_window ^= 1;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
}
|
||||
|
||||
// 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
|
||||
if(show_another_window){
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello from another window!");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
|
||||
if(show_demo_window){
|
||||
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
||||
Scene.camera->endUpdate();
|
||||
Scene.camera->showRaster();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyUp(int key)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
KeyDown(int key)
|
||||
{
|
||||
switch(key){
|
||||
case sk::KEY_ESC:
|
||||
sk::globals.quit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sk::EventStatus
|
||||
AppEventHandler(sk::Event e, void *param)
|
||||
{
|
||||
using namespace sk;
|
||||
Rect *r;
|
||||
|
||||
ImGuiEventHandler(e, param);
|
||||
|
||||
switch(e){
|
||||
case INITIALIZE:
|
||||
Init();
|
||||
return EVENTPROCESSED;
|
||||
case RWINITIALIZE:
|
||||
return ::InitRW() ? EVENTPROCESSED : EVENTERROR;
|
||||
case PLUGINATTACH:
|
||||
return attachPlugins() ? EVENTPROCESSED : EVENTERROR;
|
||||
case KEYDOWN:
|
||||
KeyDown(*(int*)param);
|
||||
return EVENTPROCESSED;
|
||||
case KEYUP:
|
||||
KeyUp(*(int*)param);
|
||||
return EVENTPROCESSED;
|
||||
case RESIZE:
|
||||
r = (Rect*)param;
|
||||
sk::globals.width = r->w;
|
||||
sk::globals.height = r->h;
|
||||
// TODO: set aspect ratio
|
||||
if(Scene.camera)
|
||||
sk::CameraSize(Scene.camera, r);
|
||||
break;
|
||||
case IDLE:
|
||||
Draw(*(float*)param);
|
||||
return EVENTPROCESSED;
|
||||
}
|
||||
return sk::EVENTNOTPROCESSED;
|
||||
}
|
Loading…
Reference in New Issue
Block a user