|
|
|
@@ -1,314 +0,0 @@ |
|
|
|
/* |
|
|
|
* DISTRHO Plugin Framework (DPF) |
|
|
|
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> |
|
|
|
* |
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any purpose with |
|
|
|
* or without fee is hereby granted, provided that the above copyright notice and this |
|
|
|
* permission notice appear in all copies. |
|
|
|
* |
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD |
|
|
|
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN |
|
|
|
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER |
|
|
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
|
|
*/ |
|
|
|
|
|
|
|
#include "Application.hpp" |
|
|
|
|
|
|
|
#include <GL/glew.h> |
|
|
|
|
|
|
|
#include "ImGuiUI.hpp" |
|
|
|
#include <imgui.h> |
|
|
|
#if !defined(IMGUI_GL2) && !defined(IMGUI_GL3) |
|
|
|
# define IMGUI_GL2 1 |
|
|
|
#endif |
|
|
|
#if defined(IMGUI_GL2) |
|
|
|
# include <imgui_impl_opengl2.h> |
|
|
|
#elif defined(IMGUI_GL3) |
|
|
|
# include <imgui_impl_opengl3.h> |
|
|
|
#endif |
|
|
|
#include <chrono> |
|
|
|
#include <cmath> |
|
|
|
|
|
|
|
START_NAMESPACE_DGL |
|
|
|
|
|
|
|
struct ImGuiUI::Impl |
|
|
|
{ |
|
|
|
explicit Impl(ImGuiUI* self); |
|
|
|
~Impl(); |
|
|
|
|
|
|
|
void setupGL(); |
|
|
|
void cleanupGL(); |
|
|
|
|
|
|
|
static int mouseButtonToImGui(int button); |
|
|
|
|
|
|
|
ImGuiUI* fSelf = nullptr; |
|
|
|
ImGuiContext* fContext = nullptr; |
|
|
|
Color fBackgroundColor{0.25f, 0.25f, 0.25f}; |
|
|
|
int fRepaintIntervalMs = 15; |
|
|
|
|
|
|
|
using Clock = std::chrono::steady_clock; |
|
|
|
Clock::time_point fLastRepainted; |
|
|
|
bool fWasEverPainted = false; |
|
|
|
}; |
|
|
|
|
|
|
|
ImGuiUI::ImGuiUI(Window& windowToMapTo) |
|
|
|
: TopLevelWidget(windowToMapTo), |
|
|
|
fImpl(new ImGuiUI::Impl(this)) |
|
|
|
{ |
|
|
|
getApp().addIdleCallback(this); |
|
|
|
} |
|
|
|
|
|
|
|
ImGuiUI::~ImGuiUI() |
|
|
|
{ |
|
|
|
delete fImpl; |
|
|
|
} |
|
|
|
|
|
|
|
void ImGuiUI::setBackgroundColor(Color color) |
|
|
|
{ |
|
|
|
fImpl->fBackgroundColor = color; |
|
|
|
} |
|
|
|
|
|
|
|
void ImGuiUI::setRepaintInterval(int intervalMs) |
|
|
|
{ |
|
|
|
fImpl->fRepaintIntervalMs = intervalMs; |
|
|
|
} |
|
|
|
|
|
|
|
void ImGuiUI::onDisplay() |
|
|
|
{ |
|
|
|
ImGui::SetCurrentContext(fImpl->fContext); |
|
|
|
|
|
|
|
#if defined(IMGUI_GL2) |
|
|
|
ImGui_ImplOpenGL2_NewFrame(); |
|
|
|
#elif defined(IMGUI_GL3) |
|
|
|
ImGui_ImplOpenGL3_NewFrame(); |
|
|
|
#endif |
|
|
|
|
|
|
|
ImGui::NewFrame(); |
|
|
|
onImGuiDisplay(); |
|
|
|
ImGui::Render(); |
|
|
|
|
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
|
|
|
|
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); |
|
|
|
|
|
|
|
Color backgroundColor = fImpl->fBackgroundColor; |
|
|
|
glClearColor( |
|
|
|
backgroundColor.red, backgroundColor.green, |
|
|
|
backgroundColor.blue, backgroundColor.alpha); |
|
|
|
glClear(GL_COLOR_BUFFER_BIT); |
|
|
|
glLoadIdentity(); |
|
|
|
|
|
|
|
#if defined(IMGUI_GL2) |
|
|
|
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); |
|
|
|
#elif defined(IMGUI_GL3) |
|
|
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); |
|
|
|
#endif |
|
|
|
|
|
|
|
fImpl->fLastRepainted = Impl::Clock::now(); |
|
|
|
fImpl->fWasEverPainted = true; |
|
|
|
} |
|
|
|
|
|
|
|
bool ImGuiUI::onKeyboard(const KeyboardEvent& event) |
|
|
|
{ |
|
|
|
ImGui::SetCurrentContext(fImpl->fContext); |
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
|
|
|
|
if (event.press) |
|
|
|
io.AddInputCharacter(event.key); |
|
|
|
|
|
|
|
int imGuiKey = event.key; |
|
|
|
if (imGuiKey >= 0 && imGuiKey < 128) |
|
|
|
{ |
|
|
|
if (imGuiKey >= 'a' && imGuiKey <= 'z') |
|
|
|
imGuiKey = imGuiKey - 'a' + 'A'; |
|
|
|
io.KeysDown[imGuiKey] = event.press; |
|
|
|
} |
|
|
|
|
|
|
|
return io.WantCaptureKeyboard; |
|
|
|
} |
|
|
|
|
|
|
|
bool ImGuiUI::onSpecial(const SpecialEvent& event) |
|
|
|
{ |
|
|
|
ImGui::SetCurrentContext(fImpl->fContext); |
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
|
|
|
|
int imGuiKey = IM_ARRAYSIZE(io.KeysDown) - event.key; |
|
|
|
io.KeysDown[imGuiKey] = event.press; |
|
|
|
|
|
|
|
switch (event.key) |
|
|
|
{ |
|
|
|
case kKeyShift: |
|
|
|
io.KeyShift = event.press; |
|
|
|
break; |
|
|
|
case kKeyControl: |
|
|
|
io.KeyCtrl = event.press; |
|
|
|
break; |
|
|
|
case kKeyAlt: |
|
|
|
io.KeyAlt = event.press; |
|
|
|
break; |
|
|
|
case kKeySuper: |
|
|
|
io.KeySuper = event.press; |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return io.WantCaptureKeyboard; |
|
|
|
} |
|
|
|
|
|
|
|
bool ImGuiUI::onMouse(const MouseEvent& event) |
|
|
|
{ |
|
|
|
ImGui::SetCurrentContext(fImpl->fContext); |
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
|
|
|
|
int imGuiButton = Impl::mouseButtonToImGui(event.button); |
|
|
|
if (imGuiButton != -1) |
|
|
|
io.MouseDown[imGuiButton] = event.press; |
|
|
|
|
|
|
|
return io.WantCaptureMouse; |
|
|
|
} |
|
|
|
|
|
|
|
bool ImGuiUI::onMotion(const MotionEvent& event) |
|
|
|
{ |
|
|
|
ImGui::SetCurrentContext(fImpl->fContext); |
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
|
|
|
|
// FIXME |
|
|
|
const double scaleFactor = 1; // getScaleFactor(); |
|
|
|
io.MousePos.x = std::round(scaleFactor * event.pos.getX()); |
|
|
|
io.MousePos.y = std::round(scaleFactor * event.pos.getY()); |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool ImGuiUI::onScroll(const ScrollEvent& event) |
|
|
|
{ |
|
|
|
ImGui::SetCurrentContext(fImpl->fContext); |
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
|
|
|
|
io.MouseWheel += event.delta.getY(); |
|
|
|
io.MouseWheelH += event.delta.getX(); |
|
|
|
|
|
|
|
return io.WantCaptureMouse; |
|
|
|
} |
|
|
|
|
|
|
|
void ImGuiUI::onResize(const ResizeEvent& event) |
|
|
|
{ |
|
|
|
TopLevelWidget::onResize(event); |
|
|
|
|
|
|
|
const uint width = event.size.getWidth(); |
|
|
|
const uint height = event.size.getHeight(); |
|
|
|
|
|
|
|
ImGui::SetCurrentContext(fImpl->fContext); |
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
|
|
|
|
const double scaleFactor = getScaleFactor(); |
|
|
|
io.DisplaySize.x = std::round(scaleFactor * width); |
|
|
|
io.DisplaySize.y = std::round(scaleFactor * height); |
|
|
|
} |
|
|
|
|
|
|
|
void ImGuiUI::idleCallback() |
|
|
|
{ |
|
|
|
bool shouldRepaint; |
|
|
|
|
|
|
|
if (fImpl->fWasEverPainted) |
|
|
|
{ |
|
|
|
Impl::Clock::duration elapsed = |
|
|
|
Impl::Clock::now() - fImpl->fLastRepainted; |
|
|
|
std::chrono::milliseconds elapsedMs = |
|
|
|
std::chrono::duration_cast<std::chrono::milliseconds>(elapsed); |
|
|
|
shouldRepaint = elapsedMs.count() > fImpl->fRepaintIntervalMs; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
shouldRepaint = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (shouldRepaint) |
|
|
|
repaint(); |
|
|
|
} |
|
|
|
|
|
|
|
ImGuiUI::Impl::Impl(ImGuiUI* self) |
|
|
|
: fSelf(self) |
|
|
|
{ |
|
|
|
setupGL(); |
|
|
|
} |
|
|
|
|
|
|
|
ImGuiUI::Impl::~Impl() |
|
|
|
{ |
|
|
|
cleanupGL(); |
|
|
|
} |
|
|
|
|
|
|
|
void ImGuiUI::Impl::setupGL() |
|
|
|
{ |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(glewInit() == 0,); |
|
|
|
|
|
|
|
IMGUI_CHECKVERSION(); |
|
|
|
fContext = ImGui::CreateContext(); |
|
|
|
ImGui::SetCurrentContext(fContext); |
|
|
|
|
|
|
|
ImGuiIO &io = ImGui::GetIO(); |
|
|
|
const double scaleFactor = fSelf->getScaleFactor(); |
|
|
|
io.DisplaySize.x = std::round(scaleFactor * fSelf->getWidth()); |
|
|
|
io.DisplaySize.y = std::round(scaleFactor * fSelf->getHeight()); |
|
|
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; |
|
|
|
io.IniFilename = nullptr; |
|
|
|
|
|
|
|
io.KeyMap[ImGuiKey_Tab] = '\t'; |
|
|
|
io.KeyMap[ImGuiKey_LeftArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyLeft; |
|
|
|
io.KeyMap[ImGuiKey_RightArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyRight; |
|
|
|
io.KeyMap[ImGuiKey_UpArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyUp; |
|
|
|
io.KeyMap[ImGuiKey_DownArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyDown; |
|
|
|
io.KeyMap[ImGuiKey_PageUp] = IM_ARRAYSIZE(io.KeysDown) - kKeyPageUp; |
|
|
|
io.KeyMap[ImGuiKey_PageDown] = IM_ARRAYSIZE(io.KeysDown) - kKeyPageDown; |
|
|
|
io.KeyMap[ImGuiKey_Home] = IM_ARRAYSIZE(io.KeysDown) - kKeyHome; |
|
|
|
io.KeyMap[ImGuiKey_End] = IM_ARRAYSIZE(io.KeysDown) - kKeyEnd; |
|
|
|
io.KeyMap[ImGuiKey_Insert] = IM_ARRAYSIZE(io.KeysDown) - kKeyInsert; |
|
|
|
io.KeyMap[ImGuiKey_Delete] = 127; |
|
|
|
io.KeyMap[ImGuiKey_Backspace] = '\b'; |
|
|
|
io.KeyMap[ImGuiKey_Space] = ' '; |
|
|
|
io.KeyMap[ImGuiKey_Enter] = '\r'; |
|
|
|
io.KeyMap[ImGuiKey_Escape] = 27; |
|
|
|
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'; |
|
|
|
|
|
|
|
#if defined(IMGUI_GL2) |
|
|
|
ImGui_ImplOpenGL2_Init(); |
|
|
|
#elif defined(IMGUI_GL3) |
|
|
|
ImGui_ImplOpenGL3_Init(); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void ImGuiUI::Impl::cleanupGL() |
|
|
|
{ |
|
|
|
ImGui::SetCurrentContext(fContext); |
|
|
|
#if defined(IMGUI_GL2) |
|
|
|
ImGui_ImplOpenGL2_Shutdown(); |
|
|
|
#elif defined(IMGUI_GL3) |
|
|
|
ImGui_ImplOpenGL3_Shutdown(); |
|
|
|
#endif |
|
|
|
ImGui::DestroyContext(fContext); |
|
|
|
} |
|
|
|
|
|
|
|
int ImGuiUI::Impl::mouseButtonToImGui(int button) |
|
|
|
{ |
|
|
|
switch (button) |
|
|
|
{ |
|
|
|
default: |
|
|
|
return -1; |
|
|
|
case 1: |
|
|
|
return 0; |
|
|
|
case 2: |
|
|
|
return 2; |
|
|
|
case 3: |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
END_NAMESPACE_DGL |