Signed-off-by: falkTX <falktx@falktx.com>tags/22.02
@@ -497,15 +497,7 @@ struct HostMIDICC : Module { | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
struct CardinalMIDILearnPJ301MPort : PJ301MPort { | |||
void onDragStart(const DragStartEvent& e) override { | |||
PJ301MPort::onDragStart(e); | |||
} | |||
void onDragEnd(const DragEndEvent& e) override { | |||
PJ301MPort::onDragEnd(e); | |||
} | |||
}; | |||
#ifndef HEADLESS | |||
/** | |||
* Based on VCVRack's CcChoice as defined in src/core/plugin.hpp | |||
* Copyright (C) 2016-2021 VCV. | |||
@@ -523,7 +515,14 @@ struct CardinalCcChoice : CardinalLedDisplayChoice { | |||
CardinalCcChoice(HostMIDICC* const m, const int i) | |||
: CardinalLedDisplayChoice(), | |||
module(m), | |||
id(i) {} | |||
id(i) | |||
{ | |||
// Module browser setup | |||
if (m == nullptr) | |||
{ | |||
text = string::f("%d", i+1); | |||
} | |||
} | |||
void step() override | |||
{ | |||
@@ -691,14 +690,14 @@ struct HostMIDICCWidget : ModuleWidget { | |||
{ | |||
const float x = startX_In + int(i / 6) * padding; | |||
const float y = startY + int(i % 6) * padding; | |||
addInput(createInput<CardinalMIDILearnPJ301MPort>(Vec(x, y), module, i)); | |||
addInput(createInput<PJ301MPort>(Vec(x, y), module, i)); | |||
} | |||
for (int i=0; i<18; ++i) | |||
{ | |||
const float x = startX_Out + int(i / 6) * padding; | |||
const float y = startY + int(i % 6) * padding; | |||
addOutput(createOutput<CardinalMIDILearnPJ301MPort>(Vec(x, y), module, i)); | |||
addOutput(createOutput<PJ301MPort>(Vec(x, y), module, i)); | |||
} | |||
CCGridDisplay* const display = createWidget<CCGridDisplay>(Vec(startX_In - 3.0f, 70.0f)); | |||
@@ -775,6 +774,9 @@ struct HostMIDICCWidget : ModuleWidget { | |||
menu->addChild(outputChannelItem); | |||
} | |||
}; | |||
#else | |||
typedef ModuleWidget HostMIDICCWidget; | |||
#endif | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
@@ -404,15 +404,7 @@ struct HostMIDIGate : Module { | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
struct CardinalMIDILearnPJ301MPort : PJ301MPort { | |||
void onDragStart(const DragStartEvent& e) override { | |||
PJ301MPort::onDragStart(e); | |||
} | |||
void onDragEnd(const DragEndEvent& e) override { | |||
PJ301MPort::onDragEnd(e); | |||
} | |||
}; | |||
#ifndef HEADLESS | |||
/** | |||
* Based on VCVRack's NoteChoice as defined in src/core/plugin.hpp | |||
* Copyright (C) 2016-2021 VCV. | |||
@@ -605,14 +597,14 @@ struct HostMIDIGateWidget : ModuleWidget { | |||
{ | |||
const float x = startX_In + int(i / 6) * padding; | |||
const float y = startY + int(i % 6) * padding; | |||
addInput(createInput<CardinalMIDILearnPJ301MPort>(Vec(x, y), module, i)); | |||
addInput(createInput<PJ301MPort>(Vec(x, y), module, i)); | |||
} | |||
for (int i=0; i<18; ++i) | |||
{ | |||
const float x = startX_Out + int(i / 6) * padding; | |||
const float y = startY + int(i % 6) * padding; | |||
addOutput(createOutput<CardinalMIDILearnPJ301MPort>(Vec(x, y), module, i)); | |||
addOutput(createOutput<PJ301MPort>(Vec(x, y), module, i)); | |||
} | |||
NoteGridDisplay* const display = createWidget<NoteGridDisplay>(Vec(startX_In - 3.0f, 70.0f)); | |||
@@ -696,6 +688,9 @@ struct HostMIDIGateWidget : ModuleWidget { | |||
)); | |||
} | |||
}; | |||
#else | |||
typedef ModuleWidget HostMIDIGateWidget; | |||
#endif | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
@@ -90,10 +90,10 @@ struct HostMIDIMap : Module { | |||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
for (int id = 0; id < MAX_MIDI_CONTROL; ++id) | |||
// { | |||
// paramHandles[id].color = nvgRGB(0xff, 0xff, 0x40); | |||
{ | |||
paramHandles[id].color = nvgRGBf(0.76f, 0.11f, 0.22f); | |||
pcontext->engine->addParamHandle(¶mHandles[id]); | |||
// } | |||
} | |||
for (int i = 0; i < MAX_MIDI_CONTROL; i++) | |||
valueFilters[i].setTau(1 / 30.f); | |||
@@ -460,18 +460,27 @@ struct HostMIDIMap : Module { | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
struct MIDIMapChoice : CardinalLedDisplayChoice { | |||
#ifndef HEADLESS | |||
struct CardinalMIDIMapChoice : CardinalLedDisplayChoice { | |||
HostMIDIMap* const module; | |||
const int id; | |||
int disableLearnFrames = -1; | |||
ParamWidget* lastTouchedParam = nullptr; | |||
MIDIMapChoice(HostMIDIMap* const m, const int i) | |||
CardinalMIDIMapChoice(HostMIDIMap* const m, const int i) | |||
: CardinalLedDisplayChoice(), | |||
module(m), | |||
id(i) | |||
{ | |||
alignTextCenter = false; | |||
// Module browser setup | |||
if (m == nullptr) | |||
{ | |||
bgColor = nvgRGB(0, 0, 0); | |||
color.a = 0.75f; | |||
text = "Click here to map"; | |||
} | |||
} | |||
void draw(const DrawArgs& args) override | |||
@@ -489,7 +498,7 @@ struct MIDIMapChoice : CardinalLedDisplayChoice { | |||
void step() override | |||
{ | |||
if (!module) | |||
if (module == nullptr) | |||
return; | |||
// Set bgColor and selected state | |||
@@ -609,7 +618,7 @@ struct MIDIMapChoice : CardinalLedDisplayChoice { | |||
struct HostMIDIMapDisplay : Widget { | |||
HostMIDIMap* module; | |||
ScrollWidget* scroll; | |||
MIDIMapChoice* choices[MAX_MIDI_CONTROL]; | |||
CardinalMIDIMapChoice* choices[MAX_MIDI_CONTROL]; | |||
LedDisplaySeparator* separators[MAX_MIDI_CONTROL]; | |||
void drawLayer(const DrawArgs& args, int layer) override | |||
@@ -634,13 +643,15 @@ struct HostMIDIMapDisplay : Widget { | |||
{ | |||
LedDisplaySeparator* separator = createWidget<LedDisplaySeparator>(Vec(0.0f, posY)); | |||
separator->box.size = Vec(box.size.x, 1.0f); | |||
separator->visible = false; | |||
scroll->container->addChild(separator); | |||
separators[id] = separator; | |||
} | |||
MIDIMapChoice* const choice = new MIDIMapChoice(module, id); | |||
CardinalMIDIMapChoice* const choice = new CardinalMIDIMapChoice(module, id); | |||
choice->box.pos = Vec(0.0f, posY); | |||
choice->box.size = Vec(box.size.x, 20.0f); | |||
choice->visible = id == 0; | |||
scroll->container->addChild(choice); | |||
choices[id] = choice; | |||
@@ -722,6 +733,9 @@ struct HostMIDIMapWidget : ModuleWidget { | |||
menu->addChild(inputChannelItem); | |||
} | |||
}; | |||
#else | |||
typedef ModuleWidget HostMIDIMapWidget; | |||
#endif | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
@@ -745,25 +745,33 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||
: ImGuiWidget(), | |||
module(m) | |||
{ | |||
if (module->fCarlaHostHandle == nullptr) | |||
{ | |||
fDrawingState = kDrawingErrorInit; | |||
fIdleState = kIdleNothing; | |||
fPopupError = "Ildaeil backend failed to init properly, cannot continue."; | |||
return; | |||
} | |||
std::strcpy(fPluginSearchString, "Search..."); | |||
if (checkIfPluginIsLoaded()) | |||
fIdleState = kIdleInitPluginAlreadyLoaded; | |||
if (m != nullptr) | |||
{ | |||
if (m->fCarlaHostHandle == nullptr) | |||
{ | |||
fDrawingState = kDrawingErrorInit; | |||
fIdleState = kIdleNothing; | |||
fPopupError = "Ildaeil backend failed to init properly, cannot continue."; | |||
return; | |||
} | |||
if (checkIfPluginIsLoaded()) | |||
fIdleState = kIdleInitPluginAlreadyLoaded; | |||
module->fUI = this; | |||
m->fUI = this; | |||
} | |||
else | |||
{ | |||
fDrawingState = kDrawingPluginList; | |||
fIdleState = kIdleNothing; | |||
} | |||
} | |||
~IldaeilWidget() override | |||
{ | |||
if (module->fCarlaHostHandle != nullptr) | |||
if (module != nullptr && module->fCarlaHostHandle != nullptr) | |||
{ | |||
if (idleCallbackActive) | |||
{ | |||
@@ -1009,6 +1017,9 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||
void widgetCreated() | |||
{ | |||
if (module == nullptr) | |||
return; | |||
if (const CarlaHostHandle handle = module->fCarlaHostHandle) | |||
{ | |||
const CardinalPluginContext* const pcontext = module->pcontext; | |||
@@ -1031,6 +1042,9 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||
void widgetDestroyed() | |||
{ | |||
if (module == nullptr) | |||
return; | |||
if (const CarlaHostHandle handle = module->fCarlaHostHandle) | |||
{ | |||
const CardinalPluginContext* const pcontext = module->pcontext; | |||
@@ -1532,7 +1546,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||
if (ImGui::Button("Load Plugin")) | |||
fIdleState = kIdleLoadSelectedPlugin; | |||
if (fPluginType != PLUGIN_INTERNAL && module->canUseBridges) | |||
if (fPluginType != PLUGIN_INTERNAL && (module == nullptr || module->canUseBridges)) | |||
{ | |||
ImGui::SameLine(); | |||
ImGui::Checkbox("Run in bridge mode", &fPluginWillRunInBridgeMode); | |||
@@ -1657,7 +1671,7 @@ struct IldaeilModuleWidget : ModuleWidget { | |||
setModule(module); | |||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Ildaeil.svg"))); | |||
if (module != nullptr && module->pcontext != nullptr) | |||
if (module == nullptr || module->pcontext != nullptr) | |||
{ | |||
ildaeilWidget = new IldaeilWidget(module); | |||
ildaeilWidget->box.pos = Vec(2 * RACK_GRID_WIDTH, 0); | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Dear ImGui for DPF, converted to VCV | |||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
@@ -145,7 +145,7 @@ float ImGuiWidget::getScaleFactor() const noexcept | |||
void ImGuiWidget::onContextCreate(const ContextCreateEvent& e) | |||
{ | |||
OpenGlWidget::onContextCreate(e); | |||
OpenGlWidgetWithBrowserPreview::onContextCreate(e); | |||
DISTRHO_SAFE_ASSERT_RETURN(!imData->created,); | |||
ImGui::SetCurrentContext(imData->context); | |||
@@ -162,7 +162,7 @@ void ImGuiWidget::onContextDestroy(const ContextDestroyEvent& e) | |||
imData->created = false; | |||
} | |||
OpenGlWidget::onContextDestroy(e); | |||
OpenGlWidgetWithBrowserPreview::onContextDestroy(e); | |||
} | |||
void ImGuiWidget::setAsCurrentContext() | |||
@@ -308,11 +308,37 @@ void ImGuiWidget::onSelectText(const SelectTextEvent& e) | |||
void ImGuiWidget::drawFramebuffer() | |||
{ | |||
const float scaleFactor = APP->window->pixelRatio; | |||
drawFramebufferCommon(getFramebufferSize(), scaleFactor); | |||
} | |||
void ImGuiWidget::drawFramebufferForBrowserPreview() | |||
{ | |||
if (imData->created) | |||
{ | |||
ImGui::SetCurrentContext(imData->context); | |||
ImGui_ImplOpenGL2_Shutdown(); | |||
ImGui::DestroyContext(imData->context); | |||
imData->created = false; | |||
imData->fontGenerated = false; | |||
imData->originalScaleFactor = 0.0f; | |||
imData->scaleFactor = 0.0f; | |||
} | |||
imData->context = ImGui::CreateContext(); | |||
ImGui::SetCurrentContext(imData->context); | |||
ImGuiIO& io(ImGui::GetIO()); | |||
ImGui_ImplOpenGL2_Init(); | |||
imData->created = true; | |||
const math::Vec fbSize = getFramebufferSize(); | |||
const float scaleFactor = APP->window->pixelRatio; | |||
drawFramebufferCommon(box.size.mult(oversample), oversample); | |||
} | |||
void ImGuiWidget::drawFramebufferCommon(const Vec& fbSize, const float scaleFactor) | |||
{ | |||
ImGui::SetCurrentContext(imData->context); | |||
ImGuiIO& io(ImGui::GetIO()); | |||
if (d_isNotEqual(imData->scaleFactor, scaleFactor)) | |||
{ | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Dear ImGui for DPF, converted to VCV | |||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
@@ -20,7 +20,7 @@ | |||
#include "plugin.hpp" | |||
#include "DearImGui/imgui.h" | |||
struct ImGuiWidget : OpenGlWidget { | |||
struct ImGuiWidget : OpenGlWidgetWithBrowserPreview { | |||
struct PrivateData; | |||
PrivateData* const imData; | |||
@@ -50,4 +50,6 @@ protected: | |||
private: | |||
void drawFramebuffer() override; | |||
void drawFramebufferForBrowserPreview() override; | |||
void drawFramebufferCommon(const Vec& fbSize, float scaleFactor); | |||
}; |
@@ -326,21 +326,24 @@ struct TextEditorModuleWidget : ModuleWidget { | |||
addChild(rightHandle = new ModuleResizeHandle(module, this, true)); | |||
addChild(new ModuleResizeHandle(module, this, false)); | |||
box.size = Vec(RACK_GRID_WIDTH * (module != nullptr ? module->width : DEFAULT_WIDTH), RACK_GRID_HEIGHT); | |||
textEditorModule = module; | |||
textEditorWidget = new ImGuiTextEditor(); | |||
textEditorWidget->box.pos = Vec(RACK_GRID_WIDTH, 0); | |||
textEditorWidget->box.size = Vec(box.size.x - 2 * RACK_GRID_WIDTH, box.size.y); | |||
addChild(textEditorWidget); | |||
if (module != nullptr) | |||
{ | |||
box.size = Vec(RACK_GRID_WIDTH * module->width, RACK_GRID_HEIGHT); | |||
textEditorModule = module; | |||
textEditorWidget = new ImGuiTextEditor(); | |||
textEditorWidget->setFileWithKnownText(module->file, module->text); | |||
textEditorWidget->setLanguageDefinition(module->lang); | |||
textEditorWidget->box.pos = Vec(RACK_GRID_WIDTH, 0); | |||
textEditorWidget->box.size = Vec((module->width - 2) * RACK_GRID_WIDTH, box.size.y); | |||
addChild(textEditorWidget); | |||
textEditorWidget->setFileWithKnownText(module->file, module->text); | |||
module->widgetPtr = textEditorWidget; | |||
} | |||
else | |||
{ | |||
box.size = Vec(RACK_GRID_WIDTH * DEFAULT_WIDTH, RACK_GRID_HEIGHT); | |||
textEditorWidget->setLanguageDefinition(DEFAULT_LANG); | |||
textEditorWidget->setText(DEFAULT_TEXT); | |||
} | |||
} | |||
@@ -61,13 +61,13 @@ struct glBarsModule : Module { | |||
}; | |||
#ifndef HEADLESS | |||
struct glBarsRendererWidget : OpenGlWidget { | |||
struct glBarsRendererWidget : OpenGlWidgetWithBrowserPreview { | |||
glBarsModule* const glBars; | |||
glBarsRendererWidget(glBarsModule* const module) | |||
: glBars(module) | |||
{ | |||
if (APP->window->pixelRatio < 2.0f) | |||
if (glBars != nullptr && APP->window->pixelRatio < 2.0f) | |||
oversample = 2.0f; | |||
} | |||
@@ -75,22 +75,34 @@ struct glBarsRendererWidget : OpenGlWidget { | |||
{ | |||
} | |||
void drawLayer(const DrawArgs& args, int layer) override | |||
void drawLayer(const DrawArgs& args, const int layer) override | |||
{ | |||
if (layer != 1) | |||
return; | |||
OpenGlWidget::draw(args); | |||
OpenGlWidgetWithBrowserPreview::draw(args); | |||
} | |||
void drawFramebuffer() override { | |||
math::Vec fbSize = getFramebufferSize(); | |||
void drawFramebuffer() override | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(glBars != nullptr,); | |||
drawFramebuffer(glBars->state, getFramebufferSize()); | |||
} | |||
void drawFramebufferForBrowserPreview() override | |||
{ | |||
glBarsState state; | |||
drawFramebuffer(state, box.size); | |||
} | |||
void drawFramebuffer(glBarsState& state, const Vec& fbSize) | |||
{ | |||
glDisable(GL_BLEND); | |||
glMatrixMode(GL_PROJECTION); | |||
glPushMatrix(); | |||
glLoadIdentity(); | |||
glViewport(0.0, -100, fbSize.x * oversample, fbSize.y * oversample); | |||
glViewport(0.0, -50 * oversample, fbSize.x * oversample, fbSize.y * oversample); | |||
glFrustum(-1, 1, -1, 1, 1.5, 10); | |||
glMatrixMode(GL_MODELVIEW); | |||
glPushMatrix(); | |||
@@ -99,7 +111,7 @@ struct glBarsRendererWidget : OpenGlWidget { | |||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | |||
glClear(GL_COLOR_BUFFER_BIT); | |||
glBars->state.Render(); | |||
state.Render(); | |||
glPopMatrix(); | |||
glMatrixMode(GL_PROJECTION); | |||
@@ -107,18 +119,17 @@ struct glBarsRendererWidget : OpenGlWidget { | |||
glEnable(GL_BLEND); | |||
} | |||
void step() override { | |||
void step() override | |||
{ | |||
OpenGlWidget::step(); | |||
oversample = APP->window->pixelRatio < 2.0f ? 2.0f : 1.0f; | |||
if (glBars != nullptr) | |||
oversample = APP->window->pixelRatio < 2.0f ? 2.0f : 1.0f; | |||
} | |||
}; | |||
struct glBarsWidget : ModuleWidget { | |||
glBarsRendererWidget* const glBarsRenderer; | |||
glBarsWidget(glBarsModule* const module) | |||
: glBarsRenderer(new glBarsRendererWidget(module)) | |||
{ | |||
setModule(module); | |||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/glBars.svg"))); | |||
@@ -131,6 +142,7 @@ struct glBarsWidget : ModuleWidget { | |||
addInput(createInput<PJ301MPort>(Vec(135.0f, 20.0f), module, glBarsModule::IN1_INPUT)); | |||
const float size = mm2px(127.0f); | |||
glBarsRendererWidget* const glBarsRenderer = new glBarsRendererWidget(module); | |||
glBarsRenderer->box.pos = Vec((box.size.x - size) * 0.5f, (box.size.y - size) * 0.5f); | |||
glBarsRenderer->box.size = Vec(size, size); | |||
addChild(glBarsRenderer); | |||
@@ -25,6 +25,7 @@ | |||
using namespace rack; | |||
#ifndef HEADLESS | |||
struct CardinalLedDisplayChoice : LedDisplayChoice { | |||
bool alignTextCenter = true; | |||
@@ -60,6 +61,59 @@ struct CardinalLedDisplayChoice : LedDisplayChoice { | |||
} | |||
}; | |||
struct OpenGlWidgetWithBrowserPreview : OpenGlWidget { | |||
NVGLUframebuffer* fb = nullptr; | |||
void draw(const DrawArgs& args) override | |||
{ | |||
if (args.fb == nullptr) | |||
return OpenGlWidget::draw(args); | |||
// set oversample to current scale | |||
float trans[6]; | |||
nvgCurrentTransform(args.vg, trans); | |||
oversample = std::max(1.0f, trans[0]); | |||
// recreate framebuffer | |||
deleteFramebuffer(); | |||
fb = nvgluCreateFramebuffer(args.vg, box.size.x * oversample, box.size.y * oversample, 0); | |||
DISTRHO_SAFE_ASSERT_RETURN(fb != nullptr,); | |||
// draw our special framebuffer | |||
nvgluBindFramebuffer(fb); | |||
drawFramebufferForBrowserPreview(); | |||
// reset to regular framebuffer | |||
nvgluBindFramebuffer(args.fb); | |||
// render image generated by our framebuffer | |||
nvgBeginPath(args.vg); | |||
nvgRect(args.vg, 0.0f, 0.0f, box.size.x, box.size.y); | |||
NVGpaint paint = nvgImagePattern(args.vg, | |||
0.0f, 0.0f, box.size.x, box.size.y, | |||
0.0f, fb->image, 1.0f); | |||
nvgFillPaint(args.vg, paint); | |||
nvgFill(args.vg); | |||
} | |||
void onContextDestroy(const ContextDestroyEvent& e) override | |||
{ | |||
deleteFramebuffer(); | |||
OpenGlWidget::onContextDestroy(e); | |||
} | |||
void deleteFramebuffer() | |||
{ | |||
if (fb == nullptr) | |||
return; | |||
nvgluDeleteFramebuffer(fb); | |||
fb = nullptr; | |||
} | |||
virtual void drawFramebufferForBrowserPreview() = 0; | |||
}; | |||
#endif | |||
extern Plugin* pluginInstance; | |||
extern Model* modelAudioFile; | |||