1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-09 23:54:20 +00:00
imgui/backends/imgui_impl_emscripten.cpp

644 lines
24 KiB
C++

// dear imgui: Platform Backend for Emscripten
// This needs to be used along with a Renderer (e.g. OpenGL3)
// Implemented features:
// [X] Platform: Clipboard support (with IMGUI_IMPL_EMSCRIPTEN_ENABLE_CLIPBOARD).
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (with IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENTS).
// [X] Platform: Keyboard support.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// 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.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// Configuration flags to add in your imconfig file:
// #define IMGUI_IMPL_EMSCRIPTEN_ENABLE_CLIPBOARD // Enable clipboard support, requires "Module['_ImGui_ImplEmscripten_ClipboardPasteCallback']"
// #define IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENTS // Handle inputs using pointer events, requires "Module['_ImGui_ImplEmscripten_PointerEvent']" and "touch-action: none" to properly accept touch inputs.
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include <emscripten/html5.h>
struct ImGui_ImplEmscripten_BackendData
{
const char* ClipboardTextData;
char* TargetId;
double Time;
int Width;
int Height;
ImGuiMouseCursor LastMouseCursor;
int GamepadsCount;
int PressedButtons;
};
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplEmscripten_BackendData* ImGui_ImplEmscripten_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplEmscripten_BackendData*)ImGui::GetIO().BackendPlatformUserData : nullptr;
}
static ImGui_ImplEmscripten_BackendData* ImGui_ImplEmscripten_GetBackendData(ImGuiIO& io)
{
return (ImGui_ImplEmscripten_BackendData*)io.BackendPlatformUserData;
}
// Functions
static bool ImGui_ImplEmscripten_UpdateMouseCursor(ImGuiIO& io, ImGuiMouseCursor imgui_cursor)
{
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return false;
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData(io);
const char* name = NULL;
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{
name = "none";
}
else
{
switch (imgui_cursor)
{
case ImGuiMouseCursor_Arrow: name = "default"; break;
case ImGuiMouseCursor_TextInput: name = "text"; break;
case ImGuiMouseCursor_ResizeAll: name = "move"; break;
case ImGuiMouseCursor_ResizeNS: name = "ns-resize"; break;
case ImGuiMouseCursor_ResizeEW: name = "ew-resize"; break;
case ImGuiMouseCursor_ResizeNESW: name = "nesw-resize"; break;
case ImGuiMouseCursor_ResizeNWSE: name = "nwse-resize"; break;
case ImGuiMouseCursor_Hand: name = "pointer"; break;
case ImGuiMouseCursor_Wait: name = "wait"; break;
case ImGuiMouseCursor_Progress: name = "progress"; break;
case ImGuiMouseCursor_NotAllowed: name = "not-allowed"; break;
}
}
if (name)
{
EM_ASM({
document.querySelector(UTF8ToString($0)).style.cursor = UTF8ToString($1);
}, bd->TargetId, name);
return true;
}
return false;
}
// FIXME: Lookup complex keys in the hash map
// Not using charCode/keyCode because they're deprecated, tho SDL still uses them.
static ImGuiKey ImGui_ImplEmscripten_KeyToImGuiKey(const EM_UTF8(&key)[32])
{
if (key[1] == '\0')
{
char c = key[0];
if (c >= 'a' && c <= 'z')
return (ImGuiKey)((c - 'a') + ImGuiKey_A);
else if (c >= '0' && c <= '9')
return (ImGuiKey)((c - '0') + ImGuiKey_0);
else
{
switch (c)
{
case '\'': return ImGuiKey_Apostrophe;
case ',': return ImGuiKey_Comma;
case '-': return ImGuiKey_Minus;
case '.': return ImGuiKey_Period;
case '/': return ImGuiKey_Slash;
case ';': return ImGuiKey_Semicolon;
case '=': return ImGuiKey_Equal;
case '[': return ImGuiKey_LeftBracket;
case '\\': return ImGuiKey_Backslash;
case ']': return ImGuiKey_RightBracket;
case '`': return ImGuiKey_GraveAccent;
case ' ': return ImGuiKey_Space;
case 0x09: return ImGuiKey_Tab;
case '+': return ImGuiKey_KeypadAdd;
case '*': return ImGuiKey_KeypadMultiply;
}
}
}
else
{
char c0 = key[0];
char c1 = key[1];
char c2 = key[2];
if (c0 == 'F' && c1 != '\0' && (c2 == '\0' || key[3] == '\0'))
{
// F1-F9
if (c2 == '\0' && (c1 >= '1' && c1 <= '9'))
return (ImGuiKey)((c1 - '1') + ImGuiKey_F1);
else if (c1 == '1' && (c2 >= '0' && c2 <= '9')) // F10-F19
return (ImGuiKey)((c2 - '0') + ImGuiKey_F10);
else if (c1 == '2' && (c2 >= '0' && c2 <= '4')) // F20-F24
return (ImGuiKey)((c2 - '0') + ImGuiKey_F20);
}
// Slowest path
if (!strcmp(key, "Tab"))
return ImGuiKey_Tab;
else if (!strcmp(key, "ArrowLeft"))
return ImGuiKey_LeftArrow;
else if (!strcmp(key, "ArrowRight"))
return ImGuiKey_RightArrow;
else if (!strcmp(key, "ArrowUp"))
return ImGuiKey_UpArrow;
else if (!strcmp(key, "ArrowDown"))
return ImGuiKey_DownArrow;
else if (!strcmp(key, "PageUp"))
return ImGuiKey_PageUp;
else if (!strcmp(key, "PageDown"))
return ImGuiKey_PageDown;
else if (!strcmp(key, "Home"))
return ImGuiKey_Home;
else if (!strcmp(key, "End"))
return ImGuiKey_End;
else if (!strcmp(key, "Insert"))
return ImGuiKey_Insert;
else if (!strcmp(key, "Delete"))
return ImGuiKey_Delete;
else if (!strcmp(key, "Backspace"))
return ImGuiKey_Backspace;
else if (!strcmp(key, "Space"))
return ImGuiKey_Space;
else if (!strcmp(key, "Enter"))
return ImGuiKey_Enter;
else if (!strcmp(key, "Escape"))
return ImGuiKey_Escape;
else if (!strcmp(key, "ContextMenu"))
return ImGuiKey_Menu;
else if (!strcmp(key, "CapsLock"))
return ImGuiKey_CapsLock;
else if (!strcmp(key, "ScrollLock"))
return ImGuiKey_ScrollLock;
else if (!strcmp(key, "NumLock"))
return ImGuiKey_NumLock;
else if (!strcmp(key, "PrintScreen"))
return ImGuiKey_PrintScreen;
else if (!strcmp(key, "Pause"))
return ImGuiKey_Pause;
}
return ImGuiKey_None;
}
static bool ImGui_ImplEmscripten_KeyCallback(int type, const EmscriptenKeyboardEvent* event, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
switch (type)
{
case EMSCRIPTEN_EVENT_KEYDOWN:
case EMSCRIPTEN_EVENT_KEYUP:
{
if (event->repeat)
{
if (event->key[1] == '\0')
io.AddInputCharacter(event->key[0]);
return false;
}
io.AddKeyEvent(ImGuiMod_Ctrl, event->ctrlKey);
io.AddKeyEvent(ImGuiMod_Shift, event->shiftKey);
io.AddKeyEvent(ImGuiMod_Alt, event->altKey);
io.AddKeyEvent(ImGuiMod_Super, event->metaKey);
ImGuiKey key = ImGui_ImplEmscripten_KeyToImGuiKey(event->key);
if (key != ImGuiKey_None)
{
bool down = type == EMSCRIPTEN_EVENT_KEYDOWN;
if (down && event->key[1] == '\0')
io.AddInputCharacter(event->key[0]);
io.AddKeyEvent(key, down);
}
// Without this those keys won't be dispatched with "keyup"
if (key == ImGuiKey_Tab || key == ImGuiKey_Backspace)
return true;
return false;
}
}
return false;
}
#ifndef IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENTS
static bool ImGui_ImplEmscripten_MouseCallback(int type, const EmscriptenMouseEvent* event, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
switch (type)
{
case EMSCRIPTEN_EVENT_MOUSEDOWN:
case EMSCRIPTEN_EVENT_MOUSEUP:
{
unsigned short button = event->button;
switch (button)
{
case 0: button = 0; break;
case 1: button = 2; break;
case 2: button = 1; break;
default: return false;
}
io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
io.AddMouseButtonEvent(button, type == EMSCRIPTEN_EVENT_MOUSEDOWN);
return false;
}
case EMSCRIPTEN_EVENT_MOUSEMOVE:
{
io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
io.AddMousePosEvent((float)event->clientX, (float)event->clientY);
break;
}
}
return false;
}
#endif
static bool ImGui_ImplEmscripten_WheelCallback(int type, const EmscriptenWheelEvent* event, void* user_data)
{
if (type == EMSCRIPTEN_EVENT_WHEEL)
{
ImGuiIO& io = ImGui::GetIO();
switch (event->deltaMode)
{
case DOM_DELTA_PIXEL:
{
io.AddMouseWheelEvent(-(float)event->deltaX / 100.f, -(float)event->deltaY / 100.f);
break;
}
}
}
return false;
}
static bool ImGui_ImplEmscripten_FocusCallback(int type, const EmscriptenFocusEvent* event, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
switch (type)
{
case EMSCRIPTEN_EVENT_FOCUSIN:
case EMSCRIPTEN_EVENT_FOCUSOUT:
{
io.AddFocusEvent(type == EMSCRIPTEN_EVENT_FOCUSIN);
break;
}
}
return false;
}
#ifdef IMGUI_IMPL_EMSCRIPTEN_ENABLE_CLIPBOARD
static const char* ImGui_ImplEmscripten_GetClipboardText(ImGuiContext*)
{
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData();
return bd->ClipboardTextData;
}
static void ImGui_ImplEmscripten_SetClipboardText(ImGuiContext*, const char* text)
{
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData();
if (bd->ClipboardTextData)
free((void*)bd->ClipboardTextData);
bd->ClipboardTextData = strdup(text);
if (bd->ClipboardTextData)
{
EM_ASM({
try { navigator.clipboard.writeText(UTF8ToString($0)); }
catch (err) { console.error(err); }
}, bd->ClipboardTextData);
}
}
extern "C"
{
EMSCRIPTEN_KEEPALIVE
void ImGui_ImplEmscripten_ClipboardPasteCallback(const char* text)
{
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData();
if (bd->ClipboardTextData)
free((void*)bd->ClipboardTextData);
bd->ClipboardTextData = strdup(text);
}
};
static void ImGui_ImplEmscripten_SetupClipboardCallbacks(ImGui_ImplEmscripten_BackendData* bd)
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_SetClipboardTextFn = ImGui_ImplEmscripten_SetClipboardText;
platform_io.Platform_GetClipboardTextFn = ImGui_ImplEmscripten_GetClipboardText;
EM_ASM({
const el = document.querySelector(UTF8ToString($0));
document.addEventListener('paste', (ev) => {
Module['_ImGui_ImplEmscripten_ClipboardPasteCallback'](stringToNewUTF8(ev.clipboardData.getData('text/plain')));
});
}, bd->TargetId);
}
#endif
#ifdef IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENTS
extern "C"
{
#define IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENT_HAS_POS 1
#define IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENT_HAS_BUTTON 2
#define IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENT_IS_PRIMARY 4
EMSCRIPTEN_KEEPALIVE
void ImGui_ImplEmscripten_PointerEvent(int type, int pointer_type, int flags, int x, int y, int buttons)
{
if (!(flags & IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENT_IS_PRIMARY))
return;
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData(io);
if (type == 5)
{
for (int i = 0; i < ImGuiMouseButton_COUNT; i++)
io.AddMouseButtonEvent((ImGuiMouseButton)i, false);
}
else if (pointer_type >= 0 && pointer_type <= 2)
{
ImGuiMouseSource source;
switch (pointer_type)
{
case 0: source = ImGuiMouseSource_Mouse; break;
case 1: source = ImGuiMouseSource_TouchScreen; break;
case 2: source = ImGuiMouseSource_Pen; break;
}
io.AddMouseSourceEvent(source);
if (flags & IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENT_HAS_POS)
io.AddMousePosEvent((float)x, (float)y);
if (flags & IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENT_HAS_BUTTON)
{
// HACK: Browser executes pointerup/down only for single mouse button if multiple buttons were pressed at the same time
#define PROCESS_BUTTON(key, flag) if ((buttons & flag) != (bd->PressedButtons & flag)) { io.AddMouseButtonEvent(key, buttons & flag); }
PROCESS_BUTTON(ImGuiMouseButton_Left, 1);
PROCESS_BUTTON(ImGuiMouseButton_Right, 2);
PROCESS_BUTTON(ImGuiMouseButton_Middle, 4);
PROCESS_BUTTON(3, 8);
PROCESS_BUTTON(4, 16);
#undef PROCESS_BUTTON
}
}
if (type == 0 || type == 1 || type == 3)
bd->PressedButtons = buttons;
}
};
static void ImGui_ImplEmscripten_SetupPointerEvents(ImGui_ImplEmscripten_BackendData* bd)
{
EM_ASM({
function t(name)
{
switch (name)
{
case "mouse": return 0;
case "touch": return 1;
case "pen": return 2;
default: return -1;
}
}
function p(ev)
{
return ev.isPrimary ? 4 : 0;
}
const el = document.querySelector(UTF8ToString($0));
const cb = Module['_ImGui_ImplEmscripten_PointerEvent'];
el.imguiHandlePointerDown = function(ev) { cb(0, t(ev.pointerType), 1 | 2 | p(ev), ev.clientX, ev.clientY, ev.buttons); };
el.imguiHandlePointerUp = function(ev) { cb(1, t(ev.pointerType), 1 | 2 | p(ev), ev.clientX, ev.clientY, ev.buttons); };
el.imguiHandlePointerMove = function(ev) { cb(2, t(ev.pointerType), 1 | p(ev), ev.clientX, ev.clientY, ev.buttons); };
el.imguiHandlePointerCancel = function(ev) { cb(3, t(ev.pointerType), 2 | p(ev), 0, 0, ev.buttons); };
el.imguiHandlePointerEnter = function(ev) { cb(4, t(ev.pointerType), 0 | p(ev), 0, 0, ev.buttons); };
el.imguiHandlePointerLeave = function(ev) { cb(5, t(ev.pointerType), 0 | p(ev), 0, 0, ev.buttons); };
el.addEventListener('pointerdown', el.imguiHandlePointerDown);
el.addEventListener('pointerup', el.imguiHandlePointerUp);
el.addEventListener('pointermove', el.imguiHandlePointerMove);
el.addEventListener('pointercancel', el.imguiHandlePointerCancel);
el.addEventListener('pointerenter', el.imguiHandlePointerEnter);
el.addEventListener('pointerleave', el.imguiHandlePointerLeave);
}, bd->TargetId);
}
static void ImGui_ImplEmscripten_ClearPointerEvents(ImGui_ImplEmscripten_BackendData* bd)
{
EM_ASM({
const el = document.querySelector(UTF8ToString($0));
el.removeEventListener('pointerdown', el.imguiHandlePointerDown);
el.removeEventListener('pointerup', el.imguiHandlePointerUp);
el.removeEventListener('pointermove', el.imguiHandlePointerMove);
el.removeEventListener('pointercancel', el.imguiHandlePointerCancel);
el.removeEventListener('pointerenter', el.imguiHandlePointerEnter);
el.removeEventListener('pointerleave', el.imguiHandlePointerLeave);
delete el.imguiHandlePointerDown;
delete el.imguiHandlePointerUp;
delete el.imguiHandlePointerMove;
delete el.imguiHandlePointerCancel;
delete el.imguiHandlePointerEnter;
delete el.imguiHandlePointerLeave;
}, bd->TargetId);
}
#endif
static bool ImGui_ImplEmscripten_GamepadCallback(int type, const EmscriptenGamepadEvent* event, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData(io);
if (type == EMSCRIPTEN_EVENT_GAMEPADCONNECTED)
bd->GamepadsCount++;
else if (type == EMSCRIPTEN_EVENT_GAMEPADDISCONNECTED)
bd->GamepadsCount--;
if (bd->GamepadsCount > 0)
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
else
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
return false;
}
static void ImGui_ImplEmscripten_UpdateGamepads(ImGuiIO& io)
{
if (!(io.BackendFlags & ImGuiBackendFlags_HasGamepad))
return;
EmscriptenGamepadEvent state;
if (emscripten_sample_gamepad_data() != EMSCRIPTEN_RESULT_SUCCESS || emscripten_get_gamepad_status(0, &state) != EMSCRIPTEN_RESULT_SUCCESS)
return;
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_IDX) { io.AddKeyEvent(KEY_NO, state.digitalButton[BUTTON_IDX]); }
#define MAP_ANALOG(KEY_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); io.AddKeyAnalogEvent(KEY_NO, vn > 0.10f, IM_SATURATE(vn)); }
MAP_BUTTON(ImGuiKey_GamepadStart, 9);
MAP_BUTTON(ImGuiKey_GamepadBack, 8);
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, 2);
MAP_BUTTON(ImGuiKey_GamepadFaceRight, 1);
MAP_BUTTON(ImGuiKey_GamepadFaceUp, 3);
MAP_BUTTON(ImGuiKey_GamepadFaceDown, 0);
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, 14);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, 15);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, 12);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, 13);
MAP_BUTTON(ImGuiKey_GamepadL1, 4);
MAP_BUTTON(ImGuiKey_GamepadR1, 5);
MAP_ANALOG(ImGuiKey_GamepadL2, state.analogButton[6], 0.125, 1.0);
MAP_ANALOG(ImGuiKey_GamepadR2, state.analogButton[7], 0.125, 1.0);
MAP_BUTTON(ImGuiKey_GamepadL3, 10);
MAP_BUTTON(ImGuiKey_GamepadR3, 11);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, state.axis[0], -0.25, -1.0);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, state.axis[0], +0.25, +1.0);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, state.axis[1], -0.25, -1.0);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, state.axis[1], +0.25, +1.0);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, state.axis[2], -0.25, -1.0);
MAP_ANALOG(ImGuiKey_GamepadRStickRight, state.axis[2], +0.25, +1.0);
MAP_ANALOG(ImGuiKey_GamepadRStickUp, state.axis[3], -0.25, -1.0);
MAP_ANALOG(ImGuiKey_GamepadRStickDown, state.axis[3], +0.25, +1.0);
#undef MAP_BUTTON
#undef MAP_ANALOG
#undef IM_SATURATE
}
bool ImGui_ImplEmscripten_Init(const char* target_id)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
ImGui_ImplEmscripten_BackendData* bd = IM_NEW(ImGui_ImplEmscripten_BackendData)();
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = "imgui_impl_emscripten";
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
double width, height;
emscripten_get_element_css_size(target_id, &width, &height);
bd->Width = width;
bd->Height = height;
bd->Time = emscripten_performance_now();
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
bd->ClipboardTextData = nullptr;
bd->GamepadsCount = 0;
bd->PressedButtons = 0;
size_t target_id_size = strlen(target_id);
bd->TargetId = (char*)IM_ALLOC(target_id_size + 1);
memcpy(bd->TargetId, target_id, target_id_size + 1);
io.DisplaySize = { (float)bd->Width, (float)bd->Height };
emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, &ImGui_ImplEmscripten_KeyCallback);
emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, &ImGui_ImplEmscripten_KeyCallback);
#ifdef IMGUI_IMPL_EMSCRIPTEN_ENABLE_CLIPBOARD
ImGui_ImplEmscripten_SetupClipboardCallbacks(bd);
#endif
#ifndef IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENTS
emscripten_set_click_callback(target_id, NULL, false, &ImGui_ImplEmscripten_MouseCallback);
emscripten_set_mousedown_callback(target_id, NULL, false, &ImGui_ImplEmscripten_MouseCallback);
emscripten_set_mouseup_callback(target_id, NULL, false, &ImGui_ImplEmscripten_MouseCallback);
emscripten_set_dblclick_callback(target_id, NULL, false, &ImGui_ImplEmscripten_MouseCallback);
emscripten_set_mousemove_callback(target_id, NULL, false, &ImGui_ImplEmscripten_MouseCallback);
emscripten_set_mouseenter_callback(target_id, NULL, false, &ImGui_ImplEmscripten_MouseCallback);
emscripten_set_mouseleave_callback(target_id, NULL, false, &ImGui_ImplEmscripten_MouseCallback);
#else
ImGui_ImplEmscripten_SetupPointerEvents(bd);
#endif
emscripten_set_wheel_callback(target_id, NULL, false, &ImGui_ImplEmscripten_WheelCallback);
emscripten_set_focusin_callback(target_id, NULL, false, &ImGui_ImplEmscripten_FocusCallback);
emscripten_set_focusout_callback(target_id, NULL, false, &ImGui_ImplEmscripten_FocusCallback);
emscripten_set_gamepadconnected_callback(NULL, false, &ImGui_ImplEmscripten_GamepadCallback);
emscripten_set_gamepaddisconnected_callback(NULL, false, &ImGui_ImplEmscripten_GamepadCallback);
return true;
}
void ImGui_ImplEmscripten_Shutdown()
{
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData();
emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL);
emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL);
#ifndef IMGUI_IMPL_EMSCRIPTEN_POINTER_EVENTS
emscripten_set_click_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_mousedown_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_mouseup_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_dblclick_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_mousemove_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_mouseenter_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_mouseleave_callback(bd->TargetId, NULL, false, NULL);
#else
ImGui_ImplEmscripten_ClearPointerEvents(bd);
#endif
emscripten_set_wheel_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_focusin_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_focusout_callback(bd->TargetId, NULL, false, NULL);
emscripten_set_gamepadconnected_callback(NULL, false, NULL);
emscripten_set_gamepaddisconnected_callback(NULL, false, NULL);
free((void*)bd->TargetId);
IM_DELETE(bd);
}
void ImGui_ImplEmscripten_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData(io);
double current_time = emscripten_performance_now();
io.DeltaTime = (float)((current_time - bd->Time) / 1000.0);
bd->Time = current_time;
// Update OS mouse cursor with the cursor requested by imgui
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
if (bd->LastMouseCursor != mouse_cursor)
{
bd->LastMouseCursor = mouse_cursor;
ImGui_ImplEmscripten_UpdateMouseCursor(io, mouse_cursor);
}
ImGui_ImplEmscripten_UpdateGamepads(io);
}
void ImGui_ImplEmscripten_UpdateCanvasSize(int width, int height)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplEmscripten_BackendData* bd = ImGui_ImplEmscripten_GetBackendData(io);
bd->Width = width;
bd->Height = height;
io.DisplaySize = { (float)bd->Width, (float)bd->Height };
}
#endif // #ifndef IMGUI_DISABLE