summaryrefslogtreecommitdiff
path: root/contrib/imgui/rlImGui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/imgui/rlImGui.cpp')
-rw-r--r--contrib/imgui/rlImGui.cpp508
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);
+}