Browse Source

Special trickery to allow browser preview of framebuffer panels

Signed-off-by: falkTX <falktx@falktx.com>
tags/22.02
falkTX 3 years ago
parent
commit
54bc763d0d
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
9 changed files with 196 additions and 74 deletions
  1. +14
    -12
      plugins/Cardinal/src/HostMIDI-CC.cpp
  2. +6
    -11
      plugins/Cardinal/src/HostMIDI-Gate.cpp
  3. +22
    -8
      plugins/Cardinal/src/HostMIDI-Map.cpp
  4. +28
    -14
      plugins/Cardinal/src/Ildaeil.cpp
  5. +32
    -6
      plugins/Cardinal/src/ImGuiWidget.cpp
  6. +4
    -2
      plugins/Cardinal/src/ImGuiWidget.hpp
  7. +11
    -8
      plugins/Cardinal/src/TextEditor.cpp
  8. +25
    -13
      plugins/Cardinal/src/glBars.cpp
  9. +54
    -0
      plugins/Cardinal/src/plugin.hpp

+ 14
- 12
plugins/Cardinal/src/HostMIDI-CC.cpp View File

@@ -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

// --------------------------------------------------------------------------------------------------------------------



+ 6
- 11
plugins/Cardinal/src/HostMIDI-Gate.cpp View File

@@ -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

// --------------------------------------------------------------------------------------------------------------------



+ 22
- 8
plugins/Cardinal/src/HostMIDI-Map.cpp View File

@@ -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(&paramHandles[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

// --------------------------------------------------------------------------------------------------------------------



+ 28
- 14
plugins/Cardinal/src/Ildaeil.cpp View File

@@ -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);


+ 32
- 6
plugins/Cardinal/src/ImGuiWidget.cpp View File

@@ -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))
{


+ 4
- 2
plugins/Cardinal/src/ImGuiWidget.hpp View File

@@ -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);
};

+ 11
- 8
plugins/Cardinal/src/TextEditor.cpp View File

@@ -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);
}
}



+ 25
- 13
plugins/Cardinal/src/glBars.cpp View File

@@ -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);


+ 54
- 0
plugins/Cardinal/src/plugin.hpp View File

@@ -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;


Loading…
Cancel
Save