mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-11 00:04:24 +00:00
Merge 1e0f1c2625 into b467a0466c
This commit is contained in:
commit
16d669e3b0
6 changed files with 982 additions and 0 deletions
644
backends/imgui_impl_emscripten.cpp
Normal file
644
backends/imgui_impl_emscripten.cpp
Normal file
|
|
@ -0,0 +1,644 @@
|
|||
// 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
|
||||
30
backends/imgui_impl_emscripten.h
Normal file
30
backends/imgui_impl_emscripten.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// 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
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplEmscripten_Init(const char* target_id);
|
||||
IMGUI_IMPL_API void ImGui_ImplEmscripten_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplEmscripten_NewFrame();
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplEmscripten_UpdateCanvasSize(int width, int height);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
1
examples/example_emscripten_opengl3/.gitignore
vendored
Normal file
1
examples/example_emscripten_opengl3/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
web/
|
||||
102
examples/example_emscripten_opengl3/Makefile
Normal file
102
examples/example_emscripten_opengl3/Makefile
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#
|
||||
# Makefile to use with Emscripten+opengl3
|
||||
# See https://emscripten.org/docs/getting_started/downloads.html
|
||||
# for installation instructions.
|
||||
#
|
||||
# This Makefile assumes you have loaded emscripten's environment.
|
||||
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
|
||||
#
|
||||
# Running `make -f Makefile.emscripten` will produce three files:
|
||||
# - web/index.html
|
||||
# - web/index.js
|
||||
# - web/index.wasm
|
||||
#
|
||||
# All three are needed to run the demo.
|
||||
|
||||
CC = emcc
|
||||
CXX = em++
|
||||
WEB_DIR = web
|
||||
EXE = $(WEB_DIR)/index.html
|
||||
IMGUI_DIR = ../..
|
||||
SOURCES = main.cpp
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_emscripten.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
ifneq ($(OS),Windows_NT)
|
||||
UNAME_S := $(shell uname -s)
|
||||
endif
|
||||
CPPFLAGS = -DIMGUI_IMPL_OPENGL_ES2
|
||||
LDFLAGS =
|
||||
EMS =
|
||||
|
||||
# Use pointer events for this example (they properly support Mouse/TouchScreen/Pen)
|
||||
CPPFLAGS += -DIMGUI_IMPL_EMSCRIPTEN_POINTER_EVENTS
|
||||
|
||||
# Enable clipboard support
|
||||
CPPFLAGS += -DIMGUI_IMPL_EMSCRIPTEN_ENABLE_CLIPBOARD
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## EMSCRIPTEN OPTIONS
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
|
||||
EMS += -s DISABLE_EXCEPTION_CATCHING=1
|
||||
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
|
||||
|
||||
# Build as single file (binary text encoded in .html file)
|
||||
#LDFLAGS += -sSINGLE_FILE
|
||||
|
||||
# Uncomment next line to fix possible rendering bugs with Emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877)
|
||||
#EMS += -s BINARYEN_TRAP_MODE=clamp
|
||||
#EMS += -s SAFE_HEAP=1 ## Adds overhead
|
||||
|
||||
# Emscripten allows preloading a file or folder to be accessible at runtime.
|
||||
# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
|
||||
# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
|
||||
# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
|
||||
USE_FILE_SYSTEM ?= 0
|
||||
ifeq ($(USE_FILE_SYSTEM), 0)
|
||||
LDFLAGS += -s NO_FILESYSTEM=1
|
||||
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
|
||||
endif
|
||||
ifeq ($(USE_FILE_SYSTEM), 1)
|
||||
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
|
||||
endif
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## FINAL BUILD FLAGS
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
#CPPFLAGS += -g
|
||||
CPPFLAGS += -Wall -Wformat -Os $(EMS)
|
||||
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
|
||||
LDFLAGS += $(EMS)
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## BUILD RULES
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
%.o:%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/backends/%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
all: $(EXE)
|
||||
@echo Build complete for $(EXE)
|
||||
|
||||
$(WEB_DIR):
|
||||
mkdir $@
|
||||
|
||||
serve: all
|
||||
python3 -m http.server -d $(WEB_DIR)
|
||||
|
||||
$(EXE): $(OBJS) $(WEB_DIR)
|
||||
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJS) $(WEB_DIR)
|
||||
204
examples/example_emscripten_opengl3/main.cpp
Normal file
204
examples/example_emscripten_opengl3/main.cpp
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
// Dear ImGui: standalone example application for Emscripten + OpenGL 3, using programmable pipeline
|
||||
// (Emscripten is a complete Open Source compiler toolchain to WebAssembly.)
|
||||
|
||||
// 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
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_emscripten.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h> // Use GL ES 2
|
||||
|
||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/console.h>
|
||||
|
||||
#define TARGET_ELEMENT_ID "#canvas"
|
||||
|
||||
static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE g_ContextHandle;
|
||||
static int g_CanvasWidth;
|
||||
static int g_CanvasHeight;
|
||||
|
||||
static void ResizeCanvas(int width, int height)
|
||||
{
|
||||
g_CanvasWidth = width;
|
||||
g_CanvasHeight = height;
|
||||
emscripten_set_canvas_element_size(TARGET_ELEMENT_ID, g_CanvasWidth, g_CanvasHeight);
|
||||
}
|
||||
|
||||
static bool CreateWebGLContext()
|
||||
{
|
||||
EmscriptenWebGLContextAttributes attr{};
|
||||
emscripten_webgl_init_context_attributes(&attr);
|
||||
attr.majorVersion = 1;
|
||||
attr.minorVersion = 0;
|
||||
attr.antialias = false;
|
||||
attr.depth = false;
|
||||
attr.stencil = false;
|
||||
attr.alpha = true;
|
||||
|
||||
g_ContextHandle = emscripten_webgl_create_context(TARGET_ELEMENT_ID, &attr);
|
||||
if (g_ContextHandle != 0)
|
||||
{
|
||||
double width, height;
|
||||
emscripten_get_element_css_size(TARGET_ELEMENT_ID, &width, &height);
|
||||
ResizeCanvas((int)width, (int)height);
|
||||
}
|
||||
|
||||
return g_ContextHandle != 0;
|
||||
}
|
||||
|
||||
static bool WindowResizeCallback(int type, const EmscriptenUiEvent* event, void* user_data)
|
||||
{
|
||||
ResizeCanvas(event->windowInnerWidth, event->windowInnerHeight);
|
||||
ImGui_ImplEmscripten_UpdateCanvasSize(g_CanvasWidth, g_CanvasHeight);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
const float main_scale = 1.f;
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||
const char* glsl_version = "#version 100";
|
||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||
const char* glsl_version = "#version 300 es";
|
||||
#else
|
||||
// GL 3.0 + GLSL 130
|
||||
const char* glsl_version = "#version 130";
|
||||
#endif
|
||||
|
||||
if (!CreateWebGLContext())
|
||||
{
|
||||
emscripten_console_error("Failed to create webgl context");
|
||||
return 1;
|
||||
}
|
||||
|
||||
emscripten_webgl_make_context_current(g_ContextHandle);
|
||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, (em_ui_callback_func)&WindowResizeCallback);
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplEmscripten_Init(TARGET_ELEMENT_ID);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// 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 a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author!
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// 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
|
||||
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
|
||||
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
|
||||
io.IniFilename = nullptr;
|
||||
EMSCRIPTEN_MAINLOOP_BEGIN
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// 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, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// Emscripten backend uses callbacks to handle events so there is no need in this!
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplEmscripten_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 create 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 / io.Framerate, io.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();
|
||||
int display_w, display_h;
|
||||
emscripten_webgl_get_drawing_buffer_size(g_ContextHandle, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
EMSCRIPTEN_MAINLOOP_END;
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplEmscripten_NewFrame();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
touch-action: none;
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -o-crisp-edges;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue