commit
8cb40073f7
|
|
@ -4,14 +4,16 @@
|
|||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imconfig.h" />
|
||||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imgui.h" />
|
||||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imgui_internal.h" />
|
||||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imgui_stdlib.h" />
|
||||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imstb_rectpack.h" />
|
||||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imstb_textedit.h" />
|
||||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imstb_truetype.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui.cpp" />
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_demo.cpp" />
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_draw.cpp" />
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_stdlib.cpp" />
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_tables.cpp" />
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_widgets.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
|
|
|
|||
|
|
@ -27,19 +27,25 @@
|
|||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imstb_truetype.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\3rd-party\imgui\imgui_stdlib.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_demo.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_draw.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_widgets.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_tables.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\3rd-party\imgui\imgui_stdlib.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -4,12 +4,13 @@ set(SOURCE_FILES
|
|||
imconfig.h
|
||||
imgui.cpp
|
||||
imgui.h
|
||||
imgui_demo.cpp
|
||||
imgui_draw.cpp
|
||||
imgui_internal.h
|
||||
imgui_widgets.cpp
|
||||
imstb_rectpack.h
|
||||
imstb_textedit.h
|
||||
imstb_truetype.h)
|
||||
imstb_truetype.h
|
||||
imgui_stdlib.h
|
||||
imgui_stdlib.cpp)
|
||||
|
||||
add_library(libimgui ${SOURCE_FILES})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2019 Omar Cornut
|
||||
Copyright (c) 2014-2023 Omar Cornut
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
|
|
@ -1,40 +1,53 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
// A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h)
|
||||
// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
|
||||
// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ dear imgui is used, which include
|
||||
// the imgui*.cpp files but also _any_ of your code that uses imgui. This is because some compile-time options have an affect on data structures.
|
||||
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
||||
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
||||
//-----------------------------------------------------------------------------
|
||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec( dllexport )
|
||||
//#define IMGUI_API __declspec( dllimport )
|
||||
|
||||
//---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
|
||||
|
||||
//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
|
||||
//---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
|
||||
#define IMGUI_DISABLE_DEMO_WINDOWS
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function.
|
||||
//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf.
|
||||
//#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
|
|
@ -42,32 +55,75 @@
|
|||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of imgui cpp files.
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||
|
||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||
//#define IMGUI_USE_STB_SPRINTF
|
||||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
|
||||
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
|
||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||
constexpr 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; } \
|
||||
constexpr 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); }
|
||||
*/
|
||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
||||
//#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it.
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||
//#define ImDrawIdx unsigned int
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||
//struct ImDrawList;
|
||||
//struct ImDrawCmd;
|
||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||
//#define ImDrawCallback MyImDrawCallback
|
||||
|
||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, const MyMatrix44& v);
|
||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,85 @@
|
|||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
|
||||
// Changelog:
|
||||
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
|
||||
|
||||
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
|
||||
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_stdlib.h"
|
||||
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#endif
|
||||
|
||||
struct InputTextCallback_UserData
|
||||
{
|
||||
std::string* Str;
|
||||
ImGuiInputTextCallback ChainCallback;
|
||||
void* ChainCallbackUserData;
|
||||
};
|
||||
|
||||
static int InputTextCallback(ImGuiInputTextCallbackData* data)
|
||||
{
|
||||
InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData;
|
||||
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
|
||||
{
|
||||
// Resize string callback
|
||||
// If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want.
|
||||
std::string* str = user_data->Str;
|
||||
IM_ASSERT(data->Buf == str->c_str());
|
||||
str->resize(data->BufTextLen);
|
||||
data->Buf = (char*)str->c_str();
|
||||
}
|
||||
else if (user_data->ChainCallback)
|
||||
{
|
||||
// Forward to user callback, if any
|
||||
data->UserData = user_data->ChainCallbackUserData;
|
||||
return user_data->ChainCallback(data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||
{
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
|
||||
flags |= ImGuiInputTextFlags_CallbackResize;
|
||||
|
||||
InputTextCallback_UserData cb_user_data;
|
||||
cb_user_data.Str = str;
|
||||
cb_user_data.ChainCallback = callback;
|
||||
cb_user_data.ChainCallbackUserData = user_data;
|
||||
return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
|
||||
}
|
||||
|
||||
bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||
{
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
|
||||
flags |= ImGuiInputTextFlags_CallbackResize;
|
||||
|
||||
InputTextCallback_UserData cb_user_data;
|
||||
cb_user_data.Str = str;
|
||||
cb_user_data.ChainCallback = callback;
|
||||
cb_user_data.ChainCallbackUserData = user_data;
|
||||
return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data);
|
||||
}
|
||||
|
||||
bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||
{
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
|
||||
flags |= ImGuiInputTextFlags_CallbackResize;
|
||||
|
||||
InputTextCallback_UserData cb_user_data;
|
||||
cb_user_data.Str = str;
|
||||
cb_user_data.ChainCallback = callback;
|
||||
cb_user_data.ChainCallbackUserData = user_data;
|
||||
return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
|
||||
// Changelog:
|
||||
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
|
||||
|
||||
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
|
||||
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ImGui
|
||||
{
|
||||
// ImGui::InputText() with std::string
|
||||
// Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
|
||||
IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
|
||||
IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
|
||||
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,9 +1,19 @@
|
|||
// stb_rect_pack.h - v0.11 - public domain - rectangle packing
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
//
|
||||
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Before #including,
|
||||
//
|
||||
// #define STB_RECT_PACK_IMPLEMENTATION
|
||||
//
|
||||
// in the file that you want to have the implementation.
|
||||
//
|
||||
// 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).
|
||||
|
|
@ -31,9 +41,13 @@
|
|||
//
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
// Fabian Giesen
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
// 0.09 (2016-08-27) fix compiler warnings
|
||||
|
|
@ -72,11 +86,10 @@ 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
|
||||
|
||||
#define STBRP__MAXVAL 0x7fffffff
|
||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
|
|
@ -252,9 +265,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
|
|||
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];
|
||||
|
|
@ -273,11 +283,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +355,13 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
|||
width -= width % c->align;
|
||||
STBRP_ASSERT(width % c->align == 0);
|
||||
|
||||
// if it can't possibly fit, bail immediately
|
||||
if (width > c->width || height > c->height) {
|
||||
fr.prev_link = NULL;
|
||||
fr.x = fr.y = 0;
|
||||
return fr;
|
||||
}
|
||||
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
while (node->x + width <= c->width) {
|
||||
|
|
@ -412,11 +425,11 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
|||
}
|
||||
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 + 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);
|
||||
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
|
|
@ -530,12 +543,6 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *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 int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i, all_rects_packed = 1;
|
||||
|
|
@ -543,9 +550,6 @@ STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int nu
|
|||
// 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
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// [ImGui] this is a slightly modified version of stb_textedit.h 1.12. Those changes would need to be pushed into nothings/stb
|
||||
// [ImGui] - 2018-06: fixed undo/redo after pasting large amount of text (over 32 kb). Redo will still fail when undo buffers are exhausted, but text won't be corrupted (see nothings/stb issue #620)
|
||||
// [ImGui] - 2018-06: fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||
// [ImGui] - fixed some minor warnings
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_textedit.h 1.14.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000)
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
|
||||
// stb_textedit.h - v1.12 - public domain - Sean Barrett
|
||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
||||
// Development of this library was sponsored by RAD Game Tools
|
||||
//
|
||||
// This C header file implements the guts of a multi-line text-editing
|
||||
|
|
@ -34,6 +36,8 @@
|
|||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.14 (2021-07-11) page up/down, various fixes
|
||||
// 1.13 (2019-02-07) fix bug in undo size management
|
||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
||||
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
|
||||
|
|
@ -56,6 +60,7 @@
|
|||
// Ulf Winklemann: move-by-word in 1.1
|
||||
// Fabian Giesen: secondary key inputs in 1.5
|
||||
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
|
||||
// Louis Schnellbach: page up/down in 1.14
|
||||
//
|
||||
// Bugfixes:
|
||||
// Scott Graham
|
||||
|
|
@ -91,8 +96,8 @@
|
|||
// moderate sizes. The undo system does no memory allocations, so
|
||||
// it grows STB_TexteditState by the worst-case storage which is (in bytes):
|
||||
//
|
||||
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
|
||||
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
|
||||
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT
|
||||
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT
|
||||
//
|
||||
//
|
||||
// Implementation mode:
|
||||
|
|
@ -146,6 +151,8 @@
|
|||
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
|
||||
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
|
||||
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
|
||||
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
|
||||
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
|
||||
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
|
||||
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
|
||||
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
|
||||
|
|
@ -168,14 +175,10 @@
|
|||
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
||||
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
||||
//
|
||||
// Todo:
|
||||
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
|
||||
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
|
||||
//
|
||||
// Keyboard input must be encoded as a single integer value; e.g. a character code
|
||||
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
|
||||
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
|
||||
// i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
|
||||
// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
|
||||
//
|
||||
// You can encode other things, such as CONTROL or ALT, in additional bits, and
|
||||
// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
|
||||
|
|
@ -335,6 +338,10 @@ typedef struct
|
|||
// each textfield keeps its own insert mode state. to keep an app-wide
|
||||
// insert mode, copy this value in/out of the app state
|
||||
|
||||
int row_count_per_page;
|
||||
// page size in number of row.
|
||||
// this value MUST be set to >0 for pageup or pagedown in multilines documents.
|
||||
|
||||
/////////////////////
|
||||
//
|
||||
// private data
|
||||
|
|
@ -518,29 +525,14 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
|||
int z = STB_TEXTEDIT_STRINGLEN(str);
|
||||
int i=0, first;
|
||||
|
||||
if (n == z) {
|
||||
// if it's at the end, then find the last line -- simpler than trying to
|
||||
// explicitly handle this case in the regular code
|
||||
if (single_line) {
|
||||
if (n == z && single_line) {
|
||||
// special case if it's at the end (may not be needed?)
|
||||
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
|
||||
find->y = 0;
|
||||
find->first_char = 0;
|
||||
find->length = z;
|
||||
find->height = r.ymax - r.ymin;
|
||||
find->x = r.x1;
|
||||
} else {
|
||||
find->y = 0;
|
||||
find->x = 0;
|
||||
find->height = 1;
|
||||
while (i < z) {
|
||||
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
||||
prev_start = i;
|
||||
i += r.num_chars;
|
||||
}
|
||||
find->first_char = i;
|
||||
find->length = 0;
|
||||
find->prev_first = prev_start;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -551,9 +543,13 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
|||
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
||||
if (n < i + r.num_chars)
|
||||
break;
|
||||
if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line
|
||||
break; // [DEAR IMGUI]
|
||||
prev_start = i;
|
||||
i += r.num_chars;
|
||||
find->y += r.baseline_y_delta;
|
||||
if (i == z) // [DEAR IMGUI]
|
||||
break; // [DEAR IMGUI]
|
||||
}
|
||||
|
||||
find->first_char = first = i;
|
||||
|
|
@ -692,7 +688,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
|
|||
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
{
|
||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||
stb_textedit_delete_selection(str,state); // implicity clamps
|
||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
||||
state->has_preferred_x = 0;
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -712,9 +708,7 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
|
|||
state->has_preferred_x = 0;
|
||||
return 1;
|
||||
}
|
||||
// remove the undo since we didn't actually insert the characters
|
||||
if (state->undostate.undo_point)
|
||||
--state->undostate.undo_point;
|
||||
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -744,7 +738,7 @@ retry:
|
|||
state->has_preferred_x = 0;
|
||||
}
|
||||
} else {
|
||||
stb_textedit_delete_selection(str,state); // implicity clamps
|
||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
||||
stb_text_makeundo_insert(state, state->cursor, 1);
|
||||
++state->cursor;
|
||||
|
|
@ -853,12 +847,16 @@ retry:
|
|||
break;
|
||||
|
||||
case STB_TEXTEDIT_K_DOWN:
|
||||
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {
|
||||
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
|
||||
case STB_TEXTEDIT_K_PGDOWN:
|
||||
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
|
||||
StbFindState find;
|
||||
StbTexteditRow row;
|
||||
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
|
||||
int row_count = is_page ? state->row_count_per_page : 1;
|
||||
|
||||
if (state->single_line) {
|
||||
if (!is_page && state->single_line) {
|
||||
// on windows, up&down in single-line behave like left&right
|
||||
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
|
||||
goto retry;
|
||||
|
|
@ -873,11 +871,19 @@ retry:
|
|||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
|
||||
// now find character position down a row
|
||||
if (find.length) {
|
||||
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
float x;
|
||||
for (j = 0; j < row_count; ++j) {
|
||||
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
int start = find.first_char + find.length;
|
||||
|
||||
if (find.length == 0)
|
||||
break;
|
||||
|
||||
// [DEAR IMGUI]
|
||||
// going down while being on the last line shouldn't bring us to that line end
|
||||
if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
break;
|
||||
|
||||
// now find character position down a row
|
||||
state->cursor = start;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
x = row.x0;
|
||||
|
|
@ -899,17 +905,25 @@ retry:
|
|||
|
||||
if (sel)
|
||||
state->select_end = state->cursor;
|
||||
|
||||
// go to next line
|
||||
find.first_char = find.first_char + find.length;
|
||||
find.length = row.num_chars;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case STB_TEXTEDIT_K_UP:
|
||||
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
|
||||
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
|
||||
case STB_TEXTEDIT_K_PGUP:
|
||||
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
|
||||
StbFindState find;
|
||||
StbTexteditRow row;
|
||||
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
|
||||
int row_count = is_page ? state->row_count_per_page : 1;
|
||||
|
||||
if (state->single_line) {
|
||||
if (!is_page && state->single_line) {
|
||||
// on windows, up&down become left&right
|
||||
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
|
||||
goto retry;
|
||||
|
|
@ -924,11 +938,14 @@ retry:
|
|||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
|
||||
for (j = 0; j < row_count; ++j) {
|
||||
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
|
||||
// can only go up if there's a previous row
|
||||
if (find.prev_first != find.first_char) {
|
||||
if (find.prev_first == find.first_char)
|
||||
break;
|
||||
|
||||
// now find character position up a row
|
||||
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
float x;
|
||||
state->cursor = find.prev_first;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
x = row.x0;
|
||||
|
|
@ -950,6 +967,14 @@ retry:
|
|||
|
||||
if (sel)
|
||||
state->select_end = state->cursor;
|
||||
|
||||
// go to previous line
|
||||
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
|
||||
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
|
||||
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
--prev_scan;
|
||||
find.first_char = find.prev_first;
|
||||
find.prev_first = prev_scan;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1073,10 +1098,6 @@ retry:
|
|||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// @TODO:
|
||||
// STB_TEXTEDIT_K_PGUP - move cursor up a page
|
||||
// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1132,7 +1153,14 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
|||
state->undo_rec[i].char_storage += n;
|
||||
}
|
||||
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
|
||||
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
|
||||
// [DEAR IMGUI]
|
||||
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
|
||||
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
|
||||
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
|
||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
|
||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
|
||||
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
|
||||
|
||||
// now move redo_point to point to the new one
|
||||
++state->redo_point;
|
||||
}
|
||||
|
|
@ -1341,6 +1369,7 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
|
|||
state->initialized = 1;
|
||||
state->single_line = (unsigned char) is_single_line;
|
||||
state->insert_mode = 0;
|
||||
state->row_count_per_page = 0;
|
||||
}
|
||||
|
||||
// API initialize
|
||||
|
|
|
|||
|
|
@ -1,8 +1,19 @@
|
|||
// [ImGui] this is a slightly modified version of stb_truetype.h 1.19. Those changes would need to be pushed into nothings/stb
|
||||
// grep for [ImGui] to find the changes.
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_truetype.h 1.26.
|
||||
// Mostly fixing for compiler and static analyzer warnings.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
|
||||
// stb_truetype.h - v1.19 - public domain
|
||||
// authored from 2009-2016 by Sean Barrett / RAD Game Tools
|
||||
// stb_truetype.h - v1.26 - public domain
|
||||
// authored from 2009-2021 by Sean Barrett / RAD Game Tools
|
||||
//
|
||||
// =======================================================================
|
||||
//
|
||||
// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
|
||||
//
|
||||
// This library does no range checking of the offsets found in the file,
|
||||
// meaning an attacker can use it to read arbitrary memory.
|
||||
//
|
||||
// =======================================================================
|
||||
//
|
||||
// This library processes TrueType files:
|
||||
// parse files
|
||||
|
|
@ -35,11 +46,11 @@
|
|||
// Daniel Ribeiro Maciel
|
||||
//
|
||||
// Bug/warning reports/fixes:
|
||||
// "Zer" on mollyrocket Fabian "ryg" Giesen
|
||||
// Cass Everitt Martins Mozeiko
|
||||
// stoiko (Haemimont Games) Cap Petschulat
|
||||
// Brian Hook Omar Cornut
|
||||
// Walter van Niftrik github:aloucks
|
||||
// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe
|
||||
// Cass Everitt Martins Mozeiko github:aloucks
|
||||
// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam
|
||||
// Brian Hook Omar Cornut github:vassvik
|
||||
// Walter van Niftrik Ryan Griege
|
||||
// David Gow Peter LaValle
|
||||
// David Given Sergey Popov
|
||||
// Ivan-Assen Ivanov Giumo X. Clanjor
|
||||
|
|
@ -47,11 +58,18 @@
|
|||
// Johan Duparc Thomas Fields
|
||||
// Hou Qiming Derek Vinyard
|
||||
// Rob Loach Cort Stratton
|
||||
// Kenney Phillis Jr. github:oyvindjam
|
||||
// Brian Costabile github:vassvik
|
||||
// Kenney Phillis Jr. Brian Costabile
|
||||
// Ken Voskuil (kaesve)
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.26 (2021-08-28) fix broken rasterizer
|
||||
// 1.25 (2021-07-11) many fixes
|
||||
// 1.24 (2020-02-05) fix warning
|
||||
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
|
||||
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
|
||||
// 1.21 (2019-02-25) fix warning
|
||||
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
|
||||
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
|
||||
// 1.18 (2018-01-29) add missing function
|
||||
// 1.17 (2017-07-23) make more arguments const; doc fix
|
||||
|
|
@ -78,7 +96,7 @@
|
|||
//
|
||||
// USAGE
|
||||
//
|
||||
// Include this file in whatever places neeed to refer to it. In ONE C/C++
|
||||
// Include this file in whatever places need to refer to it. In ONE C/C++
|
||||
// file, write:
|
||||
// #define STB_TRUETYPE_IMPLEMENTATION
|
||||
// before the #include of this file. This expands out the actual
|
||||
|
|
@ -245,19 +263,6 @@
|
|||
// recommend it.
|
||||
//
|
||||
//
|
||||
// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
|
||||
//
|
||||
// Documentation & header file 520 LOC \___ 660 LOC documentation
|
||||
// Sample code 140 LOC /
|
||||
// Truetype parsing 620 LOC ---- 620 LOC TrueType
|
||||
// Software rasterization 240 LOC \ .
|
||||
// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
|
||||
// Bitmap management 100 LOC /
|
||||
// Baked bitmap interface 70 LOC /
|
||||
// Font name matching & access 150 LOC ---- 150
|
||||
// C runtime library abstraction 60 LOC ---- 60
|
||||
//
|
||||
//
|
||||
// PERFORMANCE MEASUREMENTS FOR 1.06:
|
||||
//
|
||||
// 32-bit 64-bit
|
||||
|
|
@ -272,8 +277,8 @@
|
|||
//// SAMPLE PROGRAMS
|
||||
////
|
||||
//
|
||||
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
|
||||
//
|
||||
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
|
||||
// See "tests/truetype_demo_win32.c" for a complete version.
|
||||
#if 0
|
||||
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
||||
#include "stb_truetype.h"
|
||||
|
|
@ -299,6 +304,8 @@ void my_stbtt_initfont(void)
|
|||
void my_stbtt_print(float x, float y, char *text)
|
||||
{
|
||||
// assume orthographic projection with units = screen pixels, origin at top left
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, ftex);
|
||||
glBegin(GL_QUADS);
|
||||
|
|
@ -306,10 +313,10 @@ void my_stbtt_print(float x, float y, char *text)
|
|||
if (*text >= 32 && *text < 128) {
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
|
||||
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
|
||||
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
|
||||
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
|
||||
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
|
||||
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
|
||||
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
|
||||
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
|
||||
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
|
||||
}
|
||||
++text;
|
||||
}
|
||||
|
|
@ -559,6 +566,8 @@ STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int p
|
|||
//
|
||||
// It's inefficient; you might want to c&p it and optimize it.
|
||||
|
||||
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
|
||||
// Query the font vertical metrics without having to create a font first.
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -644,6 +653,12 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
|
|||
// To use with PackFontRangesGather etc., you must set it before calls
|
||||
// call to PackFontRangesGatherRects.
|
||||
|
||||
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
|
||||
// If skip != 0, this tells stb_truetype to skip any codepoints for which
|
||||
// there is no corresponding glyph. If skip=0, which is the default, then
|
||||
// codepoints without a glyph recived the font's "missing character" glyph,
|
||||
// typically an empty box by convention.
|
||||
|
||||
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
|
||||
int char_index, // character to display
|
||||
float *xpos, float *ypos, // pointers to current position in screen pixel space
|
||||
|
|
@ -672,6 +687,7 @@ struct stbtt_pack_context {
|
|||
int height;
|
||||
int stride_in_bytes;
|
||||
int padding;
|
||||
int skip_missing;
|
||||
unsigned int h_oversample, v_oversample;
|
||||
unsigned char *pixels;
|
||||
void *nodes;
|
||||
|
|
@ -697,7 +713,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
|
|||
// file will only define one font and it always be at offset 0, so it will
|
||||
// return '0' for index 0, and -1 for all other indices.
|
||||
|
||||
// The following structure is defined publically so you can declare one on
|
||||
// The following structure is defined publicly so you can declare one on
|
||||
// the stack or as a global or etc, but you should treat it as opaque.
|
||||
struct stbtt_fontinfo
|
||||
{
|
||||
|
|
@ -707,7 +723,7 @@ struct stbtt_fontinfo
|
|||
|
||||
int numGlyphs; // number of glyphs, needed for range checking
|
||||
|
||||
int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
|
||||
int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
|
||||
int index_map; // a cmap mapping for our chosen character encoding
|
||||
int indexToLocFormat; // format needed to map from glyph index to glyph
|
||||
|
||||
|
|
@ -736,6 +752,7 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
|
|||
// and you want a speed-up, call this function with the character you're
|
||||
// going to process, then use glyph-based functions instead of the
|
||||
// codepoint-based functions.
|
||||
// Returns 0 if the character codepoint is not defined in the font.
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -789,6 +806,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
|
|||
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
|
||||
// as above, but takes one or more glyph indices for greater efficiency
|
||||
|
||||
typedef struct stbtt_kerningentry
|
||||
{
|
||||
int glyph1; // use stbtt_FindGlyphIndex
|
||||
int glyph2;
|
||||
int advance;
|
||||
} stbtt_kerningentry;
|
||||
|
||||
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
|
||||
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
|
||||
// Retrieves a complete list of all of the kerning pairs provided by the font
|
||||
// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
|
||||
// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
@ -823,7 +852,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
|
|||
// returns # of vertices and fills *vertices with the pointer to them
|
||||
// these are expressed in "unscaled" coordinates
|
||||
//
|
||||
// The shape is a series of countours. Each one starts with
|
||||
// The shape is a series of contours. Each one starts with
|
||||
// a STBTT_moveto, then consists of a series of mixed
|
||||
// STBTT_lineto and STBTT_curveto segments. A lineto
|
||||
// draws a line from previous endpoint to its x,y; a curveto
|
||||
|
|
@ -833,6 +862,12 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
|
|||
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
|
||||
// frees the data allocated above
|
||||
|
||||
STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
|
||||
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
|
||||
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
|
||||
// fills svg with the character's SVG data.
|
||||
// returns data size or 0 if SVG not found.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BITMAP RENDERING
|
||||
|
|
@ -919,7 +954,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
|||
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
|
||||
// These functions compute a discretized SDF field for a single character, suitable for storing
|
||||
// in a single-channel texture, sampling with bilinear filtering, and testing against
|
||||
// larger than some threshhold to produce scalable fonts.
|
||||
// larger than some threshold to produce scalable fonts.
|
||||
// info -- the font
|
||||
// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
|
||||
// glyph/codepoint -- the character to generate the SDF for
|
||||
|
|
@ -1334,6 +1369,22 @@ static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
|
|||
return stbtt__cff_get_index(&cff);
|
||||
}
|
||||
|
||||
// since most people won't use this, find this table the first time it's needed
|
||||
static int stbtt__get_svg(stbtt_fontinfo *info)
|
||||
{
|
||||
stbtt_uint32 t;
|
||||
if (info->svg < 0) {
|
||||
t = stbtt__find_table(info->data, info->fontstart, "SVG ");
|
||||
if (t) {
|
||||
stbtt_uint32 offset = ttULONG(info->data + t + 2);
|
||||
info->svg = t + offset;
|
||||
} else {
|
||||
info->svg = 0;
|
||||
}
|
||||
}
|
||||
return info->svg;
|
||||
}
|
||||
|
||||
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
|
||||
{
|
||||
stbtt_uint32 cmap, t;
|
||||
|
|
@ -1413,6 +1464,8 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
|
|||
else
|
||||
info->numGlyphs = 0xffff;
|
||||
|
||||
info->svg = -1;
|
||||
|
||||
// find a cmap encoding table we understand *now* to avoid searching
|
||||
// later. (todo: could make this installable)
|
||||
// the same regardless of glyph.
|
||||
|
|
@ -1496,12 +1549,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
|
|||
search += 2;
|
||||
|
||||
{
|
||||
stbtt_uint16 offset, start;
|
||||
stbtt_uint16 offset, start, last;
|
||||
stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
|
||||
|
||||
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
|
||||
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
|
||||
if (unicode_codepoint < start)
|
||||
last = ttUSHORT(data + endCount + 2*item);
|
||||
if (unicode_codepoint < start || unicode_codepoint > last)
|
||||
return 0;
|
||||
|
||||
offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
|
||||
|
|
@ -1761,7 +1814,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
|||
}
|
||||
}
|
||||
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
|
||||
} else if (numberOfContours == -1) {
|
||||
} else if (numberOfContours < 0) {
|
||||
// Compound shapes.
|
||||
int more = 1;
|
||||
stbtt_uint8 *comp = data + g + 10;
|
||||
|
|
@ -1828,7 +1881,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
|||
if (comp_verts) STBTT_free(comp_verts, info->userdata);
|
||||
return 0;
|
||||
}
|
||||
if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595
|
||||
if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
|
||||
STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
|
||||
if (vertices) STBTT_free(vertices, info->userdata);
|
||||
vertices = tmp;
|
||||
|
|
@ -1838,9 +1891,6 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
|||
// More components ?
|
||||
more = flags & (1<<5);
|
||||
}
|
||||
} else if (numberOfContours < 0) {
|
||||
// @TODO other compound variations?
|
||||
STBTT_assert(0);
|
||||
} else {
|
||||
// numberOfCounters == 0, do nothing
|
||||
}
|
||||
|
|
@ -1958,7 +2008,7 @@ static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int gly
|
|||
start = end;
|
||||
}
|
||||
}
|
||||
if (fdselector == -1) stbtt__new_buf(NULL, 0);
|
||||
if (fdselector == -1) return stbtt__new_buf(NULL, 0); // [DEAR IMGUI] fixed, see #6007 and nothings/stb#1422
|
||||
return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
|
||||
}
|
||||
|
||||
|
|
@ -2094,7 +2144,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
|
|||
subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
|
||||
has_subrs = 1;
|
||||
}
|
||||
// fallthrough
|
||||
// FALLTHROUGH
|
||||
case 0x1D: // callgsubr
|
||||
if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
|
||||
v = (int) s[--sp];
|
||||
|
|
@ -2199,7 +2249,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
|
|||
} break;
|
||||
|
||||
default:
|
||||
if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560
|
||||
if (b0 != 255 && b0 != 28 && b0 < 32)
|
||||
return STBTT__CSERR("reserved operator");
|
||||
|
||||
// push immediate
|
||||
|
|
@ -2269,6 +2319,48 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
|
|||
}
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
|
||||
{
|
||||
stbtt_uint8 *data = info->data + info->kern;
|
||||
|
||||
// we only look at the first table. it must be 'horizontal' and format 0.
|
||||
if (!info->kern)
|
||||
return 0;
|
||||
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
|
||||
return 0;
|
||||
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
|
||||
return 0;
|
||||
|
||||
return ttUSHORT(data+10);
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
|
||||
{
|
||||
stbtt_uint8 *data = info->data + info->kern;
|
||||
int k, length;
|
||||
|
||||
// we only look at the first table. it must be 'horizontal' and format 0.
|
||||
if (!info->kern)
|
||||
return 0;
|
||||
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
|
||||
return 0;
|
||||
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
|
||||
return 0;
|
||||
|
||||
length = ttUSHORT(data+10);
|
||||
if (table_length < length)
|
||||
length = table_length;
|
||||
|
||||
for (k = 0; k < length; k++)
|
||||
{
|
||||
table[k].glyph1 = ttUSHORT(data+18+(k*6));
|
||||
table[k].glyph2 = ttUSHORT(data+20+(k*6));
|
||||
table[k].advance = ttSHORT(data+22+(k*6));
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
|
||||
{
|
||||
stbtt_uint8 *data = info->data + info->kern;
|
||||
|
|
@ -2323,7 +2415,8 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp
|
|||
return m;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
|
||||
|
|
@ -2347,12 +2440,10 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp
|
|||
return startCoverageIndex + glyph - strawStart;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// There are no other cases.
|
||||
STBTT_assert(0);
|
||||
} break;
|
||||
default: return -1; // unsupported
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
@ -2370,10 +2461,8 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
|||
|
||||
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
|
||||
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
|
||||
|
||||
// [ImGui: commented to fix static analyzer warning]
|
||||
//classDefTable = classDef1ValueArray + 2 * glyphCount;
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
|
||||
|
|
@ -2395,18 +2484,15 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
|||
else
|
||||
return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
|
||||
}
|
||||
|
||||
// [ImGui: commented to fix static analyzer warning]
|
||||
//classDefTable = classRangeRecords + 6 * classRangeCount;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
// There are no other cases.
|
||||
STBTT_assert(0);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
default:
|
||||
return -1; // Unsupported definition type, return an error.
|
||||
}
|
||||
|
||||
// "All glyphs not assigned to a class fall into class 0". (OpenType spec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Define to STBTT_assert(x) if you want to break on unimplemented formats.
|
||||
|
|
@ -2418,7 +2504,7 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
|
|||
stbtt_uint8 *lookupList;
|
||||
stbtt_uint16 lookupCount;
|
||||
stbtt_uint8 *data;
|
||||
stbtt_int32 i;
|
||||
stbtt_int32 i, sti;
|
||||
|
||||
if (!info->gpos) return 0;
|
||||
|
||||
|
|
@ -2438,9 +2524,9 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
|
|||
stbtt_uint16 lookupType = ttUSHORT(lookupTable);
|
||||
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
|
||||
stbtt_uint8 *subTableOffsets = lookupTable + 6;
|
||||
switch(lookupType) {
|
||||
case 2: { // Pair Adjustment Positioning Subtable
|
||||
stbtt_int32 sti;
|
||||
if (lookupType != 2) // Pair Adjustment Positioning Subtable
|
||||
continue;
|
||||
|
||||
for (sti=0; sti<subTableCount; sti++) {
|
||||
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
|
||||
stbtt_uint8 *table = lookupTable + subtableOffset;
|
||||
|
|
@ -2455,20 +2541,15 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
|
|||
int straw, needle;
|
||||
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
||||
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
||||
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
|
||||
stbtt_int32 valueRecordPairSizeInBytes = 2;
|
||||
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
|
||||
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
|
||||
stbtt_uint8 *pairValueTable = table + pairPosOffset;
|
||||
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
|
||||
stbtt_uint8 *pairValueArray = pairValueTable + 2;
|
||||
// TODO: Support more formats.
|
||||
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
|
||||
if (valueFormat1 != 4) return 0;
|
||||
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
|
||||
if (valueFormat2 != 0) return 0;
|
||||
|
||||
STBTT_assert(coverageIndex < pairSetCount);
|
||||
STBTT__NOTUSED(pairSetCount);
|
||||
if (coverageIndex >= pairSetCount) return 0;
|
||||
|
||||
needle=glyph2;
|
||||
r=pairValueCount-1;
|
||||
|
|
@ -2491,12 +2572,15 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
|
|||
return xAdvance;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
} else
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
||||
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
||||
|
||||
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
|
||||
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
|
||||
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
|
||||
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
|
||||
|
|
@ -2504,36 +2588,24 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
|
|||
|
||||
stbtt_uint16 class1Count = ttUSHORT(table + 12);
|
||||
stbtt_uint16 class2Count = ttUSHORT(table + 14);
|
||||
STBTT_assert(glyph1class < class1Count);
|
||||
STBTT_assert(glyph2class < class2Count);
|
||||
stbtt_uint8 *class1Records, *class2Records;
|
||||
stbtt_int16 xAdvance;
|
||||
|
||||
// TODO: Support more formats.
|
||||
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
|
||||
if (valueFormat1 != 4) return 0;
|
||||
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
|
||||
if (valueFormat2 != 0) return 0;
|
||||
if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
|
||||
if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
|
||||
|
||||
if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
|
||||
stbtt_uint8 *class1Records = table + 16;
|
||||
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
|
||||
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
|
||||
class1Records = table + 16;
|
||||
class2Records = class1Records + 2 * (glyph1class * class2Count);
|
||||
xAdvance = ttSHORT(class2Records + 2 * glyph2class);
|
||||
return xAdvance;
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
// There are no other cases.
|
||||
STBTT_assert(0);
|
||||
} else
|
||||
return 0;
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
default:
|
||||
// TODO: Implement other stuff.
|
||||
break;
|
||||
return 0; // Unsupported position format
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2546,8 +2618,7 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int
|
|||
|
||||
if (info->gpos)
|
||||
xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
|
||||
|
||||
if (info->kern)
|
||||
else if (info->kern)
|
||||
xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
|
||||
|
||||
return xAdvance;
|
||||
|
|
@ -2608,6 +2679,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
|||
STBTT_free(v, info->userdata);
|
||||
}
|
||||
|
||||
STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
|
||||
{
|
||||
int i;
|
||||
stbtt_uint8 *data = info->data;
|
||||
stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
|
||||
|
||||
int numEntries = ttUSHORT(svg_doc_list);
|
||||
stbtt_uint8 *svg_docs = svg_doc_list + 2;
|
||||
|
||||
for(i=0; i<numEntries; i++) {
|
||||
stbtt_uint8 *svg_doc = svg_docs + (12 * i);
|
||||
if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
|
||||
return svg_doc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
|
||||
{
|
||||
stbtt_uint8 *data = info->data;
|
||||
stbtt_uint8 *svg_doc;
|
||||
|
||||
if (info->svg == 0)
|
||||
return 0;
|
||||
|
||||
svg_doc = stbtt_FindSVGDoc(info, gl);
|
||||
if (svg_doc != NULL) {
|
||||
*svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
|
||||
return ttULONG(svg_doc + 8);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
|
||||
{
|
||||
return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// antialiasing software rasterizer
|
||||
|
|
@ -2957,6 +3067,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg
|
|||
}
|
||||
}
|
||||
|
||||
static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
|
||||
{
|
||||
STBTT_assert(top_width >= 0);
|
||||
STBTT_assert(bottom_width >= 0);
|
||||
return (top_width + bottom_width) / 2.0f * height;
|
||||
}
|
||||
|
||||
static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
|
||||
{
|
||||
return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
|
||||
}
|
||||
|
||||
static float stbtt__sized_triangle_area(float height, float width)
|
||||
{
|
||||
return height * width / 2;
|
||||
}
|
||||
|
||||
static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
|
||||
{
|
||||
float y_bottom = y_top+1;
|
||||
|
|
@ -3011,13 +3138,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
|
|||
float height;
|
||||
// simple case, only spans one pixel
|
||||
int x = (int) x_top;
|
||||
height = sy1 - sy0;
|
||||
height = (sy1 - sy0) * e->direction;
|
||||
STBTT_assert(x >= 0 && x < len);
|
||||
scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
|
||||
scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
|
||||
scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
|
||||
scanline_fill[x] += height; // everything right of this pixel is filled
|
||||
} else {
|
||||
int x,x1,x2;
|
||||
float y_crossing, step, sign, area;
|
||||
float y_crossing, y_final, step, sign, area;
|
||||
// covers 2+ pixels
|
||||
if (x_top > x_bottom) {
|
||||
// flip scanline vertically; signed area is the same
|
||||
|
|
@ -3029,31 +3156,83 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
|
|||
dx = -dx;
|
||||
dy = -dy;
|
||||
t = x0, x0 = xb, xb = t;
|
||||
(void)dx; // [ImGui: fix static analyzer warning]
|
||||
}
|
||||
STBTT_assert(dy >= 0);
|
||||
STBTT_assert(dx >= 0);
|
||||
|
||||
x1 = (int) x_top;
|
||||
x2 = (int) x_bottom;
|
||||
// compute intersection with y axis at x1+1
|
||||
y_crossing = (x1+1 - x0) * dy + y_top;
|
||||
y_crossing = y_top + dy * (x1+1 - x0);
|
||||
|
||||
// compute intersection with y axis at x2
|
||||
y_final = y_top + dy * (x2 - x0);
|
||||
|
||||
// x1 x_top x2 x_bottom
|
||||
// y_top +------|-----+------------+------------+--------|---+------------+
|
||||
// | | | | | |
|
||||
// | | | | | |
|
||||
// sy0 | Txxxxx|............|............|............|............|
|
||||
// y_crossing | *xxxxx.......|............|............|............|
|
||||
// | | xxxxx..|............|............|............|
|
||||
// | | /- xx*xxxx........|............|............|
|
||||
// | | dy < | xxxxxx..|............|............|
|
||||
// y_final | | \- | xx*xxx.........|............|
|
||||
// sy1 | | | | xxxxxB...|............|
|
||||
// | | | | | |
|
||||
// | | | | | |
|
||||
// y_bottom +------------+------------+------------+------------+------------+
|
||||
//
|
||||
// goal is to measure the area covered by '.' in each pixel
|
||||
|
||||
// if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
|
||||
// @TODO: maybe test against sy1 rather than y_bottom?
|
||||
if (y_crossing > y_bottom)
|
||||
y_crossing = y_bottom;
|
||||
|
||||
sign = e->direction;
|
||||
// area of the rectangle covered from y0..y_crossing
|
||||
area = sign * (y_crossing-sy0);
|
||||
// area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
|
||||
scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
|
||||
|
||||
step = sign * dy;
|
||||
// area of the rectangle covered from sy0..y_crossing
|
||||
area = sign * (y_crossing-sy0);
|
||||
|
||||
// area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
|
||||
scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
|
||||
|
||||
// check if final y_crossing is blown up; no test case for this
|
||||
if (y_final > y_bottom) {
|
||||
int denom = (x2 - (x1+1));
|
||||
y_final = y_bottom;
|
||||
if (denom != 0) { // [DEAR IMGUI] Avoid div by zero (https://github.com/nothings/stb/issues/1316)
|
||||
dy = (y_final - y_crossing ) / denom; // if denom=0, y_final = y_crossing, so y_final <= y_bottom
|
||||
}
|
||||
}
|
||||
|
||||
// in second pixel, area covered by line segment found in first pixel
|
||||
// is always a rectangle 1 wide * the height of that line segment; this
|
||||
// is exactly what the variable 'area' stores. it also gets a contribution
|
||||
// from the line segment within it. the THIRD pixel will get the first
|
||||
// pixel's rectangle contribution, the second pixel's rectangle contribution,
|
||||
// and its own contribution. the 'own contribution' is the same in every pixel except
|
||||
// the leftmost and rightmost, a trapezoid that slides down in each pixel.
|
||||
// the second pixel's contribution to the third pixel will be the
|
||||
// rectangle 1 wide times the height change in the second pixel, which is dy.
|
||||
|
||||
step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
|
||||
// which multiplied by 1-pixel-width is how much pixel area changes for each step in x
|
||||
// so the area advances by 'step' every time
|
||||
|
||||
for (x = x1+1; x < x2; ++x) {
|
||||
scanline[x] += area + step/2;
|
||||
scanline[x] += area + step/2; // area of trapezoid is 1*step/2
|
||||
area += step;
|
||||
}
|
||||
y_crossing += dy * (x2 - (x1+1));
|
||||
STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
|
||||
STBTT_assert(sy1 > y_final-0.01f);
|
||||
|
||||
STBTT_assert(STBTT_fabs(area) <= 1.01f);
|
||||
|
||||
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
|
||||
// area covered in the last pixel is the rectangle from all the pixels to the left,
|
||||
// plus the trapezoid filled by the line segment in this pixel all the way to the right edge
|
||||
scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
|
||||
|
||||
// the rest of the line is filled based on the total height of the line segment in this pixel
|
||||
scanline_fill[x2] += sign * (sy1-sy0);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -3061,6 +3240,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
|
|||
// clipping logic. since this does not match the intended use
|
||||
// of this library, we use a different, very slow brute
|
||||
// force implementation
|
||||
// note though that this does happen some of the time because
|
||||
// x_top and x_bottom can be extrapolated at the top & bottom of
|
||||
// the shape and actually lie outside the bounding box
|
||||
int x;
|
||||
for (x=0; x < len; ++x) {
|
||||
// cases:
|
||||
|
|
@ -3167,7 +3349,13 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
|||
if (e->y0 != e->y1) {
|
||||
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
|
||||
if (z != NULL) {
|
||||
STBTT_assert(z->ey >= scan_y_top);
|
||||
if (j == 0 && off_y != 0) {
|
||||
if (z->ey < scan_y_top) {
|
||||
// this can happen due to subpixel positioning and some kind of fp rounding error i think
|
||||
z->ey = scan_y_top;
|
||||
}
|
||||
}
|
||||
STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
|
||||
// insert at front
|
||||
z->next = active;
|
||||
active = z;
|
||||
|
|
@ -3236,7 +3424,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
|
|||
|
||||
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
|
||||
{
|
||||
/* threshhold for transitioning to insertion sort */
|
||||
/* threshold for transitioning to insertion sort */
|
||||
while (n > 12) {
|
||||
stbtt__edge t;
|
||||
int c01,c12,c,m,i,j;
|
||||
|
|
@ -3371,7 +3559,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
|
|||
points[n].y = y;
|
||||
}
|
||||
|
||||
// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
|
||||
// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
|
||||
static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
|
||||
{
|
||||
// midpoint
|
||||
|
|
@ -3796,6 +3984,7 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in
|
|||
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
|
||||
spc->h_oversample = 1;
|
||||
spc->v_oversample = 1;
|
||||
spc->skip_missing = 0;
|
||||
|
||||
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
|
||||
|
||||
|
|
@ -3821,6 +4010,11 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
|
|||
spc->v_oversample = v_oversample;
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
|
||||
{
|
||||
spc->skip_missing = skip;
|
||||
}
|
||||
|
||||
#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
|
||||
|
||||
static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
|
||||
|
|
@ -3963,6 +4157,7 @@ static float stbtt__oversample_shift(int oversample)
|
|||
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
||||
{
|
||||
int i,j,k;
|
||||
int missing_glyph_added = 0;
|
||||
|
||||
k=0;
|
||||
for (i=0; i < num_ranges; ++i) {
|
||||
|
|
@ -3974,6 +4169,9 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
|
|||
int x0,y0,x1,y1;
|
||||
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
|
||||
int glyph = stbtt_FindGlyphIndex(info, codepoint);
|
||||
if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
|
||||
rects[k].w = rects[k].h = 0;
|
||||
} else {
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
|
||||
scale * spc->h_oversample,
|
||||
scale * spc->v_oversample,
|
||||
|
|
@ -3981,6 +4179,9 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
|
|||
&x0,&y0,&x1,&y1);
|
||||
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
||||
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
||||
if (glyph == 0)
|
||||
missing_glyph_added = 1;
|
||||
}
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
|
@ -4014,7 +4215,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info
|
|||
// rects array must be big enough to accommodate all characters in the given ranges
|
||||
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
||||
{
|
||||
int i,j,k, return_value = 1;
|
||||
int i,j,k, missing_glyph = -1, return_value = 1;
|
||||
|
||||
// save current values
|
||||
int old_h_over = spc->h_oversample;
|
||||
|
|
@ -4033,7 +4234,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
|
|||
sub_y = stbtt__oversample_shift(spc->v_oversample);
|
||||
for (j=0; j < ranges[i].num_chars; ++j) {
|
||||
stbrp_rect *r = &rects[k];
|
||||
if (r->was_packed) {
|
||||
if (r->was_packed && r->w != 0 && r->h != 0) {
|
||||
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
|
||||
int advance, lsb, x0,y0,x1,y1;
|
||||
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
|
||||
|
|
@ -4079,6 +4280,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
|
|||
bc->yoff = (float) y0 * recip_v + sub_y;
|
||||
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
|
||||
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
|
||||
|
||||
if (glyph == 0)
|
||||
missing_glyph = j;
|
||||
} else if (spc->skip_missing) {
|
||||
return_value = 0;
|
||||
} else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
|
||||
ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
|
||||
} else {
|
||||
return_value = 0; // if any fail, report failure
|
||||
}
|
||||
|
|
@ -4102,7 +4310,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect
|
|||
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
||||
{
|
||||
stbtt_fontinfo info;
|
||||
int i,j,n, return_value = 1;
|
||||
int i, j, n, return_value; // [DEAR IMGUI] removed = 1;
|
||||
//stbrp_context *context = (stbrp_context *) spc->pack_info;
|
||||
stbrp_rect *rects;
|
||||
|
||||
|
|
@ -4147,6 +4355,19 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *
|
|||
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
|
||||
{
|
||||
int i_ascent, i_descent, i_lineGap;
|
||||
float scale;
|
||||
stbtt_fontinfo info;
|
||||
stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
|
||||
scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
|
||||
stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
|
||||
*ascent = (float) i_ascent * scale;
|
||||
*descent = (float) i_descent * scale;
|
||||
*lineGap = (float) i_lineGap * scale;
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
|
||||
{
|
||||
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
||||
|
|
@ -4258,15 +4479,14 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
|||
float y_frac;
|
||||
int winding = 0;
|
||||
|
||||
orig[0] = x;
|
||||
//orig[1] = y; // [ImGui] commmented double assignment without reading
|
||||
|
||||
// make sure y never passes through a vertex of the shape
|
||||
y_frac = (float) STBTT_fmod(y, 1.0f);
|
||||
if (y_frac < 0.01f)
|
||||
y += 0.01f;
|
||||
else if (y_frac > 0.99f)
|
||||
y -= 0.01f;
|
||||
|
||||
orig[0] = x;
|
||||
orig[1] = y;
|
||||
|
||||
// test a ray from (-infinity,y) to (x,y)
|
||||
|
|
@ -4328,7 +4548,7 @@ static float stbtt__cuberoot( float x )
|
|||
return (float) STBTT_pow( x,1.0f/3.0f);
|
||||
}
|
||||
|
||||
// x^3 + c*x^2 + b*x + a = 0
|
||||
// x^3 + a*x^2 + b*x + c = 0
|
||||
static int stbtt__solve_cubic(float a, float b, float c, float* r)
|
||||
{
|
||||
float s = -a / 3;
|
||||
|
|
@ -4367,12 +4587,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
|||
int w,h;
|
||||
unsigned char *data;
|
||||
|
||||
// if one scale is 0, use same scale for both
|
||||
if (scale_x == 0) scale_x = scale_y;
|
||||
if (scale_y == 0) {
|
||||
if (scale_x == 0) return NULL; // if both scales are 0, return NULL
|
||||
scale_y = scale_x;
|
||||
}
|
||||
if (scale == 0) return NULL;
|
||||
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
|
||||
|
||||
|
|
@ -4438,18 +4653,17 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
|||
for (i=0; i < num_verts; ++i) {
|
||||
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
|
||||
|
||||
// check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
|
||||
float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
|
||||
if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
|
||||
float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
|
||||
|
||||
float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
|
||||
if (dist2 < min_dist*min_dist)
|
||||
min_dist = (float) STBTT_sqrt(dist2);
|
||||
|
||||
if (verts[i].type == STBTT_vline) {
|
||||
float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
|
||||
|
||||
// coarse culling against bbox
|
||||
//if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
|
||||
// sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
|
||||
float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
|
||||
dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
|
||||
STBTT_assert(i != 0);
|
||||
if (dist < min_dist) {
|
||||
// check position along line
|
||||
|
|
@ -4476,7 +4690,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
|||
float ax = x1-x0, ay = y1-y0;
|
||||
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
|
||||
float mx = x0 - sx, my = y0 - sy;
|
||||
float res[3],px,py,t,it;
|
||||
float res[3] = {0.f,0.f,0.f};
|
||||
float px,py,t,it,dist2;
|
||||
float a_inv = precompute[i];
|
||||
if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
|
||||
float a = 3*(ax*bx + ay*by);
|
||||
|
|
@ -4503,6 +4718,10 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
|||
float d = (mx*ax+my*ay) * a_inv;
|
||||
num = stbtt__solve_cubic(b, c, d, res);
|
||||
}
|
||||
dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
|
||||
if (dist2 < min_dist*min_dist)
|
||||
min_dist = (float) STBTT_sqrt(dist2);
|
||||
|
||||
if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
|
||||
t = res[0], it = 1.0f - t;
|
||||
px = it*it*x0 + 2*t*it*x1 + t*t*x2;
|
||||
|
|
@ -4762,6 +4981,12 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
|
|||
|
||||
// FULL VERSION HISTORY
|
||||
//
|
||||
// 1.25 (2021-07-11) many fixes
|
||||
// 1.24 (2020-02-05) fix warning
|
||||
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
|
||||
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
|
||||
// 1.21 (2019-02-25) fix warning
|
||||
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
|
||||
// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
|
||||
// 1.18 (2018-01-29) add missing function
|
||||
// 1.17 (2017-07-23) make more arguments const; doc fix
|
||||
|
|
|
|||
|
|
@ -13,64 +13,162 @@ namespace kiwano
|
|||
{
|
||||
namespace imgui
|
||||
{
|
||||
ImGuiModule::ImGuiModule()
|
||||
|
||||
ImGuiKey KeyCodeToImGuiKey(const KeyCode code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case KeyCode::Tab:
|
||||
return ImGuiKey_Tab;
|
||||
case KeyCode::Left:
|
||||
return ImGuiKey_LeftArrow;
|
||||
case KeyCode::Right:
|
||||
return ImGuiKey_RightArrow;
|
||||
case KeyCode::Up:
|
||||
return ImGuiKey_UpArrow;
|
||||
case KeyCode::Down:
|
||||
return ImGuiKey_DownArrow;
|
||||
case KeyCode::Delete:
|
||||
return ImGuiKey_Delete;
|
||||
case KeyCode::Back:
|
||||
return ImGuiKey_Backspace;
|
||||
case KeyCode::Space:
|
||||
return ImGuiKey_Space;
|
||||
case KeyCode::Enter:
|
||||
return ImGuiKey_Enter;
|
||||
case KeyCode::Esc:
|
||||
return ImGuiKey_Escape;
|
||||
case KeyCode::Num0:
|
||||
case KeyCode::Num1:
|
||||
case KeyCode::Num2:
|
||||
case KeyCode::Num3:
|
||||
case KeyCode::Num4:
|
||||
case KeyCode::Num5:
|
||||
case KeyCode::Num6:
|
||||
case KeyCode::Num7:
|
||||
case KeyCode::Num8:
|
||||
case KeyCode::Num9:
|
||||
return ImGuiKey(ImGuiKey_0 + (code - KeyCode::Num0));
|
||||
case KeyCode::Numpad0:
|
||||
case KeyCode::Numpad1:
|
||||
case KeyCode::Numpad2:
|
||||
case KeyCode::Numpad3:
|
||||
case KeyCode::Numpad4:
|
||||
case KeyCode::Numpad5:
|
||||
case KeyCode::Numpad6:
|
||||
case KeyCode::Numpad7:
|
||||
case KeyCode::Numpad8:
|
||||
case KeyCode::Numpad9:
|
||||
return ImGuiKey(ImGuiKey_Keypad0 + (code - KeyCode::Numpad0));
|
||||
case KeyCode::A:
|
||||
case KeyCode::B:
|
||||
case KeyCode::C:
|
||||
case KeyCode::D:
|
||||
case KeyCode::E:
|
||||
case KeyCode::F:
|
||||
case KeyCode::G:
|
||||
case KeyCode::H:
|
||||
case KeyCode::I:
|
||||
case KeyCode::J:
|
||||
case KeyCode::K:
|
||||
case KeyCode::L:
|
||||
case KeyCode::M:
|
||||
case KeyCode::N:
|
||||
case KeyCode::O:
|
||||
case KeyCode::P:
|
||||
case KeyCode::Q:
|
||||
case KeyCode::R:
|
||||
case KeyCode::S:
|
||||
case KeyCode::T:
|
||||
case KeyCode::U:
|
||||
case KeyCode::V:
|
||||
case KeyCode::W:
|
||||
case KeyCode::X:
|
||||
case KeyCode::Y:
|
||||
case KeyCode::Z:
|
||||
return ImGuiKey(ImGuiKey_A + (code - KeyCode::A));
|
||||
case KeyCode::F1:
|
||||
case KeyCode::F2:
|
||||
case KeyCode::F3:
|
||||
case KeyCode::F4:
|
||||
case KeyCode::F5:
|
||||
case KeyCode::F6:
|
||||
case KeyCode::F7:
|
||||
case KeyCode::F8:
|
||||
case KeyCode::F9:
|
||||
case KeyCode::F10:
|
||||
case KeyCode::F11:
|
||||
case KeyCode::F12:
|
||||
return ImGuiKey(ImGuiKey_F1 + (code - KeyCode::F1));
|
||||
default:
|
||||
return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiModule::ImGuiModule() {}
|
||||
|
||||
void ImGuiModule::SetupModule()
|
||||
{
|
||||
window_ = Application::GetInstance().GetWindow();
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
(void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
window_ = Application::GetInstance().GetWindow();
|
||||
this->InitPlatform();
|
||||
ImGui_Impl_Init();
|
||||
}
|
||||
|
||||
void ImGuiModule::InitPlatform()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
io.BackendPlatformUserData = (void*)this;
|
||||
io.BackendPlatformName = "imgui_impl_win32";
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
|
||||
|
||||
// Set platform dependent data in viewport
|
||||
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)window_->GetHandle();
|
||||
|
||||
// Setup Platform/Renderer bindings
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |=
|
||||
ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
|
||||
io.BackendPlatformName = "imgui_impl_win32";
|
||||
io.ImeWindowHandle = window_->GetHandle();
|
||||
|
||||
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during
|
||||
// the application lifetime.
|
||||
io.KeyMap[ImGuiKey_Tab] = (int)KeyCode::Tab;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = (int)KeyCode::Left;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = (int)KeyCode::Right;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = (int)KeyCode::Up;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = (int)KeyCode::Down;
|
||||
io.KeyMap[ImGuiKey_Delete] = (int)KeyCode::Delete;
|
||||
io.KeyMap[ImGuiKey_Backspace] = (int)KeyCode::Back;
|
||||
io.KeyMap[ImGuiKey_Space] = (int)KeyCode::Space;
|
||||
io.KeyMap[ImGuiKey_Enter] = (int)KeyCode::Enter;
|
||||
io.KeyMap[ImGuiKey_Escape] = (int)KeyCode::Esc;
|
||||
io.KeyMap[ImGuiKey_A] = (int)KeyCode::A;
|
||||
io.KeyMap[ImGuiKey_C] = (int)KeyCode::C;
|
||||
io.KeyMap[ImGuiKey_V] = (int)KeyCode::V;
|
||||
io.KeyMap[ImGuiKey_X] = (int)KeyCode::X;
|
||||
io.KeyMap[ImGuiKey_Y] = (int)KeyCode::Y;
|
||||
io.KeyMap[ImGuiKey_Z] = (int)KeyCode::Z;
|
||||
|
||||
ImGui_Impl_Init();
|
||||
}
|
||||
|
||||
void ImGuiModule::DestroyModule()
|
||||
{
|
||||
ImGui_Impl_Shutdown();
|
||||
this->ShutdownPlatform();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
void ImGuiModule::ShutdownPlatform()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
}
|
||||
|
||||
void ImGuiModule::OnUpdate(UpdateModuleContext& ctx)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup time step
|
||||
io.DeltaTime = ctx.dt.GetSeconds();
|
||||
if (io.DeltaTime <= 0.f)
|
||||
{
|
||||
// Prevent from failed assertion
|
||||
io.DeltaTime = 0.0001f;
|
||||
}
|
||||
|
||||
// Read keyboard modifiers inputs
|
||||
io.KeyCtrl = Input::GetInstance().IsDown(KeyCode::Ctrl);
|
||||
|
|
@ -79,9 +177,6 @@ void ImGuiModule::OnUpdate(UpdateModuleContext& ctx)
|
|||
io.KeySuper = Input::GetInstance().IsDown(KeyCode::Super);
|
||||
// io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below.
|
||||
|
||||
// Update OS mouse position
|
||||
UpdateMousePos();
|
||||
|
||||
// Update OS mouse cursor with the cursor requested by imgui
|
||||
UpdateMouseCursor();
|
||||
|
||||
|
|
@ -93,7 +188,6 @@ void ImGuiModule::BeforeRender(RenderModuleContext& ctx)
|
|||
ImGui_Impl_NewFrame();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
Size display_size = Renderer::GetInstance().GetOutputSize();
|
||||
|
|
@ -118,7 +212,12 @@ void ImGuiModule::HandleEvent(EventModuleContext& ctx)
|
|||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (evt->IsType<MouseEvent>())
|
||||
{
|
||||
if (evt->IsType<MouseDownEvent>())
|
||||
if (evt->IsType<MouseMoveEvent>())
|
||||
{
|
||||
const auto& pos = dynamic_cast<MouseMoveEvent*>(evt)->pos;
|
||||
io.AddMousePosEvent(pos.x, pos.y);
|
||||
}
|
||||
else if (evt->IsType<MouseDownEvent>())
|
||||
{
|
||||
MouseButton button = dynamic_cast<MouseDownEvent*>(evt)->button;
|
||||
int index = 0;
|
||||
|
|
@ -128,7 +227,7 @@ void ImGuiModule::HandleEvent(EventModuleContext& ctx)
|
|||
index = 1;
|
||||
else if (button == MouseButton::Middle)
|
||||
index = 2;
|
||||
io.MouseDown[index] = true;
|
||||
io.AddMouseButtonEvent(index, true);
|
||||
}
|
||||
else if (evt->IsType<MouseUpEvent>())
|
||||
{
|
||||
|
|
@ -140,12 +239,12 @@ void ImGuiModule::HandleEvent(EventModuleContext& ctx)
|
|||
index = 1;
|
||||
else if (button == MouseButton::Middle)
|
||||
index = 2;
|
||||
io.MouseDown[index] = false;
|
||||
io.AddMouseButtonEvent(index, false);
|
||||
}
|
||||
else if (evt->IsType<MouseWheelEvent>())
|
||||
{
|
||||
float wheel = dynamic_cast<MouseWheelEvent*>(evt)->wheel;
|
||||
io.MouseWheel += wheel;
|
||||
io.AddMouseWheelEvent(0.0f, wheel);
|
||||
}
|
||||
}
|
||||
else if (evt->IsType<KeyEvent>())
|
||||
|
|
@ -153,42 +252,38 @@ void ImGuiModule::HandleEvent(EventModuleContext& ctx)
|
|||
if (evt->IsType<KeyDownEvent>())
|
||||
{
|
||||
KeyCode key = dynamic_cast<KeyDownEvent*>(evt)->code;
|
||||
io.KeysDown[(int)key] = true;
|
||||
io.AddKeyEvent(KeyCodeToImGuiKey(key), true);
|
||||
}
|
||||
else if (evt->IsType<KeyUpEvent>())
|
||||
{
|
||||
KeyCode key = dynamic_cast<KeyUpEvent*>(evt)->code;
|
||||
io.KeysDown[(int)key] = false;
|
||||
io.AddKeyEvent(KeyCodeToImGuiKey(key), false);
|
||||
}
|
||||
else if (evt->IsType<KeyCharEvent>())
|
||||
{
|
||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||
char ch = dynamic_cast<KeyCharEvent*>(evt)->value;
|
||||
io.AddInputCharacter(static_cast<ImWchar>(ch));
|
||||
}
|
||||
else if (evt->IsType<IMEInputEvent>())
|
||||
{
|
||||
const auto& str = dynamic_cast<IMEInputEvent*>(evt)->value;
|
||||
const auto utf8_str = strings::WideToUTF8(strings::NarrowToWide(str));
|
||||
io.AddInputCharactersUTF8(utf8_str.c_str());
|
||||
}
|
||||
}
|
||||
else if (evt->IsType<WindowEvent>())
|
||||
{
|
||||
if (evt->IsType<WindowFocusChangedEvent>())
|
||||
{
|
||||
bool focus = dynamic_cast<WindowFocusChangedEvent*>(evt)->focus;
|
||||
io.AddFocusEvent(focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Next();
|
||||
}
|
||||
|
||||
void ImGuiModule::UpdateMousePos()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by
|
||||
// user)
|
||||
if (io.WantSetMousePos)
|
||||
{
|
||||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||
::ClientToScreen(window_->GetHandle(), &pos);
|
||||
::SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
|
||||
Point pos = Input::GetInstance().GetMousePos();
|
||||
io.MousePos = ImVec2(pos.x, pos.y);
|
||||
}
|
||||
|
||||
void ImGuiModule::UpdateMouseCursor()
|
||||
{
|
||||
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
|
|
@ -227,6 +322,9 @@ void ImGuiModule::UpdateMouseCursor()
|
|||
case ImGuiMouseCursor_Hand:
|
||||
cursor = CursorType::Hand;
|
||||
break;
|
||||
case ImGuiMouseCursor_NotAllowed:
|
||||
cursor = CursorType::No;
|
||||
break;
|
||||
}
|
||||
|
||||
window_->SetCursor(cursor);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ public:
|
|||
void HandleEvent(EventModuleContext& ctx) override;
|
||||
|
||||
private:
|
||||
void UpdateMousePos();
|
||||
void InitPlatform();
|
||||
|
||||
void ShutdownPlatform();
|
||||
|
||||
void UpdateMouseCursor();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,89 +2,132 @@
|
|||
|
||||
#include <kiwano-imgui/imgui_impl/imgui_impl_dx10.h>
|
||||
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx10.h"
|
||||
|
||||
// DirectX
|
||||
#include <stdio.h>
|
||||
#include <d3d10_1.h>
|
||||
#include <d3d10.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
|
||||
#endif
|
||||
|
||||
// DirectX data
|
||||
static ID3D10Device* g_pd3dDevice = NULL;
|
||||
static IDXGIFactory* g_pFactory = NULL;
|
||||
static ID3D10Buffer* g_pVB = NULL;
|
||||
static ID3D10Buffer* g_pIB = NULL;
|
||||
static ID3D10Blob* g_pVertexShaderBlob = NULL;
|
||||
static ID3D10VertexShader* g_pVertexShader = NULL;
|
||||
static ID3D10InputLayout* g_pInputLayout = NULL;
|
||||
static ID3D10Buffer* g_pVertexConstantBuffer = NULL;
|
||||
static ID3D10Blob* g_pPixelShaderBlob = NULL;
|
||||
static ID3D10PixelShader* g_pPixelShader = NULL;
|
||||
static ID3D10SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D10ShaderResourceView* g_pFontTextureView = NULL;
|
||||
static ID3D10RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D10BlendState* g_pBlendState = NULL;
|
||||
static ID3D10DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
struct ImGui_ImplDX10_Data
|
||||
{
|
||||
ID3D10Device* pd3dDevice;
|
||||
IDXGIFactory* pFactory;
|
||||
ID3D10Buffer* pVB;
|
||||
ID3D10Buffer* pIB;
|
||||
ID3D10VertexShader* pVertexShader;
|
||||
ID3D10InputLayout* pInputLayout;
|
||||
ID3D10Buffer* pVertexConstantBuffer;
|
||||
ID3D10PixelShader* pPixelShader;
|
||||
ID3D10SamplerState* pFontSampler;
|
||||
ID3D10ShaderResourceView* pFontTextureView;
|
||||
ID3D10RasterizerState* pRasterizerState;
|
||||
ID3D10BlendState* pBlendState;
|
||||
ID3D10DepthStencilState* pDepthStencilState;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
ImGui_ImplDX10_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER_DX10
|
||||
{
|
||||
float mvp[4][4];
|
||||
};
|
||||
|
||||
// Render Function
|
||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from
|
||||
// your main loop)
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx)
|
||||
{
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3D10_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
|
||||
vp.Width = (UINT)draw_data->DisplaySize.x;
|
||||
vp.Height = (UINT)draw_data->DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(bd->pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(bd->pVertexShader);
|
||||
ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||
ctx->PSSetShader(bd->pPixelShader);
|
||||
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
|
||||
ctx->GSSetShader(nullptr);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||
ctx->RSSetState(bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
ID3D10Device* ctx = g_pd3dDevice;
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
ID3D10Device* ctx = bd->pd3dDevice;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB)
|
||||
{
|
||||
g_pVB->Release();
|
||||
g_pVB = NULL;
|
||||
}
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D10_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
if (ctx->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB)
|
||||
{
|
||||
g_pIB->Release();
|
||||
g_pIB = NULL;
|
||||
}
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D10_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
if (ctx->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
ImDrawVert* vtx_dst = NULL;
|
||||
ImDrawIdx* idx_dst = NULL;
|
||||
g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
|
||||
g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
|
||||
ImDrawVert* vtx_dst = nullptr;
|
||||
ImDrawIdx* idx_dst = nullptr;
|
||||
bd->pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
|
||||
bd->pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
|
|
@ -93,33 +136,32 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
|||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
g_pVB->Unmap();
|
||||
g_pIB->Unmap();
|
||||
bd->pVB->Unmap();
|
||||
bd->pIB->Unmap();
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
||||
// draw_data->DisplayPos+data_data->DisplaySize (bottom right).
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
{
|
||||
void* mapped_resource;
|
||||
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
if (bd->pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
|
||||
VERTEX_CONSTANT_BUFFER_DX10* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX10*)mapped_resource;
|
||||
float L = draw_data->DisplayPos.x;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||
float mvp[4][4] = {
|
||||
float mvp[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.5f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
g_pVertexConstantBuffer->Unmap();
|
||||
bd->pVertexConstantBuffer->Unmap();
|
||||
}
|
||||
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and
|
||||
// verbose. Close your eyes!)
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
struct BACKUP_DX10_STATE
|
||||
{
|
||||
UINT ScissorRectsCount, ViewportsCount;
|
||||
|
|
@ -135,13 +177,14 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
|||
ID3D10SamplerState* PSSampler;
|
||||
ID3D10PixelShader* PS;
|
||||
ID3D10VertexShader* VS;
|
||||
ID3D10GeometryShader* GS;
|
||||
D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||
ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
|
||||
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
|
||||
DXGI_FORMAT IndexBufferFormat;
|
||||
ID3D10InputLayout* InputLayout;
|
||||
};
|
||||
BACKUP_DX10_STATE old;
|
||||
BACKUP_DX10_STATE old = {};
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
|
|
@ -153,43 +196,20 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
|||
ctx->PSGetShader(&old.PS);
|
||||
ctx->VSGetShader(&old.VS);
|
||||
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
ctx->GSGetShader(&old.GS);
|
||||
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
ctx->IAGetInputLayout(&old.InputLayout);
|
||||
|
||||
// Setup viewport
|
||||
D3D10_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
|
||||
vp.Width = (UINT)draw_data->DisplaySize.x;
|
||||
vp.Height = (UINT)draw_data->DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(g_pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(g_pVertexShader);
|
||||
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
ctx->PSSetShader(g_pPixelShader);
|
||||
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
|
||||
ctx->RSSetState(g_pRasterizerState);
|
||||
// Setup desired DX state
|
||||
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
int idx_offset = 0;
|
||||
ImVec2 pos = draw_data->DisplayPos;
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
|
|
@ -198,68 +218,57 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
|||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback (registered via ImDrawList::AddCallback)
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y),
|
||||
(LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
|
||||
const D3D10_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
|
||||
// Bind texture, Draw
|
||||
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->TextureId;
|
||||
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->GetTexID();
|
||||
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore modified DX state
|
||||
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
ctx->RSSetState(old.RS);
|
||||
if (old.RS)
|
||||
old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask);
|
||||
if (old.BlendState)
|
||||
old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef);
|
||||
if (old.DepthStencilState)
|
||||
old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource);
|
||||
if (old.PSShaderResource)
|
||||
old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler);
|
||||
if (old.PSSampler)
|
||||
old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS);
|
||||
if (old.PS)
|
||||
old.PS->Release();
|
||||
ctx->VSSetShader(old.VS);
|
||||
if (old.VS)
|
||||
old.VS->Release();
|
||||
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
if (old.VSConstantBuffer)
|
||||
old.VSConstantBuffer->Release();
|
||||
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release();
|
||||
ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release();
|
||||
ctx->GSSetShader(old.GS); if (old.GS) old.GS->Release();
|
||||
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset);
|
||||
if (old.IndexBuffer)
|
||||
old.IndexBuffer->Release();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
if (old.VertexBuffer)
|
||||
old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout);
|
||||
if (old.InputLayout)
|
||||
old.InputLayout->Release();
|
||||
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX10_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
|
|
@ -279,12 +288,13 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
|||
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D10Texture2D* pTexture = NULL;
|
||||
ID3D10Texture2D* pTexture = nullptr;
|
||||
D3D10_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != nullptr);
|
||||
|
||||
// Create texture view
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||
|
|
@ -293,14 +303,15 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
|||
srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView);
|
||||
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &bd->pFontTextureView);
|
||||
pTexture->Release();
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
|
||||
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
|
||||
|
||||
// Create texture sampler
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
{
|
||||
D3D10_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
|
|
@ -312,28 +323,28 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
|||
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return false;
|
||||
if (g_pFontSampler)
|
||||
if (bd->pFontSampler)
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of
|
||||
// d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) If you would like to use this DX10 sample code but remove this
|
||||
// dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to
|
||||
// CreateVertexShader()/CreatePixelShader() [preferred solution] 2) use code to detect any version of the DLL and
|
||||
// grab a pointer to D3DCompile from the DLL.
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX10 sample code but remove this dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||
|
||||
// Create the vertex shader
|
||||
{
|
||||
static const char* vertexShader = "cbuffer vertexBuffer : register(b0) \
|
||||
static const char* vertexShader =
|
||||
"cbuffer vertexBuffer : register(b0) \
|
||||
{\
|
||||
float4x4 ProjectionMatrix; \
|
||||
};\
|
||||
|
|
@ -360,46 +371,45 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
return output;\
|
||||
}";
|
||||
|
||||
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob,
|
||||
NULL);
|
||||
if (g_pVertexShaderBlob
|
||||
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
|
||||
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(),
|
||||
g_pVertexShaderBlob->GetBufferSize(), &g_pVertexShader)
|
||||
!= S_OK)
|
||||
ID3DBlob* vertexShaderBlob;
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pVertexShader) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the input layout
|
||||
D3D10_INPUT_ELEMENT_DESC local_layout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA,
|
||||
0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA,
|
||||
0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA,
|
||||
0 },
|
||||
D3D10_INPUT_ELEMENT_DESC local_layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(),
|
||||
g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout)
|
||||
!= S_OK)
|
||||
if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
}
|
||||
vertexShaderBlob->Release();
|
||||
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D10_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX10);
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the pixel shader
|
||||
{
|
||||
static const char* pixelShader = "struct PS_INPUT\
|
||||
static const char* pixelShader =
|
||||
"struct PS_INPUT\
|
||||
{\
|
||||
float4 pos : SV_POSITION;\
|
||||
float4 col : COLOR0;\
|
||||
|
|
@ -414,17 +424,16 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
return out_col; \
|
||||
}";
|
||||
|
||||
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob,
|
||||
NULL);
|
||||
if (g_pPixelShaderBlob
|
||||
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
|
||||
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(),
|
||||
g_pPixelShaderBlob->GetBufferSize(), &g_pPixelShader)
|
||||
!= S_OK)
|
||||
ID3DBlob* pixelShaderBlob;
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), &bd->pPixelShader) != S_OK)
|
||||
{
|
||||
pixelShaderBlob->Release();
|
||||
return false;
|
||||
}
|
||||
pixelShaderBlob->Release();
|
||||
}
|
||||
|
||||
// Create the blending setup
|
||||
{
|
||||
|
|
@ -435,11 +444,11 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
|
||||
desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
|
||||
desc.BlendOp = D3D10_BLEND_OP_ADD;
|
||||
desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
|
||||
desc.DestBlendAlpha = D3D10_BLEND_ZERO;
|
||||
desc.SrcBlendAlpha = D3D10_BLEND_ONE;
|
||||
desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
|
||||
desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
|
||||
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||
bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
|
|
@ -450,7 +459,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
desc.CullMode = D3D10_CULL_NONE;
|
||||
desc.ScissorEnable = true;
|
||||
desc.DepthClipEnable = true;
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
|
|
@ -461,11 +470,10 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
|
||||
desc.DepthFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.StencilEnable = false;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp =
|
||||
D3D10_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX10_CreateFontsTexture();
|
||||
|
|
@ -475,116 +483,76 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
|
||||
void ImGui_ImplDX10_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return;
|
||||
|
||||
if (g_pFontSampler)
|
||||
{
|
||||
g_pFontSampler->Release();
|
||||
g_pFontSampler = NULL;
|
||||
}
|
||||
if (g_pFontTextureView)
|
||||
{
|
||||
g_pFontTextureView->Release();
|
||||
g_pFontTextureView = NULL;
|
||||
ImGui::GetIO().Fonts->TexID = NULL;
|
||||
} // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (g_pIB)
|
||||
{
|
||||
g_pIB->Release();
|
||||
g_pIB = NULL;
|
||||
}
|
||||
if (g_pVB)
|
||||
{
|
||||
g_pVB->Release();
|
||||
g_pVB = NULL;
|
||||
}
|
||||
|
||||
if (g_pBlendState)
|
||||
{
|
||||
g_pBlendState->Release();
|
||||
g_pBlendState = NULL;
|
||||
}
|
||||
if (g_pDepthStencilState)
|
||||
{
|
||||
g_pDepthStencilState->Release();
|
||||
g_pDepthStencilState = NULL;
|
||||
}
|
||||
if (g_pRasterizerState)
|
||||
{
|
||||
g_pRasterizerState->Release();
|
||||
g_pRasterizerState = NULL;
|
||||
}
|
||||
if (g_pPixelShader)
|
||||
{
|
||||
g_pPixelShader->Release();
|
||||
g_pPixelShader = NULL;
|
||||
}
|
||||
if (g_pPixelShaderBlob)
|
||||
{
|
||||
g_pPixelShaderBlob->Release();
|
||||
g_pPixelShaderBlob = NULL;
|
||||
}
|
||||
if (g_pVertexConstantBuffer)
|
||||
{
|
||||
g_pVertexConstantBuffer->Release();
|
||||
g_pVertexConstantBuffer = NULL;
|
||||
}
|
||||
if (g_pInputLayout)
|
||||
{
|
||||
g_pInputLayout->Release();
|
||||
g_pInputLayout = NULL;
|
||||
}
|
||||
if (g_pVertexShader)
|
||||
{
|
||||
g_pVertexShader->Release();
|
||||
g_pVertexShader = NULL;
|
||||
}
|
||||
if (g_pVertexShaderBlob)
|
||||
{
|
||||
g_pVertexShaderBlob->Release();
|
||||
g_pVertexShaderBlob = NULL;
|
||||
}
|
||||
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
|
||||
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; }
|
||||
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; }
|
||||
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; }
|
||||
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; }
|
||||
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; }
|
||||
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX10_Init(ID3D10Device* device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX10_Data* bd = IM_NEW(ImGui_ImplDX10_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx10";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
// Get factory from device
|
||||
IDXGIDevice* pDXGIDevice = NULL;
|
||||
IDXGIAdapter* pDXGIAdapter = NULL;
|
||||
IDXGIFactory* pFactory = NULL;
|
||||
|
||||
IDXGIDevice* pDXGIDevice = nullptr;
|
||||
IDXGIAdapter* pDXGIAdapter = nullptr;
|
||||
IDXGIFactory* pFactory = nullptr;
|
||||
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
|
||||
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
|
||||
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
|
||||
{
|
||||
g_pd3dDevice = device;
|
||||
g_pFactory = pFactory;
|
||||
bd->pd3dDevice = device;
|
||||
bd->pFactory = pFactory;
|
||||
}
|
||||
if (pDXGIDevice)
|
||||
pDXGIDevice->Release();
|
||||
if (pDXGIAdapter)
|
||||
pDXGIAdapter->Release();
|
||||
if (pDXGIDevice) pDXGIDevice->Release();
|
||||
if (pDXGIAdapter) pDXGIAdapter->Release();
|
||||
bd->pd3dDevice->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX10_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
if (g_pFactory)
|
||||
{
|
||||
g_pFactory->Release();
|
||||
g_pFactory = NULL;
|
||||
}
|
||||
g_pd3dDevice = NULL;
|
||||
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplDX10_NewFrame()
|
||||
{
|
||||
if (!g_pFontSampler)
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX10_Init()?");
|
||||
|
||||
if (!bd->pFontSampler)
|
||||
ImGui_ImplDX10_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <imgui/imgui.h>
|
||||
|
||||
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct ID3D10Device;
|
||||
|
||||
|
|
@ -12,8 +13,9 @@ IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown();
|
|||
IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,88 +2,134 @@
|
|||
|
||||
#include <kiwano-imgui/imgui_impl/imgui_impl_dx11.h>
|
||||
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx11.h"
|
||||
|
||||
// DirectX
|
||||
#include <stdio.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
|
||||
#endif
|
||||
|
||||
// DirectX data
|
||||
static ID3D11Device* g_pd3dDevice = NULL;
|
||||
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
|
||||
static IDXGIFactory* g_pFactory = NULL;
|
||||
static ID3D11Buffer* g_pVB = NULL;
|
||||
static ID3D11Buffer* g_pIB = NULL;
|
||||
static ID3D10Blob* g_pVertexShaderBlob = NULL;
|
||||
static ID3D11VertexShader* g_pVertexShader = NULL;
|
||||
static ID3D11InputLayout* g_pInputLayout = NULL;
|
||||
static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
|
||||
static ID3D10Blob* g_pPixelShaderBlob = NULL;
|
||||
static ID3D11PixelShader* g_pPixelShader = NULL;
|
||||
static ID3D11SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D11ShaderResourceView* g_pFontTextureView = NULL;
|
||||
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D11BlendState* g_pBlendState = NULL;
|
||||
static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
// DirectX11 data
|
||||
struct ImGui_ImplDX11_Data
|
||||
{
|
||||
ID3D11Device* pd3dDevice;
|
||||
ID3D11DeviceContext* pd3dDeviceContext;
|
||||
IDXGIFactory* pFactory;
|
||||
ID3D11Buffer* pVB;
|
||||
ID3D11Buffer* pIB;
|
||||
ID3D11VertexShader* pVertexShader;
|
||||
ID3D11InputLayout* pInputLayout;
|
||||
ID3D11Buffer* pVertexConstantBuffer;
|
||||
ID3D11PixelShader* pPixelShader;
|
||||
ID3D11SamplerState* pFontSampler;
|
||||
ID3D11ShaderResourceView* pFontTextureView;
|
||||
ID3D11RasterizerState* pRasterizerState;
|
||||
ID3D11BlendState* pBlendState;
|
||||
ID3D11DepthStencilState* pDepthStencilState;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER_DX11
|
||||
{
|
||||
float mvp[4][4];
|
||||
};
|
||||
|
||||
// Render Function
|
||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from
|
||||
// your main loop)
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3D11_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
|
||||
vp.Width = draw_data->DisplaySize.x;
|
||||
vp.Height = draw_data->DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Setup shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(bd->pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
|
||||
ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||
ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
|
||||
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
|
||||
ctx->GSSetShader(nullptr, nullptr, 0);
|
||||
ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
|
||||
// Setup blend state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||
ctx->RSSetState(bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB)
|
||||
{
|
||||
g_pVB->Release();
|
||||
g_pVB = NULL;
|
||||
}
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
|
||||
return;
|
||||
}
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB)
|
||||
{
|
||||
g_pIB->Release();
|
||||
g_pIB = NULL;
|
||||
}
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
// Upload vertex/index data into a single contiguous GPU buffer
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
||||
|
|
@ -95,33 +141,32 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
|||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
ctx->Unmap(g_pVB, 0);
|
||||
ctx->Unmap(g_pIB, 0);
|
||||
ctx->Unmap(bd->pVB, 0);
|
||||
ctx->Unmap(bd->pIB, 0);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
||||
// draw_data->DisplayPos+data_data->DisplaySize (bottom right).
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
|
||||
VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData;
|
||||
float L = draw_data->DisplayPos.x;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||
float mvp[4][4] = {
|
||||
float mvp[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.5f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
ctx->Unmap(g_pVertexConstantBuffer, 0);
|
||||
ctx->Unmap(bd->pVertexConstantBuffer, 0);
|
||||
}
|
||||
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and
|
||||
// verbose. Close your eyes!)
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
struct BACKUP_DX11_STATE
|
||||
{
|
||||
UINT ScissorRectsCount, ViewportsCount;
|
||||
|
|
@ -137,15 +182,16 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
|||
ID3D11SamplerState* PSSampler;
|
||||
ID3D11PixelShader* PS;
|
||||
ID3D11VertexShader* VS;
|
||||
UINT PSInstancesCount, VSInstancesCount;
|
||||
ID3D11ClassInstance *PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
|
||||
ID3D11GeometryShader* GS;
|
||||
UINT PSInstancesCount, VSInstancesCount, GSInstancesCount;
|
||||
ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation
|
||||
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
|
||||
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
|
||||
DXGI_FORMAT IndexBufferFormat;
|
||||
ID3D11InputLayout* InputLayout;
|
||||
};
|
||||
BACKUP_DX11_STATE old;
|
||||
BACKUP_DX11_STATE old = {};
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
|
|
@ -154,124 +200,87 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
|||
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
ctx->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
old.PSInstancesCount = old.VSInstancesCount = 256;
|
||||
old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256;
|
||||
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
|
||||
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
|
||||
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
|
||||
|
||||
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
ctx->IAGetInputLayout(&old.InputLayout);
|
||||
|
||||
// Setup viewport
|
||||
D3D11_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
|
||||
vp.Width = draw_data->DisplaySize.x;
|
||||
vp.Height = draw_data->DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(g_pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(g_pVertexShader, NULL, 0);
|
||||
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
ctx->PSSetShader(g_pPixelShader, NULL, 0);
|
||||
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
|
||||
ctx->RSSetState(g_pRasterizerState);
|
||||
// Setup desired DX state
|
||||
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
int idx_offset = 0;
|
||||
ImVec2 pos = draw_data->DisplayPos;
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_idx_offset = 0;
|
||||
int global_vtx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback (registered via ImDrawList::AddCallback)
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y),
|
||||
(LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
|
||||
const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
|
||||
// Bind texture, Draw
|
||||
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId;
|
||||
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
|
||||
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore modified DX state
|
||||
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
ctx->RSSetState(old.RS);
|
||||
if (old.RS)
|
||||
old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask);
|
||||
if (old.BlendState)
|
||||
old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef);
|
||||
if (old.DepthStencilState)
|
||||
old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource);
|
||||
if (old.PSShaderResource)
|
||||
old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler);
|
||||
if (old.PSSampler)
|
||||
old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount);
|
||||
if (old.PS)
|
||||
old.PS->Release();
|
||||
for (UINT i = 0; i < old.PSInstancesCount; i++)
|
||||
if (old.PSInstances[i])
|
||||
old.PSInstances[i]->Release();
|
||||
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount);
|
||||
if (old.VS)
|
||||
old.VS->Release();
|
||||
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
if (old.VSConstantBuffer)
|
||||
old.VSConstantBuffer->Release();
|
||||
for (UINT i = 0; i < old.VSInstancesCount; i++)
|
||||
if (old.VSInstances[i])
|
||||
old.VSInstances[i]->Release();
|
||||
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
|
||||
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
|
||||
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
|
||||
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||
ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
|
||||
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
|
||||
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset);
|
||||
if (old.IndexBuffer)
|
||||
old.IndexBuffer->Release();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
if (old.VertexBuffer)
|
||||
old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout);
|
||||
if (old.InputLayout)
|
||||
old.InputLayout->Release();
|
||||
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
|
@ -290,15 +299,14 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
|||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D11Texture2D* pTexture = NULL;
|
||||
ID3D11Texture2D* pTexture = nullptr;
|
||||
D3D11_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != nullptr);
|
||||
|
||||
if (pTexture)
|
||||
{
|
||||
// Create texture view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
|
|
@ -306,16 +314,15 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
|||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
|
||||
|
||||
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
|
||||
pTexture->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
|
||||
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
|
||||
|
||||
// Create texture sampler
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
|
|
@ -327,28 +334,28 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
|||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return false;
|
||||
if (g_pFontSampler)
|
||||
if (bd->pFontSampler)
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of
|
||||
// d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) If you would like to use this DX11 sample code but remove this
|
||||
// dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to
|
||||
// CreateVertexShader()/CreatePixelShader() [preferred solution] 2) use code to detect any version of the DLL and
|
||||
// grab a pointer to D3DCompile from the DLL.
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX11 sample code but remove this dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||
|
||||
// Create the vertex shader
|
||||
{
|
||||
static const char* vertexShader = "cbuffer vertexBuffer : register(b0) \
|
||||
static const char* vertexShader =
|
||||
"cbuffer vertexBuffer : register(b0) \
|
||||
{\
|
||||
float4x4 ProjectionMatrix; \
|
||||
};\
|
||||
|
|
@ -375,46 +382,45 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
return output;\
|
||||
}";
|
||||
|
||||
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob,
|
||||
NULL);
|
||||
if (g_pVertexShaderBlob
|
||||
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
|
||||
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(),
|
||||
g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader)
|
||||
!= S_OK)
|
||||
ID3DBlob* vertexShaderBlob;
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the input layout
|
||||
D3D11_INPUT_ELEMENT_DESC local_layout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA,
|
||||
0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA,
|
||||
0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA,
|
||||
0 },
|
||||
D3D11_INPUT_ELEMENT_DESC local_layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(),
|
||||
g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout)
|
||||
!= S_OK)
|
||||
if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
}
|
||||
vertexShaderBlob->Release();
|
||||
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11);
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the pixel shader
|
||||
{
|
||||
static const char* pixelShader = "struct PS_INPUT\
|
||||
static const char* pixelShader =
|
||||
"struct PS_INPUT\
|
||||
{\
|
||||
float4 pos : SV_POSITION;\
|
||||
float4 col : COLOR0;\
|
||||
|
|
@ -429,17 +435,16 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
return out_col; \
|
||||
}";
|
||||
|
||||
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob,
|
||||
NULL);
|
||||
if (g_pPixelShaderBlob
|
||||
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
|
||||
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(),
|
||||
g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader)
|
||||
!= S_OK)
|
||||
ID3DBlob* pixelShaderBlob;
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK)
|
||||
{
|
||||
pixelShaderBlob->Release();
|
||||
return false;
|
||||
}
|
||||
pixelShaderBlob->Release();
|
||||
}
|
||||
|
||||
// Create the blending setup
|
||||
{
|
||||
|
|
@ -450,11 +455,11 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||
bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
|
|
@ -465,7 +470,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
desc.CullMode = D3D11_CULL_NONE;
|
||||
desc.ScissorEnable = true;
|
||||
desc.DepthClipEnable = true;
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
|
|
@ -476,11 +481,10 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.StencilEnable = false;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp =
|
||||
D3D11_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_CreateFontsTexture();
|
||||
|
|
@ -490,118 +494,80 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
|
||||
void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return;
|
||||
|
||||
if (g_pFontSampler)
|
||||
{
|
||||
g_pFontSampler->Release();
|
||||
g_pFontSampler = NULL;
|
||||
}
|
||||
if (g_pFontTextureView)
|
||||
{
|
||||
g_pFontTextureView->Release();
|
||||
g_pFontTextureView = NULL;
|
||||
ImGui::GetIO().Fonts->TexID = NULL;
|
||||
} // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (g_pIB)
|
||||
{
|
||||
g_pIB->Release();
|
||||
g_pIB = NULL;
|
||||
}
|
||||
if (g_pVB)
|
||||
{
|
||||
g_pVB->Release();
|
||||
g_pVB = NULL;
|
||||
}
|
||||
|
||||
if (g_pBlendState)
|
||||
{
|
||||
g_pBlendState->Release();
|
||||
g_pBlendState = NULL;
|
||||
}
|
||||
if (g_pDepthStencilState)
|
||||
{
|
||||
g_pDepthStencilState->Release();
|
||||
g_pDepthStencilState = NULL;
|
||||
}
|
||||
if (g_pRasterizerState)
|
||||
{
|
||||
g_pRasterizerState->Release();
|
||||
g_pRasterizerState = NULL;
|
||||
}
|
||||
if (g_pPixelShader)
|
||||
{
|
||||
g_pPixelShader->Release();
|
||||
g_pPixelShader = NULL;
|
||||
}
|
||||
if (g_pPixelShaderBlob)
|
||||
{
|
||||
g_pPixelShaderBlob->Release();
|
||||
g_pPixelShaderBlob = NULL;
|
||||
}
|
||||
if (g_pVertexConstantBuffer)
|
||||
{
|
||||
g_pVertexConstantBuffer->Release();
|
||||
g_pVertexConstantBuffer = NULL;
|
||||
}
|
||||
if (g_pInputLayout)
|
||||
{
|
||||
g_pInputLayout->Release();
|
||||
g_pInputLayout = NULL;
|
||||
}
|
||||
if (g_pVertexShader)
|
||||
{
|
||||
g_pVertexShader->Release();
|
||||
g_pVertexShader = NULL;
|
||||
}
|
||||
if (g_pVertexShaderBlob)
|
||||
{
|
||||
g_pVertexShaderBlob->Release();
|
||||
g_pVertexShaderBlob = NULL;
|
||||
}
|
||||
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
|
||||
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; }
|
||||
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; }
|
||||
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; }
|
||||
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; }
|
||||
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; }
|
||||
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx11";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
// Get factory from device
|
||||
IDXGIDevice* pDXGIDevice = NULL;
|
||||
IDXGIAdapter* pDXGIAdapter = NULL;
|
||||
IDXGIFactory* pFactory = NULL;
|
||||
IDXGIDevice* pDXGIDevice = nullptr;
|
||||
IDXGIAdapter* pDXGIAdapter = nullptr;
|
||||
IDXGIFactory* pFactory = nullptr;
|
||||
|
||||
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
|
||||
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
|
||||
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
|
||||
{
|
||||
g_pd3dDevice = device;
|
||||
g_pd3dDeviceContext = device_context;
|
||||
g_pFactory = pFactory;
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDeviceContext = device_context;
|
||||
bd->pFactory = pFactory;
|
||||
}
|
||||
if (pDXGIDevice)
|
||||
pDXGIDevice->Release();
|
||||
if (pDXGIAdapter)
|
||||
pDXGIAdapter->Release();
|
||||
if (pDXGIDevice) pDXGIDevice->Release();
|
||||
if (pDXGIAdapter) pDXGIAdapter->Release();
|
||||
bd->pd3dDevice->AddRef();
|
||||
bd->pd3dDeviceContext->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
if (g_pFactory)
|
||||
{
|
||||
g_pFactory->Release();
|
||||
g_pFactory = NULL;
|
||||
}
|
||||
g_pd3dDevice = NULL;
|
||||
g_pd3dDeviceContext = NULL;
|
||||
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_NewFrame()
|
||||
{
|
||||
if (!g_pFontSampler)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX11_Init()?");
|
||||
|
||||
if (!bd->pFontSampler)
|
||||
ImGui_ImplDX11_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <imgui/imgui.h>
|
||||
|
||||
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
|
@ -13,8 +14,9 @@ IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
|
|||
IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ private:
|
|||
RenderContextPtr render_ctx_;
|
||||
};
|
||||
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 画布渲染上下文
|
||||
class KGE_API CanvasRenderContext : public ObjectBase
|
||||
|
|
@ -411,7 +410,7 @@ inline void CanvasRenderContext::DrawTexture(TexturePtr texture, const Point& po
|
|||
|
||||
if (texture)
|
||||
{
|
||||
Rect dest_rect(pos, size);
|
||||
Rect dest_rect(pos, pos + size);
|
||||
ctx_->DrawTexture(*texture, crop_rect, &dest_rect);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,40 +81,60 @@ WideString FormatArgs(const wchar_t* format, va_list args)
|
|||
return result;
|
||||
}
|
||||
|
||||
String WideToNarrow(const WideString& str)
|
||||
String WideToNarrowWithCodePage(const WideString& str, UINT code_page)
|
||||
{
|
||||
if (str.empty())
|
||||
return String();
|
||||
|
||||
int len = ::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
|
||||
int len = ::WideCharToMultiByte(code_page, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
|
||||
if (len > 0)
|
||||
{
|
||||
String result;
|
||||
result.resize(len - 1);
|
||||
|
||||
::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, &result[0], len, NULL, NULL);
|
||||
::WideCharToMultiByte(code_page, 0, str.c_str(), -1, &result[0], len, NULL, NULL);
|
||||
return result;
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
WideString NarrowToWide(const String& str)
|
||||
WideString NarrowToWideWithCodePage(const String& str, UINT code_page)
|
||||
{
|
||||
if (str.empty())
|
||||
return WideString();
|
||||
|
||||
int len = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
|
||||
int len = ::MultiByteToWideChar(code_page, 0, str.c_str(), -1, NULL, 0);
|
||||
if (len > 0)
|
||||
{
|
||||
WideString result;
|
||||
result.resize(len - 1);
|
||||
|
||||
::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &result[0], len);
|
||||
::MultiByteToWideChar(code_page, 0, str.c_str(), -1, &result[0], len);
|
||||
return result;
|
||||
}
|
||||
return WideString();
|
||||
}
|
||||
|
||||
String WideToNarrow(const WideString& str)
|
||||
{
|
||||
return WideToNarrowWithCodePage(str, CP_ACP);
|
||||
}
|
||||
|
||||
WideString NarrowToWide(const String& str)
|
||||
{
|
||||
return NarrowToWideWithCodePage(str, CP_ACP);
|
||||
}
|
||||
|
||||
String WideToUTF8(const WideString& str)
|
||||
{
|
||||
return WideToNarrowWithCodePage(str, CP_UTF8);
|
||||
}
|
||||
|
||||
WideString UTF8ToWide(const String& str)
|
||||
{
|
||||
return NarrowToWideWithCodePage(str, CP_UTF8);
|
||||
}
|
||||
|
||||
#endif // KGE_PLATFORM_WINDOWS
|
||||
|
||||
} // namespace string
|
||||
|
|
|
|||
|
|
@ -66,6 +66,14 @@ String WideToNarrow(const WideString& str);
|
|||
/// @brief Õ×Ö·û´®×ª¿í×Ö·û´®
|
||||
WideString NarrowToWide(const String& str);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief ¿í×Ö·û´®×ª utf8 ×Ö·û´®
|
||||
String WideToUTF8(const WideString& str);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief utf8 ×Ö·û´®×ª¿í×Ö·û´®
|
||||
WideString UTF8ToWide(const String& str);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,4 +26,10 @@ KeyCharEvent::KeyCharEvent()
|
|||
{
|
||||
}
|
||||
|
||||
IMEInputEvent::IMEInputEvent()
|
||||
: KeyEvent(KGE_EVENT(IMEInputEvent))
|
||||
, value()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ KGE_DECLARE_SMART_PTR(KeyEvent);
|
|||
KGE_DECLARE_SMART_PTR(KeyDownEvent);
|
||||
KGE_DECLARE_SMART_PTR(KeyUpEvent);
|
||||
KGE_DECLARE_SMART_PTR(KeyCharEvent);
|
||||
KGE_DECLARE_SMART_PTR(IMEInputEvent);
|
||||
|
||||
/**
|
||||
* \addtogroup Event
|
||||
|
|
@ -72,13 +73,23 @@ public:
|
|||
KeyCharEvent();
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 输入法输入事件
|
||||
class KGE_API IMEInputEvent : public KeyEvent
|
||||
{
|
||||
public:
|
||||
String value; ///< 输入内容
|
||||
|
||||
IMEInputEvent();
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsSameEventType<KeyEvent>
|
||||
{
|
||||
inline bool operator()(const Event* evt) const
|
||||
{
|
||||
return evt->GetType() == KGE_EVENT(KeyDownEvent) || evt->GetType() == KGE_EVENT(KeyUpEvent)
|
||||
|| evt->GetType() == KGE_EVENT(KeyCharEvent);
|
||||
|| evt->GetType() == KGE_EVENT(KeyCharEvent) || evt->GetType() == KGE_EVENT(IMEInputEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enum class CursorType
|
|||
SizeNS, ///< 指向上下方向的箭头
|
||||
SizeNESW, ///< 指向左下到右上方向的箭头
|
||||
SizeNWSE, ///< 指向左上到右下方向的箭头
|
||||
No, ///< ½ûÖ¹
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ private:
|
|||
bool is_moving_or_resizing_;
|
||||
bool is_minimized_;
|
||||
CursorType mouse_cursor_;
|
||||
HIMC imc_;
|
||||
HIMC imc_restore_;
|
||||
int mouse_flag_;
|
||||
String device_name_;
|
||||
|
||||
Vector<Resolution> resolutions_;
|
||||
|
|
@ -173,7 +174,8 @@ WindowWin32Impl::WindowWin32Impl()
|
|||
, is_minimized_(false)
|
||||
, mouse_cursor_(CursorType::Arrow)
|
||||
, key_map_{}
|
||||
, imc_(nullptr)
|
||||
, imc_restore_(nullptr)
|
||||
, mouse_flag_{}
|
||||
{
|
||||
// Keys
|
||||
key_map_[VK_UP] = KeyCode::Up;
|
||||
|
|
@ -329,17 +331,17 @@ void WindowWin32Impl::PumpEvents()
|
|||
|
||||
void WindowWin32Impl::SetImmEnabled(bool enable)
|
||||
{
|
||||
const bool enabled = imc_ != nullptr;
|
||||
const bool enabled = imc_restore_ == nullptr;
|
||||
if (enable != enabled)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
imc_ = ::ImmAssociateContext(handle_, nullptr);
|
||||
::ImmAssociateContext(handle_, imc_restore_);
|
||||
imc_restore_ = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
::ImmAssociateContext(handle_, imc_);
|
||||
imc_ = nullptr;
|
||||
imc_restore_ = ::ImmAssociateContext(handle_, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -510,6 +512,9 @@ void WindowWin32Impl::UpdateCursor()
|
|||
case CursorType::Hand:
|
||||
win32_cursor = IDC_HAND;
|
||||
break;
|
||||
case CursorType::No:
|
||||
win32_cursor = IDC_NO;
|
||||
break;
|
||||
}
|
||||
::SetCursor(::LoadCursor(nullptr, win32_cursor));
|
||||
}
|
||||
|
|
@ -552,6 +557,38 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
|
|||
}
|
||||
break;
|
||||
|
||||
case WM_IME_CHAR:
|
||||
{
|
||||
// no need to handle
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case WM_IME_COMPOSITION:
|
||||
{
|
||||
if (lparam & GCS_RESULTSTR)
|
||||
{
|
||||
const auto hIMC = ::ImmGetContext(hwnd);
|
||||
if (hIMC)
|
||||
{
|
||||
// Get the size of the result string.
|
||||
auto dwSize = ::ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, NULL, 0);
|
||||
|
||||
// increase buffer size for terminating null character
|
||||
dwSize += sizeof(char);
|
||||
|
||||
// Get the result strings that is generated by IME.
|
||||
String buf(size_t(dwSize), 0);
|
||||
::ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, const_cast<char*>(buf.data()), dwSize);
|
||||
::ImmReleaseContext(hwnd, hIMC);
|
||||
|
||||
IMEInputEventPtr evt = new IMEInputEvent;
|
||||
evt->value = std::move(buf);
|
||||
this->PushEvent(evt);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_RBUTTONDOWN:
|
||||
|
|
@ -575,6 +612,10 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
|
|||
evt->button = MouseButton::Middle;
|
||||
}
|
||||
|
||||
if (mouse_flag_ == 0 && ::GetCapture() == nullptr)
|
||||
::SetCapture(hwnd);
|
||||
mouse_flag_ |= 1 << int(evt->button);
|
||||
|
||||
this->PushEvent(evt);
|
||||
}
|
||||
break;
|
||||
|
|
@ -599,6 +640,10 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
|
|||
evt->button = MouseButton::Middle;
|
||||
}
|
||||
|
||||
mouse_flag_ &= ~(1 << int(evt->button));
|
||||
if (mouse_flag_ == 0 && ::GetCapture() == hwnd)
|
||||
::ReleaseCapture();
|
||||
|
||||
this->PushEvent(evt);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue