diff options
Diffstat (limited to 'contrib/imgui/rlImGui.cpp')
-rw-r--r-- | contrib/imgui/rlImGui.cpp | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/contrib/imgui/rlImGui.cpp b/contrib/imgui/rlImGui.cpp new file mode 100644 index 0000000..6dec01e --- /dev/null +++ b/contrib/imgui/rlImGui.cpp @@ -0,0 +1,508 @@ +/********************************************************************************************** +* +* raylibExtras * Utilities and Shared Components for Raylib +* +* rlImGui * basic ImGui integration +* +* LICENSE: ZLIB +* +* Copyright (c) 2020 Jeffery Myers +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +**********************************************************************************************/ +#include "rlImGui.h" + +#include "imgui.h" +#include "raylib.h" +#include "rlgl.h" + +#ifdef PLATFORM_DESKTOP +#include <GLFW/glfw3.h> +#endif + +#include <math.h> + +#ifndef NO_FONT_AWESOME +#include "extras/FA6FreeSolidFontData.h" +#endif + +static Texture2D FontTexture; + +static ImGuiMouseCursor CurrentMouseCursor = ImGuiMouseCursor_COUNT; +static MouseCursor MouseCursorMap[ImGuiMouseCursor_COUNT]; + +static const char* rlImGuiGetClipText(void*) +{ + return GetClipboardText(); +} + +static void rlImGuiSetClipText(void*, const char* text) +{ + SetClipboardText(text); +} + +static void rlImGuiNewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + if (IsWindowFullscreen()) + { + int monitor = GetCurrentMonitor(); + io.DisplaySize.x = float(GetMonitorWidth(monitor)); + io.DisplaySize.y = float(GetMonitorHeight(monitor)); + } + else + { + io.DisplaySize.x = float(GetScreenWidth()); + io.DisplaySize.y = float(GetScreenHeight()); + } + + int width = int(io.DisplaySize.x), height = int(io.DisplaySize.y); +#ifdef PLATFORM_DESKTOP + glfwGetFramebufferSize(glfwGetCurrentContext(), &width, &height); +#endif + if (width > 0 && height > 0) { + io.DisplayFramebufferScale = ImVec2(width / io.DisplaySize.x, height / io.DisplaySize.y); + } + else { + io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); + } + + io.DeltaTime = GetFrameTime(); + + io.KeyCtrl = IsKeyDown(KEY_RIGHT_CONTROL) || IsKeyDown(KEY_LEFT_CONTROL); + io.KeyShift = IsKeyDown(KEY_RIGHT_SHIFT) || IsKeyDown(KEY_LEFT_SHIFT); + io.KeyAlt = IsKeyDown(KEY_RIGHT_ALT) || IsKeyDown(KEY_LEFT_ALT); + io.KeySuper = IsKeyDown(KEY_RIGHT_SUPER) || IsKeyDown(KEY_LEFT_SUPER); + + if (io.WantSetMousePos) + { + SetMousePosition((int)io.MousePos.x, (int)io.MousePos.y); + } + else + { + io.MousePos.x = (float)GetMouseX(); + io.MousePos.y = (float)GetMouseY(); + } + + io.MouseDown[0] = IsMouseButtonDown(MOUSE_LEFT_BUTTON); + io.MouseDown[1] = IsMouseButtonDown(MOUSE_RIGHT_BUTTON); + io.MouseDown[2] = IsMouseButtonDown(MOUSE_MIDDLE_BUTTON); + + if (GetMouseWheelMove() > 0) + io.MouseWheel += 1; + else if (GetMouseWheelMove() < 0) + io.MouseWheel -= 1; + + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) + { + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (imgui_cursor != CurrentMouseCursor || io.MouseDrawCursor) + { + CurrentMouseCursor = imgui_cursor; + if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) + { + HideCursor(); + } + else + { + ShowCursor(); + + if (!(io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)) + { + SetMouseCursor((imgui_cursor > -1 && imgui_cursor < ImGuiMouseCursor_COUNT) ? MouseCursorMap[imgui_cursor] : MOUSE_CURSOR_DEFAULT); + } + } + } + } +} + +#define FOR_ALL_KEYS(X) \ + do { \ + X(KEY_APOSTROPHE); \ + X(KEY_COMMA); \ + X(KEY_MINUS); \ + X(KEY_PERIOD); \ + X(KEY_SLASH); \ + X(KEY_ZERO); \ + X(KEY_ONE); \ + X(KEY_TWO); \ + X(KEY_THREE); \ + X(KEY_FOUR); \ + X(KEY_FIVE); \ + X(KEY_SIX); \ + X(KEY_SEVEN); \ + X(KEY_EIGHT); \ + X(KEY_NINE); \ + X(KEY_SEMICOLON); \ + X(KEY_EQUAL); \ + X(KEY_A); \ + X(KEY_B); \ + X(KEY_C); \ + X(KEY_D); \ + X(KEY_E); \ + X(KEY_F); \ + X(KEY_G); \ + X(KEY_H); \ + X(KEY_I); \ + X(KEY_J); \ + X(KEY_K); \ + X(KEY_L); \ + X(KEY_M); \ + X(KEY_N); \ + X(KEY_O); \ + X(KEY_P); \ + X(KEY_Q); \ + X(KEY_R); \ + X(KEY_S); \ + X(KEY_T); \ + X(KEY_U); \ + X(KEY_V); \ + X(KEY_W); \ + X(KEY_X); \ + X(KEY_Y); \ + X(KEY_Z); \ + X(KEY_SPACE); \ + X(KEY_ESCAPE); \ + X(KEY_ENTER); \ + X(KEY_TAB); \ + X(KEY_BACKSPACE); \ + X(KEY_INSERT); \ + X(KEY_DELETE); \ + X(KEY_RIGHT); \ + X(KEY_LEFT); \ + X(KEY_DOWN); \ + X(KEY_UP); \ + X(KEY_PAGE_UP); \ + X(KEY_PAGE_DOWN); \ + X(KEY_HOME); \ + X(KEY_END); \ + X(KEY_CAPS_LOCK); \ + X(KEY_SCROLL_LOCK); \ + X(KEY_NUM_LOCK); \ + X(KEY_PRINT_SCREEN); \ + X(KEY_PAUSE); \ + X(KEY_F1); \ + X(KEY_F2); \ + X(KEY_F3); \ + X(KEY_F4); \ + X(KEY_F5); \ + X(KEY_F6); \ + X(KEY_F7); \ + X(KEY_F8); \ + X(KEY_F9); \ + X(KEY_F10); \ + X(KEY_F11); \ + X(KEY_F12); \ + X(KEY_LEFT_SHIFT); \ + X(KEY_LEFT_CONTROL); \ + X(KEY_LEFT_ALT); \ + X(KEY_LEFT_SUPER); \ + X(KEY_RIGHT_SHIFT); \ + X(KEY_RIGHT_CONTROL); \ + X(KEY_RIGHT_ALT); \ + X(KEY_RIGHT_SUPER); \ + X(KEY_KB_MENU); \ + X(KEY_LEFT_BRACKET); \ + X(KEY_BACKSLASH); \ + X(KEY_RIGHT_BRACKET); \ + X(KEY_GRAVE); \ + X(KEY_KP_0); \ + X(KEY_KP_1); \ + X(KEY_KP_2); \ + X(KEY_KP_3); \ + X(KEY_KP_4); \ + X(KEY_KP_5); \ + X(KEY_KP_6); \ + X(KEY_KP_7); \ + X(KEY_KP_8); \ + X(KEY_KP_9); \ + X(KEY_KP_DECIMAL); \ + X(KEY_KP_DIVIDE); \ + X(KEY_KP_MULTIPLY); \ + X(KEY_KP_SUBTRACT); \ + X(KEY_KP_ADD); \ + X(KEY_KP_ENTER); \ + X(KEY_KP_EQUAL); \ + } while(0) + +#define SET_KEY_DOWN(KEY) io.KeysDown[KEY] = IsKeyDown(KEY) + + +static void rlImGuiEvents() +{ + ImGuiIO& io = ImGui::GetIO(); + FOR_ALL_KEYS(SET_KEY_DOWN); + + unsigned int pressed = GetCharPressed(); + if (pressed != 0) + io.AddInputCharacter(pressed); +} + +static void rlImGuiTriangleVert(ImDrawVert& idx_vert) +{ + Color* c; + c = (Color*)&idx_vert.col; + rlColor4ub(c->r, c->g, c->b, c->a); + rlTexCoord2f(idx_vert.uv.x, idx_vert.uv.y); + rlVertex2f(idx_vert.pos.x, idx_vert.pos.y); +} + +static void rlImGuiRenderTriangles(unsigned int count, int indexStart, const ImVector<ImDrawIdx>& indexBuffer, const ImVector<ImDrawVert>& vertBuffer, void* texturePtr) +{ + if (count < 3) + return; + + Texture* texture = (Texture*)texturePtr; + + unsigned int textureId = (texture == nullptr) ? 0 : texture->id; + + rlBegin(RL_TRIANGLES); + rlSetTexture(textureId); + + for (unsigned int i = 0; i <= (count - 3); i += 3) + { + if(rlCheckRenderBatchLimit(3)) + { + rlBegin(RL_TRIANGLES); + rlSetTexture(textureId); + } + + ImDrawIdx indexA = indexBuffer[indexStart + i]; + ImDrawIdx indexB = indexBuffer[indexStart + i + 1]; + ImDrawIdx indexC = indexBuffer[indexStart + i + 2]; + + ImDrawVert vertexA = vertBuffer[indexA]; + ImDrawVert vertexB = vertBuffer[indexB]; + ImDrawVert vertexC = vertBuffer[indexC]; + + rlImGuiTriangleVert(vertexA); + rlImGuiTriangleVert(vertexB); + rlImGuiTriangleVert(vertexC); + } + rlEnd(); +} + +static void EnableScissor(float x, float y, float width, float height) +{ + rlEnableScissorTest(); + ImGuiIO& io = ImGui::GetIO(); + rlScissor((int)(x * io.DisplayFramebufferScale.x), + int((GetScreenHeight() - (int)(y + height)) * io.DisplayFramebufferScale.y), + (int)(width * io.DisplayFramebufferScale.x), + (int)(height * io.DisplayFramebufferScale.y)); +} + +static void rlRenderData(ImDrawData* data) +{ + rlDrawRenderBatchActive(); + rlDisableBackfaceCulling(); + + for (int l = 0; l < data->CmdListsCount; ++l) + { + const ImDrawList* commandList = data->CmdLists[l]; + + for (const auto& cmd : commandList->CmdBuffer) + { + EnableScissor(cmd.ClipRect.x - data->DisplayPos.x, cmd.ClipRect.y - data->DisplayPos.y, cmd.ClipRect.z - (cmd.ClipRect.x - data->DisplayPos.x), cmd.ClipRect.w - (cmd.ClipRect.y - data->DisplayPos.y)); + if (cmd.UserCallback != nullptr) + { + cmd.UserCallback(commandList, &cmd); + + continue; + } + + rlImGuiRenderTriangles(cmd.ElemCount, cmd.IdxOffset, commandList->IdxBuffer, commandList->VtxBuffer, cmd.TextureId); + rlDrawRenderBatchActive(); + } + } + + rlSetTexture(0); + rlDisableScissorTest(); + rlEnableBackfaceCulling(); +} + +void SetupMouseCursors() +{ + MouseCursorMap[ImGuiMouseCursor_Arrow] = MOUSE_CURSOR_ARROW; + MouseCursorMap[ImGuiMouseCursor_TextInput] = MOUSE_CURSOR_IBEAM; + MouseCursorMap[ImGuiMouseCursor_Hand] = MOUSE_CURSOR_POINTING_HAND; + MouseCursorMap[ImGuiMouseCursor_ResizeAll] = MOUSE_CURSOR_RESIZE_ALL; + MouseCursorMap[ImGuiMouseCursor_ResizeEW] = MOUSE_CURSOR_RESIZE_EW; + MouseCursorMap[ImGuiMouseCursor_ResizeNESW] = MOUSE_CURSOR_RESIZE_NESW; + MouseCursorMap[ImGuiMouseCursor_ResizeNS] = MOUSE_CURSOR_RESIZE_NS; + MouseCursorMap[ImGuiMouseCursor_ResizeNWSE] = MOUSE_CURSOR_RESIZE_NWSE; + MouseCursorMap[ImGuiMouseCursor_NotAllowed] = MOUSE_CURSOR_NOT_ALLOWED; +} + +void rlImGuiBeginInitImGui() +{ + ImGui::CreateContext(nullptr); +} + +void rlImGuiEndInitImGui() +{ + SetupMouseCursors(); + + ImGuiIO& io = ImGui::GetIO(); + io.BackendPlatformName = "imgui_impl_raylib"; + + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; + + io.KeyMap[ImGuiKey_Tab] = KEY_TAB; + io.KeyMap[ImGuiKey_LeftArrow] = KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_PageDown] = KEY_PAGE_UP; + io.KeyMap[ImGuiKey_Home] = KEY_HOME; + io.KeyMap[ImGuiKey_End] = KEY_END; + io.KeyMap[ImGuiKey_Insert] = KEY_INSERT; + io.KeyMap[ImGuiKey_Delete] = KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = KEY_SPACE; + io.KeyMap[ImGuiKey_Enter] = KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = KEY_ESCAPE; + io.KeyMap[ImGuiKey_KeyPadEnter] = KEY_KP_ENTER; + io.KeyMap[ImGuiKey_A] = KEY_A; + io.KeyMap[ImGuiKey_C] = KEY_C; + io.KeyMap[ImGuiKey_V] = KEY_V; + io.KeyMap[ImGuiKey_X] = KEY_X; + io.KeyMap[ImGuiKey_Y] = KEY_Y; + io.KeyMap[ImGuiKey_Z] = KEY_Z; + + io.MousePos = ImVec2(0, 0); + + io.SetClipboardTextFn = rlImGuiSetClipText; + io.GetClipboardTextFn = rlImGuiGetClipText; + + io.ClipboardUserData = nullptr; + + + rlImGuiReloadFonts(); +} + +void rlImGuiSetup(bool dark) +{ + rlImGuiBeginInitImGui(); + + if (dark) + ImGui::StyleColorsDark(); + else + ImGui::StyleColorsLight(); + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->AddFontDefault(); + +#ifndef NO_FONT_AWESOME + static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; + ImFontConfig icons_config; + icons_config.MergeMode = true; + icons_config.PixelSnapH = true; + icons_config.FontDataOwnedByAtlas = false; + io.Fonts->AddFontFromMemoryCompressedTTF((void*)fa_solid_900_compressed_data, fa_solid_900_compressed_size, FONT_AWESOME_ICON_SIZE, &icons_config, icons_ranges); +#endif + + rlImGuiEndInitImGui(); +} + +void rlImGuiReloadFonts() +{ + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels = nullptr; + + int width; + int height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, nullptr); + Image image = GenImageColor(width, height, BLANK); + memcpy(image.data, pixels, width * height * 4); + + if (FontTexture.id != 0) + UnloadTexture(FontTexture); + + FontTexture = LoadTextureFromImage(image); + UnloadImage(image); + io.Fonts->TexID = &FontTexture; +} + +void rlImGuiBegin() +{ + rlImGuiNewFrame(); + rlImGuiEvents(); + ImGui::NewFrame(); +} + +void rlImGuiEnd() +{ + ImGui::Render(); + rlRenderData(ImGui::GetDrawData()); +} + +void rlImGuiShutdown() +{ + UnloadTexture(FontTexture); + + ImGui::DestroyContext(); +} + +void rlImGuiImage(const Texture *image) +{ + ImGui::Image((ImTextureID)image, ImVec2(float(image->width), float(image->height))); +} + +bool rlImGuiImageButton(const Texture *image) { + return ImGui::ImageButton((ImTextureID)image, ImVec2(float(image->width), float(image->height))); +} + +void rlImGuiImageSize(const Texture *image, int width, int height) +{ + ImGui::Image((ImTextureID)image, ImVec2(float(width), float(height))); +} + +void rlImGuiImageRect(const Texture* image, int destWidth, int destHeight, Rectangle sourceRect) +{ + ImVec2 uv0; + ImVec2 uv1; + + if (sourceRect.width < 0) + { + uv0.x = -((float)sourceRect.x / image->width); + uv1.x = (uv0.x - (float)(fabs(sourceRect.width) / image->width)); + } + else + { + uv0.x = (float)sourceRect.x / image->width; + uv1.x = uv0.x + (float)(sourceRect.width / image->width); + } + + if (sourceRect.height < 0) + { + uv0.y = -((float)sourceRect.y / image->height); + uv1.y = (uv0.y - (float)(fabs(sourceRect.height) / image->height)); + } + else + { + uv0.y = (float)sourceRect.y / image->height; + uv1.y = uv0.y + (float)(sourceRect.height / image->height); + } + + ImGui::Image((ImTextureID)image, ImVec2(float(destWidth), float(destHeight)),uv0,uv1); +} |