Compare commits

..

1 Commits

28 changed files with 847 additions and 451 deletions

View File

@ -37,10 +37,14 @@ jobs:
- name: Fix Projects
shell: powershell
run: |
# CI workers do not supporter older Visual Studio versions. Fix projects to target newer available version.
# WARNING: This will need updating if toolset/sdk change in project files!
gci -recurse -filter "*.vcxproj" | ForEach-Object {
(Get-Content $_.FullName) -Replace "<PlatformToolset>v\d{3}</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>[\d\.]+</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
# Fix SDK and toolset for most samples.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
}
# Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long.
@ -493,3 +497,34 @@ jobs:
run: |
cd examples/example_android_opengl3/android
gradle assembleDebug
Discord-CI:
runs-on: ubuntu-18.04
if: always()
needs: [Windows, Linux, MacOS, iOS, Emscripten, Android]
steps:
- uses: dearimgui/github_discord_notifier@latest
with:
discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
github-token: ${{ github.token }}
action-task: discord-jobs
discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
discord-username: GitHub Actions
discord-job-new-failure-message: ''
discord-job-fixed-failure-message: ''
discord-job-new-failure-embed: |
{
"title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
"description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke [{{ job.name }}]({{ job.url }}) build job.\nFailing steps: {{ failing_steps }}",
"url": "{{ job.url }}",
"color": "0xFF0000",
"timestamp": "{{ run.updated_at }}"
}
discord-job-fixed-failure-embed: |
{
"title": "`{{ github.branch }}` branch is no longer failing!",
"description": "Build failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
"color": "0x00FF00",
"url": "{{ github.context.payload.head_commit.url }}",
"timestamp": "{{ run.completed_at }}"
}

View File

@ -270,7 +270,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
bd->PrevUserCallbackWindowFocus = NULL;
bd->PrevUserCallbackCursorEnter = NULL;
bd->PrevUserCallbackMousebutton = NULL;
bd->PrevUserCallbackScroll = NULL;
bd->PrevUserCallbackKey = NULL;

View File

@ -0,0 +1,318 @@
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
// Implemented features:
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
// Missing features:
// [ ] Renderer: Clipping rectangles are not honored.
// 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
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-08: Renderer: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
#include "imgui.h"
#include "imgui_impl_marmalade.h"
#include <s3eClipboard.h>
#include <s3ePointer.h>
#include <s3eKeyboard.h>
#include <IwTexture.h>
#include <IwGx.h>
// Data
static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false };
static CIwTexture* g_FontTexture = NULL;
static char* g_ClipboardText = NULL;
static bool g_osdKeyboardEnabled = false;
// use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor
static ImVec2 g_RenderScale = ImVec2(1.0f, 1.0f);
// Render function.
void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
const int nVert = cmd_list->VtxBuffer.Size;
CIwFVec2* pVertStream = IW_GX_ALLOC(CIwFVec2, nVert);
CIwFVec2* pUVStream = IW_GX_ALLOC(CIwFVec2, nVert);
CIwColour* pColStream = IW_GX_ALLOC(CIwColour, nVert);
for (int i = 0; i < nVert; i++)
{
// FIXME-OPT: optimize multiplication on GPU using vertex shader/projection matrix.
pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x;
pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y;
pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x;
pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y;
pColStream[i] = cmd_list->VtxBuffer[i].col;
}
IwGxSetVertStreamScreenSpace(pVertStream, nVert);
IwGxSetUVStream(pUVStream);
IwGxSetColStream(pColStream, nVert);
IwGxSetNormStream(0);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// FIXME: Not honoring ClipRect fields.
CIwMaterial* pCurrentMaterial = IW_GX_ALLOC_MATERIAL();
pCurrentMaterial->SetShadeMode(CIwMaterial::SHADE_FLAT);
pCurrentMaterial->SetCullMode(CIwMaterial::CULL_NONE);
pCurrentMaterial->SetFiltering(false);
pCurrentMaterial->SetAlphaMode(CIwMaterial::ALPHA_BLEND);
pCurrentMaterial->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_NORMAL);
pCurrentMaterial->SetAlphaTestMode(CIwMaterial::ALPHATEST_DISABLED);
pCurrentMaterial->SetTexture((CIwTexture*)pcmd->GetTexID());
IwGxSetMaterial(pCurrentMaterial);
IwGxDrawPrims(IW_GX_TRI_LIST, (uint16*)(idx_buffer + pcmd->IdxOffset), pcmd->ElemCount);
}
}
IwGxFlush();
}
// TODO: restore modified state (i.e. mvp matrix)
}
static const char* ImGui_Marmalade_GetClipboardText(void* /*user_data*/)
{
if (!s3eClipboardAvailable())
return NULL;
if (int size = s3eClipboardGetText(NULL, 0))
{
if (g_ClipboardText)
delete[] g_ClipboardText;
g_ClipboardText = new char[size];
g_ClipboardText[0] = '\0';
s3eClipboardGetText(g_ClipboardText, size);
}
return g_ClipboardText;
}
static void ImGui_Marmalade_SetClipboardText(void* /*user_data*/, const char* text)
{
if (s3eClipboardAvailable())
s3eClipboardSetText(text);
}
int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data)
{
// pEvent->m_Button is of type s3ePointerButton and indicates which mouse
// button was pressed. For touchscreen this should always have the value
// S3E_POINTER_BUTTON_SELECT
s3ePointerEvent* pEvent = (s3ePointerEvent*)system_data;
if (pEvent->m_Pressed == 1)
{
if (pEvent->m_Button == S3E_POINTER_BUTTON_LEFTMOUSE)
g_MousePressed[0] = true;
if (pEvent->m_Button == S3E_POINTER_BUTTON_RIGHTMOUSE)
g_MousePressed[1] = true;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE)
g_MousePressed[2] = true;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP)
io.MouseWheel += pEvent->m_y;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN)
io.MouseWheel += pEvent->m_y;
}
return 0;
}
int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
s3eKeyboardEvent* e = (s3eKeyboardEvent*)system_data;
if (e->m_Pressed == 1)
io.KeysDown[e->m_Key] = true;
if (e->m_Pressed == 0)
io.KeysDown[e->m_Key] = false;
io.KeyCtrl = s3eKeyboardGetState(s3eKeyLeftControl) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightControl) == S3E_KEY_STATE_DOWN;
io.KeyShift = s3eKeyboardGetState(s3eKeyLeftShift) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightShift) == S3E_KEY_STATE_DOWN;
io.KeyAlt = s3eKeyboardGetState(s3eKeyLeftAlt) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightAlt) == S3E_KEY_STATE_DOWN;
io.KeySuper = s3eKeyboardGetState(s3eKeyLeftWindows) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightWindows) == S3E_KEY_STATE_DOWN;
return 0;
}
int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data;
io.AddInputCharacter((unsigned int)e->m_Char);
return 0;
}
bool ImGui_Marmalade_CreateDeviceObjects()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system
g_FontTexture = new CIwTexture();
g_FontTexture->SetModifiable(true);
CIwImage& image = g_FontTexture->GetImage();
image.SetFormat(CIwImage::ARGB_8888);
image.SetWidth(width);
image.SetHeight(height);
image.SetBuffers(); // allocates and own buffers
image.ReadTexels(pixels);
g_FontTexture->SetMipMapping(false);
g_FontTexture->SetFiltering(false);
g_FontTexture->Upload();
// Store our identifier
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
return true;
}
void ImGui_Marmalade_InvalidateDeviceObjects()
{
if (g_ClipboardText)
{
delete[] g_ClipboardText;
g_ClipboardText = NULL;
}
if (g_FontTexture)
{
ImGui::GetIO().Fonts->SetTexID(0);
delete g_FontTexture;
g_FontTexture = NULL;
}
}
bool ImGui_Marmalade_Init(bool install_callbacks)
{
ImGuiIO& io = ImGui::GetIO();
io.BackendPlatformName = io.BackendRendererName = "imgui_impl_marmalade";
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = s3eKeyTab
io.KeyMap[ImGuiKey_LeftArrow] = s3eKeyLeft;
io.KeyMap[ImGuiKey_RightArrow] = s3eKeyRight;
io.KeyMap[ImGuiKey_UpArrow] = s3eKeyUp;
io.KeyMap[ImGuiKey_DownArrow] = s3eKeyDown;
io.KeyMap[ImGuiKey_PageUp] = s3eKeyPageUp;
io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown;
io.KeyMap[ImGuiKey_Home] = s3eKeyHome;
io.KeyMap[ImGuiKey_End] = s3eKeyEnd;
io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert;
io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete;
io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace;
io.KeyMap[ImGuiKey_Space] = s3eKeySpace;
io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter;
io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc;
io.KeyMap[ImGuiKey_KeyPadEnter] = s3eKeyNumPadEnter;
io.KeyMap[ImGuiKey_A] = s3eKeyA;
io.KeyMap[ImGuiKey_C] = s3eKeyC;
io.KeyMap[ImGuiKey_V] = s3eKeyV;
io.KeyMap[ImGuiKey_X] = s3eKeyX;
io.KeyMap[ImGuiKey_Y] = s3eKeyY;
io.KeyMap[ImGuiKey_Z] = s3eKeyZ;
io.SetClipboardTextFn = ImGui_Marmalade_SetClipboardText;
io.GetClipboardTextFn = ImGui_Marmalade_GetClipboardText;
if (install_callbacks)
{
s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, ImGui_Marmalade_PointerButtonEventCallback, 0);
s3eKeyboardRegister(S3E_KEYBOARD_KEY_EVENT, ImGui_Marmalade_KeyCallback, 0);
s3eKeyboardRegister(S3E_KEYBOARD_CHAR_EVENT, ImGui_Marmalade_CharCallback, 0);
}
return true;
}
void ImGui_Marmalade_Shutdown()
{
ImGui_Marmalade_InvalidateDeviceObjects();
}
void ImGui_Marmalade_NewFrame()
{
if (!g_FontTexture)
ImGui_Marmalade_CreateDeviceObjects();
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
int w = IwGxGetScreenWidth(), h = IwGxGetScreenHeight();
io.DisplaySize = ImVec2((float)w, (float)h);
// For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
io.DisplayFramebufferScale = g_scale;
// Setup time step
double current_time = s3eTimerGetUST() / 1000.0f;
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
g_Time = current_time;
double mouse_x, mouse_y;
mouse_x = s3ePointerGetX();
mouse_y = s3ePointerGetY();
io.MousePos = ImVec2((float)mouse_x / g_scale.x, (float)mouse_y / g_scale.y); // Mouse position (set to -FLT_MAX,-FLT_MAX if no mouse / on another screen, etc.)
for (int i = 0; i < 3; i++)
{
io.MouseDown[i] = g_MousePressed[i] || s3ePointerGetState((s3ePointerButton)i) != S3E_POINTER_STATE_UP; // 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.
g_MousePressed[i] = false;
}
// TODO: Hide OS mouse cursor if ImGui is drawing it
// s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1));
// Show/hide OSD keyboard
if (io.WantTextInput)
{
// Some text input widget is active?
if (!g_osdKeyboardEnabled)
{
g_osdKeyboardEnabled = true;
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 1); // show OSD keyboard
}
}
else
{
// No text input widget is active
if (g_osdKeyboardEnabled)
{
g_osdKeyboardEnabled = false;
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 0); // hide OSD keyboard
}
}
}

View File

@ -0,0 +1,28 @@
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
// Implemented features:
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
// 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
IMGUI_IMPL_API bool ImGui_Marmalade_Init(bool install_callbacks);
IMGUI_IMPL_API void ImGui_Marmalade_Shutdown();
IMGUI_IMPL_API void ImGui_Marmalade_NewFrame();
IMGUI_IMPL_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_Marmalade_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_Marmalade_CreateDeviceObjects();
// Callbacks (installed by default if you enable 'install_callbacks' during initialization)
// You can also handle inputs yourself and use those as a reference.
IMGUI_IMPL_API int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data);
IMGUI_IMPL_API int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data);
IMGUI_IMPL_API int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data);

View File

@ -14,7 +14,6 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@ -175,8 +174,6 @@ struct ImGui_ImplOpenGL3_Data
GLuint AttribLocationVtxUV;
GLuint AttribLocationVtxColor;
unsigned int VboHandle, ElementsHandle;
GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize;
bool HasClipOrigin;
ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); }
@ -428,20 +425,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
const ImDrawList* cmd_list = draw_data->CmdLists[n];
// Upload vertex/index buffers
GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
if (bd->VertexBufferSize < vtx_buffer_size)
{
bd->VertexBufferSize = vtx_buffer_size;
glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW);
}
if (bd->IndexBufferSize < idx_buffer_size)
{
bd->IndexBufferSize = idx_buffer_size;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW);
}
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{

View File

@ -249,13 +249,11 @@ typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
#endif
#endif /* GL_VERSION_1_5 */
#ifndef GL_VERSION_2_0
@ -449,7 +447,6 @@ union GL3WProcs {
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
PFNGLBUFFERDATAPROC BufferData;
PFNGLBUFFERSUBDATAPROC BufferSubData;
PFNGLCLEARPROC Clear;
PFNGLCLEARCOLORPROC ClearColor;
PFNGLCOMPILESHADERPROC CompileShader;
@ -509,7 +506,6 @@ GL3W_API extern union GL3WProcs imgl3wProcs;
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
#define glBufferData imgl3wProcs.gl.BufferData
#define glBufferSubData imgl3wProcs.gl.BufferSubData
#define glClear imgl3wProcs.gl.Clear
#define glClearColor imgl3wProcs.gl.ClearColor
#define glCompileShader imgl3wProcs.gl.CompileShader
@ -696,7 +692,6 @@ static const char *proc_names[] = {
"glBlendEquationSeparate",
"glBlendFuncSeparate",
"glBufferData",
"glBufferSubData",
"glClear",
"glClearColor",
"glCompileShader",

View File

@ -5,10 +5,10 @@
// Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space).
// Issues:
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// 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
@ -18,7 +18,7 @@
@class NSEvent;
@class NSView;
IMGUI_IMPL_API bool ImGui_ImplOSX_Init(NSView* _Nonnull view);
IMGUI_IMPL_API bool ImGui_ImplOSX_Init();
IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown();
IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view);
IMGUI_IMPL_API bool ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view);

View File

@ -5,25 +5,21 @@
// Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space).
// Issues:
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
// 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
#import "imgui.h"
#import "imgui_impl_osx.h"
#include "imgui.h"
#include "imgui_impl_osx.h"
#import <Cocoa/Cocoa.h>
#import <mach/mach_time.h>
#import <Carbon/Carbon.h>
#import <GameController/GameController.h>
#include <mach/mach_time.h>
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-13: *BREAKING CHANGE* Add NSView parameter to ImGui_ImplOSX_Init(). Generally fix keyboard support. Using kVK_* codes for keyboard keys.
// 2021-12-13: Add game controller support.
// 2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards.
// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events.
// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key.
@ -41,17 +37,15 @@
// 2018-07-07: Initial version.
@class ImFocusObserver;
@class KeyEventResponder;
// Data
static double g_HostClockPeriod = 0.0;
static double g_Time = 0.0;
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_MouseCursorHidden = false;
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
static ImFocusObserver* g_FocusObserver = nil;
static KeyEventResponder* g_KeyEventResponder = nil;
static double g_HostClockPeriod = 0.0;
static double g_Time = 0.0;
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_MouseCursorHidden = false;
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
static ImFocusObserver* g_FocusObserver = NULL;
// Undocumented methods for creating cursors.
@interface NSCursor()
@ -80,102 +74,6 @@ static void resetKeys()
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
}
/**
KeyEventResponder implements the NSTextInputClient protocol as is required by the macOS text input manager.
The macOS text input manager is invoked by calling the interpretKeyEvents method from the keyDown method.
Keyboard events are then evaluated by the macOS input manager and valid text input is passed back via the
insertText:replacementRange method.
This is the same approach employed by other cross-platform libraries such as SDL2:
https://github.com/spurious/SDL-mirror/blob/e17aacbd09e65a4fd1e166621e011e581fb017a8/src/video/cocoa/SDL_cocoakeyboard.m#L53
and GLFW:
https://github.com/glfw/glfw/blob/b55a517ae0c7b5127dffa79a64f5406021bf9076/src/cocoa_window.m#L722-L723
*/
@interface KeyEventResponder: NSView<NSTextInputClient>
@end
@implementation KeyEventResponder
- (void)viewDidMoveToWindow
{
// Ensure self is a first responder to receive the input events.
[self.window makeFirstResponder:self];
}
- (void)keyDown:(NSEvent*)event
{
// Call to the macOS input manager system.
[self interpretKeyEvents:@[event]];
}
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
{
ImGuiIO& io = ImGui::GetIO();
NSString* characters;
if ([aString isKindOfClass:[NSAttributedString class]])
characters = [aString string];
else
characters = (NSString*)aString;
io.AddInputCharactersUTF8(characters.UTF8String);
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (void)doCommandBySelector:(SEL)myselector
{
}
- (nullable NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
{
return nil;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point
{
return 0;
}
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
{
return NSZeroRect;
}
- (BOOL)hasMarkedText
{
return NO;
}
- (NSRange)markedRange
{
return NSMakeRange(NSNotFound, 0);
}
- (NSRange)selectedRange
{
return NSMakeRange(NSNotFound, 0);
}
- (void)setMarkedText:(nonnull id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
{
}
- (void)unmarkText
{
}
- (nonnull NSArray<NSAttributedStringKey>*)validAttributesForMarkedText
{
return @[];
}
@end
@interface ImFocusObserver : NSObject
- (void)onApplicationBecomeActive:(NSNotification*)aNotification;
@ -205,7 +103,7 @@ static void resetKeys()
@end
// Functions
bool ImGui_ImplOSX_Init(NSView* view)
bool ImGui_ImplOSX_Init()
{
ImGuiIO& io = ImGui::GetIO();
@ -217,28 +115,29 @@ bool ImGui_ImplOSX_Init(NSView* view)
io.BackendPlatformName = "imgui_impl_osx";
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array.
io.KeyMap[ImGuiKey_Tab] = kVK_Tab;
io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow;
io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow;
io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow;
io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow;
io.KeyMap[ImGuiKey_PageUp] = kVK_PageUp;
io.KeyMap[ImGuiKey_PageDown] = kVK_PageDown;
io.KeyMap[ImGuiKey_Home] = kVK_Home;
io.KeyMap[ImGuiKey_End] = kVK_End;
io.KeyMap[ImGuiKey_Insert] = kVK_F13;
io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete;
io.KeyMap[ImGuiKey_Backspace] = kVK_Delete;
io.KeyMap[ImGuiKey_Space] = kVK_Space;
io.KeyMap[ImGuiKey_Enter] = kVK_Return;
io.KeyMap[ImGuiKey_Escape] = kVK_Escape;
io.KeyMap[ImGuiKey_KeyPadEnter] = kVK_ANSI_KeypadEnter;
io.KeyMap[ImGuiKey_A] = kVK_ANSI_A;
io.KeyMap[ImGuiKey_C] = kVK_ANSI_C;
io.KeyMap[ImGuiKey_V] = kVK_ANSI_V;
io.KeyMap[ImGuiKey_X] = kVK_ANSI_X;
io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y;
io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z;
const int offset_for_function_keys = 256 - 0xF700;
io.KeyMap[ImGuiKey_Tab] = '\t';
io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Backspace] = 127;
io.KeyMap[ImGuiKey_Space] = 32;
io.KeyMap[ImGuiKey_Enter] = 13;
io.KeyMap[ImGuiKey_Escape] = 27;
io.KeyMap[ImGuiKey_KeyPadEnter] = 3;
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
io.KeyMap[ImGuiKey_X] = 'X';
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
// Load cursors. Some of them are undocumented.
g_MouseCursorHidden = false;
@ -291,11 +190,6 @@ bool ImGui_ImplOSX_Init(NSView* view)
name:NSApplicationDidResignActiveNotification
object:nil];
// Add the NSTextInputClient to the view hierarchy,
// to receive keyboard events and translate them to input text.
g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
[view addSubview:g_KeyEventResponder];
return true;
}
@ -330,12 +224,8 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
}
else
{
NSCursor* desired = g_MouseCursors[imgui_cursor] ?: g_MouseCursors[ImGuiMouseCursor_Arrow];
// -[NSCursor set] generates measureable overhead if called unconditionally.
if (desired != NSCursor.currentCursor)
{
[desired set];
}
// Show OS mouse cursor
[g_MouseCursors[g_MouseCursors[imgui_cursor] ? imgui_cursor : ImGuiMouseCursor_Arrow] set];
if (g_MouseCursorHidden)
{
g_MouseCursorHidden = false;
@ -344,50 +234,6 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
}
}
void ImGui_ImplOSX_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
GCController* controller;
if (@available(macOS 11.0, *))
controller = GCController.current;
else
controller = GCController.controllers.firstObject;
if (controller == nil || controller.extendedGamepad == nil)
{
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
return;
}
GCExtendedGamepad* gp = controller.extendedGamepad;
#define MAP_BUTTON(NAV_NO, NAME) { io.NavInputs[NAV_NO] = gp.NAME.isPressed ? 1.0 : 0.0; }
MAP_BUTTON(ImGuiNavInput_Activate, buttonA);
MAP_BUTTON(ImGuiNavInput_Cancel, buttonB);
MAP_BUTTON(ImGuiNavInput_Menu, buttonX);
MAP_BUTTON(ImGuiNavInput_Input, buttonY);
MAP_BUTTON(ImGuiNavInput_DpadLeft, dpad.left);
MAP_BUTTON(ImGuiNavInput_DpadRight, dpad.right);
MAP_BUTTON(ImGuiNavInput_DpadUp, dpad.up);
MAP_BUTTON(ImGuiNavInput_DpadDown, dpad.down);
MAP_BUTTON(ImGuiNavInput_FocusPrev, leftShoulder);
MAP_BUTTON(ImGuiNavInput_FocusNext, rightShoulder);
MAP_BUTTON(ImGuiNavInput_TweakSlow, leftTrigger);
MAP_BUTTON(ImGuiNavInput_TweakFast, rightTrigger);
#undef MAP_BUTTON
io.NavInputs[ImGuiNavInput_LStickLeft] = gp.leftThumbstick.left.value;
io.NavInputs[ImGuiNavInput_LStickRight] = gp.leftThumbstick.right.value;
io.NavInputs[ImGuiNavInput_LStickUp] = gp.leftThumbstick.up.value;
io.NavInputs[ImGuiNavInput_LStickDown] = gp.leftThumbstick.down.value;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
}
void ImGui_ImplOSX_NewFrame(NSView* view)
{
// Setup display size
@ -410,25 +256,19 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
g_Time = current_time;
ImGui_ImplOSX_UpdateMouseCursorAndButtons();
ImGui_ImplOSX_UpdateGamepads();
}
NSString* NSStringFromPhase(NSEventPhase phase)
static int mapCharacterToKey(int c)
{
static NSString* strings[] =
{
@"none",
@"began",
@"stationary",
@"changed",
@"ended",
@"cancelled",
@"mayBegin",
};
int pos = phase == NSEventPhaseNone ? 0 : __builtin_ctzl((NSUInteger)phase) + 1;
return strings[pos];
if (c >= 'a' && c <= 'z')
return c - 'a' + 'A';
if (c == 25) // SHIFT+TAB -> TAB
return 9;
if (c >= 0 && c < 256)
return c;
if (c >= 0xF700 && c < 0xF700 + 256)
return c - 0xF700 + 256;
return -1;
}
bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
@ -461,21 +301,6 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
if (event.type == NSEventTypeScrollWheel)
{
// Ignore canceled events.
//
// From macOS 12.1, scrolling with two fingers and then decelerating
// by tapping two fingers results in two events appearing:
//
// 1. A scroll wheel NSEvent, with a phase == NSEventPhaseMayBegin, when the user taps
// two fingers to decelerate or stop the scroll events.
//
// 2. A scroll wheel NSEvent, with a phase == NSEventPhaseCancelled, when the user releases the
// two-finger tap. It is this event that sometimes contains large values for scrollingDeltaX and
// scrollingDeltaY. When these are added to the current x and y positions of the scrolling view,
// it appears to jump up or down. It can be observed in Preview, various JetBrains IDEs and here.
if (event.phase == NSEventPhaseCancelled)
return false;
double wheel_dx = 0.0;
double wheel_dy = 0.0;
@ -497,8 +322,6 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
wheel_dy = [event deltaY];
}
//NSLog(@"dx=%0.3ff, dy=%0.3f, phase=%@", wheel_dx, wheel_dy, NSStringFromPhase(event.phase));
if (fabs(wheel_dx) > 0.0)
io.MouseWheelH += (float)wheel_dx * 0.1f;
if (fabs(wheel_dy) > 0.0)
@ -506,37 +329,57 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
return io.WantCaptureMouse;
}
if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp)
// FIXME: All the key handling is wrong and broken. Refer to GLFW's cocoa_init.mm and cocoa_window.mm.
if (event.type == NSEventTypeKeyDown)
{
unsigned short code = event.keyCode;
IM_ASSERT(code >= 0 && code < IM_ARRAYSIZE(io.KeysDown));
io.KeysDown[code] = event.type == NSEventTypeKeyDown;
NSEventModifierFlags flags = event.modifierFlags;
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0;
io.KeyShift = (flags & NSEventModifierFlagShift) != 0;
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0;
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0;
NSString* str = [event characters];
NSUInteger len = [str length];
for (NSUInteger i = 0; i < len; i++)
{
int c = [str characterAtIndex:i];
if (!io.KeySuper && !(c >= 0xF700 && c <= 0xFFFF) && c != 127)
io.AddInputCharacter((unsigned int)c);
// We must reset in case we're pressing a sequence of special keys while keeping the command pressed
int key = mapCharacterToKey(c);
if (key != -1 && key < 256 && !io.KeySuper)
resetKeys();
if (key != -1)
io.KeysDown[key] = true;
}
return io.WantCaptureKeyboard;
}
if (event.type == NSEventTypeKeyUp)
{
NSString* str = [event characters];
NSUInteger len = [str length];
for (NSUInteger i = 0; i < len; i++)
{
int c = [str characterAtIndex:i];
int key = mapCharacterToKey(c);
if (key != -1)
io.KeysDown[key] = false;
}
return io.WantCaptureKeyboard;
}
if (event.type == NSEventTypeFlagsChanged)
{
NSEventModifierFlags flags = event.modifierFlags;
switch (event.keyCode)
{
case kVK_Control:
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0;
break;
case kVK_Shift:
io.KeyShift = (flags & NSEventModifierFlagShift) != 0;
break;
case kVK_Option:
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0;
break;
case kVK_Command:
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0;
break;
}
unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
bool oldKeyCtrl = io.KeyCtrl;
bool oldKeyShift = io.KeyShift;
bool oldKeyAlt = io.KeyAlt;
bool oldKeySuper = io.KeySuper;
io.KeyCtrl = flags & NSEventModifierFlagControl;
io.KeyShift = flags & NSEventModifierFlagShift;
io.KeyAlt = flags & NSEventModifierFlagOption;
io.KeySuper = flags & NSEventModifierFlagCommand;
// We must reset them as we will not receive any keyUp event if they where pressed with a modifier
if ((oldKeyShift && !io.KeyShift) || (oldKeyCtrl && !io.KeyCtrl) || (oldKeyAlt && !io.KeyAlt) || (oldKeySuper && !io.KeySuper))
resetKeys();
return io.WantCaptureKeyboard;
}

View File

@ -18,7 +18,6 @@
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// 2021-12-21: Update SDL_RenderGeometryRaw() format to work with SDL 2.0.19.
// 2021-12-03: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2021-10-06: Backup and restore modified ClipRect/Viewport.
// 2021-09-21: Initial version.
@ -175,11 +174,7 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
const float* xy = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, pos));
const float* uv = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, uv));
#if SDL_VERSION_ATLEAST(2,0,19)
const SDL_Color* color = (const SDL_Color*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.19+
#else
const int* color = (const int*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.17 and 2.0.18
#endif
const int* color = (const int*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col));
// Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();

View File

@ -33,9 +33,8 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness.
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus.
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host windo doesn't have focus.
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
@ -427,23 +426,11 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
if (wParam < 256)
io.KeysDown[wParam] = down;
if (wParam == VK_CONTROL)
{
io.KeysDown[VK_LCONTROL] = ((::GetKeyState(VK_LCONTROL) & 0x8000) != 0);
io.KeysDown[VK_RCONTROL] = ((::GetKeyState(VK_RCONTROL) & 0x8000) != 0);
io.KeyCtrl = io.KeysDown[VK_LCONTROL] || io.KeysDown[VK_RCONTROL];
}
io.KeyCtrl = down;
if (wParam == VK_SHIFT)
{
io.KeysDown[VK_LSHIFT] = ((::GetKeyState(VK_LSHIFT) & 0x8000) != 0);
io.KeysDown[VK_RSHIFT] = ((::GetKeyState(VK_RSHIFT) & 0x8000) != 0);
io.KeyShift = io.KeysDown[VK_LSHIFT] || io.KeysDown[VK_RSHIFT];
}
io.KeyShift = down;
if (wParam == VK_MENU)
{
io.KeysDown[VK_LMENU] = ((::GetKeyState(VK_LMENU) & 0x8000) != 0);
io.KeysDown[VK_RMENU] = ((::GetKeyState(VK_RMENU) & 0x8000) != 0);
io.KeyAlt = io.KeysDown[VK_LMENU] || io.KeysDown[VK_RMENU];
}
io.KeyAlt = down;
return 0;
}
case WM_SETFOCUS:

View File

@ -12,7 +12,7 @@ your application or engine to easily integrate Dear ImGui.** Each backend is typ
e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp), etc.
- For some high-level frameworks, a single backend usually handle both 'Platform' and 'Renderer' parts.<BR>
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)), Marmalade ([imgui_impl_marmalade.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_marmalade.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
An application usually combines 1 Platform backend + 1 Renderer backend + main Dear ImGui sources.
For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details.
@ -82,13 +82,14 @@ List of Renderer Backends:
List of high-level Frameworks Backends (combining Platform + Renderer):
imgui_impl_allegro5.cpp
imgui_impl_marmalade.cpp
Emscripten is also supported.
The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/examples/example_emscripten_opengl3) app uses imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp, but other combos are possible.
### Backends for third-party frameworks, graphics API or other languages
See https://github.com/ocornut/imgui/wiki/Bindings for the full list (e.g. Adventure Game Studio, Cinder, Cocos2d-x, Game Maker Studio2, Godot, L<EFBFBD>VE+LUA, Magnum, Monogame, Ogre, openFrameworks, OpenSceneGraph, SFML, Sokol, Unity, Unreal Engine and many others).
See https://github.com/ocornut/imgui/wiki/Bindings for the full list.
### Recommended Backends

View File

@ -31,16 +31,13 @@ HOW TO UPDATE?
- Please report any issue!
-----------------------------------------------------------------------
VERSION 1.86 (Released 2021-12-22)
VERSION 1.86 WIP (In Progress)
-----------------------------------------------------------------------
Breaking Changes:
- Removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges.
Please open an issue if you think you really need this function. (#3841)
- Backends: OSX: Added NSView* parameter to ImGui_ImplOSX_Init(). (#4759) [@stuartcarnie]
- Backends: Marmalade: Removed obsolete Marmalade backend (imgui_impl_marmalade.cpp) + example app. (#368, #375)
Find last supported version at https://github.com/ocornut/imgui/wiki/Bindings
Other Changes:
@ -51,12 +48,12 @@ Other Changes:
- Added GetMouseClickedCount() function, returning the number of successive clicks. (#3229) [@kudaba]
(so IsMouseDoubleClicked(ImGuiMouseButton_Left) is same as GetMouseClickedCount(ImGuiMouseButton_Left) == 2,
but it allows testing for triple clicks and more).
- Modals: fixed issue hovering popups inside a child windows inside a modal. (#4676, #4527)
- Modals: fixed issue hovering popups inside a child inside a modal. (#4676, #4527)
- Modals, Popups, Windows: changes how appearing windows are interrupting popups and modals. (#4317) [@rokups]
- appearing windows created from within the begin stack of a popup/modal will no longer close it.
- appearing windows created not within the begin stack of a modal will no longer close the modal,
and automatically appear behind it.
- Fixed IsWindowFocused()/IsWindowHovered() issues with child windows inside popups. (#4676)
- Fixed IsWindowFocused()/IsWindowHovered() issues with childs inside popups. (#4676)
- Nav: Ctrl+tabbing to cycle through windows is now enabled regardless of using the _NavEnableKeyboard
configuration flag. This is part of an effort to generalize the use of keyboard inputs. (#4023, #787).
Note that while this is active you can also moving windows (with arrow) and resize (shift+arrows).
@ -68,17 +65,11 @@ Other Changes:
- Nav: with ImGuiConfigFlags_NavEnableSetMousePos enabled: Fixed absolute mouse position when using
Home/End leads to scrolling. Fixed not setting mouse position when a failed move request (e.g. when
already at edge) reactivates the navigation highlight.
- Menus: fixed closing a menu inside a popup/modal by clicking on the popup/modal. (#3496, #4797)
- Menus: fixed closing a menu by clicking on its menu-bar item when inside a popup. (#3496, #4797) [@xndcn]
- Menus: fixed menu inside a popup/modal not inhibiting hovering of items in the popup/modal. (#3496, #4797)
- Menus: fixed sub-menu items inside a popups from closing the popup.
- Menus: fixed top-level menu from not consistently using style.PopupRounding. (#4788)
- InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682)
- Inputtext, Nav: fixed using SetKeyboardFocusHere() on InputTextMultiline(). (#4761)
- InputText: made double-click select word, triple-line select line. Word delimitation logic differs
slightly from the one used by CTRL+arrows. (#2244)
- InputText: fixed ReadOnly flag preventing callbacks from receiving the text buffer. (#4762) [@actondev]
- InputText: fixed Shift+Delete from not cutting into clipboard. (#4818, #1541) [@corporateshark]
- InputTextMultiline: fixed incorrect padding when FrameBorder > 0. (#3781, #4794)
- InputTextMultiline: fixed vertical tracking with large values of FramePadding.y. (#3781, #4794)
- Separator: fixed cover all columns while called inside a table. (#4787)
@ -96,8 +87,6 @@ Other Changes:
- Clipper: fixed invalid state when number of frozen table row is smaller than ItemCount.
- Drag and Drop: BeginDragDropSource() with ImGuiDragDropFlags_SourceAllowNullID doesn't lose
tooltip when scrolling. (#143)
- Fonts: fixed infinite loop in ImFontGlyphRangesBuilder::AddRanges() when passing UINT16_MAX or UINT32_MAX
without the IMGUI_USE_WCHAR32 compile-time option. (#4802) [@SlavicPotato]
- Metrics: Added a node showing windows in submission order and showing the Begin() stack.
- Misc: Added missing ImGuiMouseCursor_NotAllowed cursor for software rendering (when the
io.MouseDrawCursor flag is enabled). (#4713) [@nobody-special666]
@ -107,20 +96,12 @@ Other Changes:
- Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce
likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling
vkCmdSetScissor() explicitly every frame. (#4644)
- Backends: OpenGL3: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports
with some Intel HD drivers, and perhaps improve performances. (#4468, #4504, #2981, #3381) [@parbo]
- Backends: OpenGL2, Allegro5, Marmalade: Fixed mishandling of the ImDrawCmd::IdxOffset field.
This is an old bug, but due to the way we created drawlists, it never had any visible side-effect before.
The new code for handling Modal and CTRL+Tab dimming/whitening recently made the bug surface. (#4790)
- Backends: Win32: Store left/right variants of Ctrl/Shift/Alt mods in KeysDown[] array. (#2625) [@thedmd]
- Backends: DX12: Fixed DRAW_EMPTY_SCISSOR_RECTANGLE warnings. (#4775)
- Backends: SDL_Renderer: Added support for large meshes (64k+ vertices) with 16-bit indices,
enabling 'ImGuiBackendFlags_RendererHasVtxOffset' in the backend. (#3926) [@rokups]
- Backends: SDL_Renderer: Fix for SDL 2.0.19+ RenderGeometryRaw() API signature change. (#4819) [@sridenour]
- Backends: OSX: Generally fix keyboard support. Keyboard arrays indexed using kVK_* codes, e.g.
ImGui::IsKeyPressed(kVK_Space). Don't set mouse cursor shape unconditionally. Handle two fingers scroll
cancel event. (#4759, #4253, #1873) [@stuartcarnie]
- Backends: OSX: Add Game Controller support (need linking GameController framework) (#4759) [@stuartcarnie]
- Backends: WebGPU: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer() and
wgpuRenderPassEncoderSetIndexBuffer() functions as validation layers appears to not do what the
in-flux specs says. (#4766) [@meshula]
@ -707,6 +688,9 @@ Other Changes:
- Style: Changed default style.WindowRounding value to 0.0f (matches default for multi-viewports).
- Style: Reduced the size of the resizing grip, made alpha less prominent.
- Style: Classic: Increase the default alpha value of WindowBg to be closer to other styles.
- Demo: Added a fancy "particle text" demo in Examples->Custom Rendering. [@bdero]
Originally done as a 1024 bytes source, as part of the "ImDrawList coding party" challenge:
https://github.com/ocornut/imgui/issues/3606
- Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width.
- Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...)
when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn]

View File

@ -141,6 +141,10 @@ GLUT (e.g., FreeGLUT on Linux/Windows, GLUT framework on OSX) + OpenGL2 example.
= main.cpp + imgui_impl_glut.cpp + imgui_impl_opengl2.cpp <BR>
Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
[example_marmalade/](https://github.com/ocornut/imgui/blob/master/examples/example_marmalade/) <BR>
Marmalade example using IwGx. <BR>
= main.cpp + imgui_impl_marmalade.cpp
[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
= main.cpp <BR>

View File

@ -118,7 +118,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/
Officially maintained backends/bindings (in repository):
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU.
- Platforms: GLFW, SDL2, Win32, Glut, OSX, Android.
- Frameworks: Allegro5, Emscripten.
- Frameworks: Emscripten, Allegro5, Marmalade.
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...

View File

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05318E0E274C397200A8DE2E /* GameController.framework */; };
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; };
@ -33,7 +32,6 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
05318E0E274C397200A8DE2E /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
5079822D257677DB0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
@ -78,7 +76,6 @@
files = (
8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */,
83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */,
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */,
83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -136,7 +133,6 @@
83BBE9E320EB46B800295997 /* Frameworks */ = {
isa = PBXGroup;
children = (
05318E0E274C397200A8DE2E /* GameController.framework */,
8309BDC5253CCCFE0045E2A1 /* AppKit.framework */,
8309BD8E253CCAAA0045E2A1 /* UIKit.framework */,
83BBE9EE20EB471C00295997 /* ModelIO.framework */,

View File

@ -119,7 +119,7 @@
return event;
}];
ImGui_ImplOSX_Init(self.view);
ImGui_ImplOSX_Init();
#endif
}

View File

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05E31B57274EF0360083FCB6 /* GameController.framework */; };
07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82EDA213941D00078D120 /* imgui_widgets.cpp */; };
4080A99820B02D340036BA46 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A98A20B02CD90036BA46 /* main.mm */; };
4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */; };
@ -33,7 +32,6 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
05E31B57274EF0360083FCB6 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
07A82EDA213941D00078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
4080A96B20B029B00036BA46 /* example_osx_opengl2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = example_osx_opengl2; sourceTree = BUILT_PRODUCTS_DIR; };
4080A98A20B02CD90036BA46 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; };
@ -59,7 +57,6 @@
files = (
4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */,
4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */,
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -98,7 +95,6 @@
4080A9B120B034E40036BA46 /* Frameworks */ = {
isa = PBXGroup;
children = (
05E31B57274EF0360083FCB6 /* GameController.framework */,
4080A9B420B034EA0036BA46 /* OpenGL.framework */,
4080A9B220B034E40036BA46 /* Cocoa.framework */,
);

View File

@ -58,7 +58,7 @@
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_ImplOSX_Init(self);
ImGui_ImplOSX_Init();
ImGui_ImplOpenGL2_Init();
// Load Fonts
@ -146,9 +146,12 @@
animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.017 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES];
}
-(void)reshape { [super reshape]; [[self openGLContext] update]; [self updateAndDrawDemoView]; }
-(void)reshape { [[self openGLContext] update]; [self updateAndDrawDemoView]; }
-(void)drawRect:(NSRect)bounds { [self updateAndDrawDemoView]; }
-(void)animationTimerFired:(NSTimer*)timer { [self setNeedsDisplay:YES]; }
-(BOOL)acceptsFirstResponder { return (YES); }
-(BOOL)becomeFirstResponder { return (YES); }
-(BOOL)resignFirstResponder { return (YES); }
-(void)dealloc { animationTimer = nil; }
//-----------------------------------------------------------------------------------

View File

@ -0,0 +1,32 @@
# This file is for configuration settings for your
# application.
#
# The syntax is similar to windows .ini files ie
#
# [GroupName]
# Setting = Value
#
# Which can be read by your application using
# e.g s3eConfigGetString("GroupName", "Setting", string)
#
# All settings must be documented in .config.txt files.
# New settings specific to this application should be
# documented in app.config.txt
#
# Some conditional operations are also permitted, see the
# S3E documentation for details.
[S3E]
MemSize=6000000
MemSizeDebug=6000000
DispFixRot=FixedLandscape
# emulate iphone 5 resolution, change these settings to emulate other display resolution
WinWidth=1136
WinHeight=640
[GX]
DataCacheSize=131070
[Util]
#MemoryBreakpoint=1282

View File

@ -0,0 +1,124 @@
// Dear ImGui: standalone example application for Marmalade
// 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
// Copyright (C) 2015 by Giovanni Zito
// This file is part of Dear ImGui
#include "imgui.h"
#include "imgui_impl_marmalade.h"
#include <stdio.h>
#include <s3eKeyboard.h>
#include <s3ePointer.h>
#include <IwGx.h>
int main(int, char**)
{
IwGxInit();
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_Marmalade_Init(true);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - Read 'docs/FONTS.md' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
while (true)
{
if (s3eDeviceCheckQuitRequest())
break;
// Poll and handle inputs
// 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.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
s3eKeyboardUpdate();
s3ePointerUpdate();
// Start the Dear ImGui frame
ImGui_Marmalade_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
IwGxSetColClear(clear_color.x * 255, clear_color.y * 255, clear_color.z * 255, clear_color.w * 255);
IwGxClear();
ImGui_Marmalade_RenderDrawData(ImGui::GetDrawData());
IwGxSwapBuffers();
s3eDeviceYield(0);
}
// Cleanup
ImGui_Marmalade_Shutdown();
ImGui::DestroyContext();
IwGxTerminate();
return 0;
}

View File

@ -0,0 +1,47 @@
#!/usr/bin/env mkb
# ImGui - standalone example application for Marmalade
# Copyright (C) 2015 by Giovanni Zito
# This file is part of ImGui
# https://github.com/ocornut/imgui
define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS
define _snprintf=snprintf
options
{
optimise-speed=1
}
includepaths
{
../..
../../backends
}
subprojects
{
iwgx
}
files
{
(.)
["imgui"]
../../imgui.cpp
../../imgui_demo.cpp
../../imgui_draw.cpp
../../imgui_tables.cpp
../../imgui_widgets.cpp
../../imconfig.h
../../imgui.h
../../imgui_internal.h
["imgui","Marmalade backend"]
../../backends/imgui_impl_marmalade.h
../../backends/imgui_impl_marmalade.cpp
main.cpp
}

View File

@ -1,4 +1,4 @@
// dear imgui, v1.86
// dear imgui, v1.86 WIP
// (main code and documentation)
// Help:
@ -380,7 +380,6 @@ CODE
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2021/12/20 (1.86) - backends: removed obsolete Marmalade backend (imgui_impl_marmalade.cpp) + example. Find last supported version at https://github.com/ocornut/imgui/wiki/Bindings
- 2021/11/04 (1.86) - removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges. Please open an issue if you think you really need this function.
- 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inline redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead for generally 'GetContentRegionAvail().x' is more useful.
- 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):
@ -5287,29 +5286,6 @@ static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settin
window->Collapsed = settings->Collapsed;
}
static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags)
{
ImGuiContext& g = *GImGui;
const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0;
const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild;
if ((just_created || child_flag_changed) && !new_is_explicit_child)
{
IM_ASSERT(!g.WindowsFocusOrder.contains(window));
g.WindowsFocusOrder.push_back(window);
window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1);
}
else if (!just_created && child_flag_changed && new_is_explicit_child)
{
IM_ASSERT(g.WindowsFocusOrder[window->FocusOrder] == window);
for (int n = window->FocusOrder + 1; n < g.WindowsFocusOrder.Size; n++)
g.WindowsFocusOrder[n]->FocusOrder--;
g.WindowsFocusOrder.erase(g.WindowsFocusOrder.Data + window->FocusOrder);
window->FocusOrder = -1;
}
window->IsExplicitChild = new_is_explicit_child;
}
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
{
ImGuiContext& g = *GImGui;
@ -5349,12 +5325,16 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
}
if (!(flags & ImGuiWindowFlags_ChildWindow))
{
g.WindowsFocusOrder.push_back(window);
window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1);
}
if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
g.Windows.push_front(window); // Quite slow but rare and only once
else
g.Windows.push_back(window);
UpdateWindowInFocusOrderList(window, true, window->Flags);
return window;
}
@ -5954,8 +5934,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const bool window_just_created = (window == NULL);
if (window_just_created)
window = CreateNewWindow(name, flags);
else
UpdateWindowInFocusOrderList(window, window_just_created, flags);
// Automatically disable manual moving/resizing when NoInputs is set
if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
@ -6012,8 +5990,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window_stack_data.StackSizesOnBegin.SetToCurrentState();
g.CurrentWindowStack.push_back(window_stack_data);
g.CurrentWindow = NULL;
if (flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuCount++;
if (flags & ImGuiWindowFlags_Popup)
{
@ -6571,8 +6547,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->HiddenFramesCanSkipItems = 1;
// Update the Hidden flag
bool hidden_regular = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0);
window->Hidden = hidden_regular || (window->HiddenFramesForRenderOnly > 0);
window->Hidden = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0) || (window->HiddenFramesForRenderOnly > 0);
// Disable inputs for requested number of frames
if (window->DisableInputsFrames > 0)
@ -6583,7 +6558,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Update the SkipItems flag, used to early out of all items functions (no layout required)
bool skip_items = false;
if (window->Collapsed || !window->Active || hidden_regular)
if (window->Collapsed || !window->Active || window->Hidden)
if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0)
skip_items = true;
window->SkipItems = skip_items;
@ -6620,8 +6595,6 @@ void ImGui::End()
// Pop from window stack
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
if (window->Flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuCount--;
if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back();
g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithCurrentState();
@ -8709,7 +8682,7 @@ void ImGui::CloseCurrentPopup()
ImGuiWindow* parent_popup_window = g.OpenPopupStack[popup_idx - 1].Window;
bool close_parent = false;
if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu))
if (parent_popup_window && !(parent_popup_window->Flags & ImGuiWindowFlags_MenuBar))
if (parent_popup_window == NULL || !(parent_popup_window->Flags & ImGuiWindowFlags_Modal))
close_parent = true;
if (!close_parent)
break;
@ -8737,7 +8710,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
char name[20];
if (flags & ImGuiWindowFlags_ChildMenu)
ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuCount); // Recycle windows based on depth
ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
else
ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
@ -12038,7 +12011,8 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list,
}
ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list
if (window && IsItemHovered() && fg_draw_list)
IM_ASSERT(fg_draw_list != NULL); // For static analyzers
if (window && IsItemHovered())
fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
if (!node_open)
return;
@ -12530,9 +12504,6 @@ void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* dat
// Stack Tool: Display UI
void ImGui::ShowStackToolWindow(bool* p_open)
{
ImGuiContext& g = *GImGui;
if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize))
SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver);
if (!Begin("Dear ImGui Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
{
End();
@ -12540,6 +12511,7 @@ void ImGui::ShowStackToolWindow(bool* p_open)
}
// Display hovered/active status
ImGuiContext& g = *GImGui;
const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
const ImGuiID active_id = g.ActiveId;
#ifdef IMGUI_ENABLE_TEST_ENGINE

View File

@ -1,4 +1,4 @@
// dear imgui, v1.86
// dear imgui, v1.86 WIP
// (headers)
// Help:
@ -63,8 +63,8 @@ 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.86"
#define IMGUI_VERSION_NUM 18600
#define IMGUI_VERSION "1.86 WIP"
#define IMGUI_VERSION_NUM 18518
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE

View File

@ -1,4 +1,4 @@
// dear imgui, v1.86
// dear imgui, v1.86 WIP
// (demo code)
// Help:
@ -3345,26 +3345,11 @@ static void ShowDemoWindowPopups()
}
// Call the more complete ShowExampleMenuFile which we use in various places of this demo
if (ImGui::Button("With a menu.."))
if (ImGui::Button("File Menu.."))
ImGui::OpenPopup("my_file_popup");
if (ImGui::BeginPopup("my_file_popup", ImGuiWindowFlags_MenuBar))
if (ImGui::BeginPopup("my_file_popup"))
{
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("File"))
{
ShowExampleMenuFile();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Edit"))
{
ImGui::MenuItem("Dummy");
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
ImGui::Text("Hello from popup!");
ImGui::Button("This is a dummy button..");
ShowExampleMenuFile();
ImGui::EndPopup();
}
@ -7324,6 +7309,83 @@ static void ShowExampleAppWindowTitles(bool*)
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
//-----------------------------------------------------------------------------
// Mini "Particle Text" demo by Brandon DeRosier
// Originally done as a 1024 bytes source, as part of the "ImDrawList coding party" challenge:
// - https://github.com/ocornut/imgui/issues/3606#issuecomment-734636054
// - https://twitter.com/algebrandon/status/1332182010593304576
// This is a fun thing to inspire people to see the potential of using ImDrawList for custom drawing.
// Don't do this at home!
static void ShowFxParticleText(ImDrawList* draw_list, ImVec2 p0, ImVec2 p1, float time)
{
// The base diameter (and distance apart) all of the circles should be on the grid.
// The actual diameter is inflated a bit from this value so that the circles smoosh together.
const float diameter = 11.0f;
const float scale = (p1.x - p0.x) / 400.0f;
// This packed array contains a 17x13 grid (221-bit) spelling the word "DEAR IMGUI"
// Our storage 32x7 (224-bit) so the least significant 3 bits are unused (hence the -3 in the loop below).
const unsigned int GRID[] = { 0xD9000080, 0x750A2B18, 0xDC2A2A17, 0x0200025D, 0x5AB1E800, 0x26EAB555, 0x01800100 };
// Storage for a rotating circle (we use the index for sorting and for computing the color)
struct GridCircle { float x, y, z; int index; };
GridCircle circles[221];
// Helper functions
struct f
{
// This is a S-curve function `1/(1+e^-t)`, but with a range of 0 to 2 PI
// because this demo happens to only use it for computing rotations.
// See also: https://en.wikipedia.org/wiki/Sigmoid_function
static float Sigmoid(float T) { return 1.f / (1 + expf(-(T))) * 3.141592f * 2.0f; }
// This is a Sine function with an exponentially decaying magnitude `sin(t)`.
// The intended domain is 0 to ~5, and the range is -1 to 1.
static float Bounce(float T) { return sinf((T) * 3.0f) * expf(-(T)); }
// 2D rotation formula. This demo uses Euler angles, and so this formula is used
// three times (once for each basis axis) when computing the position of each circle.
// See also: https://en.wikipedia.org/wiki/Rotation_matrix
static void Rotate(float& u, float& v, float r) { float U = u; u = cosf(r) * u - sinf(r) * v; v = sinf(r) * U + cosf(r) * v; }
// Sorting function so that circles with higher Z values (which are further away from the camera) are given lower order
static int IMGUI_CDECL GridCircleCompareByZ(const void* a, const void* b) { return (((const GridCircle*)b)->z - ((const GridCircle*)a)->z > 0.0f) ? 1 : -1; }
};
// For each circle in the grid: rotate, calculate z and calculate x
const float loop_time = fmodf(time, 6.0f) * 10.0f;
for (int n = 3; n < 224; n++)
{
int index = (n - 3);
float x = (float)(index % 17) * diameter - 9.0f * diameter;
float y = (float)(index / 17) * diameter - 6.0f * diameter;
float z = 0.0f;
float distance = sqrtf(x * x + y * y) / 32.0f;
f::Rotate(x, y, f::Sigmoid(loop_time - 20 - distance) + cosf(time / 2) / 4); // Rotate on Z axis
f::Rotate(y, z, f::Sigmoid(loop_time - 4 - distance) + cosf(time / 3) / 4); // Rotate on X axis
f::Rotate(x, z, f::Sigmoid(loop_time - 12 - distance) + cosf(time / 7) / 4); // Rotate on Y axis
z -= (loop_time - distance > 28) ? f::Bounce((loop_time - 28 - distance) / 2) * 50 : 0;
z = (GRID[n / 32] & (1 << (n % 32))) ? z / 100.f + 1.f : 0.0f;
circles[index].x = p0.x + (p1.x - p0.x) * 0.5f + scale * x / z;
circles[index].y = p0.y + (p1.y - p0.y) * 0.5f + scale * y / z;
circles[index].z = z;
circles[index].index = index;
}
// Sort back-to-front, then draw
qsort(&circles[0], 221, sizeof(circles[0]), f::GridCircleCompareByZ);
for (int i = 0; i < 221; i++)
{
GridCircle* c = &circles[i];
if (c->z == 0.0f)
continue;
ImU32 col = IM_COL32(c->index > 102 ? 0 : 255, c->index < 102 ? 0 : 255, IM_CLAMP((int)(765 - c->z * 637), 0, 255), 255);
float rad = diameter * .8f / c->z;
draw_list->AddCircleFilled(ImVec2(c->x, c->y), rad * scale, col);
}
}
// Demonstrate using the low-level ImDrawList to draw custom shapes.
static void ShowExampleAppCustomRendering(bool* p_open)
{
@ -7341,6 +7403,29 @@ static void ShowExampleAppCustomRendering(bool* p_open)
if (ImGui::BeginTabBar("##TabBar"))
{
if (ImGui::BeginTabItem("Fancy demo"))
{
// Mini "Particle Text" demo by Brandon DeRosier
// See ShowFxParticleText() for details!
static float time = 0.0f;
if (ImGui::IsWindowAppearing())
time = 0.0f;
else
time += ImGui::GetIO().DeltaTime;
float w = ImGui::GetContentRegionAvail().x;
float h = (float)(int)(w / 1.777f);
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImGui::InvisibleButton("canvas", ImVec2(w, h));
ImVec2 p0 = ImGui::GetItemRectMin();
ImVec2 p1 = ImGui::GetItemRectMax();
draw_list->PushClipRect(p0, p1, true);
draw_list->AddRectFilled(p0, p1, IM_COL32(0, 0, 0, 100));
ShowFxParticleText(draw_list, p0, p1, time);
draw_list->AddRect(p0, p1, IM_COL32(100, 100, 100, 100));
draw_list->PopClipRect();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Primitives"))
{
ImGui::PushItemWidth(-ImGui::GetFontSize() * 15);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.86
// dear imgui, v1.86 WIP
// (drawing and font code)
/*
@ -3080,8 +3080,8 @@ void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end)
void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges)
{
for (; ranges[0]; ranges += 2)
for (unsigned int c = ranges[0]; c <= ranges[1] && c <= IM_UNICODE_CODEPOINT_MAX; c++) //-V560
AddChar((ImWchar)c);
for (ImWchar c = ranges[0]; c <= ranges[1]; c++)
AddChar(c);
}
void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.86
// dear imgui, v1.86 WIP
// (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
@ -1580,7 +1580,6 @@ struct ImGuiContext
ImVector<ImGuiGroupData>GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
int BeginMenuCount;
// Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
@ -1802,7 +1801,6 @@ struct ImGuiContext
LastActiveIdTimer = 0.0f;
CurrentItemFlags = ImGuiItemFlags_None;
BeginMenuCount = 0;
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
@ -1984,7 +1982,6 @@ struct IMGUI_API ImGuiWindow
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
bool Hidden; // Do not display (== HiddenFrames*** > 0)
bool IsFallbackWindow; // Set on the "Debug##Default" window.
bool IsExplicitChild; // Set when passed _ChildWindow, left to false by BeginDocked()
bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.86
// dear imgui, v1.86 WIP
// (tables and columns code)
/*

View File

@ -1,4 +1,4 @@
// dear imgui, v1.86
// dear imgui, v1.86 WIP
// (widgets code)
/*
@ -3695,11 +3695,11 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx])) : 1; }
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
#ifdef __APPLE__ // FIXME: Move setting to IO structure
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_MAC
#else
static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_WIN
#endif
@ -4317,7 +4317,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly)
{
if (!state->HasSelection())
@ -6868,23 +6868,6 @@ void ImGui::EndMainMenuBar()
End();
}
static bool IsRootOfOpenMenuSet()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if ((g.OpenPopupStack.Size <= g.BeginPopupStack.Size) || (window->Flags & ImGuiWindowFlags_ChildMenu))
return false;
// Initially we used 'OpenParentId' to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) based on parent ID.
// This would however prevent the use of e.g. PuhsID() user code submitting menus.
// Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag,
// making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects.
// Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup
// doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first chilld menu.
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size];
return (/*upper_popup->OpenParentId == window->IDStack.back() &&*/ upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu));
}
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
{
ImGuiWindow* window = GetCurrentWindow();
@ -6897,9 +6880,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
// The first menu in a hierarchy isn't so hovering doesn't get accross (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation.
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
if (window->Flags & ImGuiWindowFlags_ChildMenu)
if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu))
flags |= ImGuiWindowFlags_ChildWindow;
// If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
@ -6918,12 +6900,11 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
g.MenusIdSubmittedThisFrame.push_back(id);
ImVec2 label_size = CalcTextSize(label, NULL, true);
// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window)
const bool menuset_is_open = IsRootOfOpenMenuSet();
bool pressed;
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
ImGuiWindow* backed_nav_window = g.NavWindow;
if (menuset_is_open)
g.NavWindow = window;
g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
@ -6933,7 +6914,6 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (!enabled)
BeginDisabled();
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
bool pressed;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
// Menu inside an horizontal menu bar
@ -7050,9 +7030,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (menu_is_open)
{
SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos.
PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
PopStyleVar();
}
else
{
@ -7095,19 +7073,13 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
ImVec2 pos = window->DC.CursorPos;
ImVec2 label_size = CalcTextSize(label, NULL, true);
const bool menuset_is_open = IsRootOfOpenMenuSet();
ImGuiWindow* backed_nav_window = g.NavWindow;
if (menuset_is_open)
g.NavWindow = window;
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
bool pressed;
PushID(label);
if (!enabled)
BeginDisabled();
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
@ -7117,7 +7089,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f));
pressed = Selectable("", selected, flags, ImVec2(w, 0.0f));
PopStyleVar();
RenderText(text_pos, label);
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@ -7132,7 +7104,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
if (icon_w > 0.0f)
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
@ -7149,8 +7121,6 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
if (!enabled)
EndDisabled();
PopID();
if (menuset_is_open)
g.NavWindow = backed_nav_window;
return pressed;
}