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 | * Based on VCVRack's CcChoice as defined in src/core/plugin.hpp | ||||
* Copyright (C) 2016-2021 VCV. | * Copyright (C) 2016-2021 VCV. | ||||
@@ -523,7 +515,14 @@ struct CardinalCcChoice : CardinalLedDisplayChoice { | |||||
CardinalCcChoice(HostMIDICC* const m, const int i) | CardinalCcChoice(HostMIDICC* const m, const int i) | ||||
: CardinalLedDisplayChoice(), | : CardinalLedDisplayChoice(), | ||||
module(m), | module(m), | ||||
id(i) {} | |||||
id(i) | |||||
{ | |||||
// Module browser setup | |||||
if (m == nullptr) | |||||
{ | |||||
text = string::f("%d", i+1); | |||||
} | |||||
} | |||||
void step() override | void step() override | ||||
{ | { | ||||
@@ -691,14 +690,14 @@ struct HostMIDICCWidget : ModuleWidget { | |||||
{ | { | ||||
const float x = startX_In + int(i / 6) * padding; | const float x = startX_In + int(i / 6) * padding; | ||||
const float y = startY + 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) | for (int i=0; i<18; ++i) | ||||
{ | { | ||||
const float x = startX_Out + int(i / 6) * padding; | const float x = startX_Out + int(i / 6) * padding; | ||||
const float y = startY + 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)); | CCGridDisplay* const display = createWidget<CCGridDisplay>(Vec(startX_In - 3.0f, 70.0f)); | ||||
@@ -775,6 +774,9 @@ struct HostMIDICCWidget : ModuleWidget { | |||||
menu->addChild(outputChannelItem); | 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 | * Based on VCVRack's NoteChoice as defined in src/core/plugin.hpp | ||||
* Copyright (C) 2016-2021 VCV. | * Copyright (C) 2016-2021 VCV. | ||||
@@ -605,14 +597,14 @@ struct HostMIDIGateWidget : ModuleWidget { | |||||
{ | { | ||||
const float x = startX_In + int(i / 6) * padding; | const float x = startX_In + int(i / 6) * padding; | ||||
const float y = startY + 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) | for (int i=0; i<18; ++i) | ||||
{ | { | ||||
const float x = startX_Out + int(i / 6) * padding; | const float x = startX_Out + int(i / 6) * padding; | ||||
const float y = startY + 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)); | 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); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
for (int id = 0; id < MAX_MIDI_CONTROL; ++id) | 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]); | pcontext->engine->addParamHandle(¶mHandles[id]); | ||||
// } | |||||
} | |||||
for (int i = 0; i < MAX_MIDI_CONTROL; i++) | for (int i = 0; i < MAX_MIDI_CONTROL; i++) | ||||
valueFilters[i].setTau(1 / 30.f); | valueFilters[i].setTau(1 / 30.f); | ||||
@@ -460,18 +460,27 @@ struct HostMIDIMap : Module { | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
struct MIDIMapChoice : CardinalLedDisplayChoice { | |||||
#ifndef HEADLESS | |||||
struct CardinalMIDIMapChoice : CardinalLedDisplayChoice { | |||||
HostMIDIMap* const module; | HostMIDIMap* const module; | ||||
const int id; | const int id; | ||||
int disableLearnFrames = -1; | int disableLearnFrames = -1; | ||||
ParamWidget* lastTouchedParam = nullptr; | ParamWidget* lastTouchedParam = nullptr; | ||||
MIDIMapChoice(HostMIDIMap* const m, const int i) | |||||
CardinalMIDIMapChoice(HostMIDIMap* const m, const int i) | |||||
: CardinalLedDisplayChoice(), | : CardinalLedDisplayChoice(), | ||||
module(m), | module(m), | ||||
id(i) | id(i) | ||||
{ | { | ||||
alignTextCenter = false; | 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 | void draw(const DrawArgs& args) override | ||||
@@ -489,7 +498,7 @@ struct MIDIMapChoice : CardinalLedDisplayChoice { | |||||
void step() override | void step() override | ||||
{ | { | ||||
if (!module) | |||||
if (module == nullptr) | |||||
return; | return; | ||||
// Set bgColor and selected state | // Set bgColor and selected state | ||||
@@ -609,7 +618,7 @@ struct MIDIMapChoice : CardinalLedDisplayChoice { | |||||
struct HostMIDIMapDisplay : Widget { | struct HostMIDIMapDisplay : Widget { | ||||
HostMIDIMap* module; | HostMIDIMap* module; | ||||
ScrollWidget* scroll; | ScrollWidget* scroll; | ||||
MIDIMapChoice* choices[MAX_MIDI_CONTROL]; | |||||
CardinalMIDIMapChoice* choices[MAX_MIDI_CONTROL]; | |||||
LedDisplaySeparator* separators[MAX_MIDI_CONTROL]; | LedDisplaySeparator* separators[MAX_MIDI_CONTROL]; | ||||
void drawLayer(const DrawArgs& args, int layer) override | void drawLayer(const DrawArgs& args, int layer) override | ||||
@@ -634,13 +643,15 @@ struct HostMIDIMapDisplay : Widget { | |||||
{ | { | ||||
LedDisplaySeparator* separator = createWidget<LedDisplaySeparator>(Vec(0.0f, posY)); | LedDisplaySeparator* separator = createWidget<LedDisplaySeparator>(Vec(0.0f, posY)); | ||||
separator->box.size = Vec(box.size.x, 1.0f); | separator->box.size = Vec(box.size.x, 1.0f); | ||||
separator->visible = false; | |||||
scroll->container->addChild(separator); | scroll->container->addChild(separator); | ||||
separators[id] = 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.pos = Vec(0.0f, posY); | ||||
choice->box.size = Vec(box.size.x, 20.0f); | choice->box.size = Vec(box.size.x, 20.0f); | ||||
choice->visible = id == 0; | |||||
scroll->container->addChild(choice); | scroll->container->addChild(choice); | ||||
choices[id] = choice; | choices[id] = choice; | ||||
@@ -722,6 +733,9 @@ struct HostMIDIMapWidget : ModuleWidget { | |||||
menu->addChild(inputChannelItem); | menu->addChild(inputChannelItem); | ||||
} | } | ||||
}; | }; | ||||
#else | |||||
typedef ModuleWidget HostMIDIMapWidget; | |||||
#endif | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
@@ -745,25 +745,33 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||||
: ImGuiWidget(), | : ImGuiWidget(), | ||||
module(m) | module(m) | ||||
{ | { | ||||
if (module->fCarlaHostHandle == nullptr) | |||||
{ | |||||
fDrawingState = kDrawingErrorInit; | |||||
fIdleState = kIdleNothing; | |||||
fPopupError = "Ildaeil backend failed to init properly, cannot continue."; | |||||
return; | |||||
} | |||||
std::strcpy(fPluginSearchString, "Search..."); | 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 | ~IldaeilWidget() override | ||||
{ | { | ||||
if (module->fCarlaHostHandle != nullptr) | |||||
if (module != nullptr && module->fCarlaHostHandle != nullptr) | |||||
{ | { | ||||
if (idleCallbackActive) | if (idleCallbackActive) | ||||
{ | { | ||||
@@ -1009,6 +1017,9 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||||
void widgetCreated() | void widgetCreated() | ||||
{ | { | ||||
if (module == nullptr) | |||||
return; | |||||
if (const CarlaHostHandle handle = module->fCarlaHostHandle) | if (const CarlaHostHandle handle = module->fCarlaHostHandle) | ||||
{ | { | ||||
const CardinalPluginContext* const pcontext = module->pcontext; | const CardinalPluginContext* const pcontext = module->pcontext; | ||||
@@ -1031,6 +1042,9 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||||
void widgetDestroyed() | void widgetDestroyed() | ||||
{ | { | ||||
if (module == nullptr) | |||||
return; | |||||
if (const CarlaHostHandle handle = module->fCarlaHostHandle) | if (const CarlaHostHandle handle = module->fCarlaHostHandle) | ||||
{ | { | ||||
const CardinalPluginContext* const pcontext = module->pcontext; | const CardinalPluginContext* const pcontext = module->pcontext; | ||||
@@ -1532,7 +1546,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||||
if (ImGui::Button("Load Plugin")) | if (ImGui::Button("Load Plugin")) | ||||
fIdleState = kIdleLoadSelectedPlugin; | fIdleState = kIdleLoadSelectedPlugin; | ||||
if (fPluginType != PLUGIN_INTERNAL && module->canUseBridges) | |||||
if (fPluginType != PLUGIN_INTERNAL && (module == nullptr || module->canUseBridges)) | |||||
{ | { | ||||
ImGui::SameLine(); | ImGui::SameLine(); | ||||
ImGui::Checkbox("Run in bridge mode", &fPluginWillRunInBridgeMode); | ImGui::Checkbox("Run in bridge mode", &fPluginWillRunInBridgeMode); | ||||
@@ -1657,7 +1671,7 @@ struct IldaeilModuleWidget : ModuleWidget { | |||||
setModule(module); | setModule(module); | ||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Ildaeil.svg"))); | 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 = new IldaeilWidget(module); | ||||
ildaeilWidget->box.pos = Vec(2 * RACK_GRID_WIDTH, 0); | ildaeilWidget->box.pos = Vec(2 * RACK_GRID_WIDTH, 0); | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* Dear ImGui for DPF, converted to VCV | * 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> | * Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | ||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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) | void ImGuiWidget::onContextCreate(const ContextCreateEvent& e) | ||||
{ | { | ||||
OpenGlWidget::onContextCreate(e); | |||||
OpenGlWidgetWithBrowserPreview::onContextCreate(e); | |||||
DISTRHO_SAFE_ASSERT_RETURN(!imData->created,); | DISTRHO_SAFE_ASSERT_RETURN(!imData->created,); | ||||
ImGui::SetCurrentContext(imData->context); | ImGui::SetCurrentContext(imData->context); | ||||
@@ -162,7 +162,7 @@ void ImGuiWidget::onContextDestroy(const ContextDestroyEvent& e) | |||||
imData->created = false; | imData->created = false; | ||||
} | } | ||||
OpenGlWidget::onContextDestroy(e); | |||||
OpenGlWidgetWithBrowserPreview::onContextDestroy(e); | |||||
} | } | ||||
void ImGuiWidget::setAsCurrentContext() | void ImGuiWidget::setAsCurrentContext() | ||||
@@ -308,11 +308,37 @@ void ImGuiWidget::onSelectText(const SelectTextEvent& e) | |||||
void ImGuiWidget::drawFramebuffer() | 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); | 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)) | if (d_isNotEqual(imData->scaleFactor, scaleFactor)) | ||||
{ | { | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* Dear ImGui for DPF, converted to VCV | * 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> | * Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | ||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * Permission to use, copy, modify, and/or distribute this software for any purpose with | ||||
@@ -20,7 +20,7 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "DearImGui/imgui.h" | #include "DearImGui/imgui.h" | ||||
struct ImGuiWidget : OpenGlWidget { | |||||
struct ImGuiWidget : OpenGlWidgetWithBrowserPreview { | |||||
struct PrivateData; | struct PrivateData; | ||||
PrivateData* const imData; | PrivateData* const imData; | ||||
@@ -50,4 +50,6 @@ protected: | |||||
private: | private: | ||||
void drawFramebuffer() override; | 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(rightHandle = new ModuleResizeHandle(module, this, true)); | ||||
addChild(new ModuleResizeHandle(module, this, false)); | 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) | 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->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; | module->widgetPtr = textEditorWidget; | ||||
} | } | ||||
else | 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 | #ifndef HEADLESS | ||||
struct glBarsRendererWidget : OpenGlWidget { | |||||
struct glBarsRendererWidget : OpenGlWidgetWithBrowserPreview { | |||||
glBarsModule* const glBars; | glBarsModule* const glBars; | ||||
glBarsRendererWidget(glBarsModule* const module) | glBarsRendererWidget(glBarsModule* const module) | ||||
: glBars(module) | : glBars(module) | ||||
{ | { | ||||
if (APP->window->pixelRatio < 2.0f) | |||||
if (glBars != nullptr && APP->window->pixelRatio < 2.0f) | |||||
oversample = 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) | if (layer != 1) | ||||
return; | 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); | glDisable(GL_BLEND); | ||||
glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
glPushMatrix(); | glPushMatrix(); | ||||
glLoadIdentity(); | 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); | glFrustum(-1, 1, -1, 1, 1.5, 10); | ||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glPushMatrix(); | glPushMatrix(); | ||||
@@ -99,7 +111,7 @@ struct glBarsRendererWidget : OpenGlWidget { | |||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | ||||
glClear(GL_COLOR_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT); | ||||
glBars->state.Render(); | |||||
state.Render(); | |||||
glPopMatrix(); | glPopMatrix(); | ||||
glMatrixMode(GL_PROJECTION); | glMatrixMode(GL_PROJECTION); | ||||
@@ -107,18 +119,17 @@ struct glBarsRendererWidget : OpenGlWidget { | |||||
glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
} | } | ||||
void step() override { | |||||
void step() override | |||||
{ | |||||
OpenGlWidget::step(); | 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 { | struct glBarsWidget : ModuleWidget { | ||||
glBarsRendererWidget* const glBarsRenderer; | |||||
glBarsWidget(glBarsModule* const module) | glBarsWidget(glBarsModule* const module) | ||||
: glBarsRenderer(new glBarsRendererWidget(module)) | |||||
{ | { | ||||
setModule(module); | setModule(module); | ||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/glBars.svg"))); | 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)); | addInput(createInput<PJ301MPort>(Vec(135.0f, 20.0f), module, glBarsModule::IN1_INPUT)); | ||||
const float size = mm2px(127.0f); | 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.pos = Vec((box.size.x - size) * 0.5f, (box.size.y - size) * 0.5f); | ||||
glBarsRenderer->box.size = Vec(size, size); | glBarsRenderer->box.size = Vec(size, size); | ||||
addChild(glBarsRenderer); | addChild(glBarsRenderer); | ||||
@@ -25,6 +25,7 @@ | |||||
using namespace rack; | using namespace rack; | ||||
#ifndef HEADLESS | |||||
struct CardinalLedDisplayChoice : LedDisplayChoice { | struct CardinalLedDisplayChoice : LedDisplayChoice { | ||||
bool alignTextCenter = true; | 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 Plugin* pluginInstance; | ||||
extern Model* modelAudioFile; | extern Model* modelAudioFile; | ||||