Make preset save/load actions work, requires rebuild
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
6be9bac686
commit
18f6e9a9b4
7 changed files with 374 additions and 0 deletions
40
include/app/ModuleWidget.hpp
Normal file
40
include/app/ModuleWidget.hpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* DISTRHO Cardinal Plugin
|
||||||
|
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 3 of
|
||||||
|
* the License, or any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* For a full copy of the GNU General Public License see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef BUILDING_PLUGIN_MODULES
|
||||||
|
# include <plugin/Model.hpp>
|
||||||
|
# undef ModuleWidget
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include_next <app/ModuleWidget.hpp>
|
||||||
|
|
||||||
|
#ifdef BUILDING_PLUGIN_MODULES
|
||||||
|
namespace rack {
|
||||||
|
namespace app {
|
||||||
|
struct CardinalModuleWidget : ModuleWidget {
|
||||||
|
CardinalModuleWidget() : ModuleWidget() {}
|
||||||
|
DEPRECATED CardinalModuleWidget(engine::Module* module) : ModuleWidget() {
|
||||||
|
setModule(module);
|
||||||
|
}
|
||||||
|
void onButton(const ButtonEvent& e) override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# define ModuleWidget CardinalModuleWidget
|
||||||
|
#endif
|
28
include/app/RackWidget.hpp
Normal file
28
include/app/RackWidget.hpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* DISTRHO Cardinal Plugin
|
||||||
|
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 3 of
|
||||||
|
* the License, or any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* For a full copy of the GNU General Public License see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef BUILDING_PLUGIN_MODULES
|
||||||
|
# undef ModuleWidget
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include_next <app/RackWidget.hpp>
|
||||||
|
|
||||||
|
#ifdef BUILDING_PLUGIN_MODULES
|
||||||
|
# define ModuleWidget CardinalModuleWidget
|
||||||
|
#endif
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// check if PRIVATE is defined already before including any headers
|
||||||
#ifdef PRIVATE
|
#ifdef PRIVATE
|
||||||
# define PRIVATE_WAS_DEFINED
|
# define PRIVATE_WAS_DEFINED
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,10 +35,12 @@
|
||||||
#define BINARY_END(sym) ((const void*) sym + sym##_len)
|
#define BINARY_END(sym) ((const void*) sym + sym##_len)
|
||||||
#define BINARY_SIZE(sym) (sym##_len)
|
#define BINARY_SIZE(sym) (sym##_len)
|
||||||
|
|
||||||
|
// undefine PRIVATE if needed
|
||||||
#if defined(PRIVATE) && !defined(PRIVATE_WAS_DEFINED)
|
#if defined(PRIVATE) && !defined(PRIVATE_WAS_DEFINED)
|
||||||
# undef PRIVATE
|
# undef PRIVATE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// and also our flag
|
||||||
#undef PRIVATE_WAS_DEFINED
|
#undef PRIVATE_WAS_DEFINED
|
||||||
|
|
||||||
// Cardinal specific API
|
// Cardinal specific API
|
||||||
|
|
29
include/plugin/Model.hpp
Normal file
29
include/plugin/Model.hpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* DISTRHO Cardinal Plugin
|
||||||
|
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 3 of
|
||||||
|
* the License, or any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* For a full copy of the GNU General Public License see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef BUILDING_PLUGIN_MODULES
|
||||||
|
namespace rack {
|
||||||
|
namespace app {
|
||||||
|
struct CardinalModuleWidget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# define ModuleWidget CardinalModuleWidget
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include_next <plugin/Model.hpp>
|
|
@ -658,6 +658,7 @@ else
|
||||||
BASE_FLAGS += -DARCH_LIN
|
BASE_FLAGS += -DARCH_LIN
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
BASE_FLAGS += -DBUILDING_PLUGIN_MODULES
|
||||||
BASE_FLAGS += -fno-finite-math-only
|
BASE_FLAGS += -fno-finite-math-only
|
||||||
BASE_FLAGS += -I../dpf/dgl/src/nanovg
|
BASE_FLAGS += -I../dpf/dgl/src/nanovg
|
||||||
BASE_FLAGS += -I../dpf/distrho
|
BASE_FLAGS += -I../dpf/distrho
|
||||||
|
|
272
src/CardinalModuleWidget.cpp
Normal file
272
src/CardinalModuleWidget.cpp
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
/*
|
||||||
|
* DISTRHO Cardinal Plugin
|
||||||
|
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 3 of
|
||||||
|
* the License, or any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* For a full copy of the GNU General Public License see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is partially based on VCVRack's ModuleWidget.cpp
|
||||||
|
* Copyright (C) 2016-2021 VCV.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BUILDING_PLUGIN_MODULES
|
||||||
|
#include <app/ModuleWidget.hpp>
|
||||||
|
#include <app/RackWidget.hpp>
|
||||||
|
#include <plugin/Model.hpp>
|
||||||
|
#undef ModuleWidget
|
||||||
|
|
||||||
|
#include <app/Scene.hpp>
|
||||||
|
#include <engine/Engine.hpp>
|
||||||
|
#include <ui/MenuSeparator.hpp>
|
||||||
|
#include <context.hpp>
|
||||||
|
#include <helpers.hpp>
|
||||||
|
#include <system.hpp>
|
||||||
|
|
||||||
|
namespace rack {
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
struct ModuleWidget::Internal {
|
||||||
|
math::Vec dragOffset;
|
||||||
|
math::Vec dragRackPos;
|
||||||
|
bool dragEnabled = true;
|
||||||
|
math::Vec oldPos;
|
||||||
|
widget::Widget* panel = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void CardinalModuleWidget__loadDialog(ModuleWidget* const w)
|
||||||
|
{
|
||||||
|
std::string presetDir = w->model->getUserPresetDirectory();
|
||||||
|
system::createDirectories(presetDir);
|
||||||
|
|
||||||
|
WeakPtr<ModuleWidget> weakThis = w;
|
||||||
|
|
||||||
|
async_dialog_filebrowser(false, presetDir.c_str(), "Load preset", [=](char* pathC) {
|
||||||
|
// Delete directories if empty
|
||||||
|
DEFER({
|
||||||
|
try {
|
||||||
|
system::remove(presetDir);
|
||||||
|
system::remove(system::getDirectory(presetDir));
|
||||||
|
}
|
||||||
|
catch (Exception& e) {
|
||||||
|
// Ignore exceptions if directory cannot be removed.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
if (!pathC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
weakThis->loadAction(pathC);
|
||||||
|
}
|
||||||
|
catch (Exception& e) {
|
||||||
|
async_dialog_message(e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::free(pathC);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardinalModuleWidget__saveDialog(ModuleWidget* const w)
|
||||||
|
{
|
||||||
|
const std::string presetDir = w->model->getUserPresetDirectory();
|
||||||
|
system::createDirectories(presetDir);
|
||||||
|
|
||||||
|
WeakPtr<ModuleWidget> weakThis = w;
|
||||||
|
|
||||||
|
async_dialog_filebrowser(true, presetDir.c_str(), "Save preset", [=](char* pathC) {
|
||||||
|
// Delete directories if empty
|
||||||
|
DEFER({
|
||||||
|
try {
|
||||||
|
system::remove(presetDir);
|
||||||
|
system::remove(system::getDirectory(presetDir));
|
||||||
|
}
|
||||||
|
catch (Exception& e) {
|
||||||
|
// Ignore exceptions if directory cannot be removed.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
if (!pathC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string path = pathC;
|
||||||
|
std::free(pathC);
|
||||||
|
|
||||||
|
// Automatically append .vcvm extension
|
||||||
|
if (system::getExtension(path) != ".vcvm")
|
||||||
|
path += ".vcvm";
|
||||||
|
|
||||||
|
weakThis->save(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CardinalModuleWidget__createContextMenu(ModuleWidget* const w,
|
||||||
|
plugin::Model* const model,
|
||||||
|
engine::Module* const module) {
|
||||||
|
DISTRHO_SAFE_ASSERT_RETURN(model != nullptr,);
|
||||||
|
|
||||||
|
ui::Menu* menu = createMenu();
|
||||||
|
|
||||||
|
WeakPtr<ModuleWidget> weakThis = w;
|
||||||
|
|
||||||
|
// Brand and module name
|
||||||
|
menu->addChild(createMenuLabel(model->name));
|
||||||
|
menu->addChild(createMenuLabel(model->plugin->brand));
|
||||||
|
|
||||||
|
// Info
|
||||||
|
menu->addChild(createSubmenuItem("Info", "", [=](ui::Menu* menu) {
|
||||||
|
model->appendContextMenu(menu);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Preset
|
||||||
|
menu->addChild(createSubmenuItem("Preset", "", [=](ui::Menu* menu) {
|
||||||
|
menu->addChild(createMenuItem("Copy", RACK_MOD_CTRL_NAME "+C", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->copyClipboard();
|
||||||
|
}));
|
||||||
|
|
||||||
|
menu->addChild(createMenuItem("Paste", RACK_MOD_CTRL_NAME "+V", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->pasteClipboardAction();
|
||||||
|
}));
|
||||||
|
|
||||||
|
menu->addChild(createMenuItem("Open", "", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
CardinalModuleWidget__loadDialog(weakThis);
|
||||||
|
}));
|
||||||
|
|
||||||
|
menu->addChild(createMenuItem("Save as", "", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
CardinalModuleWidget__saveDialog(weakThis);
|
||||||
|
}));
|
||||||
|
|
||||||
|
/* TODO
|
||||||
|
// Scan `<user dir>/presets/<plugin slug>/<module slug>` for presets.
|
||||||
|
menu->addChild(new ui::MenuSeparator);
|
||||||
|
menu->addChild(createMenuLabel("User presets"));
|
||||||
|
appendPresetItems(menu, weakThis, weakThis->model->getUserPresetDirectory());
|
||||||
|
|
||||||
|
// Scan `<plugin dir>/presets/<module slug>` for presets.
|
||||||
|
menu->addChild(new ui::MenuSeparator);
|
||||||
|
menu->addChild(createMenuLabel("Factory presets"));
|
||||||
|
appendPresetItems(menu, weakThis, weakThis->model->getFactoryPresetDirectory());
|
||||||
|
*/
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->resetAction();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Randomize
|
||||||
|
menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->randomizeAction();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Disconnect cables
|
||||||
|
menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->disconnectAction();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Bypass
|
||||||
|
std::string bypassText = RACK_MOD_CTRL_NAME "+E";
|
||||||
|
bool bypassed = module && module->isBypassed();
|
||||||
|
if (bypassed)
|
||||||
|
bypassText += " " CHECKMARK_STRING;
|
||||||
|
menu->addChild(createMenuItem("Bypass", bypassText, [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->bypassAction(!bypassed);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Duplicate
|
||||||
|
menu->addChild(createMenuItem("Duplicate", RACK_MOD_CTRL_NAME "+D", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->cloneAction(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Duplicate with cables
|
||||||
|
menu->addChild(createMenuItem("└ with cables", RACK_MOD_SHIFT_NAME "+" RACK_MOD_CTRL_NAME "+D", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->cloneAction(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
menu->addChild(createMenuItem("Delete", "Backspace/Delete", [=]() {
|
||||||
|
if (!weakThis)
|
||||||
|
return;
|
||||||
|
weakThis->removeAction();
|
||||||
|
}, false, true));
|
||||||
|
|
||||||
|
w->appendContextMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardinalModuleWidget::onButton(const ButtonEvent& e)
|
||||||
|
{
|
||||||
|
bool selected = APP->scene->rack->isSelected(this);
|
||||||
|
|
||||||
|
if (selected) {
|
||||||
|
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||||
|
ui::Menu* menu = createMenu();
|
||||||
|
// TODO customize this one too
|
||||||
|
APP->scene->rack->appendSelectionContextMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
e.consume(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpaqueWidget::onButton(e);
|
||||||
|
|
||||||
|
if (e.getTarget() == this) {
|
||||||
|
// Set starting drag position
|
||||||
|
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||||
|
internal->dragOffset = e.pos;
|
||||||
|
}
|
||||||
|
// Toggle selection on Shift-click
|
||||||
|
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) {
|
||||||
|
APP->scene->rack->select(this, !selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.isConsumed() && !selected) {
|
||||||
|
// Open context menu on right-click
|
||||||
|
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||||
|
CardinalModuleWidget__createContextMenu(this, model, module);
|
||||||
|
e.consume(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,6 +87,7 @@ BUILD_CXX_FLAGS += -DnsvgParseFromFile=nsvgParseFromFileCardinal
|
||||||
# Rack files to build
|
# Rack files to build
|
||||||
|
|
||||||
RACK_FILES += AsyncDialog.cpp
|
RACK_FILES += AsyncDialog.cpp
|
||||||
|
RACK_FILES += CardinalModuleWidget.cpp
|
||||||
RACK_FILES += override/Engine.cpp
|
RACK_FILES += override/Engine.cpp
|
||||||
RACK_FILES += override/MenuBar.cpp
|
RACK_FILES += override/MenuBar.cpp
|
||||||
RACK_FILES += override/Scene.cpp
|
RACK_FILES += override/Scene.cpp
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue