UI: use the default sdl backend from dearimgui

updated dearimgui
master
Martin Gerhardy 2022-01-22 15:00:00 +01:00
parent 2e54cd4142
commit 2d147a406d
62 changed files with 766 additions and 1331 deletions

View File

@ -116,11 +116,10 @@ update-backward:
# the backend code is just copied to merge in potiential changes
update-dearimgui:
$(call UPDATE_GIT,imgui,https://github.com/ocornut/imgui.git -b docking)
cp $(UPDATEDIR)/imgui.sync/im*.h $(UPDATEDIR)/imgui.sync/im*.cpp $(UPDATEDIR)/imgui.sync/misc/cpp/* contrib/libs/dearimgui/dearimgui
cp $(UPDATEDIR)/imgui.sync/backends/imgui_impl_sdl.cpp contrib/libs/dearimgui/dearimgui
cp $(UPDATEDIR)/imgui.sync/im*.h $(UPDATEDIR)/imgui.sync/im*.cpp $(UPDATEDIR)/imgui.sync/misc/cpp/* src/modules/ui/imgui/dearimgui
cp $(UPDATEDIR)/imgui.sync/backends/imgui_impl_sdl.* src/modules/ui/imgui/dearimgui/backends
cp $(UPDATEDIR)/imgui.sync/misc/fonts/binary_to_compressed_c.cpp tools/binary_to_compressed_c
mv contrib/libs/dearimgui/dearimgui/imgui_demo.cpp src/tests/testimgui/Demo.cpp
sed -i 's/"imgui.h"/"ui\/imgui\/IMGUI.h"/g' src/tests/testimgui/Demo.cpp
mv src/modules/ui/imgui/dearimgui/imgui_demo.cpp src/tests/testimgui/Demo.cpp
update-flatbuffers:
$(call UPDATE_GIT,flatbuffers,https://github.com/google/flatbuffers.git)

View File

@ -8,5 +8,4 @@ add_subdirectory(gtest)
add_subdirectory(sdl2)
add_subdirectory(sdl2_mixer)
add_subdirectory(simplecpp)
add_subdirectory(dearimgui)
add_subdirectory(libuv)

View File

@ -1,30 +0,0 @@
set(SRCS
dearimgui/imgui.cpp dearimgui/imgui_draw.cpp
dearimgui/imgui_widgets.cpp
dearimgui/imgui_tables.cpp
dearimgui/imgui_stdlib.cpp dearimgui/imgui_stdlib.h
dearimgui/imgui.h
dearimgui/imgui_internal.h
dearimgui/imconfig.h
dearimgui/imstb_rectpack.h
dearimgui/imstb_textedit.h
dearimgui/imstb_truetype.h
)
set(LIB_NAME dearimgui)
engine_add_library(
LIB ${LIB_NAME}
SRCS ${SRCS}
)
if (APPLE)
target_link_libraries(${LIB_NAME} PRIVATE "-framework Carbon")
endif()
set(ADDITIONAL_COMPILE_FLAGS)
check_c_compiler_flag("-Wimplicit-fallthrough=0" HAS_IMPLICIT_FALLTHROUGH)
if (HAS_IMPLICIT_FALLTHROUGH)
set(ADDITIONAL_COMPILE_FLAGS "${ADDITIONAL_COMPILE_FLAGS} -Wimplicit-fallthrough=0")
endif()
set_target_properties(${LIB_NAME} PROPERTIES COMPILE_FLAGS "${ADDITIONAL_COMPILE_FLAGS}")
target_include_directories(dearimgui PRIVATE dearimgui)

View File

@ -3,7 +3,6 @@
*/
#include "TestApp.h"
#include "ui/imgui/IMGUI.h"
#include "core/Color.h"
#include "command/Command.h"
#include "video/ScopedPolygonMode.h"

View File

@ -5,7 +5,6 @@
#pragma once
#include "ui/imgui/IMGUIApp.h"
#include "ui/imgui/IMGUI.h"
#include "video/Camera.h"
#include "render/Axis.h"
#include "render/Plane.h"

View File

@ -5,15 +5,27 @@ set(SRCS
FileDialog.cpp FileDialog.h
IconsFontAwesome5.h
IconsForkAwesome.h
IMGUI.cpp IMGUI.h
IMGUIEx.cpp IMGUIEx.h
IMGUIApp.cpp IMGUIApp.h
IMGUIInternal.h
IMGUIStyle.cpp IMGUIStyle.h
Notify.cpp Notify.h
ScopedStyle.h
TextEditor.h TextEditor.cpp
Window.h Window.cpp
WindowStack.h WindowStack.cpp
dearimgui/imgui.cpp dearimgui/imgui_draw.cpp
dearimgui/imgui_widgets.cpp
dearimgui/imgui_tables.cpp
dearimgui/imgui_stdlib.cpp dearimgui/imgui_stdlib.h
dearimgui/imgui.h
dearimgui/imgui_internal.h
dearimgui/imconfig.h
dearimgui/imstb_rectpack.h
dearimgui/imstb_textedit.h
dearimgui/imstb_truetype.h
dearimgui/backends/imgui_impl_sdl.cpp dearimgui/backends/imgui_impl_sdl.h
)
set(GEN_DIR ${GENERATE_DIR}/${LIB})
@ -41,5 +53,5 @@ imgui_build_font(FontAwesomeSolid fa-solid-900.ttf)
imgui_build_font(ForkAwesomeWebFont forkawesome-webfont.ttf)
imgui_build_font(ArimoRegular Arimo-Regular.ttf)
engine_add_module(TARGET ${LIB} SRCS ${SRCS} DEPENDENCIES render app dearimgui audio)
target_include_directories(${LIB} PUBLIC . ${GEN_DIR})
engine_add_module(TARGET ${LIB} SRCS ${SRCS} DEPENDENCIES render app audio)
target_include_directories(${LIB} PUBLIC . ${GEN_DIR} dearimgui)

View File

@ -1,6 +1,10 @@
/**
* @file
*/
#include "Console.h"
#include "IMGUI.h"
#include "IMGUIApp.h"
#include "dearimgui/imgui_internal.h"
#include "core/Color.h"
namespace ui {

View File

@ -5,7 +5,7 @@
#pragma once
#include "util/Console.h"
#include "IMGUI.h"
#include "IMGUIEx.h"
#include "Notify.h"
namespace ui {

View File

@ -3,7 +3,6 @@
*/
#include "FileDialog.h"
#include "IMGUI.h"
#include "IconsFontAwesome5.h"
#include "IconsForkAwesome.h"
#include "app/App.h"
@ -18,6 +17,7 @@
#include "io/Filesystem.h"
#include "io/FormatDescription.h"
#include "ui/imgui/IMGUIApp.h"
#include "dearimgui/imgui_internal.h"
namespace ui {
namespace imgui {
@ -134,7 +134,7 @@ void FileDialog::removeBookmark(const core::String &bookmark) {
}
void FileDialog::bookmarkPanel(video::WindowedApp::OpenFileMode type, const core::String &bookmarks) {
ImGui::BeginChild("Bookmarks##filedialog", ImVec2(ImGui::Size(200), ImGui::Size(300)), true,
ImGui::BeginChild("Bookmarks##filedialog", ImVec2(200, 300), true,
ImGuiWindowFlags_HorizontalScrollbar);
bool specialDirs = false;
const float contentRegionWidth = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x;
@ -196,7 +196,7 @@ void FileDialog::setCurrentPath(video::WindowedApp::OpenFileMode type, const cor
}
void FileDialog::directoryPanel(video::WindowedApp::OpenFileMode type) {
ImGui::BeginChild("Directories##filedialog", ImVec2(ImGui::Size(200), ImGui::Size(300)), true,
ImGui::BeginChild("Directories##filedialog", ImVec2(200, 300), true,
ImGuiWindowFlags_HorizontalScrollbar);
const float contentRegionWidth = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x;
@ -235,20 +235,20 @@ bool FileDialog::hide(const core::String &file) const {
}
bool FileDialog::filesPanel() {
ImGui::BeginChild("Files##1", ImVec2(ImGui::GetContentRegionAvail().x, ImGui::Size(300)), true,
ImGui::BeginChild("Files##1", ImVec2(ImGui::GetContentRegionAvail().x, 300), true,
ImGuiWindowFlags_HorizontalScrollbar);
ImGui::Columns(4);
static float initialSpacingColumn3 = ImGui::Size(120.0f);
static float initialSpacingColumn3 = 120.0f;
if (initialSpacingColumn3 > 0) {
ImGui::SetColumnWidth(3, initialSpacingColumn3);
initialSpacingColumn3 = 0.0f;
}
static float initialSpacingColumn1 = ImGui::Size(80.0f);
static float initialSpacingColumn1 = 80.0f;
if (initialSpacingColumn1 > 0) {
ImGui::SetColumnWidth(1, initialSpacingColumn1);
initialSpacingColumn1 = 0.0f;
}
static float initialSpacingColumn2 = ImGui::Size(80.0f);
static float initialSpacingColumn2 = 80.0f;
if (initialSpacingColumn2 > 0) {
ImGui::SetColumnWidth(2, initialSpacingColumn2);
initialSpacingColumn2 = 0.0f;
@ -366,7 +366,7 @@ bool FileDialog::showFileDialog(bool *open, char *buffer, unsigned int bufferSiz
if (open == nullptr || *open) {
bool doubleClickedFile = false;
core_trace_scoped(FileDialog);
ImGui::SetNextWindowSize(ImVec2(ImGui::Size(740.0f), ImGui::Size(494.0f)), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(740.0f, 494.0f), ImGuiCond_FirstUseEver);
const char *title;
switch (type) {
case video::WindowedApp::OpenFileMode::Directory:
@ -417,7 +417,7 @@ bool FileDialog::showFileDialog(bool *open, char *buffer, unsigned int bufferSiz
if (type == video::WindowedApp::OpenFileMode::Save) {
ImGui::InputText("Filename", &_currentFile);
}
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::Size(6));
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 6);
if (ImGui::Button("New folder")) {
ImGui::OpenPopup("NewFolderPopup");
@ -487,7 +487,7 @@ bool FileDialog::showFileDialog(bool *open, char *buffer, unsigned int bufferSiz
}
if (!_filterEntries.empty()) {
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - _filterTextWidth - ImGui::Size(25.0f));
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - _filterTextWidth - 25.0f);
if (ImGui::ComboStl("Filter", &_currentFilterEntry, _filterEntries)) {
selectFilter(_currentFilterEntry);
}
@ -502,7 +502,7 @@ bool FileDialog::showFileDialog(bool *open, char *buffer, unsigned int bufferSiz
const ImVec2 cancelTextSize = ImGui::CalcTextSize("Cancel");
const ImVec2 chooseTextSize = ImGui::CalcTextSize(buttonText);
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - cancelTextSize.x - chooseTextSize.x - ImGui::Size(40.0f));
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - cancelTextSize.x - chooseTextSize.x - 40.0f);
if (ImGui::Button("Cancel") || ImGui::IsKeyDown(ImGuiKey_Escape)) {
_fileSelectIndex = 0;
_folderSelectIndex = 0;

View File

@ -4,6 +4,7 @@
#include "IMGUIApp.h"
#include "dearimgui/backends/imgui_impl_sdl.h"
#include "io/Filesystem.h"
#include "command/Command.h"
#include "core/Var.h"
@ -20,7 +21,7 @@
#include "video/TextureConfig.h"
#include "video/Types.h"
#include "IMGUI.h"
#include "IMGUIEx.h"
#include "FontAwesomeSolid.h"
#include "ForkAwesomeWebFont.h"
#include "ArimoRegular.h"
@ -43,23 +44,6 @@ IMGUIApp::IMGUIApp(const metric::MetricPtr& metric, const io::FilesystemPtr& fil
IMGUIApp::~IMGUIApp() {
}
bool IMGUIApp::onMouseWheel(int32_t x, int32_t y) {
if (_console.onMouseWheel(x, y)) {
return true;
}
if (y > 0) {
_mouseWheelY += 1;
} else if (y < 0) {
_mouseWheelY -= 1;
}
if (x > 0) {
_mouseWheelX += 1;
} else if (x < 0) {
_mouseWheelX -= 1;
}
return Super::onMouseWheel(x, y);
}
void IMGUIApp::onMouseButtonRelease(int32_t x, int32_t y, uint8_t button) {
if (_console.isActive()) {
return;
@ -71,13 +55,6 @@ void IMGUIApp::onMouseButtonPress(int32_t x, int32_t y, uint8_t button, uint8_t
if (_console.onMouseButtonPress(x, y, button)) {
return;
}
if (button == SDL_BUTTON_LEFT) {
_mousePressed[0] = true;
} else if (button == SDL_BUTTON_RIGHT) {
_mousePressed[1] = true;
} else if (button == SDL_BUTTON_MIDDLE) {
_mousePressed[2] = true;
}
Super::onMouseButtonPress(x, y, button, clicks);
}
@ -85,227 +62,9 @@ bool IMGUIApp::onTextInput(const core::String& text) {
if (_console.onTextInput(text)) {
return true;
}
ImGuiIO& io = ImGui::GetIO();
io.AddInputCharactersUTF8(text.c_str());
return true;
}
static ImGuiKey mapToImGuiKey(int32_t keycode) {
switch (keycode) {
case SDLK_TAB:
return ImGuiKey_Tab;
case SDLK_LEFT:
return ImGuiKey_LeftArrow;
case SDLK_RIGHT:
return ImGuiKey_RightArrow;
case SDLK_UP:
return ImGuiKey_UpArrow;
case SDLK_DOWN:
return ImGuiKey_DownArrow;
case SDLK_PAGEUP:
return ImGuiKey_PageUp;
case SDLK_PAGEDOWN:
return ImGuiKey_PageDown;
case SDLK_HOME:
return ImGuiKey_Home;
case SDLK_END:
return ImGuiKey_End;
case SDLK_INSERT:
return ImGuiKey_Insert;
case SDLK_DELETE:
return ImGuiKey_Delete;
case SDLK_BACKSPACE:
return ImGuiKey_Backspace;
case SDLK_SPACE:
return ImGuiKey_Space;
case SDLK_RETURN:
return ImGuiKey_Enter;
case SDLK_ESCAPE:
return ImGuiKey_Escape;
case SDLK_QUOTE:
return ImGuiKey_Apostrophe;
case SDLK_COMMA:
return ImGuiKey_Comma;
case SDLK_MINUS:
return ImGuiKey_Minus;
case SDLK_PERIOD:
return ImGuiKey_Period;
case SDLK_SLASH:
return ImGuiKey_Slash;
case SDLK_SEMICOLON:
return ImGuiKey_Semicolon;
case SDLK_EQUALS:
return ImGuiKey_Equal;
case SDLK_LEFTBRACKET:
return ImGuiKey_LeftBracket;
case SDLK_BACKSLASH:
return ImGuiKey_Backslash;
case SDLK_RIGHTBRACKET:
return ImGuiKey_RightBracket;
case SDLK_BACKQUOTE:
return ImGuiKey_GraveAccent;
case SDLK_CAPSLOCK:
return ImGuiKey_CapsLock;
case SDLK_SCROLLLOCK:
return ImGuiKey_ScrollLock;
case SDLK_NUMLOCKCLEAR:
return ImGuiKey_NumLock;
case SDLK_PRINTSCREEN:
return ImGuiKey_PrintScreen;
case SDLK_PAUSE:
return ImGuiKey_Pause;
case SDLK_KP_0:
return ImGuiKey_Keypad0;
case SDLK_KP_1:
return ImGuiKey_Keypad1;
case SDLK_KP_2:
return ImGuiKey_Keypad2;
case SDLK_KP_3:
return ImGuiKey_Keypad3;
case SDLK_KP_4:
return ImGuiKey_Keypad4;
case SDLK_KP_5:
return ImGuiKey_Keypad5;
case SDLK_KP_6:
return ImGuiKey_Keypad6;
case SDLK_KP_7:
return ImGuiKey_Keypad7;
case SDLK_KP_8:
return ImGuiKey_Keypad8;
case SDLK_KP_9:
return ImGuiKey_Keypad9;
case SDLK_KP_PERIOD:
return ImGuiKey_KeypadDecimal;
case SDLK_KP_DIVIDE:
return ImGuiKey_KeypadDivide;
case SDLK_KP_MULTIPLY:
return ImGuiKey_KeypadMultiply;
case SDLK_KP_MINUS:
return ImGuiKey_KeypadSubtract;
case SDLK_KP_PLUS:
return ImGuiKey_KeypadAdd;
case SDLK_KP_ENTER:
return ImGuiKey_KeypadEnter;
case SDLK_KP_EQUALS:
return ImGuiKey_KeypadEqual;
case SDLK_LSHIFT:
return ImGuiKey_LeftShift;
case SDLK_LCTRL:
return ImGuiKey_LeftControl;
case SDLK_LALT:
return ImGuiKey_LeftAlt;
case SDLK_LGUI:
return ImGuiKey_LeftSuper;
case SDLK_RSHIFT:
return ImGuiKey_RightShift;
case SDLK_RCTRL:
return ImGuiKey_RightControl;
case SDLK_RALT:
return ImGuiKey_RightAlt;
case SDLK_RGUI:
return ImGuiKey_RightSuper;
case SDLK_MENU:
return ImGuiKey_Menu;
case SDLK_0:
return ImGuiKey_0;
case SDLK_1:
return ImGuiKey_1;
case SDLK_2:
return ImGuiKey_2;
case SDLK_3:
return ImGuiKey_3;
case SDLK_4:
return ImGuiKey_4;
case SDLK_5:
return ImGuiKey_5;
case SDLK_6:
return ImGuiKey_6;
case SDLK_7:
return ImGuiKey_7;
case SDLK_8:
return ImGuiKey_8;
case SDLK_9:
return ImGuiKey_9;
case SDLK_a:
return ImGuiKey_A;
case SDLK_b:
return ImGuiKey_B;
case SDLK_c:
return ImGuiKey_C;
case SDLK_d:
return ImGuiKey_D;
case SDLK_e:
return ImGuiKey_E;
case SDLK_f:
return ImGuiKey_F;
case SDLK_g:
return ImGuiKey_G;
case SDLK_h:
return ImGuiKey_H;
case SDLK_i:
return ImGuiKey_I;
case SDLK_j:
return ImGuiKey_J;
case SDLK_k:
return ImGuiKey_K;
case SDLK_l:
return ImGuiKey_L;
case SDLK_m:
return ImGuiKey_M;
case SDLK_n:
return ImGuiKey_N;
case SDLK_o:
return ImGuiKey_O;
case SDLK_p:
return ImGuiKey_P;
case SDLK_q:
return ImGuiKey_Q;
case SDLK_r:
return ImGuiKey_R;
case SDLK_s:
return ImGuiKey_S;
case SDLK_t:
return ImGuiKey_T;
case SDLK_u:
return ImGuiKey_U;
case SDLK_v:
return ImGuiKey_V;
case SDLK_w:
return ImGuiKey_W;
case SDLK_x:
return ImGuiKey_X;
case SDLK_y:
return ImGuiKey_Y;
case SDLK_z:
return ImGuiKey_Z;
case SDLK_F1:
return ImGuiKey_F1;
case SDLK_F2:
return ImGuiKey_F2;
case SDLK_F3:
return ImGuiKey_F3;
case SDLK_F4:
return ImGuiKey_F4;
case SDLK_F5:
return ImGuiKey_F5;
case SDLK_F6:
return ImGuiKey_F6;
case SDLK_F7:
return ImGuiKey_F7;
case SDLK_F8:
return ImGuiKey_F8;
case SDLK_F9:
return ImGuiKey_F9;
case SDLK_F10:
return ImGuiKey_F10;
case SDLK_F11:
return ImGuiKey_F11;
case SDLK_F12:
return ImGuiKey_F12;
}
return ImGuiKey_None;
}
bool IMGUIApp::onKeyPress(int32_t key, int16_t modifier) {
if (_console.onKeyPress(key, modifier)) {
return true;
@ -313,22 +72,6 @@ bool IMGUIApp::onKeyPress(int32_t key, int16_t modifier) {
if (Super::onKeyPress(key, modifier)) {
return true;
}
ImGuiIO& io = ImGui::GetIO();
key &= ~SDLK_SCANCODE_MASK;
const ImGuiKey mappedKey = mapToImGuiKey(key);
if (mappedKey == ImGuiKey_COUNT) {
return false;
}
io.AddKeyEvent(mappedKey, true);
const int16_t modifiers = SDL_GetModState();
io.KeyShift = (modifiers & KMOD_SHIFT) != 0;
io.KeyCtrl = (modifiers & KMOD_CTRL) != 0;
io.KeyAlt = (modifiers & KMOD_ALT) != 0;
#ifdef _WIN32
io.KeySuper = false;
#else
io.KeySuper = (modifier & KMOD_GUI) != 0;
#endif
return false;
}
@ -336,64 +79,13 @@ bool IMGUIApp::onKeyRelease(int32_t key, int16_t modifier) {
if (_console.isActive()) {
return true;
}
if (Super::onKeyRelease(key, modifier)) {
return true;
}
ImGuiIO& io = ImGui::GetIO();
key &= ~SDLK_SCANCODE_MASK;
const ImGuiKey mappedKey = mapToImGuiKey(key);
if (mappedKey == ImGuiKey_COUNT) {
return false;
}
io.AddKeyEvent(mappedKey, false);
io.KeyShift = (modifier & KMOD_SHIFT) != 0;
io.KeyCtrl = (modifier & KMOD_CTRL) != 0;
io.KeyAlt = (modifier & KMOD_ALT) != 0;
#ifdef _WIN32
io.KeySuper = false;
#else
io.KeySuper = (modifier & KMOD_GUI) != 0;
#endif
Super::onKeyRelease(key, modifier);
return true;
}
void IMGUIApp::onWindowClose(void *windowHandle) {
Super::onWindowClose(windowHandle);
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(windowHandle)) {
viewport->PlatformRequestClose = true;
}
}
void IMGUIApp::onWindowMoved(void *windowHandle) {
Super::onWindowMoved(windowHandle);
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(windowHandle)) {
viewport->PlatformRequestMove = true;
}
}
void IMGUIApp::onWindowFocusGained(void *windowHandle) {
Super::onWindowFocusGained(windowHandle);
ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(windowHandle);
if (viewport != nullptr) {
ImGuiIO& io = ImGui::GetIO();
io.AddFocusEvent(true);
}
}
void IMGUIApp::onWindowFocusLost(void *windowHandle) {
Super::onWindowFocusLost(windowHandle);
ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(windowHandle);
if (viewport != nullptr) {
ImGuiIO& io = ImGui::GetIO();
io.AddFocusEvent(false);
}
}
void IMGUIApp::onWindowResize(void *windowHandle, int windowWidth, int windowHeight) {
Super::onWindowResize(windowHandle, windowWidth, windowHeight);
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(windowHandle)) {
viewport->PlatformRequestResize = true;
}
bool IMGUIApp::handleSDLEvent(SDL_Event& event) {
ImGui_ImplSDL2_ProcessEvent(&event);
return Super::handleSDLEvent(event);
}
app::AppState IMGUIApp::onConstruct() {
@ -412,32 +104,6 @@ app::AppState IMGUIApp::onConstruct() {
return state;
}
static const char* _getClipboardText(void*) {
const char* text = SDL_GetClipboardText();
if (!text) {
return nullptr;
}
const int len = (int)SDL_strlen(text);
if (len == 0) {
SDL_free((void*) text);
return "";
}
static ImVector<char> clipboardBuffer;
// Optional branch to keep clipboardBuffer.capacity() low:
if (len <= clipboardBuffer.capacity() && clipboardBuffer.capacity() > 512) {
ImVector<char> emptyBuffer;
clipboardBuffer.swap(emptyBuffer);
}
clipboardBuffer.resize(len + 1);
SDL_strlcpy(&clipboardBuffer[0], text, clipboardBuffer.size());
SDL_free((void*) text);
return (const char*) &clipboardBuffer[0];
}
static void _setClipboardText(void*, const char* text) {
SDL_SetClipboardText(text);
}
void IMGUIApp::loadFonts() {
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear();
@ -481,19 +147,6 @@ void IMGUIApp::loadFonts() {
io.Fonts->TexID = (ImTextureID)(intptr_t)_texture;
}
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend
// data.
struct _imguiViewportData {
SDL_Window *window = nullptr;
uint32_t windowID = 0;
bool windowOwned = false;
void* renderContext = nullptr;
~_imguiViewportData() {
core_assert(window == nullptr && renderContext == nullptr);
}
};
static void* _imguiAlloc(size_t size, void*) {
return core_malloc(size);
}
@ -502,275 +155,6 @@ static void _imguiFree(void *mem, void*) {
core_free(mem);
}
static IMGUIApp *_imguiGetBackendUserdata() {
return ImGui::GetCurrentContext() ? (IMGUIApp *)ImGui::GetIO().BackendPlatformUserData : nullptr;
}
static void _imguiCreateWindow(ImGuiViewport *viewport) {
IMGUIApp *bd = _imguiGetBackendUserdata();
core_assert(bd != nullptr);
_imguiViewportData *vd = IM_NEW(_imguiViewportData)();
viewport->PlatformUserData = vd;
ImGuiViewport *main_viewport = ImGui::GetMainViewport();
_imguiViewportData *main_viewport_data = (_imguiViewportData *)main_viewport->PlatformUserData;
core_assert(main_viewport_data != nullptr);
// Share GL resources with main context
bool use_opengl = (main_viewport_data->renderContext != nullptr);
core_assert(use_opengl);
SDL_GLContext backup_context = NULL;
if (use_opengl) {
backup_context = SDL_GL_GetCurrentContext();
if (SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1) != 0) {
Log::error("%s", SDL_GetError());
}
if (SDL_GL_MakeCurrent(main_viewport_data->window, main_viewport_data->renderContext) != 0) {
Log::error("%s", SDL_GetError());
}
}
Uint32 sdl_flags = 0;
sdl_flags |= use_opengl ? SDL_WINDOW_OPENGL : 0;
SDL_Window *window = (SDL_Window*)bd->windowHandle();
sdl_flags |= SDL_GetWindowFlags(window) & SDL_WINDOW_ALLOW_HIGHDPI;
sdl_flags |= SDL_WINDOW_HIDDEN;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE;
#if !defined(_WIN32)
// See SDL hack in ImGui_ImplSDL2_ShowWindow().
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) ? SDL_WINDOW_SKIP_TASKBAR : 0;
#endif
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0;
vd->window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x,
(int)viewport->Size.y, sdl_flags);
vd->windowOwned = true;
if (use_opengl) {
vd->renderContext = SDL_GL_CreateContext(vd->window);
if (SDL_GL_SetSwapInterval(0) != 0) {
Log::error("%s", SDL_GetError());
}
}
if (use_opengl && backup_context) {
if (SDL_GL_MakeCurrent(vd->window, backup_context) != 0) {
Log::error("%s", SDL_GetError());
}
}
viewport->PlatformHandle = (void *)vd->window;
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(vd->window, &info))
viewport->PlatformHandleRaw = info.info.win.window;
#endif
}
static void _imguiDestroyWindow(ImGuiViewport *viewport) {
if (_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData) {
if (vd->renderContext && vd->windowOwned)
SDL_GL_DeleteContext(vd->renderContext);
if (vd->window && vd->windowOwned)
SDL_DestroyWindow(vd->window);
vd->renderContext = NULL;
vd->window = NULL;
IM_DELETE(vd);
}
viewport->PlatformUserData = viewport->PlatformHandle = NULL;
}
static void _imguiShowWindow(ImGuiViewport *viewport) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
#if defined(_WIN32)
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
// SDL hack: Hide icon from task bar
// Note: SDL 2.0.6+ has a SDL_WINDOW_SKIP_TASKBAR flag which is supported under Windows but the way it create the
// window breaks our seamless transition.
if (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) {
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
ex_style &= ~WS_EX_APPWINDOW;
ex_style |= WS_EX_TOOLWINDOW;
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
}
// SDL hack: SDL always activate/focus windows :/
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing) {
::ShowWindow(hwnd, SW_SHOWNA);
return;
}
#endif
SDL_ShowWindow(vd->window);
}
static ImVec2 _imguiGetWindowPos(ImGuiViewport *viewport) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
int x = 0, y = 0;
SDL_GetWindowPosition(vd->window, &x, &y);
return ImVec2((float)x, (float)y);
}
static void _imguiSetWindowPos(ImGuiViewport *viewport, ImVec2 pos) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
SDL_SetWindowPosition(vd->window, (int)pos.x, (int)pos.y);
}
static ImVec2 _imguiGetWindowSize(ImGuiViewport *viewport) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
int w = 0, h = 0;
SDL_GetWindowSize(vd->window, &w, &h);
return ImVec2((float)w, (float)h);
}
static void _imguiSetWindowSize(ImGuiViewport *viewport, ImVec2 size) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
SDL_SetWindowSize(vd->window, (int)size.x, (int)size.y);
}
static void _imguiSetWindowTitle(ImGuiViewport *viewport, const char *title) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
SDL_SetWindowTitle(vd->window, title);
}
static void _imguiSetWindowAlpha(ImGuiViewport *viewport, float alpha) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
SDL_SetWindowOpacity(vd->window, alpha);
}
static void _imguiSetWindowFocus(ImGuiViewport *viewport) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
SDL_RaiseWindow(vd->window);
}
static bool _imguiGetWindowFocus(ImGuiViewport *viewport) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
return (SDL_GetWindowFlags(vd->window) & SDL_WINDOW_INPUT_FOCUS) != 0;
}
static bool _imguiGetWindowMinimized(ImGuiViewport *viewport) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
return (SDL_GetWindowFlags(vd->window) & SDL_WINDOW_MINIMIZED) != 0;
}
static void _imguiRenderWindow(ImGuiViewport *viewport, void *) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
if (vd->renderContext) {
SDL_GL_MakeCurrent(vd->window, vd->renderContext);
}
}
static void _imguiSwapBuffers(ImGuiViewport *viewport, void *) {
_imguiViewportData *vd = (_imguiViewportData *)viewport->PlatformUserData;
if (vd->renderContext) {
SDL_GL_MakeCurrent(vd->window, vd->renderContext);
SDL_GL_SwapWindow(vd->window);
}
}
static void initPlatformInterface(const char *name, IMGUIApp *userdata, SDL_Window* window, video::RendererContext rendererContext) {
ImGuiIO& io = ImGui::GetIO();
io.BackendPlatformUserData = userdata;
io.BackendPlatformName = name;
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
if (!userdata->isSingleWindowMode()) {
// io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports;
}
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
ImGuiPlatformIO &platformIO = ImGui::GetPlatformIO();
platformIO.Platform_CreateWindow = _imguiCreateWindow;
platformIO.Platform_DestroyWindow = _imguiDestroyWindow;
platformIO.Platform_ShowWindow = _imguiShowWindow;
platformIO.Platform_SetWindowPos = _imguiSetWindowPos;
platformIO.Platform_GetWindowPos = _imguiGetWindowPos;
platformIO.Platform_SetWindowSize = _imguiSetWindowSize;
platformIO.Platform_GetWindowSize = _imguiGetWindowSize;
platformIO.Platform_SetWindowFocus = _imguiSetWindowFocus;
platformIO.Platform_GetWindowFocus = _imguiGetWindowFocus;
platformIO.Platform_GetWindowMinimized = _imguiGetWindowMinimized;
platformIO.Platform_SetWindowTitle = _imguiSetWindowTitle;
platformIO.Platform_SetWindowAlpha = _imguiSetWindowAlpha;
platformIO.Platform_RenderWindow = _imguiRenderWindow;
platformIO.Platform_SwapBuffers = _imguiSwapBuffers;
// Register main window handle (which is owned by the main application, not by us)
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
_imguiViewportData *vd = IM_NEW(_imguiViewportData)();
vd->window = window;
vd->windowID = SDL_GetWindowID(window);
if (vd->windowID == 0) {
Log::error("%s", SDL_GetError());
}
vd->windowOwned = false;
vd->renderContext = rendererContext;
ImGuiViewport *mainViewport = ImGui::GetMainViewport();
mainViewport->PlatformUserData = vd;
mainViewport->PlatformHandle = vd->window;
}
static void updateMonitors() {
ImGuiPlatformIO &platformIO = ImGui::GetPlatformIO();
platformIO.Monitors.resize(0);
int displayCount = SDL_GetNumVideoDisplays();
if (displayCount < 0) {
Log::error("%s", SDL_GetError());
}
const core::VarPtr& highDPI = core::Var::getSafe(cfg::ClientWindowHighDPI);
for (int n = 0; n < displayCount; n++) {
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness
// settings, which generally needs to be set in the manifest or at runtime.
ImGuiPlatformMonitor monitor;
SDL_Rect r;
if (SDL_GetDisplayBounds(n, &r) == 0) {
monitor.MainPos = monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
monitor.MainSize = monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
} else {
Log::error("%s", SDL_GetError());
}
if (SDL_GetDisplayUsableBounds(n, &r) == 0) {
monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
} else {
Log::error("%s", SDL_GetError());
}
if (highDPI->boolVal()) {
float dpi = 0.0f;
if (SDL_GetDisplayDPI(n, &dpi, nullptr, nullptr) == 0) {
monitor.DpiScale = dpi / 96.0f;
} else {
Log::error("%s", SDL_GetError());
}
}
platformIO.Monitors.push_back(monitor);
}
}
#if 0
static void _rendererRenderWindow(ImGuiViewport *viewport, void *renderArg) {
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) {
const glm::vec4 clearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
video::clearColor(clearColor);
video::clear(video::ClearFlag::Color);
}
ImGuiIO& io = ImGui::GetIO();
IMGUIApp* app = (IMGUIApp*)io.BackendRendererUserData;
app->executeDrawCommands(viewport->DrawData);
}
#endif
static void initRendererBackend(const char *name, IMGUIApp *userdata) {
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererUserData = userdata;
io.BackendRendererName = name;
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
#if 0
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_RenderWindow = _rendererRenderWindow;
#endif
}
app::AppState IMGUIApp::onInit() {
const app::AppState state = Super::onInit();
video::checkError();
@ -806,12 +190,14 @@ app::AppState IMGUIApp::onInit() {
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
if (!isSingleWindowMode()) {
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
// io.ConfigViewportsNoAutoMerge = true;
// io.ConfigViewportsNoTaskBarIcon = true;
}
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports;
io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts;
// io.ConfigViewportsNoAutoMerge = true;
// io.ConfigViewportsNoTaskBarIcon = true;
if (_persistUISettings) {
const core::String iniFile = _appname + "-imgui.ini";
@ -831,42 +217,9 @@ app::AppState IMGUIApp::onInit() {
ImGui::StyleColorsCorporateGrey();
//ImGui::StyleColorsDark();
io.SetClipboardTextFn = _setClipboardText;
io.GetClipboardTextFn = _getClipboardText;
io.ClipboardUserData = nullptr;
ImGui_ImplSDL2_InitForOpenGL(_window, _rendererContext);
_mouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
_mouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
_mouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
_mouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
_mouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
_mouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
_mouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
_mouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
_mouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
ImGuiViewport *mainViewport = ImGui::GetMainViewport();
mainViewport->PlatformHandle = (void *)_window;
#ifdef _WIN32
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(_window, &info)) {
mainViewport->PlatformHandleRaw = info.info.win.window;
}
#endif
// Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
// you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
updateMonitors();
initPlatformInterface(_appname.c_str(), this, _window, _rendererContext);
initRendererBackend(_appname.c_str(), this);
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float);
SDL_StartTextInput();
_console.init();
@ -876,94 +229,6 @@ app::AppState IMGUIApp::onInit() {
}
void IMGUIApp::beforeUI() {
ImGuiIO &io = ImGui::GetIO();
io.DeltaTime = (float)_deltaFrameSeconds;
// Setup display size (every frame to accommodate for window resizing)
int w, h;
int display_w, display_h;
SDL_GetWindowSize(_window, &w, &h);
if (SDL_GetWindowFlags(_window) & SDL_WINDOW_MINIMIZED) {
w = h = 0;
}
SDL_GL_GetDrawableSize(_window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0) {
io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);
}
ImVec2 mousePosPrev = io.MousePos;
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
io.MouseHoveredViewport = 0;
io.MouseWheel = (float)_mouseWheelY;
io.MouseWheelH = (float)_mouseWheelX;
_mouseWheelX = _mouseWheelY = 0;
// Update mouse buttons
int mouseXLocal, mouseYLocal;
Uint32 mouseButtons = SDL_GetMouseState(&mouseXLocal, &mouseYLocal);
// If a mouse press event came, always pass it as "mouse held this frame", so we
// don't miss click-release events that are shorter than 1 frame.
io.MouseDown[0] = _mousePressed[0] || (mouseButtons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;
io.MouseDown[1] = _mousePressed[1] || (mouseButtons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MouseDown[2] = _mousePressed[2] || (mouseButtons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
_mousePressed[0] = _mousePressed[1] = _mousePressed[2] = false;
SDL_Window *mouseWindow = nullptr;
if (isSingleWindowMode() || (io.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) == 0) {
mouseWindow = (SDL_GetWindowFlags(_window) & SDL_WINDOW_INPUT_FOCUS) ? _window : nullptr;
} else {
// Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window
// is capturing)
SDL_Window *focusedWindow = SDL_GetKeyboardFocus();
SDL_Window *hoveredWindow = SDL_GetMouseFocus();
if (hoveredWindow && (_window == hoveredWindow || ImGui::FindViewportByPlatformHandle((void *)hoveredWindow))) {
mouseWindow = hoveredWindow;
} else if (focusedWindow &&
(_window == focusedWindow || ImGui::FindViewportByPlatformHandle((void *)focusedWindow))) {
mouseWindow = focusedWindow;
}
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g.
// trigger other operations outside
SDL_CaptureMouse(ImGui::IsAnyMouseDown() ? SDL_TRUE : SDL_FALSE);
}
if (mouseWindow == nullptr) {
return;
}
// Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos
// is enabled by user)
if (io.WantSetMousePos) {
if (!isSingleWindowMode() && (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != 0) {
SDL_WarpMouseGlobal((int)mousePosPrev.x, (int)mousePosPrev.y);
} else {
SDL_WarpMouseInWindow(_window, (int)mousePosPrev.x, (int)mousePosPrev.y);
}
}
if (_mouseCanUseGlobalState) {
// Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior)
int mouseXGlobal = 0, mouseYGlobal = 0;
SDL_GetGlobalMouseState(&mouseXGlobal, &mouseYGlobal);
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on
// the upper-left of the primary monitor)
io.MousePos = ImVec2((float)mouseXGlobal, (float)mouseYGlobal);
} else {
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is
// on the upper-left corner of the app window) Unlike local position obtained earlier this will be valid
// when straying out of bounds.
int windowX = 0, windowY = 0;
SDL_GetWindowPosition(mouseWindow, &windowX, &windowY);
io.MousePos = ImVec2((float)(mouseXGlobal - windowX), (float)(mouseYGlobal - windowY));
}
} else {
io.MousePos = ImVec2((float)mouseXLocal, (float)mouseYLocal);
}
}
app::AppState IMGUIApp::onRunning() {
@ -990,19 +255,7 @@ app::AppState IMGUIApp::onRunning() {
beforeUI();
}
ImGuiIO &io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) {
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) {
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
SDL_ShowCursor(SDL_FALSE);
} else {
// Show OS mouse cursor
SDL_SetCursor(_mouseCursors[imgui_cursor] ? _mouseCursors[imgui_cursor]
: _mouseCursors[ImGuiMouseCursor_Arrow]);
SDL_ShowCursor(SDL_TRUE);
}
}
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
const bool renderUI = _renderUI->boolVal();
@ -1173,10 +426,7 @@ void IMGUIApp::executeDrawCommands(ImDrawData* drawData) {
}
app::AppState IMGUIApp::onCleanup() {
for (int i = 0; i < ImGuiMouseCursor_COUNT; ++i) {
SDL_FreeCursor(_mouseCursors[i]);
}
ImGui_ImplSDL2_Shutdown();
if (ImGui::GetCurrentContext() != nullptr) {
ImGui::DestroyPlatformWindows();
ImGui::DestroyContext();

View File

@ -34,9 +34,6 @@ protected:
Console _console;
int32_t _bufferIndex = -1;
int32_t _indexBufferIndex = -1;
int8_t _mouseWheelX = 0;
int8_t _mouseWheelY = 0;
bool _mousePressed[3] = {false};
core::String _writePathIni;
core::String _writePathLog;
core::VarPtr _lastDirectory;
@ -45,7 +42,6 @@ protected:
bool _showFileDialog = false;
bool _persistUISettings = true;
SDL_Cursor* _mouseCursors[ImGuiMouseCursor_COUNT];
OpenFileMode _fileDialogMode = OpenFileMode::Directory;
std::function<void(const core::String&)> _fileDialogCallback {};
@ -58,7 +54,6 @@ protected:
virtual bool onKeyRelease(int32_t key, int16_t modifier) override;
virtual bool onKeyPress(int32_t key, int16_t modifier) override;
virtual bool onTextInput(const core::String& text) override;
virtual bool onMouseWheel(int32_t x, int32_t y) override;
virtual void onMouseButtonRelease(int32_t x, int32_t y, uint8_t button) override;
virtual void onMouseButtonPress(int32_t x, int32_t y, uint8_t button, uint8_t clicks) override;
public:
@ -68,12 +63,9 @@ public:
virtual void beforeUI();
bool handleSDLEvent(SDL_Event& event) override;
int fontSize() const;
virtual void onWindowClose(void *windowHandle) override;
virtual void onWindowMoved(void *windowHandle) override;
virtual void onWindowFocusGained(void *windowHandle) override;
virtual void onWindowFocusLost(void *windowHandle) override;
virtual void onWindowResize(void *windowHandle, int windowWidth, int windowHeight) override;
virtual app::AppState onConstruct() override;
virtual app::AppState onInit() override;
virtual app::AppState onRunning() override;

View File

@ -2,7 +2,7 @@
* @file
*/
#include "IMGUI.h"
#include "IMGUIEx.h"
#include "IMGUIApp.h"
#include "command/CommandHandler.h"
#include "core/Color.h"
@ -12,6 +12,7 @@
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "dearimgui/imgui_internal.h"
namespace ImGui {
@ -260,15 +261,6 @@ bool DisabledButton(const char *text, bool disabled) {
return pressed;
}
float Size(float size) {
return size * ImGui::GetWindowDpiScale();
}
ImVec2 Size(float size1, float size2) {
const float s = ImGui::GetWindowDpiScale();
return ImVec2(size1 * s, size2 * s);
}
void TooltipCommand(const char *command) {
if (ImGui::IsItemHovered()) {
char buf[64];

View File

@ -5,7 +5,7 @@
#pragma once
#include "IMGUIInternal.h"
#include "dearimgui/imgui.h"
#include "command/CommandHandler.h"
#include "video/Types.h"
#include "core/Common.h"
@ -55,8 +55,6 @@ IMGUI_API bool ToggleButton(const char *text, bool state);
IMGUI_API void TableKeyValue(const char *key, CORE_FORMAT_STRING const char *msg, ...) CORE_PRINTF_VARARG_FUNC(2);
IMGUI_API void TableKeyValue(const char *key, const core::String &value);
IMGUI_API bool DisabledButton(const char *text, bool disabled);
IMGUI_API float Size(float size);
IMGUI_API ImVec2 Size(float size1, float size2);
IMGUI_API bool InputText(const char *label, core::String *str, ImGuiInputTextFlags flags = 0,
ImGuiInputTextCallback callback = nullptr, void *userData = nullptr);

View File

@ -1,60 +0,0 @@
#pragma once
#include "core/Common.h"
#include "core/Assert.h"
#include <glm/fwd.hpp>
#include <glm/vec2.hpp>
#include <glm/vec4.hpp>
/**
* @addtogroup UI
* @{
*/
#define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT \
struct ImDrawVert { \
union { \
ImVec2 pos; \
struct { \
float x; \
float y; \
}; \
}; \
union { \
ImVec2 uv; \
struct { \
float u; \
float v; \
}; \
}; \
union { \
ImU32 col; \
struct { \
uint8_t r; \
uint8_t g; \
uint8_t b; \
uint8_t a; \
}; \
}; \
};
#define IM_VEC2_CLASS_EXTRA \
ImVec2(float v) { x = v; y = v; } \
ImVec2(const glm::ivec2& f) { x = f.x; y = f.y; } \
operator glm::ivec2() const { return glm::ivec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const glm::ivec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
ImVec4(const glm::vec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
operator glm::ivec4() const { return glm::ivec4(x,y,z,w); } \
operator glm::vec4() const { return glm::vec4(x,y,z,w); }
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//#define IMGUI_DISABLE_OBSOLETE_KEYIO
#define IM_ASSERT(_EXPR) core_assert(_EXPR)
#include <dearimgui/imgui.h>
#include <dearimgui/imgui_internal.h>
/**
* @}
*/

View File

@ -3,7 +3,7 @@
* @ingroup UI
*/
#include "IMGUIInternal.h"
#include "dearimgui/imgui.h"
namespace ImGui {

View File

@ -3,7 +3,7 @@
#pragma once
#include "IMGUI.h"
#include "dearimgui/imgui.h"
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
@ -11,6 +11,7 @@
#include "IconsFontAwesome5.h"
#include "core/collection/DynamicArray.h"
#include "core/String.h"
typedef int ImGuiToastType;
typedef int ImGuiToastPhase;

View File

@ -4,7 +4,7 @@
#pragma once
#include "ui/imgui/IMGUI.h"
#include "dearimgui/imgui.h"
namespace ui {
namespace imgui {

View File

@ -7,7 +7,7 @@
#include <SDL.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include "IMGUI.h" // for imGui::GetCurrentWindow()
#include "dearimgui/imgui_internal.h" // for imGui::GetCurrentWindow()
template <class InputIt1, class InputIt2, class BinaryPredicate>
bool equals(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p) {

View File

@ -6,7 +6,7 @@
#pragma once
#include "IMGUI.h"
#include "dearimgui/imgui.h"
#include "core/String.h"
#include "core/collection/DynamicArray.h"
#include "core/collection/Map.h"
@ -65,8 +65,8 @@ public:
Coordinates() : mLine(0), mColumn(0) {
}
Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn) {
assert(aLine >= 0);
assert(aColumn >= 0);
core_assert(aLine >= 0);
core_assert(aColumn >= 0);
}
static Coordinates Invalid() {
static Coordinates invalid(-1, -1);

View File

@ -3,7 +3,7 @@
*/
#include "Window.h"
#include "IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "command/Command.h"
namespace ui {

View File

@ -21,6 +21,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
// 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates.
// 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
// 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
@ -87,8 +90,8 @@ struct ImGui_ImplSDL2_Data
{
SDL_Window* Window;
Uint64 Time;
Uint32 MouseWindowID;
int MouseButtonsDown;
bool MousePressed[3];
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
char* ClipboardTextData;
bool MouseCanUseGlobalState;
@ -178,12 +181,12 @@ static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd;
case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter;
case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual;
case SDLK_LCTRL: return ImGuiKey_LeftCtrl;
case SDLK_LSHIFT: return ImGuiKey_LeftShift;
case SDLK_LCTRL: return ImGuiKey_LeftControl;
case SDLK_LALT: return ImGuiKey_LeftAlt;
case SDLK_LGUI: return ImGuiKey_LeftSuper;
case SDLK_RCTRL: return ImGuiKey_RightCtrl;
case SDLK_RSHIFT: return ImGuiKey_RightShift;
case SDLK_RCTRL: return ImGuiKey_RightControl;
case SDLK_RALT: return ImGuiKey_RightAlt;
case SDLK_RGUI: return ImGuiKey_RightSuper;
case SDLK_MENU: return ImGuiKey_Menu;
@ -239,6 +242,17 @@ static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
return ImGuiKey_None;
}
static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
{
ImGuiIO& io = ImGui::GetIO();
ImGuiKeyModFlags key_mods =
((sdl_key_mods & KMOD_CTRL) ? ImGuiKeyModFlags_Ctrl : 0) |
((sdl_key_mods & KMOD_SHIFT) ? ImGuiKeyModFlags_Shift : 0) |
((sdl_key_mods & KMOD_ALT) ? ImGuiKeyModFlags_Alt : 0) |
((sdl_key_mods & KMOD_GUI) ? ImGuiKeyModFlags_Super : 0);
io.AddKeyModsEvent(key_mods);
}
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
@ -261,15 +275,14 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
mouse_pos.x += window_x;
mouse_pos.y += window_y;
}
io.MousePos = mouse_pos;
io.AddMousePosEvent(mouse_pos.x, mouse_pos.y);
return true;
}
case SDL_MOUSEWHEEL:
{
if (event->wheel.x > 0) io.MouseWheelH += 1;
if (event->wheel.x < 0) io.MouseWheelH -= 1;
if (event->wheel.y > 0) io.MouseWheel += 1;
if (event->wheel.y < 0) io.MouseWheel -= 1;
float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f;
float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f;
io.AddMouseWheelEvent(wheel_x, wheel_y);
return true;
}
case SDL_MOUSEBUTTONDOWN:
@ -279,10 +292,9 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; }
if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; }
if (mouse_button != -1)
if (mouse_button == -1)
break;
if (event->type == SDL_MOUSEBUTTONDOWN)
bd->MousePressed[mouse_button] = true;
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN));
bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
return true;
}
@ -294,6 +306,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
case SDL_KEYDOWN:
case SDL_KEYUP:
{
ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
ImGuiKey key = ImGui_ImplSDL2_KeycodeToImGuiKey(event->key.keysym.sym);
io.AddKeyEvent(key, (event->type == SDL_KEYDOWN));
io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
@ -301,9 +314,16 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
}
case SDL_WINDOWEVENT:
{
// When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
// However we won't get a correct LEAVE event for a captured window.
Uint8 window_event = event->window.event;
if (window_event == SDL_WINDOWEVENT_ENTER)
bd->MouseWindowID = event->window.windowID;
if (window_event == SDL_WINDOWEVENT_LEAVE)
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
{
bd->MouseWindowID = 0;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
}
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true);
else if (window_event == SDL_WINDOWEVENT_FOCUS_LOST)
@ -348,7 +368,10 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
if (mouse_can_use_global_state)
{
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport;// We can call io.AddMouseViewportEvent() with correct data (optional)
}
bd->Window = window;
bd->MouseCanUseGlobalState = mouse_can_use_global_state;
@ -495,19 +518,22 @@ static void ImGui_ImplSDL2_UpdateMouseData()
mouse_x -= window_x;
mouse_y -= window_y;
}
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
}
}
// We don't support ImGuiBackendFlags_HasMouseHoveredViewport
io.MouseHoveredViewport = 0;
// Update buttons
Uint32 mouse_buttons = SDL_GetMouseState(NULL, NULL);
io.MouseDown[0] = bd->MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false;
// (Optional) When using multiple viewports: call io.AddMouseViewportEvent() with the viewport the OS mouse cursor is hovering.
// If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, Dear imGui will ignore this field and infer the information using its flawed heuristic.
// - [!] SDL backend does NOT correctly ignore viewports with the _NoInputs flag.
// Some backend are not able to handle that correctly. If a backend report an hovered viewport that has the _NoInputs flag (e.g. when dragging a window
// for docking, the viewport has the _NoInputs flag in order to allow us to find the viewport under), then Dear ImGui is forced to ignore the value reported
// by the backend, and use its flawed heuristic to guess the viewport behind.
// - [X] SDL backend correctly reports this regardless of another viewport behind focused and dragged from (we need this to find a useful drag and drop target).
ImGuiID mouse_viewport_id = 0;
if (SDL_Window* sdl_mouse_window = SDL_GetWindowFromID(bd->MouseWindowID))
if (ImGuiViewport* mouse_viewport = ImGui::FindViewportByPlatformHandle((void*)sdl_mouse_window))
mouse_viewport_id = mouse_viewport->ID;
io.AddMouseViewportEvent(mouse_viewport_id);
}
static void ImGui_ImplSDL2_UpdateMouseCursor()
@ -534,40 +560,45 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
static void ImGui_ImplSDL2_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
// Get gamepad
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
if (!game_controller)
{
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
return;
}
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
// Update gamepad inputs
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; }
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); }
#define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A
MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B
MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X
MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y
MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left
MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right
MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up
MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down
MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767);
MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
}
@ -600,18 +631,6 @@ static void ImGui_ImplSDL2_UpdateMonitors()
}
}
static void ImGui_ImplSDL2_UpdateKeyModifiers()
{
ImGuiIO& io = ImGui::GetIO();
SDL_Keymod sdl_key_mods = SDL_GetModState();
ImGuiKeyModFlags key_mods =
((sdl_key_mods & KMOD_CTRL) ? ImGuiKeyModFlags_Ctrl : 0) |
((sdl_key_mods & KMOD_SHIFT) ? ImGuiKeyModFlags_Shift : 0) |
((sdl_key_mods & KMOD_ALT) ? ImGuiKeyModFlags_Alt : 0) |
((sdl_key_mods & KMOD_GUI) ? ImGuiKeyModFlags_Super : 0);
io.AddKeyModsEvent(key_mods);
}
void ImGui_ImplSDL2_NewFrame()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
@ -635,7 +654,6 @@ void ImGui_ImplSDL2_NewFrame()
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time;
ImGui_ImplSDL2_UpdateKeyModifiers();
ImGui_ImplSDL2_UpdateMouseData();
ImGui_ImplSDL2_UpdateMouseCursor();

View File

@ -0,0 +1,37 @@
// dear imgui: Platform Backend for SDL2
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
struct SDL_Window;
typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window);
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter
#endif

View File

@ -14,9 +14,14 @@
#pragma once
#include "core/Assert.h"
#include <glm/fwd.hpp>
#include <glm/vec2.hpp>
#include <glm/vec4.hpp>
//---- 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) core_assert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
@ -27,8 +32,8 @@
//#define IMGUI_API __declspec( dllimport )
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be 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.
#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.
//---- Disable all of Dear ImGui or don't implement standard windows.
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
@ -76,19 +81,20 @@
//---- 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 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; } \
operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC2_CLASS_EXTRA \
ImVec2(float v) { x = v; y = v; } \
ImVec2(const glm::ivec2& f) { x = f.x; y = f.y; } \
operator glm::ivec2() const { return glm::ivec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const glm::ivec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
ImVec4(const glm::vec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
operator glm::ivec4() const { return glm::ivec4(x,y,z,w); } \
operator glm::vec4() const { return glm::vec4(x,y,z,w); }
//---- 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).
@ -96,6 +102,33 @@
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int
#define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT \
struct ImDrawVert { \
union { \
ImVec2 pos; \
struct { \
float x; \
float y; \
}; \
}; \
union { \
ImVec2 uv; \
struct { \
float u; \
float v; \
}; \
}; \
union { \
ImU32 col; \
struct { \
uint8_t r; \
uint8_t g; \
uint8_t b; \
uint8_t a; \
}; \
}; \
};
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
//struct ImDrawList;
//struct ImDrawCmd;

View File

@ -129,7 +129,6 @@ CODE
- CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
- CTRL+Z,CTRL+Y to undo/redo.
- ESCAPE to revert text to its original value.
- You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
- Controls are automatically adjusted for OSX to match standard OSX text editing operations.
- General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
- General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://dearimgui.org/controls_sheets
@ -256,9 +255,9 @@ CODE
io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds)
io.DisplaySize.x = 1920.0f; // set the current display width
io.DisplaySize.y = 1280.0f; // set the current display height here
io.MousePos = my_mouse_pos; // set the mouse position
io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states
io.MouseDown[1] = my_mouse_buttons[1];
io.AddMousePosEvent(mouse_x, mouse_y); // update mouse position
io.AddMouseButtonEvent(0, mouse_b[0]); // update mouse button states
io.AddMouseButtonEvent(1, mouse_b[1]); // update mouse button states
// Call NewFrame(), after this point you can use ImGui::* functions anytime
// (So you want to try calling NewFrame() as early as you can in your main loop to be able to use Dear ImGui everywhere)
@ -348,27 +347,26 @@ CODE
- You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787
- The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
- Keyboard:
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
NewFrame() will automatically fill io.NavInputs[] based on your io.AddKeyEvent() calls.
- When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
will be set. For more advanced uses, you may want to read from:
- Application: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
- Internally: NewFrame() will automatically fill io.NavInputs[] based on backend's io.AddKeyEvent() calls.
- When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard),
the io.WantCaptureKeyboard flag will be set. For more advanced uses, you may want to read from:
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
- io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
- or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions.
Please reach out if you think the game vs navigation input sharing could be improved.
- Gamepad:
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
- Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
Note that io.NavInputs[] is cleared by EndFrame().
- See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
- We use a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.).
- Application: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
- Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + call io.AddKeyEvent/AddKeyAnalogEvent() with ImGuiKey_Gamepad_XXX keys.
For analog values (0.0f to 1.0f), backend is responsible to handling a dead-zone and rescaling inputs accordingly.
Backend code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.).
- Internally: NewFrame() will automatically fill io.NavInputs[] based on backend's io.AddKeyEvent() + io.AddKeyAnalogEvent() calls.
- BEFORE 1.87, BACKENDS USED TO WRITE DIRECTLY TO io.NavInputs[]. This is going to be obsoleted in the future. Please call io functions instead!
- You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://dearimgui.org/controls_sheets
- If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo
to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
- If you need to share inputs between your game and the Dear ImGui interface, the easiest approach is to go all-or-nothing,
with a buttons combo to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
- Mouse:
- PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
- PS4/PS5 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
- Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard.
- On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag.
Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements.
@ -394,10 +392,19 @@ CODE
- likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2022/01/20 (1.87) - inputs: reworded gamepad IO.
- Backend writing to io.NavInputs[] -> backend should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX values.
- 2022/01/19 (1.87) - sliders, drags: removed support for legacy arithmetic operators (+,+-,*,/) when inputing text. This doesn't break any api/code but a feature that used to be accessible by end-users (which seemingly no one used).
- 2022/01/17 (1.87) - inputs: reworked mouse IO.
- Backend writing to io.MousePos -> backend should call io.AddMousePosEvent()
- Backend writing to io.MouseDown[] -> backend should call io.AddMouseButtonEvent()
- Backend writing to io.MouseWheel -> backend should call io.AddMouseWheelEvent()
- Backend writing to io.MouseHoveredViewpot -> backend should call io.AddMouseViewportEvent() [Docking branch only]
- 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(). Removed GetKeyIndex(), now unecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details.
- IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX)
- IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX)
- Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent()
- one case won't work with backward compatibility: if your custom backend used ImGuiKey as mock native indices (e.g. "io.KeyMap[ImGuiKey_A] = ImGuiKey_A") because those values are now larger than the legacy KeyDown[] array. Will assert.
- inputs: added io.AddKeyModsEvent() instead of writing directly to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper.
- 2022/01/05 (1.87) - inputs: renamed ImGuiKey_KeyPadEnter to ImGuiKey_KeypadEnter to align with new symbols. Kept redirection enum.
- 2022/01/05 (1.87) - removed io.ImeSetInputScreenPosFn() in favor of more flexible io.SetPlatformImeDataFn(). Removed 'void* io.ImeWindowHandle' in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'.
@ -1171,6 +1178,7 @@ ImGuiIO::ImGuiIO()
#else
ConfigMacOSXBehaviors = false;
#endif
ConfigInputTrickleEventQueue = true;
ConfigInputTextCursorBlink = true;
ConfigWindowsResizeFromEdges = true;
ConfigWindowsMoveFromTitleBarOnly = false;
@ -1192,15 +1200,25 @@ ImGuiIO::ImGuiIO()
for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
BackendUsingLegacyKeyArrays = (ImS8)-1;
BackendUsingLegacyNavInputArray = true; // assume using legacy array until proven wrong
}
// Pass in translated ASCII characters for text input.
// - with glfw you can get those from the callback set in glfwSetCharCallback()
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
// FIXME: Should in theory be called "AddCharacterEvent()" to be consistent with new API
void ImGuiIO::AddInputCharacter(unsigned int c)
{
if (c != 0)
InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
if (c == 0)
return;
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_Char;
e.Source = ImGuiInputSource_Keyboard;
e.Text.Char = c;
g.InputEventsQueue.push_back(e);
}
// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so
@ -1213,7 +1231,7 @@ void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
if ((c & 0xFC00) == 0xD800) // High surrogate, must save
{
if (InputQueueSurrogate != 0)
InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
InputQueueSurrogate = c;
return;
}
@ -1223,7 +1241,7 @@ void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
{
if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate
{
InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
}
else
{
@ -1236,7 +1254,7 @@ void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
InputQueueSurrogate = 0;
}
InputQueueCharacters.push_back(cp);
AddInputCharacter((unsigned)cp);
}
void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
@ -1246,7 +1264,7 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
unsigned int c = 0;
utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
if (c != 0)
InputQueueCharacters.push_back((ImWchar)c);
AddInputCharacter(c);
}
}
@ -1273,14 +1291,16 @@ void ImGuiIO::ClearInputKeys()
}
// Queue a new key down/up event.
// - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
// - bool down: Is the key down? use false to signify a key release.
// FIXME: In the current version this is setting key data immediately. This will evolve into a trickling queue.
void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down)
// - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
// - bool down: Is the key down? use false to signify a key release.
// - float analog_value: 0.0f..1.0f
void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
{
//if (e->Down) { IMGUI_DEBUG_LOG("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); }
if (key == ImGuiKey_None)
return;
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
IM_ASSERT(ImGui::IsNamedKey(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API.
// Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data.
@ -1289,15 +1309,26 @@ void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down)
if (BackendUsingLegacyKeyArrays == -1)
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
IM_ASSERT(KeyMap[n] == -1 && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
#endif
BackendUsingLegacyKeyArrays = 0;
#endif
if (ImGui::IsGamepadKey(key))
BackendUsingLegacyNavInputArray = false;
// Write key
const int keydata_index = (key - ImGuiKey_KeysData_OFFSET);
KeysData[keydata_index].Down = down;
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_Key;
e.Source = ImGui::IsGamepadKey(key) ? ImGuiInputSource_Gamepad : ImGuiInputSource_Keyboard;
e.Key.Key = key;
e.Key.Down = down;
e.Key.AnalogValue = analog_value;
g.InputEventsQueue.push_back(e);
}
// [Optional] Call add AddKeyEvent().
void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down)
{
AddKeyAnalogEvent(key, down, down ? 1.0f : 0.0f);
}
// [Optional] Call after AddKeyEvent().
// Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() functions with native indices.
// If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this.
void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index)
@ -1322,18 +1353,82 @@ void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native
void ImGuiIO::AddKeyModsEvent(ImGuiKeyModFlags modifiers)
{
KeyMods = modifiers;
KeyCtrl = (modifiers & ImGuiKeyModFlags_Ctrl) != 0;
KeyShift = (modifiers & ImGuiKeyModFlags_Shift) != 0;
KeyAlt = (modifiers & ImGuiKeyModFlags_Alt) != 0;
KeySuper = (modifiers & ImGuiKeyModFlags_Super) != 0;
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_KeyMods;
e.Source = ImGuiInputSource_Keyboard;
e.KeyMods.Mods = modifiers;
g.InputEventsQueue.push_back(e);
}
// Queue a mouse move event
void ImGuiIO::AddMousePosEvent(float x, float y)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_MousePos;
e.Source = ImGuiInputSource_Mouse;
e.MousePos.PosX = x;
e.MousePos.PosY = y;
g.InputEventsQueue.push_back(e);
}
void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_MouseButton;
e.Source = ImGuiInputSource_Mouse;
e.MouseButton.Button = mouse_button;
e.MouseButton.Down = down;
g.InputEventsQueue.push_back(e);
}
// Queue a mouse wheel event (most mouse/API will only have a Y component)
void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
if (wheel_x == 0.0f && wheel_y == 0.0f)
return;
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_MouseWheel;
e.Source = ImGuiInputSource_Mouse;
e.MouseWheel.WheelX = wheel_x;
e.MouseWheel.WheelY = wheel_y;
g.InputEventsQueue.push_back(e);
}
void ImGuiIO::AddMouseViewportEvent(ImGuiID viewport_id)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
IM_ASSERT(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport);
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_MouseViewport;
e.Source = ImGuiInputSource_Mouse;
e.MouseViewport.HoveredViewportID = viewport_id;
g.InputEventsQueue.push_back(e);
}
void ImGuiIO::AddFocusEvent(bool focused)
{
// We intentionally overwrite this and process in NewFrame(), in order to give a chance
// to multi-viewports backends to queue AddFocusEvent(false),AddFocusEvent(true) in same frame.
AppFocusLost = !focused;
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_Focus;
e.AppFocused.Focused = focused;
g.InputEventsQueue.push_back(e);
}
//-----------------------------------------------------------------------------
@ -3332,7 +3427,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
if (id)
{
g.ActiveIdIsAlive = id;
g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustMovedToId == id) ? (ImGuiInputSource)ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
}
// Clear declaration of inputs claimed by the widget
@ -3998,6 +4093,14 @@ static void ImGui::UpdateKeyboardInputs()
}
#endif
// Clear gamepad data if disabled
if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
for (int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++)
{
io.KeysData[i - ImGuiKey_KeysData_OFFSET].Down = false;
io.KeysData[i - ImGuiKey_KeysData_OFFSET].AnalogValue = 0.0f;
}
// Update keys
for (int i = 0; i < IM_ARRAYSIZE(io.KeysData); i++)
{
@ -4014,7 +4117,7 @@ static void ImGui::UpdateMouseInputs()
// Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
if (IsMousePosValid(&io.MousePos))
io.MousePos = g.MouseLastValidPos = ImFloor(io.MousePos);
io.MousePos = g.MouseLastValidPos = ImFloorSigned(io.MousePos);
// If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev))
@ -4375,13 +4478,9 @@ void ImGui::NewFrame()
//if (g.IO.AppFocusLost)
// ClosePopupsExceptModals();
// Clear buttons state when focus is lost
// (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle)
if (g.IO.AppFocusLost)
{
g.IO.ClearInputKeys();
g.IO.AppFocusLost = false;
}
// Process input queue (trickle as many events as possible)
g.InputEventsTrail.resize(0);
UpdateInputEvents(g.IO.ConfigInputTrickleEventQueue);
// Update keyboard input state
UpdateKeyboardInputs();
@ -6172,7 +6271,9 @@ static ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
for (int i = g.OpenPopupStack.Size - 1; i >= 0; i--)
{
ImGuiWindow* popup_window = g.OpenPopupStack.Data[i].Window;
if (popup_window == NULL || !popup_window->WasActive || !(popup_window->Flags & ImGuiWindowFlags_Modal)) // Check WasActive, because this code may run before popup renders on current frame.
if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
continue;
if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows.
continue;
if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed.
break;
@ -7962,7 +8063,7 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c
return true;
}
const ImGuiKeyData* ImGui::GetKeyData(ImGuiKey key)
ImGuiKeyData* ImGui::GetKeyData(ImGuiKey key)
{
ImGuiContext& g = *GImGui;
int index;
@ -7994,22 +8095,27 @@ static const char* const GKeyNames[] =
{
"Tab", "LeftArrow", "RightArrow", "UpArrow", "DownArrow", "PageUp", "PageDown",
"Home", "End", "Insert", "Delete", "Backspace", "Space", "Enter", "Escape",
"LeftCtrl", "LeftShift", "LeftAlt", "LeftSuper", "RightCtrl", "RightShift", "RightAlt", "RightSuper", "Menu",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
"Apostrophe", "Comma", "Minus", "Period", "Slash", "Semicolon", "Equal", "LeftBracket",
"Backslash", "RightBracket", "GraveAccent", "CapsLock", "ScrollLock", "NumLock", "PrintScreen",
"Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6",
"Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMultiply",
"KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", "LeftShift", "LeftControl",
"LeftAlt", "LeftSuper", "RightShift", "RightControl", "RightAlt", "RightSuper", "Menu",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"
"KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual",
"GamepadStart", "GamepadBack", "GamepadFaceUp", "GamepadFaceDown", "GamepadFaceLeft", "GamepadFaceRight",
"GamepadDpadUp", "GamepadDpadDown", "GamepadDpadLeft", "GamepadDpadRight",
"GamepadL1", "GamepadR1", "GamepadL2", "GamepadR2", "GamepadL3", "GamepadR3",
"GamepadLStickUp", "GamepadLStickDown", "GamepadLStickLeft", "GamepadLStickRight",
"GamepadRStickUp", "GamepadRStickDown", "GamepadRStickLeft", "GamepadRStickRight"
};
IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));
const char* ImGui::GetKeyName(ImGuiKey key)
{
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT(IsNamedKey(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
IM_ASSERT((IsNamedKey(key) || key == ImGuiKey_None) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
#else
if (IsLegacyKey(key))
{
@ -8238,6 +8344,140 @@ static const char* GetInputSourceName(ImGuiInputSource source)
}
// Process input queue
// - trickle_fast_inputs = false : process all events, turn into flattened input state (e.g. successive down/up/down/up will be lost)
// - trickle_fast_inputs = true : process as many events as possible (successive down/up/down/up will be trickled over several frames so nothing is lost) (new feature in 1.87)
void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
{
ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;
bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputed = false;
int mouse_button_changed = 0x00, key_mods_changed = 0x00;
ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
int event_n = 0;
for (; event_n < g.InputEventsQueue.Size; event_n++)
{
const ImGuiInputEvent* e = &g.InputEventsQueue[event_n];
if (e->Type == ImGuiInputEventType_MousePos)
{
ImVec2 event_pos(e->MousePos.PosX, e->MousePos.PosY);
if (IsMousePosValid(&event_pos))
event_pos = ImVec2(ImFloorSigned(event_pos.x), ImFloorSigned(event_pos.y)); // Apply same flooring as UpdateMouseInputs()
if (io.MousePos.x != event_pos.x || io.MousePos.y != event_pos.y)
{
// Trickling Rule: Stop processing queued events if we already handled a mouse button change
if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || key_mods_changed || text_inputed))
break;
io.MousePos = event_pos;
mouse_moved = true;
}
}
else if (e->Type == ImGuiInputEventType_MouseButton)
{
const ImGuiMouseButton button = e->MouseButton.Button;
IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT);
if (io.MouseDown[button] != e->MouseButton.Down)
{
// Trickling Rule: Stop processing queued events if we got multiple action on the same button
if (trickle_fast_inputs && ((mouse_button_changed & (1 << button)) || mouse_wheeled))
break;
io.MouseDown[button] = e->MouseButton.Down;
mouse_button_changed |= (1 << button);
}
}
else if (e->Type == ImGuiInputEventType_MouseWheel)
{
if (e->MouseWheel.WheelX != 0.0f || e->MouseWheel.WheelY != 0.0f)
{
// Trickling Rule: Stop processing queued events if we got multiple action on the event
if (trickle_fast_inputs && (mouse_wheeled || mouse_button_changed != 0))
break;
io.MouseWheelH += e->MouseWheel.WheelX;
io.MouseWheel += e->MouseWheel.WheelY;
mouse_wheeled = true;
}
}
else if (e->Type == ImGuiInputEventType_MouseViewport)
{
io.MouseHoveredViewport = e->MouseViewport.HoveredViewportID;
}
else if (e->Type == ImGuiInputEventType_Key)
{
IM_ASSERT(e->Key.Key != ImGuiKey_None);
const int keydata_index = (e->Key.Key - ImGuiKey_KeysData_OFFSET);
ImGuiKeyData* keydata = &io.KeysData[keydata_index];
if (keydata->Down != e->Key.Down || keydata->AnalogValue != e->Key.AnalogValue)
{
// Trickling Rule: Stop processing queued events if we got multiple action on the same button
if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_changed_mask.TestBit(keydata_index) || text_inputed || mouse_button_changed != 0))
break;
keydata->Down = e->Key.Down;
keydata->AnalogValue = e->Key.AnalogValue;
key_changed = true;
key_changed_mask.SetBit(keydata_index);
}
}
else if (e->Type == ImGuiInputEventType_KeyMods)
{
const ImGuiKeyModFlags modifiers = e->KeyMods.Mods;
if (io.KeyMods != modifiers)
{
// Trickling Rule: Stop processing queued events if we got multiple action on the same button
ImGuiKeyModFlags modifiers_that_are_changing = (io.KeyMods ^ modifiers);
if (trickle_fast_inputs && (key_mods_changed & modifiers_that_are_changing) != 0)
break;
io.KeyMods = modifiers;
io.KeyCtrl = (modifiers & ImGuiKeyModFlags_Ctrl) != 0;
io.KeyShift = (modifiers & ImGuiKeyModFlags_Shift) != 0;
io.KeyAlt = (modifiers & ImGuiKeyModFlags_Alt) != 0;
io.KeySuper = (modifiers & ImGuiKeyModFlags_Super) != 0;
key_mods_changed |= modifiers_that_are_changing;
}
}
else if (e->Type == ImGuiInputEventType_Char)
{
// Trickling Rule: Stop processing queued events if keys/mouse have been interacted with
if (trickle_fast_inputs && (key_changed || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
break;
unsigned int c = e->Text.Char;
io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
text_inputed = true;
}
else if (e->Type == ImGuiInputEventType_Focus)
{
// We intentionally overwrite this and process lower, in order to give a chance
// to multi-viewports backends to queue AddFocusEvent(false) + AddFocusEvent(true) in same frame.
io.AppFocusLost = !e->AppFocused.Focused;
}
else
{
IM_ASSERT(0 && "Unknown event!");
}
}
// Record trail (for domain-specific applications wanting to access a precise trail)
//if (event_n != 0) IMGUI_DEBUG_LOG("Processed: %d / Remaining: %d\n", event_n, g.InputEventsQueue.Size - event_n);
for (int n = 0; n < event_n; n++)
g.InputEventsTrail.push_back(g.InputEventsQueue[n]);
// Remaining events will be processed on the next frame
if (event_n == g.InputEventsQueue.Size)
g.InputEventsQueue.resize(0);
else
g.InputEventsQueue.erase(g.InputEventsQueue.Data, g.InputEventsQueue.Data + event_n);
// Clear buttons state when focus is lost
// (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle)
if (g.IO.AppFocusLost)
{
g.IO.ClearInputKeys();
g.IO.AppFocusLost = false;
}
}
//-----------------------------------------------------------------------------
// [SECTION] ERROR CHECKING
//-----------------------------------------------------------------------------
@ -10429,18 +10669,35 @@ static void ImGui::NavUpdate()
io.WantSetMousePos = false;
//if (g.NavScoringDebugCount > 0) IMGUI_DEBUG_LOG("NavScoringDebugCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.NavScoringDebugCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
// Update Gamepad->Nav inputs mapping
// Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard)
// (do it before we map Keyboard input!)
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad)
if (nav_gamepad_active && g.IO.BackendUsingLegacyNavInputArray == false)
{
if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNavInput_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs[ImGuiNavInput_Menu] > 0.0f
|| io.NavInputs[ImGuiNavInput_DpadLeft] > 0.0f || io.NavInputs[ImGuiNavInput_DpadRight] > 0.0f || io.NavInputs[ImGuiNavInput_DpadUp] > 0.0f || io.NavInputs[ImGuiNavInput_DpadDown] > 0.0f)
g.NavInputSource = ImGuiInputSource_Gamepad;
for (int n = 0; n < ImGuiNavInput_COUNT; n++)
IM_ASSERT(io.NavInputs[n] == 0.0f && "Backend needs to either only use io.AddKeyEvent()/io.AddKeyAnalogEvent(), either only fill legacy io.NavInputs[]. Not both!");
#define NAV_MAP_KEY(_KEY, _NAV_INPUT, _ACTIVATE_NAV) do { io.NavInputs[_NAV_INPUT] = io.KeysData[_KEY - ImGuiKey_KeysData_OFFSET].AnalogValue; if (_ACTIVATE_NAV && io.NavInputs[_NAV_INPUT] > 0.0f) { g.NavInputSource = ImGuiInputSource_Gamepad; } } while (0)
NAV_MAP_KEY(ImGuiKey_GamepadFaceDown, ImGuiNavInput_Activate, true);
NAV_MAP_KEY(ImGuiKey_GamepadFaceRight, ImGuiNavInput_Cancel, true);
NAV_MAP_KEY(ImGuiKey_GamepadFaceLeft, ImGuiNavInput_Menu, true);
NAV_MAP_KEY(ImGuiKey_GamepadFaceUp, ImGuiNavInput_Input, true);
NAV_MAP_KEY(ImGuiKey_GamepadDpadLeft, ImGuiNavInput_DpadLeft, true);
NAV_MAP_KEY(ImGuiKey_GamepadDpadRight, ImGuiNavInput_DpadRight, true);
NAV_MAP_KEY(ImGuiKey_GamepadDpadUp, ImGuiNavInput_DpadUp, true);
NAV_MAP_KEY(ImGuiKey_GamepadDpadDown, ImGuiNavInput_DpadDown, true);
NAV_MAP_KEY(ImGuiKey_GamepadL1, ImGuiNavInput_FocusPrev, false);
NAV_MAP_KEY(ImGuiKey_GamepadR1, ImGuiNavInput_FocusNext, false);
NAV_MAP_KEY(ImGuiKey_GamepadL1, ImGuiNavInput_TweakSlow, false);
NAV_MAP_KEY(ImGuiKey_GamepadR1, ImGuiNavInput_TweakFast, false);
NAV_MAP_KEY(ImGuiKey_GamepadLStickLeft, ImGuiNavInput_LStickLeft, false);
NAV_MAP_KEY(ImGuiKey_GamepadLStickRight, ImGuiNavInput_LStickRight, false);
NAV_MAP_KEY(ImGuiKey_GamepadLStickUp, ImGuiNavInput_LStickUp, false);
NAV_MAP_KEY(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown, false);
#undef NAV_MAP_KEY
}
// Update Keyboard->Nav inputs mapping
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
if (nav_keyboard_active)
{
#define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(_KEY)) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } while (0)
@ -12512,17 +12769,14 @@ static void ImGui::UpdateViewportsNewFrame()
{
viewport_hovered = g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(g.IO.MouseHoveredViewport) : NULL;
if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
{
// Backend failed at honoring its contract if it returned a viewport with the _NoInputs flag.
IM_ASSERT(0);
viewport_hovered = FindHoveredViewportFromPlatformWindowStack(g.IO.MousePos);
}
viewport_hovered = FindHoveredViewportFromPlatformWindowStack(g.IO.MousePos); // Backend failed to handle _NoInputs viewport: revert to our fallback.
}
else
{
// If the backend doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search:
// A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
// B) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
// B) won't take account of how the backend apply parent<>child relationship to secondary viewports, which affects their Z order.
// C) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
viewport_hovered = FindHoveredViewportFromPlatformWindowStack(g.IO.MousePos);
}
if (viewport_hovered != NULL)
@ -12736,7 +12990,8 @@ static void ImGui::WindowSelectViewport(ImGuiWindow* window)
{
// Merge into host viewport?
// We cannot test window->ViewportOwned as it set lower in the function.
bool try_to_merge_into_host_viewport = (window->Viewport && window == window->Viewport->Window && g.ActiveId == 0);
// Testing (g.ActiveId == 0 || g.ActiveIdAllowOverlap) to avoid merging during a short-term widget interaction. Main intent was to avoid during resize (see #4212)
bool try_to_merge_into_host_viewport = (window->Viewport && window == window->Viewport->Window && (g.ActiveId == 0 || g.ActiveIdAllowOverlap));
if (try_to_merge_into_host_viewport)
UpdateTryMergeWindowIntoHostViewports(window);
}
@ -17473,7 +17728,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
TreePop();
}
if (TreeNode("Inferred order (front-to-back)"))
BulletText("MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)", g.MouseViewport ? g.MouseViewport->ID : 0, g.IO.MouseHoveredViewport, g.MouseLastHoveredViewport ? g.MouseLastHoveredViewport->ID : 0);
if (TreeNode("Inferred Z order (front-to-back)"))
{
static ImVector<ImGuiViewportP*> viewports;
viewports.resize(g.Viewports.Size);

View File

@ -65,7 +65,7 @@ Index of this file:
// Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.87 WIP"
#define IMGUI_VERSION_NUM 18605
#define IMGUI_VERSION_NUM 18612
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
@ -88,11 +88,7 @@ Index of this file:
#endif
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100)
#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11
#else
#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro.
#endif
// Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions.
#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__)
@ -234,17 +230,8 @@ typedef signed short ImS16; // 16-bit signed integer
typedef unsigned short ImU16; // 16-bit unsigned integer
typedef signed int ImS32; // 32-bit signed integer == int
typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors)
#if defined(_MSC_VER) && !defined(__clang__)
typedef signed __int64 ImS64; // 64-bit signed integer (pre and post C++11 with Visual Studio)
typedef unsigned __int64 ImU64; // 64-bit unsigned integer (pre and post C++11 with Visual Studio)
#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
#include <stdint.h>
typedef int64_t ImS64; // 64-bit signed integer (pre C++11)
typedef uint64_t ImU64; // 64-bit unsigned integer (pre C++11)
#else
typedef signed long long ImS64; // 64-bit signed integer (post C++11)
typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11)
#endif
typedef signed long long ImS64; // 64-bit signed integer (C++11)
typedef unsigned long long ImU64; // 64-bit unsigned integer (C++11)
// Character types
// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)
@ -1417,8 +1404,8 @@ enum ImGuiSortDirection_
enum ImGuiKey_
{
ImGuiKey_None = 0,
ImGuiKey_Tab = 512, // == ImGuiKey_NamedKey_BEGIN
ImGuiKey_None = 0,
ImGuiKey_Tab = 512, // == ImGuiKey_NamedKey_BEGIN
ImGuiKey_LeftArrow,
ImGuiKey_RightArrow,
ImGuiKey_UpArrow,
@ -1433,32 +1420,33 @@ enum ImGuiKey_
ImGuiKey_Space,
ImGuiKey_Enter,
ImGuiKey_Escape,
ImGuiKey_Apostrophe, // '
ImGuiKey_Comma, // ,
ImGuiKey_Minus, // -
ImGuiKey_Period, // .
ImGuiKey_Slash, // /
ImGuiKey_Semicolon, // ;
ImGuiKey_Equal, // =
ImGuiKey_LeftBracket, // [
ImGuiKey_Backslash, // \ (this text inhibit multiline comment caused by backlash)
ImGuiKey_RightBracket, // ]
ImGuiKey_GraveAccent, // `
ImGuiKey_LeftCtrl, ImGuiKey_LeftShift, ImGuiKey_LeftAlt, ImGuiKey_LeftSuper,
ImGuiKey_RightCtrl, ImGuiKey_RightShift, ImGuiKey_RightAlt, ImGuiKey_RightSuper,
ImGuiKey_Menu,
ImGuiKey_0, ImGuiKey_1, ImGuiKey_2, ImGuiKey_3, ImGuiKey_4, ImGuiKey_5, ImGuiKey_6, ImGuiKey_7, ImGuiKey_8, ImGuiKey_9,
ImGuiKey_A, ImGuiKey_B, ImGuiKey_C, ImGuiKey_D, ImGuiKey_E, ImGuiKey_F, ImGuiKey_G, ImGuiKey_H, ImGuiKey_I, ImGuiKey_J,
ImGuiKey_K, ImGuiKey_L, ImGuiKey_M, ImGuiKey_N, ImGuiKey_O, ImGuiKey_P, ImGuiKey_Q, ImGuiKey_R, ImGuiKey_S, ImGuiKey_T,
ImGuiKey_U, ImGuiKey_V, ImGuiKey_W, ImGuiKey_X, ImGuiKey_Y, ImGuiKey_Z,
ImGuiKey_F1, ImGuiKey_F2, ImGuiKey_F3, ImGuiKey_F4, ImGuiKey_F5, ImGuiKey_F6,
ImGuiKey_F7, ImGuiKey_F8, ImGuiKey_F9, ImGuiKey_F10, ImGuiKey_F11, ImGuiKey_F12,
ImGuiKey_Apostrophe, // '
ImGuiKey_Comma, // ,
ImGuiKey_Minus, // -
ImGuiKey_Period, // .
ImGuiKey_Slash, // /
ImGuiKey_Semicolon, // ;
ImGuiKey_Equal, // =
ImGuiKey_LeftBracket, // [
ImGuiKey_Backslash, // \ (this text inhibit multiline comment caused by backslash)
ImGuiKey_RightBracket, // ]
ImGuiKey_GraveAccent, // `
ImGuiKey_CapsLock,
ImGuiKey_ScrollLock,
ImGuiKey_NumLock,
ImGuiKey_PrintScreen,
ImGuiKey_Pause,
ImGuiKey_Keypad0,
ImGuiKey_Keypad1,
ImGuiKey_Keypad2,
ImGuiKey_Keypad3,
ImGuiKey_Keypad4,
ImGuiKey_Keypad5,
ImGuiKey_Keypad6,
ImGuiKey_Keypad7,
ImGuiKey_Keypad8,
ImGuiKey_Keypad9,
ImGuiKey_Keypad0, ImGuiKey_Keypad1, ImGuiKey_Keypad2, ImGuiKey_Keypad3, ImGuiKey_Keypad4,
ImGuiKey_Keypad5, ImGuiKey_Keypad6, ImGuiKey_Keypad7, ImGuiKey_Keypad8, ImGuiKey_Keypad9,
ImGuiKey_KeypadDecimal,
ImGuiKey_KeypadDivide,
ImGuiKey_KeypadMultiply,
@ -1466,79 +1454,51 @@ enum ImGuiKey_
ImGuiKey_KeypadAdd,
ImGuiKey_KeypadEnter,
ImGuiKey_KeypadEqual,
ImGuiKey_LeftShift,
ImGuiKey_LeftControl,
ImGuiKey_LeftAlt,
ImGuiKey_LeftSuper,
ImGuiKey_RightShift,
ImGuiKey_RightControl,
ImGuiKey_RightAlt,
ImGuiKey_RightSuper,
ImGuiKey_Menu,
ImGuiKey_0,
ImGuiKey_1,
ImGuiKey_2,
ImGuiKey_3,
ImGuiKey_4,
ImGuiKey_5,
ImGuiKey_6,
ImGuiKey_7,
ImGuiKey_8,
ImGuiKey_9,
ImGuiKey_A,
ImGuiKey_B,
ImGuiKey_C,
ImGuiKey_D,
ImGuiKey_E,
ImGuiKey_F,
ImGuiKey_G,
ImGuiKey_H,
ImGuiKey_I,
ImGuiKey_J,
ImGuiKey_K,
ImGuiKey_L,
ImGuiKey_M,
ImGuiKey_N,
ImGuiKey_O,
ImGuiKey_P,
ImGuiKey_Q,
ImGuiKey_R,
ImGuiKey_S,
ImGuiKey_T,
ImGuiKey_U,
ImGuiKey_V,
ImGuiKey_W,
ImGuiKey_X,
ImGuiKey_Y,
ImGuiKey_Z,
ImGuiKey_F1,
ImGuiKey_F2,
ImGuiKey_F3,
ImGuiKey_F4,
ImGuiKey_F5,
ImGuiKey_F6,
ImGuiKey_F7,
ImGuiKey_F8,
ImGuiKey_F9,
ImGuiKey_F10,
ImGuiKey_F11,
ImGuiKey_F12,
ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value
// Gamepad (some of those are expected to be analog values from 0.0f to 1.0f) ..............// NAVIGATION action
ImGuiKey_GamepadStart, // Menu (Xbox) + (Switch) Start/Options (PS) // --
ImGuiKey_GamepadBack, // View (Xbox) - (Switch) Share (PS) // --
ImGuiKey_GamepadFaceUp, // Y (Xbox) X (Switch) Triangle (PS) // -> ImGuiNavInput_Input
ImGuiKey_GamepadFaceDown, // A (Xbox) B (Switch) Cross (PS) // -> ImGuiNavInput_Activate
ImGuiKey_GamepadFaceLeft, // X (Xbox) Y (Switch) Square (PS) // -> ImGuiNavInput_Menu
ImGuiKey_GamepadFaceRight, // B (Xbox) A (Switch) Circle (PS) // -> ImGuiNavInput_Cancel
ImGuiKey_GamepadDpadUp, // D-pad Up // -> ImGuiNavInput_DpadUp
ImGuiKey_GamepadDpadDown, // D-pad Down // -> ImGuiNavInput_DpadDown
ImGuiKey_GamepadDpadLeft, // D-pad Left // -> ImGuiNavInput_DpadLeft
ImGuiKey_GamepadDpadRight, // D-pad Right // -> ImGuiNavInput_DpadRight
ImGuiKey_GamepadL1, // L Bumper (Xbox) L (Switch) L1 (PS) // -> ImGuiNavInput_FocusPrev + ImGuiNavInput_TweakSlow
ImGuiKey_GamepadR1, // R Bumper (Xbox) R (Switch) R1 (PS) // -> ImGuiNavInput_FocusNext + ImGuiNavInput_TweakFast
ImGuiKey_GamepadL2, // L Trigger (Xbox) ZL (Switch) L2 (PS) [Analog]
ImGuiKey_GamepadR2, // R Trigger (Xbox) ZR (Switch) R2 (PS) [Analog]
ImGuiKey_GamepadL3, // L Thumbstick (Xbox) L3 (Switch) L3 (PS)
ImGuiKey_GamepadR3, // R Thumbstick (Xbox) R3 (Switch) R3 (PS)
ImGuiKey_GamepadLStickUp, // [Analog] // -> ImGuiNavInput_LStickUp
ImGuiKey_GamepadLStickDown, // [Analog] // -> ImGuiNavInput_LStickDown
ImGuiKey_GamepadLStickLeft, // [Analog] // -> ImGuiNavInput_LStickLeft
ImGuiKey_GamepadLStickRight, // [Analog] // -> ImGuiNavInput_LStickRight
ImGuiKey_GamepadRStickUp, // [Analog]
ImGuiKey_GamepadRStickDown, // [Analog]
ImGuiKey_GamepadRStickLeft, // [Analog]
ImGuiKey_GamepadRStickRight, // [Analog]
ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value
// Legacy range used by legacy io.KeyMap[]. Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index.
// We are ditching this method but keeping a legacy path for user code doing e.g. IsKeyPressed(MY_NATIVE_KEY_CODE)
ImGuiKey_LegacyNativeKey_BEGIN = 0,
ImGuiKey_LegacyNativeKey_END = 512, // First index after valid range
ImGuiKey_LegacyNativeKey_END = 512,
ImGuiKey_NamedKey_BEGIN = 512,
ImGuiKey_NamedKey_END = ImGuiKey_COUNT,
ImGuiKey_NamedKey_COUNT = ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN,
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
ImGuiKey_KeysData_SIZE = ImGuiKey_NamedKey_COUNT, // Size of KeysData[]: only hold named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_NamedKey_BEGIN // First key stored in KeysData[0]
ImGuiKey_KeysData_SIZE = ImGuiKey_NamedKey_COUNT, // Size of KeysData[]: only hold named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_NamedKey_BEGIN, // First key stored in KeysData[0]
#else
ImGuiKey_KeysData_SIZE = ImGuiKey_COUNT, // Size of KeysData[]: hold legacy 0..512 keycodes + named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_LegacyNativeKey_BEGIN // First key stored in KeysData[0]
ImGuiKey_KeysData_SIZE = ImGuiKey_COUNT, // Size of KeysData[]: hold legacy 0..512 keycodes + named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_LegacyNativeKey_BEGIN, // First key stored in KeysData[0]
#endif
ImGuiKey_Gamepad_BEGIN = ImGuiKey_GamepadStart,
ImGuiKey_Gamepad_END = ImGuiKey_GamepadRStickRight + 1
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter // Renamed in 1.87
@ -1624,7 +1584,7 @@ enum ImGuiBackendFlags_
// [BETA] Viewports
ImGuiBackendFlags_PlatformHasViewports = 1 << 10, // Backend Platform supports multiple viewports.
ImGuiBackendFlags_HasMouseHoveredViewport=1 << 11, // Backend Platform supports setting io.MouseHoveredViewport to the viewport directly under the mouse _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag and _REGARDLESS_ of whether another viewport is focused and may be capturing the mouse. This information is _NOT EASY_ to provide correctly with most high-level engines! Don't set this without studying _carefully_ how the backends handle ImGuiViewportFlags_NoInputs!
ImGuiBackendFlags_HasMouseHoveredViewport=1 << 11, // Backend Platform supports calling io.AddMouseViewportEvent() with the viewport under the mouse. IF POSSIBLE, ignore viewports with the ImGuiViewportFlags_NoInputs flag (Win32 backend, GLFW 3.30+ backend can do this, SDL backend cannot). If this cannot be done, Dear ImGui needs to use a flawed heuristic to find the viewport under.
ImGuiBackendFlags_RendererHasViewports = 1 << 12 // Backend Renderer supports multiple viewports.
};
@ -2004,6 +1964,7 @@ struct ImGuiKeyData
bool Down; // True for if key is down
float DownDuration; // Duration the key has been down (<0.0f: not pressed, 0.0f: just pressed, >0.0f: time held)
float DownDurationPrev; // Last frame duration the key has been down
float AnalogValue; // 0.0f..1.0f for gamepad values
};
struct ImGuiIO
@ -2047,6 +2008,7 @@ struct ImGuiIO
// Miscellaneous options
bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
@ -2081,29 +2043,24 @@ struct ImGuiIO
#endif
//------------------------------------------------------------------
// Input - Fill before calling NewFrame()
// Input - Call before calling NewFrame()
//------------------------------------------------------------------
ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.)
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all backends.
ImGuiID MouseHoveredViewport; // (Optional) When using multiple viewports: viewport the OS mouse cursor is hovering _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag, and _REGARDLESS_ of whether another viewport is focused. Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this info. If you don't imgui will infer the value using the rectangles and last focused time of the viewports it knows about (ignoring other OS windows).
bool KeyCtrl; // Keyboard modifier down: Control
bool KeyShift; // Keyboard modifier down: Shift
bool KeyAlt; // Keyboard modifier down: Alt
bool KeySuper; // Keyboard modifier down: Cmd/Super/Windows
float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs. Cleared back to zero by EndFrame(). Keyboard keys will be auto-mapped and be written here by NewFrame().
// Input Functions
IMGUI_API void AddKeyEvent(ImGuiKey key, bool down); // Queue a new key down/up event. Key should be "translated" (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
IMGUI_API void AddKeyModsEvent(ImGuiKeyModFlags modifiers);// Queue a change of Ctrl/Shift/Alt/Super modifiers
IMGUI_API void AddFocusEvent(bool focused); // Queue an hosting application/platform windows gain or loss of focus
IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate
IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string
IMGUI_API void ClearInputCharacters(); // [Internal] Clear the text input buffer manually
IMGUI_API void ClearInputKeys(); // [Internal] Release all keys
IMGUI_API void AddKeyEvent(ImGuiKey key, bool down); // Queue a new key down/up event. Key should be "translated" (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
IMGUI_API void AddKeyAnalogEvent(ImGuiKey key, bool down, float v); // Queue a new key down/up event for analog values (e.g. ImGuiKey_Gamepad_ values). Dead-zones should be handled by the backend.
IMGUI_API void AddKeyModsEvent(ImGuiKeyModFlags modifiers); // Queue a change of Ctrl/Shift/Alt/Super modifiers
IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered)
IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change
IMGUI_API void AddMouseWheelEvent(float wh_x, float wh_y); // Queue a mouse wheel update
IMGUI_API void AddMouseViewportEvent(ImGuiID id); // Queue a mouse hovered viewport. Requires backend to set ImGuiBackendFlags_HasMouseHoveredViewport to call this (for multi-viewport support).
IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window)
IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from an UTF-16 character, it can be a surrogate
IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue a new characters input from an UTF-8 string
IMGUI_API void ClearInputCharacters(); // [Internal] Clear the text input buffer manually
IMGUI_API void ClearInputKeys(); // [Internal] Release all keys
IMGUI_API void SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index = -1); // [Optional] Specify index for legacy <1.87 IsKeyXXX() functions with native indices + specify native keycode, scancode.
//------------------------------------------------------------------
@ -2138,10 +2095,24 @@ struct ImGuiIO
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
//------------------------------------------------------------------
// Main Input State
// (this block used to be written by backend, since 1.87 it is best to NOT write to those directly, call the AddXXX functions above instead)
// (reading from those variables is fair game, as they are extremely unlikely to be moving anywhere)
ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.)
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all backends.
ImGuiID MouseHoveredViewport; // (Optional) Modify using io.AddMouseViewportEvent(). With multi-viewports: viewport the OS mouse is hovering. If possible _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag is much better (few backends can handle that). Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this info. If you don't imgui will infer the value using the rectangles and last focused time of the viewports it knows about (ignoring other OS windows).
bool KeyCtrl; // Keyboard modifier down: Control
bool KeyShift; // Keyboard modifier down: Shift
bool KeyAlt; // Keyboard modifier down: Alt
bool KeySuper; // Keyboard modifier down: Cmd/Super/Windows
float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs. Cleared back to zero by EndFrame(). Keyboard keys will be auto-mapped and be written here by NewFrame().
// Other state maintained from data above + IO function calls
ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame()
ImGuiKeyModFlags KeyModsPrev; // Key mods flags (from previous frame)
ImGuiKeyData KeysData[ImGuiKey_KeysData_SIZE]; // Key state for all known keys. Use IsKeyXXX() functions to access this.
bool WantCaptureMouseUnlessPopupClose; // Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup.
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
ImVec2 MouseClickedPos[5]; // Position at time of clicking
@ -2162,6 +2133,7 @@ struct ImGuiIO
float PenPressure; // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui.
bool AppFocusLost;
ImS8 BackendUsingLegacyKeyArrays; // -1: unknown, 0: using AddKeyEvent(), 1: using legacy io.KeysDown[]
bool BackendUsingLegacyNavInputArray; // 0: using AddKeyAnalogEvent(), 1: writing to legacy io.NavInputs[] directly
ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16()
ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper.

View File

@ -207,19 +207,17 @@ namespace ImStb
// Debug Logging for selected systems. Remove the '((void)0) //' to enable.
//#define IMGUI_DEBUG_LOG_POPUP IMGUI_DEBUG_LOG // Enable log
//#define IMGUI_DEBUG_LOG_NAV IMGUI_DEBUG_LOG // Enable log
//#define IMGUI_DEBUG_LOG_IO IMGUI_DEBUG_LOG // Enable log
//#define IMGUI_DEBUG_LOG_VIEWPORT IMGUI_DEBUG_LOG // Enable log
//#define IMGUI_DEBUG_LOG_DOCKING IMGUI_DEBUG_LOG // Enable log
#define IMGUI_DEBUG_LOG_POPUP(...) ((void)0) // Disable log
#define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log
#define IMGUI_DEBUG_LOG_IO(...) ((void)0) // Disable log
#define IMGUI_DEBUG_LOG_VIEWPORT(...) ((void)0) // Disable log
#define IMGUI_DEBUG_LOG_DOCKING(...) ((void)0) // Disable log
// Static Asserts
#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100)
#define IM_STATIC_ASSERT(_COND) static_assert(_COND, "")
#else
#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1]
#endif
// "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much.
// We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code.
@ -455,6 +453,7 @@ static inline float ImInvLength(const ImVec2& lhs, float fail_value)
static inline float ImFloor(float f) { return (float)(int)(f); }
static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
static inline ImVec2 ImFloorSigned(const ImVec2& v) { return ImVec2(ImFloorSigned(v.x), ImFloorSigned(v.y)); }
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
@ -912,17 +911,62 @@ enum ImGuiPlotType
ImGuiPlotType_Histogram
};
enum ImGuiInputEventType
{
ImGuiInputEventType_None = 0,
ImGuiInputEventType_MousePos,
ImGuiInputEventType_MouseWheel,
ImGuiInputEventType_MouseButton,
ImGuiInputEventType_MouseViewport,
ImGuiInputEventType_Key,
ImGuiInputEventType_KeyMods,
ImGuiInputEventType_Char,
ImGuiInputEventType_Focus,
ImGuiInputEventType_COUNT
};
enum ImGuiInputSource
{
ImGuiInputSource_None = 0,
ImGuiInputSource_Mouse,
ImGuiInputSource_Keyboard,
ImGuiInputSource_Gamepad,
ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
ImGuiInputSource_Clipboard, // Currently only used by InputText()
ImGuiInputSource_Clipboard, // Currently only used by InputText()
ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
ImGuiInputSource_COUNT
};
// FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension?
// Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor'
struct ImGuiInputEventMousePos { float PosX, PosY; };
struct ImGuiInputEventMouseWheel { float WheelX, WheelY; };
struct ImGuiInputEventMouseButton { int Button; bool Down; };
struct ImGuiInputEventMouseViewport { ImGuiID HoveredViewportID; };
struct ImGuiInputEventKey { ImGuiKey Key; bool Down; float AnalogValue; };
struct ImGuiInputEventKeyMods { ImGuiKeyModFlags Mods; };
struct ImGuiInputEventText { unsigned int Char; };
struct ImGuiInputEventAppFocused { bool Focused; };
struct ImGuiInputEvent
{
ImGuiInputEventType Type;
ImGuiInputSource Source;
union
{
ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos
ImGuiInputEventMouseWheel MouseWheel; // if Type == ImGuiInputEventType_MouseWheel
ImGuiInputEventMouseButton MouseButton; // if Type == ImGuiInputEventType_MouseButton
ImGuiInputEventMouseViewport MouseViewport; // if Type == ImGuiInputEventType_MouseViewport
ImGuiInputEventKey Key; // if Type == ImGuiInputEventType_Key
ImGuiInputEventKeyMods KeyMods; // if Type == ImGuiInputEventType_Modifiers
ImGuiInputEventText Text; // if Type == ImGuiInputEventType_Text
ImGuiInputEventAppFocused AppFocused; // if Type == ImGuiInputEventType_Focus
};
bool AddedByTestEngine;
ImGuiInputEvent() { memset(this, 0, sizeof(*this)); }
};
// FIXME-NAV: Clarify/expose various repeat delay/rate
enum ImGuiInputReadMode
{
@ -1676,6 +1720,8 @@ struct ImGuiContext
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
ImGuiIO IO;
ImGuiPlatformIO PlatformIO;
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be tricked/written into IO structure.
ImVector<ImGuiInputEvent> InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail.
ImGuiStyle Style;
ImGuiConfigFlags ConfigFlagsCurrFrame; // = g.IO.ConfigFlags at the time of NewFrame()
ImGuiConfigFlags ConfigFlagsLastFrame;
@ -2515,7 +2561,7 @@ struct IMGUI_API ImGuiTable
ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is
ImRect WorkRect;
ImRect InnerClipRect;
ImRect BgClipRect; // We use this to cpu-clip cell background color fill
ImRect BgClipRect; // We use this to cpu-clip cell background color fill, evolve during the frame as we cross frozen rows boundaries
ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
@ -2682,6 +2728,7 @@ namespace ImGui
IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext().
// NewFrame
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock_floating_node);
@ -2830,7 +2877,8 @@ namespace ImGui
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; }
inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; }
IMGUI_API const ImGuiKeyData* GetKeyData(ImGuiKey key);
inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; }
IMGUI_API ImGuiKeyData* GetKeyData(ImGuiKey key);
IMGUI_API void SetItemUsingMouseWheel();
IMGUI_API void SetActiveIdUsingNavAndKeys();
inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; }
@ -3050,7 +3098,7 @@ namespace ImGui
IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type);
IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format);
IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format);
IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format);
IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max);

View File

@ -1569,18 +1569,21 @@ ImGuiTableColumnFlags ImGui::TableGetColumnFlags(int column_n)
// Return the cell rectangle based on currently known height.
// - Important: we generally don't know our row height until the end of the row, so Max.y will be incorrect in many situations.
// The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it.
// The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it, or in TableEndRow() when we locked that height.
// - Important: if ImGuiTableFlags_PadOuterX is set but ImGuiTableFlags_PadInnerX is not set, the outer-most left and right
// columns report a small offset so their CellBgRect can extend up to the outer border.
// FIXME: But the rendering code in TableEndRow() nullifies that with clamping required for scrolling.
ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n)
{
const ImGuiTableColumn* column = &table->Columns[column_n];
float x1 = column->MinX;
float x2 = column->MaxX;
if (column->PrevEnabledColumn == -1)
x1 -= table->CellSpacingX1;
if (column->NextEnabledColumn == -1)
x2 += table->CellSpacingX2;
//if (column->PrevEnabledColumn == -1)
// x1 -= table->OuterPaddingX;
//if (column->NextEnabledColumn == -1)
// x2 += table->OuterPaddingX;
x1 = ImMax(x1, table->WorkRect.Min.x);
x2 = ImMin(x2, table->WorkRect.Max.x);
return ImRect(x1, table->RowPosY1, x2, table->RowPosY2);
}
@ -1797,10 +1800,12 @@ void ImGui::TableEndRow(ImGuiTable* table)
ImGuiTableCellData* cell_data_end = &table->RowCellData[table->RowCellDataCurrent];
for (ImGuiTableCellData* cell_data = &table->RowCellData[0]; cell_data <= cell_data_end; cell_data++)
{
// As we render the BG here we need to clip things (for layout we would not)
// FIXME: This cancels the OuterPadding addition done by TableGetCellBgRect(), need to keep it while rendering correctly while scrolling.
const ImGuiTableColumn* column = &table->Columns[cell_data->Column];
ImRect cell_bg_rect = TableGetCellBgRect(table, cell_data->Column);
cell_bg_rect.ClipWith(table->BgClipRect);
cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped
cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped when scrolling
cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX);
window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor);
}

