Signed-off-by: falkTX <falktx@falktx.com>pull/341/head
@@ -131,7 +131,7 @@ | |||
This path must be relative to dpf/distrho/DistrhoUI.hpp | |||
@see DISTRHO_UI_USE_CUSTOM | |||
*/ | |||
#define DISTRHO_UI_CUSTOM_INCLUDE_PATH "ImGuiUI.hpp" | |||
#define DISTRHO_UI_CUSTOM_INCLUDE_PATH "DearImGui.hpp" | |||
/** | |||
The top-level-widget typedef to use for the custom toolkit. | |||
@@ -140,6 +140,6 @@ | |||
and define widget type as e.g. DGL_NAMESPACE::MyCustomTopLevelWidget. | |||
@see DISTRHO_UI_USE_CUSTOM | |||
*/ | |||
#define DISTRHO_UI_CUSTOM_WIDGET_TYPE DGL_NAMESPACE::ImGuiUI | |||
#define DISTRHO_UI_CUSTOM_WIDGET_TYPE DGL_NAMESPACE::ImGuiTopLevelWidget | |||
#define DISTRHO_UI_USER_RESIZABLE 1 |
@@ -1,35 +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 <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 <imgui.cpp> | |||
#include <imgui_draw.cpp> | |||
#include <imgui_tables.cpp> | |||
#include <imgui_widgets.cpp> | |||
#if defined(IMGUI_GL2) | |||
#include <imgui_impl_opengl2.cpp> | |||
#elif defined(IMGUI_GL3) | |||
#include <imgui_impl_opengl3.cpp> | |||
#endif |
@@ -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 |
@@ -1,56 +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. | |||
*/ | |||
#pragma once | |||
#include "TopLevelWidget.hpp" | |||
#include "Color.hpp" | |||
#ifndef DGL_OPENGL | |||
# error ImGUI is only available in OpenGL mode | |||
#endif | |||
START_NAMESPACE_DGL | |||
/** | |||
ImGui user interface class. | |||
*/ | |||
class ImGuiUI : public TopLevelWidget, | |||
public IdleCallback { | |||
public: | |||
ImGuiUI(Window& windowToMapTo); | |||
~ImGuiUI() override; | |||
void setBackgroundColor(Color color); | |||
void setRepaintInterval(int intervalMs); | |||
protected: | |||
virtual void onImGuiDisplay() = 0; | |||
virtual void onDisplay() override; | |||
virtual bool onKeyboard(const KeyboardEvent& event) override; | |||
virtual bool onSpecial(const SpecialEvent& event) override; | |||
virtual bool onMouse(const MouseEvent& event) override; | |||
virtual bool onMotion(const MotionEvent& event) override; | |||
virtual bool onScroll(const ScrollEvent& event) override; | |||
virtual void onResize(const ResizeEvent& event) override; | |||
virtual void idleCallback() override; | |||
private: | |||
struct Impl; | |||
Impl* fImpl; | |||
}; | |||
END_NAMESPACE_DGL |
@@ -17,35 +17,24 @@ FILES_DSP = \ | |||
FILES_UI = \ | |||
UISimpleGain.cpp \ | |||
ImGuiUI.cpp \ | |||
ImGuiSrc.cpp | |||
../../../DPF-Widgets/opengl/DearImGui.cpp | |||
# -------------------------------------------------------------- | |||
# Do some magic | |||
include ../../Makefile.plugins.mk | |||
BUILD_CXX_FLAGS += -I../../../imgui -I../../../imgui/backends | |||
BUILD_CXX_FLAGS += $(shell $(PKG_CONFIG) glew --cflags) | |||
LINK_FLAGS += $(shell $(PKG_CONFIG) glew --libs) | |||
# path to DPF-Widgets | |||
BUILD_CXX_FLAGS += -I../../../DPF-Widgets/opengl/ | |||
# -------------------------------------------------------------- | |||
# Enable all selected plugin types | |||
ifeq ($(HAVE_OPENGL),true) | |||
TARGETS += jack lv2_sep vst3 | |||
TARGETS += jack | |||
ifneq ($(MACOS_OR_WINDOWS),true) | |||
ifeq ($(HAVE_LIBLO),true) | |||
TARGETS += dssi | |||
endif # HAVE_LIBLO | |||
endif # MACOS_OR_WINDOWS | |||
TARGETS += lv2_sep | |||
TARGETS += vst | |||
endif # HAVE_OPENGL | |||
all: $(TARGETS) | |||
@@ -25,8 +25,6 @@ | |||
*/ | |||
#include "UISimpleGain.hpp" | |||
#include <imgui.h> | |||
// #include "Window.hpp" | |||
START_NAMESPACE_DISTRHO | |||
@@ -34,13 +32,13 @@ START_NAMESPACE_DISTRHO | |||
// Init / Deinit | |||
UISimpleGain::UISimpleGain() | |||
: UI(600, 400) | |||
: UI(600, 400) | |||
{ | |||
setGeometryConstraints(600, 400, true); | |||
} | |||
UISimpleGain::~UISimpleGain() { | |||
UISimpleGain::~UISimpleGain() | |||
{ | |||
} | |||
// ----------------------------------------------------------------------- | |||
@@ -50,13 +48,15 @@ UISimpleGain::~UISimpleGain() { | |||
A parameter has changed on the plugin side. | |||
This is called by the host to inform the UI about parameter changes. | |||
*/ | |||
void UISimpleGain::parameterChanged(uint32_t index, float value) { | |||
void UISimpleGain::parameterChanged(uint32_t index, float value) | |||
{ | |||
params[index] = value; | |||
switch (index) { | |||
case PluginSimpleGain::paramGain: | |||
// do something when Gain param is set, such as update a widget | |||
break; | |||
switch (index) | |||
{ | |||
case PluginSimpleGain::paramGain: | |||
// do something when Gain param is set, such as update a widget | |||
break; | |||
} | |||
(void)value; | |||
@@ -66,9 +66,12 @@ void UISimpleGain::parameterChanged(uint32_t index, float value) { | |||
A program has been loaded on the plugin side. | |||
This is called by the host to inform the UI about program changes. | |||
*/ | |||
void UISimpleGain::programLoaded(uint32_t index) { | |||
if (index < presetCount) { | |||
for (int i=0; i < PluginSimpleGain::paramCount; i++) { | |||
void UISimpleGain::programLoaded(uint32_t index) | |||
{ | |||
if (index < presetCount) | |||
{ | |||
for (int i=0; i < PluginSimpleGain::paramCount; i++) | |||
{ | |||
// set values for each parameter and update their widgets | |||
parameterChanged(i, factoryPresets[index].params[i]); | |||
} | |||
@@ -78,7 +81,8 @@ void UISimpleGain::programLoaded(uint32_t index) { | |||
/** | |||
Optional callback to inform the UI about a sample rate change on the plugin side. | |||
*/ | |||
void UISimpleGain::sampleRateChanged(double newSampleRate) { | |||
void UISimpleGain::sampleRateChanged(double newSampleRate) | |||
{ | |||
(void)newSampleRate; | |||
} | |||
@@ -89,10 +93,11 @@ void UISimpleGain::sampleRateChanged(double newSampleRate) { | |||
/** | |||
A function called to draw the view contents. | |||
*/ | |||
void UISimpleGain::onImGuiDisplay() { | |||
float width = getWidth(); | |||
float height = getHeight(); | |||
float margin = 20.0f; | |||
void UISimpleGain::onImGuiDisplay() | |||
{ | |||
const float width = getWidth(); | |||
const float height = getHeight(); | |||
const float margin = 20.0f; | |||
ImGui::SetNextWindowPos(ImVec2(margin, margin)); | |||
ImGui::SetNextWindowSize(ImVec2(width - 2 * margin, height - 2 * margin)); | |||
@@ -121,7 +126,8 @@ void UISimpleGain::onImGuiDisplay() { | |||
// ----------------------------------------------------------------------- | |||
UI* createUI() { | |||
UI* createUI() | |||
{ | |||
return new UISimpleGain(); | |||
} | |||