View File

@ -2000,24 +2000,10 @@ void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const
// User can input math operators (e.g. +100) to edit a numerical values.
// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format)
bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format)
{
while (ImCharIsBlankA(*buf))
buf++;
// We don't support '-' op because it would conflict with inputing negative value.
// Instead you can use +-100 to subtract from an existing value
char op = buf[0];
if (op == '+' || op == '*' || op == '/')
{
buf++;
while (ImCharIsBlankA(*buf))
buf++;
}
else
{
op = 0;
}
if (!buf[0])
return false;
@ -2029,54 +2015,11 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
if (format == NULL)
format = type_info->ScanFmt;
// FIXME-LEGACY: The aim is to remove those operators and write a proper expression evaluator at some point..
int arg1i = 0;
if (data_type == ImGuiDataType_S32)
if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64 || data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
{
int* v = (int*)p_data;
int arg0i = *v;
float arg1f = 0.0f;
if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
return false;
// Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract)
else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply
else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide
else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant
}
else if (data_type == ImGuiDataType_Float)
{
// For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
format = "%f";
float* v = (float*)p_data;
float arg0f = *v, arg1f = 0.0f;
if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
return false;
if (sscanf(buf, format, &arg1f) < 1)
return false;
if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
else if (op == '*') { *v = arg0f * arg1f; } // Multiply
else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
else { *v = arg1f; } // Assign constant
}
else if (data_type == ImGuiDataType_Double)
{
format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
double* v = (double*)p_data;
double arg0f = *v, arg1f = 0.0;
if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
return false;
if (sscanf(buf, format, &arg1f) < 1)
return false;
if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
else if (op == '*') { *v = arg0f * arg1f; } // Multiply
else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
else { *v = arg1f; } // Assign constant
}
else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
{
// All other types assign constant
// We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
// For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
format = type_info->ScanFmt;
if (sscanf(buf, format, p_data) < 1)
return false;
}
@ -3395,8 +3338,6 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
// However this may not be ideal for all uses, as some user code may break on out of bound values.
bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
{
ImGuiContext& g = *GImGui;
char fmt_buf[32];
char data_buf[32];
format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
@ -3414,7 +3355,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
memcpy(&data_backup, p_data, data_type_size);
// Apply new value (or operations) then clamp
DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL);
DataTypeApplyFromText(data_buf, data_type, p_data, NULL);
if (p_clamp_min || p_clamp_max)
{
if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
@ -3461,7 +3402,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
PushID(label);
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
// Step buttons
const ImVec2 backup_frame_padding = style.FramePadding;
@ -3498,7 +3439,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
else
{
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
}
if (value_changed)
MarkItemEdited(g.LastItemData.ID);

View File

@ -58,10 +58,7 @@ bool EventHandler::handleEvent(SDL_Event &event) {
break;
}
SDL_Window *window = SDL_GetWindowFromID(event.motion.windowID);
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) == 0u) {
break;
}
mouseMotion(event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
mouseMotion((void*)window, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
}
case SDL_MOUSEBUTTONDOWN:
@ -256,9 +253,9 @@ void EventHandler::mouseWheel(int32_t x, int32_t y) {
}
}
void EventHandler::mouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) {
void EventHandler::mouseMotion(void *windowHandle, int32_t x, int32_t y, int32_t relX, int32_t relY) {
for (IEventObserver* observer : _observers) {
observer->onMouseMotion(x, y, relX, relY);
observer->onMouseMotion(windowHandle, x, y, relX, relY);
}
}

View File

@ -62,7 +62,7 @@ public:
*/
void controllerMotion(uint8_t axis, int value, uint32_t id);
void mouseWheel(int32_t x, int32_t y);
void mouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY);
void mouseMotion(void *windowHandle, int32_t x, int32_t y, int32_t relX, int32_t relY);
void mouseButtonPress(int32_t x, int32_t y, uint8_t button, uint8_t clicks);
void mouseButtonRelease(int32_t x, int32_t y, uint8_t button);
void dropFile(const core::String& file);

View File

@ -48,7 +48,7 @@ public:
return false;
}
virtual void onMouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) {
virtual void onMouseMotion(void *windowHandle, int32_t x, int32_t y, int32_t relX, int32_t relY) {
}
virtual void onMouseButtonPress(int32_t x, int32_t y, uint8_t button, uint8_t clicks) {

View File

@ -201,9 +201,6 @@ app::AppState WindowedApp::onInit() {
return app::AppState::InitFailure;
}
SDL_EventState(SDL_MOUSEMOTION, SDL_DISABLE);
SDL_StopTextInput();
if (!_keybindingHandler.init()) {
Log::error("Failed to initialize the key binding handler");
return app::AppState::InitFailure;
@ -372,25 +369,6 @@ app::AppState WindowedApp::onInit() {
video::init(_windowDimension.x, _windowDimension.y, scaleFactor);
video::viewport(0, 0, _frameBufferDimension.x, _frameBufferDimension.y);
if (isSingleWindowMode()) {
_mouseCanUseGlobalState = false;
} else {
#if 0
// Check and store if we are on a SDL backend that supports global mouse position
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
const char *sdlBackend = SDL_GetCurrentVideoDriver();
const char *globalMouseWhitelist[] = {"windows", "cocoa", "x11", "DIVE", "VMAN"};
for (int n = 0; n < lengthof(globalMouseWhitelist); ++n) {
if (strncmp(sdlBackend, globalMouseWhitelist[n], strlen(globalMouseWhitelist[n])) == 0) {
_mouseCanUseGlobalState = true;
}
}
#else
// TODO: the window (0:0) the mouse is hovering is on SDL display 0 (0:0:2560:1440), but the global mouse position is at 3646:769
_mouseCanUseGlobalState = false;
#endif
}
video_trace_init();
return state;

View File

@ -51,7 +51,6 @@ protected:
* Will block the event queue if the window is minimized of hidden
*/
bool _powerSaveMode = true;
bool _mouseCanUseGlobalState = false;
util::KeyBindingHandler _keybindingHandler;
/**
@ -61,7 +60,7 @@ protected:
WindowedApp(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider, size_t threadPoolSize = 1);
bool handleSDLEvent(SDL_Event& event);
virtual bool handleSDLEvent(SDL_Event& event);
bool handleKeyPress(int32_t key, int16_t modifier, uint16_t count = 1u);
bool handleKeyRelease(int32_t key, int16_t modifier);

View File

@ -3,7 +3,6 @@
*/
#include "TestAnimation.h"
#include "ui/imgui/IMGUI.h"
#include "voxel/MaterialColor.h"
#include "Shared_generated.h"
#include "animation/Animation.h"

View File

@ -76,7 +76,7 @@ Index of this file:
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "ui/imgui/IMGUI.h"
#include "imgui.h"
#ifndef IMGUI_DISABLE
// System includes
@ -93,6 +93,7 @@ Index of this file:
// Visual Studio warnings
#ifdef _MSC_VER
#pragma warning (disable: 4127) // condition expression is constant
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
#endif
@ -240,7 +241,6 @@ void ImGui::ShowUserGuide()
ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
ImGui::BulletText("ESCAPE to revert.");
ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
ImGui::Unindent();
ImGui::BulletText("With keyboard navigation enabled:");
ImGui::Indent();
@ -513,8 +513,10 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Unindent();
}
ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue);
ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.");
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)");
ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
@ -535,6 +537,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
"Here we expose them as read-only fields to avoid breaking interactions with your backend.");
// Make a local copy to avoid modifying actual backend flags.
// FIXME: We don't use BeginDisabled() to keep label bright, maybe we need a BeginReadonly() equivalent..
ImGuiBackendFlags backend_flags = io.BackendFlags;
ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad);
ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors);
@ -731,10 +734,6 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
static int i0 = 123;
ImGui::InputInt("input int", &i0);
ImGui::SameLine(); HelpMarker(
"You can apply arithmetic operators +,*,/ on numerical values.\n"
" e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n"
"Use +- to subtract.");
static float f0 = 0.001f;
ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
@ -5712,7 +5711,7 @@ static void ShowDemoWindowColumns()
ImGui::TreePop();
}
namespace ImGui { extern const ImGuiKeyData* GetKeyData(ImGuiKey key); }
namespace ImGui { extern ImGuiKeyData* GetKeyData(ImGuiKey key); }
static void ShowDemoWindowMisc()
{
@ -5767,22 +5766,23 @@ static void ShowDemoWindowMisc()
}
// Display Keyboard/Mouse state
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Keyboard & Navigation State");
if (ImGui::TreeNode("Keyboard & Navigation State"))
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Keyboard, Gamepad & Navigation State");
if (ImGui::TreeNode("Keyboard, Gamepad & Navigation State"))
{
// We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allow displaying the data for old/new backends.
// User code should never have to go through such hoops: old code may use native keycodes, new code may use ImGuiKey codes.
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
struct funcs { static bool IsNativeDupe(ImGuiKey) { return false; } };
const ImGuiKey key_first = ImGuiKey_NamedKey_BEGIN;
#else
struct funcs { static bool IsNativeDupe(ImGuiKey key) { return key < ImGuiKey_LegacyNativeKey_END && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
const ImGuiKey key_first = 0;
#endif
ImGui::Text("Keys down:"); for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++) { ImGuiKey key = (ImGuiKey)(i + ImGuiKey_KeysData_OFFSET); if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (0x%X) (%.02f secs)", ImGui::GetKeyName(key), key, key, ImGui::GetKeyData(key)->DownDuration); } }
ImGui::Text("Keys pressed:"); for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++) { ImGuiKey key = (ImGuiKey)(i + ImGuiKey_KeysData_OFFSET); if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyPressed(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (0x%X)", ImGui::GetKeyName(key), key, key); } }
ImGui::Text("Keys released:"); for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++) { ImGuiKey key = (ImGuiKey)(i + ImGuiKey_KeysData_OFFSET); if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyReleased(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (0x%X)", ImGui::GetKeyName(key), key, key); } }
ImGui::Text("Keys down:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (%.02f secs)", ImGui::GetKeyName(key), key, ImGui::GetKeyData(key)->DownDuration); } }
ImGui::Text("Keys pressed:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyPressed(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
ImGui::Text("Keys released:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyReleased(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); }
ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
ImGui::TreePop();

View File

@ -5,7 +5,6 @@
#pragma once
#include "ui/imgui/IMGUIApp.h"
#include "ui/imgui/IMGUI.h"
/**
* @brief Renders the imgui demo

View File

@ -2,7 +2,6 @@
* @file
*/
#include "TestOctree.h"
#include "ui/imgui/IMGUI.h"
#include "core/Color.h"
#include "video/ScopedLineWidth.h"
#include "core/collection/Array.h"

View File

@ -3,7 +3,6 @@
*/
#include "TestOctreeVisit.h"
#include "ui/imgui/IMGUI.h"
#include "math/AABB.h"
#include "video/ScopedLineWidth.h"
#include "core/Color.h"

View File

@ -17,7 +17,6 @@
#include "voxel/Voxel.h"
#include "compute/Compute.h"
#include "io/Filesystem.h"
#include "ui/imgui/IMGUI.h"
#include "voxel/MaterialColor.h"
#include "voxelgenerator/Spiral.h"
#include "attrib/Attributes.h"

View File

@ -5,7 +5,7 @@
#include "AnimationPanel.h"
#include "core/Trace.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
namespace voxedit {

View File

@ -4,7 +4,7 @@
#include "CursorPanel.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
namespace voxedit {

View File

@ -4,7 +4,7 @@
#include "LSystemPanel.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
namespace voxedit {

View File

@ -7,7 +7,7 @@
#include "core/collection/DynamicArray.h"
#include "voxedit-util/Config.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "voxelformat/SceneGraphNode.h"
#define LAYERPOPUP "##layerpopup"

View File

@ -12,7 +12,7 @@
#include "ui/imgui/IconsFontAwesome5.h"
#include "ui/imgui/IMGUIApp.h"
#include "ui/imgui/FileDialog.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "voxedit-util/Config.h"
#include "voxedit-util/SceneManager.h"
#include "voxedit-util/anim/AnimationLuaSaver.h"
@ -20,6 +20,7 @@
#include "voxel/MaterialColor.h"
#include "voxelformat/VolumeFormat.h"
#include <glm/gtc/type_ptr.hpp>
#include "ui/imgui/dearimgui/imgui_internal.h"
#define TITLE_STATUSBAR "##statusbar"
#define TITLE_PALETTE "Palette##title"
@ -369,7 +370,7 @@ void MainWindow::update() {
core_trace_scoped(MainWindow);
const ImVec2 pos(0.0f, 0.0f);
ImGuiViewport *viewport = ImGui::GetMainViewport();
const float statusBarHeight = ImGui::Size((float)_app->fontSize()) + 16.0f;
const float statusBarHeight = (float)_app->fontSize() + 16.0f;
if (_lastOpenedFile->isDirty()) {
_lastOpenedFile->markClean();

View File

@ -6,7 +6,7 @@
#include "core/StringUtil.h"
#include "math/Axis.h"
#include "ui/imgui/IMGUIApp.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "ui/imgui/TextEditor.h"
#include "voxedit-ui/AnimationPanel.h"
#include "voxedit-ui/CursorPanel.h"

View File

@ -4,7 +4,7 @@
#include "MenuBar.h"
#include "core/GameConfig.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "ui/imgui/IconsForkAwesome.h"
#include "ui/imgui/IconsFontAwesome5.h"
#include "voxedit-util/Config.h"

View File

@ -4,7 +4,7 @@
#include "ModifierPanel.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "ui/imgui/IconsForkAwesome.h"
#include "ui/imgui/IconsFontAwesome5.h"

View File

@ -4,7 +4,7 @@
#include "NoisePanel.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
namespace voxedit {

View File

@ -5,7 +5,7 @@
#include "PalettePanel.h"
#include "core/StringUtil.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#define POPUP_TITLE_LOAD_PALETTE "Select Palette##popuptitle"
#define PALETTEACTIONPOPUP "##paletteactionpopup"
@ -36,14 +36,14 @@ void PalettePanel::update(const char *title, command::CommandExecutionListener &
const voxel::MaterialColorArray &colors = voxel::getMaterialColors();
const int maxPaletteEntries = (int)colors.size();
const float height = ImGui::GetContentRegionMax().y;
const ImVec2 windowSize(ImGui::Size(120.0f), height);
const ImVec2 windowSize(120.0f, height);
ImGui::SetNextWindowSize(windowSize, ImGuiCond_FirstUseEver);
const int currentSceneHoveredPalIdx = sceneMgr().hitCursorVoxel().getColor();
const int currentSelectedPalIdx = sceneMgr().modifier().cursorVoxel().getColor();
_hasFocus = false;
if (ImGui::Begin(title, nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse)) {
_hasFocus = ImGui::IsWindowHovered();
const ImVec2 colorButtonSize(ImGui::Size(20), ImGui::Size(20));
const ImVec2 colorButtonSize(20, 20);
const ImVec2 &pos = ImGui::GetCursorScreenPos();
bool colorHovered = false;
ImDrawList* drawList = ImGui::GetWindowDrawList();

View File

@ -3,7 +3,7 @@
*/
#include "SceneGraphPanel.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "voxedit-util/SceneManager.h"
#include "voxelformat/SceneGraph.h"
#include "voxelformat/SceneGraphNode.h"

View File

@ -7,7 +7,7 @@
#include "core/StringUtil.h"
#include "glm/ext/scalar_constants.hpp"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "ui/imgui/IconsForkAwesome.h"
#include "ui/imgui/IconsFontAwesome5.h"
@ -52,7 +52,7 @@ void ScriptPanel::update(const char *title, const char *scriptEditorTitle, ui::i
core::String &str = _scriptParameters[i];
int val = core::string::toInt(str);
if (val >= 0 && val < (int)colors.size()) {
const float size = ImGui::Size(20);
const float size = 20;
const ImVec2 v1(ImGui::GetWindowPos().x + ImGui::GetCursorPosX(), ImGui::GetWindowPos().y + ImGui::GetCursorPosY());
const ImVec2 v2(v1.x + size, v1.y + size);
ImDrawList* drawList = ImGui::GetWindowDrawList();

View File

@ -9,7 +9,7 @@
#include "voxedit-util/Config.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/Console.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "ui/imgui/IMGUIApp.h"
namespace voxedit {
@ -112,7 +112,7 @@ void StatusBar::update(const char *title, float height, const core::String &last
}
ImGui::SameLine();
ImGui::SetCursorPosX(size.x / fields * 3.0f);
ImGui::SetNextItemWidth(ImGui::Size(140.0f));
ImGui::SetNextItemWidth(140.0f);
ImGui::InputVarInt("Grid size", cfg::VoxEditGridsize);
ImGui::SameLine();
ImGui::CheckboxVar("Grayscale", cfg::VoxEditGrayInactive);

View File

@ -3,7 +3,7 @@
*/
#include "ToolsPanel.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "ui/imgui/IconsForkAwesome.h"
#include "voxedit-util/SceneManager.h"

View File

@ -4,7 +4,7 @@
#include "TreePanel.h"
#include "voxedit-util/SceneManager.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
namespace voxedit {

View File

@ -8,7 +8,7 @@
#include "core/Color.h"
#include "core/Common.h"
#include "core/Var.h"
#include "ui/imgui/IMGUI.h"
#include "ui/imgui/IMGUIEx.h"
#include "ui/imgui/IMGUIApp.h"
#include "io/Filesystem.h"
#include "video/ShapeBuilder.h"
@ -103,7 +103,7 @@ void Viewport::update() {
}
const float height = (float)app->fontSize() + ImGui::GetStyle().FramePadding.y * 2.0f;
const float maxWidth = ImGui::Size(200.0f);
const float maxWidth = 200.0f;
const ImVec2 windowSize = ImGui::GetWindowSize();
ImGui::SetCursorPos(ImVec2(0.0f, windowSize.y - height));
ImGui::SetNextItemWidth(maxWidth);