@@ -1,11 +1,13 @@ | |||||
#pragma once | #pragma once | ||||
#include "event.hpp" | |||||
#include "widgets/Widget.hpp" | |||||
#include "math.hpp" | |||||
#include <vector> | |||||
namespace rack { | namespace rack { | ||||
struct Widget; | |||||
struct WidgetState { | struct WidgetState { | ||||
Widget *rootWidget = NULL; | Widget *rootWidget = NULL; | ||||
@@ -1,441 +1,38 @@ | |||||
#pragma once | #pragma once | ||||
#include <vector> | |||||
#include <jansson.h> | |||||
#include "widgets.hpp" | |||||
#include "ui.hpp" | |||||
#include "WidgetState.hpp" | |||||
static const float SVG_DPI = 75.0; | |||||
static const float MM_PER_IN = 25.4; | |||||
namespace rack { | |||||
inline float in2px(float inches) { | |||||
return inches * SVG_DPI; | |||||
} | |||||
inline math::Vec in2px(math::Vec inches) { | |||||
return inches.mult(SVG_DPI); | |||||
} | |||||
inline float mm2px(float millimeters) { | |||||
return millimeters * (SVG_DPI / MM_PER_IN); | |||||
} | |||||
inline math::Vec mm2px(math::Vec millimeters) { | |||||
return millimeters.mult(SVG_DPI / MM_PER_IN); | |||||
} | |||||
struct Model; | |||||
struct Module; | |||||
struct Wire; | |||||
struct RackWidget; | |||||
struct ParamWidget; | |||||
struct Port; | |||||
struct SVGPanel; | |||||
//////////////////// | |||||
// module | |||||
//////////////////// | |||||
// A 1HPx3U module should be 15x380 pixels. Thus the width of a module should be a factor of 15. | |||||
static const float RACK_GRID_WIDTH = 15; | |||||
static const float RACK_GRID_HEIGHT = 380; | |||||
static const math::Vec RACK_GRID_SIZE = math::Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT); | |||||
static const std::string PRESET_FILTERS = "VCV Rack module preset (.vcvm):vcvm"; | |||||
static const std::string PATCH_FILTERS = "VCV Rack patch (.vcv):vcv"; | |||||
} // namespace rack | |||||
#include "app/AudioWidget.hpp" | |||||
#include "app/CircularShadow.hpp" | |||||
#include "app/common.hpp" | |||||
#include "app/Component.hpp" | |||||
#include "app/Knob.hpp" | |||||
#include "app/LedDisplay.hpp" | |||||
#include "app/LightWidget.hpp" | |||||
#include "app/MidiWidget.hpp" | |||||
#include "app/ModuleLightWidget.hpp" | |||||
#include "app/ModuleWidget.hpp" | #include "app/ModuleWidget.hpp" | ||||
#include "app/MomentarySwitch.hpp" | |||||
#include "app/MultiLightWidget.hpp" | |||||
#include "app/ParamWidget.hpp" | |||||
#include "app/PluginManagerWidget.hpp" | |||||
#include "app/Port.hpp" | |||||
#include "app/RackRail.hpp" | |||||
#include "app/RackScene.hpp" | |||||
#include "app/RackScrollWidget.hpp" | |||||
#include "app/RackWidget.hpp" | |||||
#include "app/SVGButton.hpp" | |||||
#include "app/SVGKnob.hpp" | |||||
#include "app/SVGPanel.hpp" | |||||
#include "app/SVGPort.hpp" | |||||
#include "app/SVGScrew.hpp" | |||||
#include "app/SVGSlider.hpp" | |||||
#include "app/SVGSwitch.hpp" | |||||
#include "app/ToggleSwitch.hpp" | |||||
#include "app/Toolbar.hpp" | |||||
#include "app/WireContainer.hpp" | |||||
#include "app/WireWidget.hpp" | |||||
namespace rack { | namespace rack { | ||||
struct WireWidget : OpaqueWidget { | |||||
Port *outputPort = NULL; | |||||
Port *inputPort = NULL; | |||||
Port *hoveredOutputPort = NULL; | |||||
Port *hoveredInputPort = NULL; | |||||
Wire *wire = NULL; | |||||
NVGcolor color; | |||||
WireWidget(); | |||||
~WireWidget(); | |||||
/** Synchronizes the plugged state of the widget to the owned wire */ | |||||
void updateWire(); | |||||
math::Vec getOutputPos(); | |||||
math::Vec getInputPos(); | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
void draw(NVGcontext *vg) override; | |||||
void drawPlugs(NVGcontext *vg); | |||||
}; | |||||
struct WireContainer : TransparentWidget { | |||||
WireWidget *activeWire = NULL; | |||||
/** Takes ownership of `w` and adds it as a child if it isn't already */ | |||||
void setActiveWire(WireWidget *w); | |||||
/** "Drops" the wire onto the port, making an engine connection if successful */ | |||||
void commitActiveWire(); | |||||
void removeTopWire(Port *port); | |||||
void removeAllWires(Port *port); | |||||
/** Returns the most recently added wire connected to the given Port, i.e. the top of the stack */ | |||||
WireWidget *getTopWire(Port *port); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
struct RackWidget : OpaqueWidget { | |||||
FramebufferWidget *rails; | |||||
// Only put ModuleWidgets in here | |||||
Widget *moduleContainer; | |||||
// Only put WireWidgets in here | |||||
WireContainer *wireContainer; | |||||
std::string lastPath; | |||||
math::Vec lastMousePos; | |||||
bool lockModules = false; | |||||
RackWidget(); | |||||
~RackWidget(); | |||||
/** Completely clear the rack's modules and wires */ | |||||
void clear(); | |||||
/** Clears the rack and loads the template patch */ | |||||
void reset(); | |||||
void loadDialog(); | |||||
void saveDialog(); | |||||
void saveAsDialog(); | |||||
/** If `lastPath` is defined, ask the user to reload it */ | |||||
void revert(); | |||||
/** Disconnects all wires */ | |||||
void disconnect(); | |||||
void save(std::string filename); | |||||
void load(std::string filename); | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
/** Creates a module and adds it to the rack */ | |||||
ModuleWidget *moduleFromJson(json_t *moduleJ); | |||||
void pastePresetClipboard(); | |||||
void addModule(ModuleWidget *m); | |||||
/** Removes the module and transfers ownership to the caller */ | |||||
void deleteModule(ModuleWidget *m); | |||||
void cloneModule(ModuleWidget *m); | |||||
/** Sets a module's box if non-colliding. Returns true if set */ | |||||
bool requestModuleBox(ModuleWidget *m, math::Rect box); | |||||
/** Moves a module to the closest non-colliding position */ | |||||
bool requestModuleBoxNearest(ModuleWidget *m, math::Rect box); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
void onHover(event::Hover &e) override; | |||||
void onButton(event::Button &e) override; | |||||
void onZoom(event::Zoom &e) override; | |||||
}; | |||||
struct RackRail : TransparentWidget { | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
//////////////////// | |||||
// ParamWidgets and other components | |||||
//////////////////// | |||||
/** A Widget that exists on a Panel and interacts with a Module */ | |||||
struct Component : OpaqueWidget { | |||||
Module *module = NULL; | |||||
}; | |||||
struct CircularShadow : TransparentWidget { | |||||
float blurRadius; | |||||
float opacity; | |||||
CircularShadow(); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
/** A Component which has control over a Param (defined in engine.hpp) */ | |||||
struct ParamWidget : Component, QuantityWidget { | |||||
int paramId; | |||||
/** Used to momentarily disable value randomization | |||||
To permanently disable or change randomization behavior, override the randomize() method instead of changing this. | |||||
*/ | |||||
bool randomizable = true; | |||||
/** Apply per-sample smoothing in the engine */ | |||||
bool smooth = false; | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
virtual void reset(); | |||||
virtual void randomize(); | |||||
void onButton(event::Button &e) override; | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
/** Implements vertical dragging behavior for ParamWidgets */ | |||||
struct Knob : ParamWidget { | |||||
/** Snap to nearest integer while dragging */ | |||||
bool snap = false; | |||||
/** Multiplier for mouse movement to adjust knob value */ | |||||
float speed = 1.0; | |||||
float dragValue; | |||||
Knob(); | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragMove(event::DragMove &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
}; | |||||
/** A knob which rotates an SVG and caches it in a framebuffer */ | |||||
struct SVGKnob : Knob, FramebufferWidget { | |||||
TransformWidget *tw; | |||||
SVGWidget *sw; | |||||
CircularShadow *shadow; | |||||
/** Angles in radians */ | |||||
float minAngle, maxAngle; | |||||
SVGKnob(); | |||||
void setSVG(std::shared_ptr<SVG> svg); | |||||
void step() override; | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
/** Behaves like a knob but linearly moves an SVGWidget between two points. | |||||
Can be used for horizontal or vertical linear faders. | |||||
*/ | |||||
struct SVGSlider : Knob, FramebufferWidget { | |||||
SVGWidget *background; | |||||
SVGWidget *handle; | |||||
/** Intermediate positions will be interpolated between these positions */ | |||||
math::Vec minHandlePos, maxHandlePos; | |||||
SVGSlider(); | |||||
void setSVGs(std::shared_ptr<SVG> backgroundSVG, std::shared_ptr<SVG> handleSVG); | |||||
void step() override; | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
/** A ParamWidget with multiple frames corresponding to its value */ | |||||
struct SVGSwitch : virtual ParamWidget, FramebufferWidget { | |||||
std::vector<std::shared_ptr<SVG>> frames; | |||||
SVGWidget *sw; | |||||
SVGSwitch(); | |||||
/** Adds an SVG file to represent the next switch position */ | |||||
void addFrame(std::shared_ptr<SVG> svg); | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
/** A switch that cycles through each mechanical position */ | |||||
struct ToggleSwitch : virtual ParamWidget { | |||||
void onDragStart(event::DragStart &e) override; | |||||
}; | |||||
/** A switch that is turned on when held and turned off when released. | |||||
Consider using SVGButton if the switch simply changes the state of your Module when clicked. | |||||
*/ | |||||
struct MomentarySwitch : virtual ParamWidget { | |||||
/** Don't randomize state */ | |||||
void randomize() override {} | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
}; | |||||
/** A Component with a default (up) and active (down) state when clicked. | |||||
Does not modify a Param, simply calls onAction() of a subclass. | |||||
*/ | |||||
struct SVGButton : Component, FramebufferWidget { | |||||
Module *module = NULL; | |||||
std::shared_ptr<SVG> defaultSVG; | |||||
std::shared_ptr<SVG> activeSVG; | |||||
SVGWidget *sw; | |||||
SVGButton(); | |||||
/** If `activeSVG` is NULL, `defaultSVG` is used as the active state instead. */ | |||||
void setSVGs(std::shared_ptr<SVG> defaultSVG, std::shared_ptr<SVG> activeSVG); | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
}; | |||||
//////////////////// | |||||
// IO widgets | |||||
//////////////////// | |||||
struct LedDisplay : virtual Widget { | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
struct LedDisplaySeparator : TransparentWidget { | |||||
LedDisplaySeparator(); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
struct LedDisplayChoice : TransparentWidget { | |||||
std::string text; | |||||
std::shared_ptr<Font> font; | |||||
math::Vec textOffset; | |||||
NVGcolor color; | |||||
LedDisplayChoice(); | |||||
void draw(NVGcontext *vg) override; | |||||
void onButton(event::Button &e) override; | |||||
}; | |||||
struct LedDisplayTextField : TextField { | |||||
std::shared_ptr<Font> font; | |||||
math::Vec textOffset; | |||||
NVGcolor color; | |||||
LedDisplayTextField(); | |||||
void draw(NVGcontext *vg) override; | |||||
int getTextPosition(math::Vec mousePos) override; | |||||
}; | |||||
struct AudioIO; | |||||
struct MidiIO; | |||||
struct AudioWidget : LedDisplay { | |||||
/** Not owned */ | |||||
AudioIO *audioIO = NULL; | |||||
LedDisplayChoice *driverChoice; | |||||
LedDisplaySeparator *driverSeparator; | |||||
LedDisplayChoice *deviceChoice; | |||||
LedDisplaySeparator *deviceSeparator; | |||||
LedDisplayChoice *sampleRateChoice; | |||||
LedDisplaySeparator *sampleRateSeparator; | |||||
LedDisplayChoice *bufferSizeChoice; | |||||
AudioWidget(); | |||||
void step() override; | |||||
}; | |||||
struct MidiWidget : LedDisplay { | |||||
/** Not owned */ | |||||
MidiIO *midiIO = NULL; | |||||
LedDisplayChoice *driverChoice; | |||||
LedDisplaySeparator *driverSeparator; | |||||
LedDisplayChoice *deviceChoice; | |||||
LedDisplaySeparator *deviceSeparator; | |||||
LedDisplayChoice *channelChoice; | |||||
MidiWidget(); | |||||
void step() override; | |||||
}; | |||||
//////////////////// | |||||
// lights | |||||
//////////////////// | |||||
struct LightWidget : TransparentWidget { | |||||
NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); | |||||
NVGcolor color = nvgRGBA(0, 0, 0, 0); | |||||
NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); | |||||
void draw(NVGcontext *vg) override; | |||||
virtual void drawLight(NVGcontext *vg); | |||||
virtual void drawHalo(NVGcontext *vg); | |||||
}; | |||||
/** Mixes a list of colors based on a list of brightness values */ | |||||
struct MultiLightWidget : LightWidget { | |||||
/** Colors of each value state */ | |||||
std::vector<NVGcolor> baseColors; | |||||
void addBaseColor(NVGcolor baseColor); | |||||
/** Sets the color to a linear combination of the baseColors with the given weights */ | |||||
void setValues(const std::vector<float> &values); | |||||
}; | |||||
/** A MultiLightWidget that points to a module's Light or a range of lights | |||||
Will access firstLightId, firstLightId + 1, etc. for each added color | |||||
*/ | |||||
struct ModuleLightWidget : MultiLightWidget { | |||||
Module *module = NULL; | |||||
int firstLightId; | |||||
void step() override; | |||||
}; | |||||
//////////////////// | |||||
// ports | |||||
//////////////////// | |||||
struct Port : Component { | |||||
enum PortType { | |||||
INPUT, | |||||
OUTPUT | |||||
}; | |||||
PortType type = INPUT; | |||||
int portId; | |||||
MultiLightWidget *plugLight; | |||||
Port(); | |||||
~Port(); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
void onButton(event::Button &e) override; | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
void onDragDrop(event::DragDrop &e) override; | |||||
void onDragEnter(event::DragEnter &e) override; | |||||
void onDragLeave(event::DragLeave &e) override; | |||||
}; | |||||
struct SVGPort : Port, FramebufferWidget { | |||||
SVGWidget *background; | |||||
CircularShadow *shadow; | |||||
SVGPort(); | |||||
void setSVG(std::shared_ptr<SVG> svg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
/** If you don't add these to your ModuleWidget, they will fall out of the rack... */ | |||||
struct SVGScrew : FramebufferWidget { | |||||
SVGWidget *sw; | |||||
SVGScrew(); | |||||
}; | |||||
//////////////////// | |||||
// scene | |||||
//////////////////// | |||||
struct Toolbar : OpaqueWidget { | |||||
Slider *wireOpacitySlider; | |||||
Slider *wireTensionSlider; | |||||
Slider *zoomSlider; | |||||
RadioButton *cpuUsageButton; | |||||
Toolbar(); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
struct PluginManagerWidget : virtual Widget { | |||||
Widget *loginWidget; | |||||
Widget *manageWidget; | |||||
Widget *downloadWidget; | |||||
PluginManagerWidget(); | |||||
void step() override; | |||||
}; | |||||
struct RackScrollWidget : ScrollWidget { | |||||
void step() override; | |||||
}; | |||||
struct RackScene : Scene { | |||||
ScrollWidget *scrollWidget; | |||||
ZoomWidget *zoomWidget; | |||||
RackScene(); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
void onHoverKey(event::HoverKey &e) override; | |||||
void onPathDrop(event::PathDrop &e) override; | |||||
}; | |||||
//////////////////// | |||||
// globals | |||||
//////////////////// | |||||
extern std::string gApplicationName; | extern std::string gApplicationName; | ||||
extern std::string gApplicationVersion; | extern std::string gApplicationVersion; | ||||
extern std::string gApiHost; | extern std::string gApiHost; | ||||
@@ -453,11 +50,4 @@ void appModuleBrowserCreate(); | |||||
json_t *appModuleBrowserToJson(); | json_t *appModuleBrowserToJson(); | ||||
void appModuleBrowserFromJson(json_t *rootJ); | void appModuleBrowserFromJson(json_t *rootJ); | ||||
/** Deprecated. Will be removed in v1 */ | |||||
json_t *colorToJson(NVGcolor color); | |||||
/** Deprecated. Will be removed in v1 */ | |||||
NVGcolor jsonToColor(json_t *colorJ); | |||||
} // namespace rack | } // namespace rack |
@@ -0,0 +1,27 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "LedDisplay.hpp" | |||||
namespace rack { | |||||
struct AudioIO; | |||||
struct AudioWidget : LedDisplay { | |||||
/** Not owned */ | |||||
AudioIO *audioIO = NULL; | |||||
LedDisplayChoice *driverChoice; | |||||
LedDisplaySeparator *driverSeparator; | |||||
LedDisplayChoice *deviceChoice; | |||||
LedDisplaySeparator *deviceSeparator; | |||||
LedDisplayChoice *sampleRateChoice; | |||||
LedDisplaySeparator *sampleRateSeparator; | |||||
LedDisplayChoice *bufferSizeChoice; | |||||
AudioWidget(); | |||||
void step() override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,16 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct CircularShadow : TransparentWidget { | |||||
float blurRadius; | |||||
float opacity; | |||||
CircularShadow(); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,17 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct Module; | |||||
/** A Widget that exists on a Panel and interacts with a Module */ | |||||
struct Component : OpaqueWidget { | |||||
Module *module = NULL; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,23 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "ParamWidget.hpp" | |||||
namespace rack { | |||||
/** Implements vertical dragging behavior for ParamWidgets */ | |||||
struct Knob : ParamWidget { | |||||
/** Snap to nearest integer while dragging */ | |||||
bool snap = false; | |||||
/** Multiplier for mouse movement to adjust knob value */ | |||||
float speed = 1.0; | |||||
float dragValue; | |||||
Knob(); | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragMove(event::DragMove &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,37 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct LedDisplay : virtual Widget { | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
struct LedDisplaySeparator : TransparentWidget { | |||||
LedDisplaySeparator(); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
struct LedDisplayChoice : TransparentWidget { | |||||
std::string text; | |||||
std::shared_ptr<Font> font; | |||||
math::Vec textOffset; | |||||
NVGcolor color; | |||||
LedDisplayChoice(); | |||||
void draw(NVGcontext *vg) override; | |||||
void onButton(event::Button &e) override; | |||||
}; | |||||
struct LedDisplayTextField : TextField { | |||||
std::shared_ptr<Font> font; | |||||
math::Vec textOffset; | |||||
NVGcolor color; | |||||
LedDisplayTextField(); | |||||
void draw(NVGcontext *vg) override; | |||||
int getTextPosition(math::Vec mousePos) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,18 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct LightWidget : TransparentWidget { | |||||
NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); | |||||
NVGcolor color = nvgRGBA(0, 0, 0, 0); | |||||
NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); | |||||
void draw(NVGcontext *vg) override; | |||||
virtual void drawLight(NVGcontext *vg); | |||||
virtual void drawHalo(NVGcontext *vg); | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,25 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "LedDisplay.hpp" | |||||
namespace rack { | |||||
struct MidiIO; | |||||
struct MidiWidget : LedDisplay { | |||||
/** Not owned */ | |||||
MidiIO *midiIO = NULL; | |||||
LedDisplayChoice *driverChoice; | |||||
LedDisplaySeparator *driverSeparator; | |||||
LedDisplayChoice *deviceChoice; | |||||
LedDisplaySeparator *deviceSeparator; | |||||
LedDisplayChoice *channelChoice; | |||||
MidiWidget(); | |||||
void step() override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,19 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "MultiLightWidget.hpp" | |||||
namespace rack { | |||||
/** A MultiLightWidget that points to a module's Light or a range of lights | |||||
Will access firstLightId, firstLightId + 1, etc. for each added color | |||||
*/ | |||||
struct ModuleLightWidget : MultiLightWidget { | |||||
Module *module = NULL; | |||||
int firstLightId; | |||||
void step() override; | |||||
}; | |||||
} // namespace rack |
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets/OpaqueWidget.hpp" | |||||
#include "app/SVGPanel.hpp" | |||||
#include "common.hpp" | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "engine.hpp" | #include "engine.hpp" | ||||
@@ -8,6 +7,10 @@ | |||||
namespace rack { | namespace rack { | ||||
struct SVGPanel; | |||||
struct Port; | |||||
struct ModuleWidget : OpaqueWidget { | struct ModuleWidget : OpaqueWidget { | ||||
Model *model = NULL; | Model *model = NULL; | ||||
/** Owns the module pointer */ | /** Owns the module pointer */ | ||||
@@ -0,0 +1,19 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
/** A switch that is turned on when held and turned off when released. | |||||
Consider using SVGButton if the switch simply changes the state of your Module when clicked. | |||||
*/ | |||||
struct MomentarySwitch : virtual ParamWidget { | |||||
/** Don't randomize state */ | |||||
void randomize() override {} | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,19 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "LightWidget.hpp" | |||||
namespace rack { | |||||
/** Mixes a list of colors based on a list of brightness values */ | |||||
struct MultiLightWidget : LightWidget { | |||||
/** Colors of each value state */ | |||||
std::vector<NVGcolor> baseColors; | |||||
void addBaseColor(NVGcolor baseColor); | |||||
/** Sets the color to a linear combination of the baseColors with the given weights */ | |||||
void setValues(const std::vector<float> &values); | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,28 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "engine.hpp" | |||||
namespace rack { | |||||
/** A Component which has control over a Param */ | |||||
struct ParamWidget : Component, QuantityWidget { | |||||
int paramId; | |||||
/** Used to momentarily disable value randomization | |||||
To permanently disable or change randomization behavior, override the randomize() method instead of changing this. | |||||
*/ | |||||
bool randomizable = true; | |||||
/** Apply per-sample smoothing in the engine */ | |||||
bool smooth = false; | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
virtual void reset(); | |||||
virtual void randomize(); | |||||
void onButton(event::Button &e) override; | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,17 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct PluginManagerWidget : virtual Widget { | |||||
Widget *loginWidget; | |||||
Widget *manageWidget; | |||||
Widget *downloadWidget; | |||||
PluginManagerWidget(); | |||||
void step() override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,30 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct Port : Component { | |||||
enum PortType { | |||||
INPUT, | |||||
OUTPUT | |||||
}; | |||||
PortType type = INPUT; | |||||
int portId; | |||||
MultiLightWidget *plugLight; | |||||
Port(); | |||||
~Port(); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
void onButton(event::Button &e) override; | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
void onDragDrop(event::DragDrop &e) override; | |||||
void onDragEnter(event::DragEnter &e) override; | |||||
void onDragLeave(event::DragLeave &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,13 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct RackRail : TransparentWidget { | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,20 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct RackScene : Scene { | |||||
ScrollWidget *scrollWidget; | |||||
ZoomWidget *zoomWidget; | |||||
RackScene(); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
void onHoverKey(event::HoverKey &e) override; | |||||
void onPathDrop(event::PathDrop &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,13 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct RackScrollWidget : ScrollWidget { | |||||
void step() override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,61 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "WireWidget.hpp" | |||||
#include "WireContainer.hpp" | |||||
#include "engine.hpp" | |||||
namespace rack { | |||||
struct RackWidget : OpaqueWidget { | |||||
FramebufferWidget *rails; | |||||
// Only put ModuleWidgets in here | |||||
Widget *moduleContainer; | |||||
// Only put WireWidgets in here | |||||
WireContainer *wireContainer; | |||||
std::string lastPath; | |||||
math::Vec lastMousePos; | |||||
bool lockModules = false; | |||||
RackWidget(); | |||||
~RackWidget(); | |||||
/** Completely clear the rack's modules and wires */ | |||||
void clear(); | |||||
/** Clears the rack and loads the template patch */ | |||||
void reset(); | |||||
void loadDialog(); | |||||
void saveDialog(); | |||||
void saveAsDialog(); | |||||
/** If `lastPath` is defined, ask the user to reload it */ | |||||
void revert(); | |||||
/** Disconnects all wires */ | |||||
void disconnect(); | |||||
void save(std::string filename); | |||||
void load(std::string filename); | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
/** Creates a module and adds it to the rack */ | |||||
ModuleWidget *moduleFromJson(json_t *moduleJ); | |||||
void pastePresetClipboard(); | |||||
void addModule(ModuleWidget *m); | |||||
/** Removes the module and transfers ownership to the caller */ | |||||
void deleteModule(ModuleWidget *m); | |||||
void cloneModule(ModuleWidget *m); | |||||
/** Sets a module's box if non-colliding. Returns true if set */ | |||||
bool requestModuleBox(ModuleWidget *m, math::Rect box); | |||||
/** Moves a module to the closest non-colliding position */ | |||||
bool requestModuleBoxNearest(ModuleWidget *m, math::Rect box); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
void onHover(event::Hover &e) override; | |||||
void onButton(event::Button &e) override; | |||||
void onZoom(event::Zoom &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,24 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "engine.hpp" | |||||
namespace rack { | |||||
/** A Component with a default (up) and active (down) state when clicked. | |||||
Does not modify a Param, simply calls onAction() of a subclass. | |||||
*/ | |||||
struct SVGButton : Component, FramebufferWidget { | |||||
std::shared_ptr<SVG> defaultSVG; | |||||
std::shared_ptr<SVG> activeSVG; | |||||
SVGWidget *sw; | |||||
SVGButton(); | |||||
/** If `activeSVG` is NULL, `defaultSVG` is used as the active state instead. */ | |||||
void setSVGs(std::shared_ptr<SVG> defaultSVG, std::shared_ptr<SVG> activeSVG); | |||||
void onDragStart(event::DragStart &e) override; | |||||
void onDragEnd(event::DragEnd &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,24 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "CircularShadow.hpp" | |||||
namespace rack { | |||||
/** A knob which rotates an SVG and caches it in a framebuffer */ | |||||
struct SVGKnob : Knob, FramebufferWidget { | |||||
TransformWidget *tw; | |||||
SVGWidget *sw; | |||||
CircularShadow *shadow; | |||||
/** Angles in radians */ | |||||
float minAngle, maxAngle; | |||||
SVGKnob(); | |||||
void setSVG(std::shared_ptr<SVG> svg); | |||||
void step() override; | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "app.hpp" | |||||
#include "widgets/FramebufferWidget.hpp" | |||||
#include "widgets/SVGWidget.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -0,0 +1,19 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "Port.hpp" | |||||
namespace rack { | |||||
struct SVGPort : Port, FramebufferWidget { | |||||
SVGWidget *background; | |||||
CircularShadow *shadow; | |||||
SVGPort(); | |||||
void setSVG(std::shared_ptr<SVG> svg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,17 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "Port.hpp" | |||||
namespace rack { | |||||
/** If you don't add these to your ModuleWidget, they will fall out of the rack... */ | |||||
struct SVGScrew : FramebufferWidget { | |||||
SVGWidget *sw; | |||||
SVGScrew(); | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,24 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
/** Behaves like a knob but linearly moves an SVGWidget between two points. | |||||
Can be used for horizontal or vertical linear faders. | |||||
*/ | |||||
struct SVGSlider : Knob, FramebufferWidget { | |||||
SVGWidget *background; | |||||
SVGWidget *handle; | |||||
/** Intermediate positions will be interpolated between these positions */ | |||||
math::Vec minHandlePos, maxHandlePos; | |||||
SVGSlider(); | |||||
void setSVGs(std::shared_ptr<SVG> backgroundSVG, std::shared_ptr<SVG> handleSVG); | |||||
void step() override; | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,20 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
/** A ParamWidget with multiple frames corresponding to its value */ | |||||
struct SVGSwitch : virtual ParamWidget, FramebufferWidget { | |||||
std::vector<std::shared_ptr<SVG>> frames; | |||||
SVGWidget *sw; | |||||
SVGSwitch(); | |||||
/** Adds an SVG file to represent the next switch position */ | |||||
void addFrame(std::shared_ptr<SVG> svg); | |||||
void onChange(event::Change &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,14 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
/** A switch that cycles through each mechanical position */ | |||||
struct ToggleSwitch : virtual ParamWidget { | |||||
void onDragStart(event::DragStart &e) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,19 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct Toolbar : OpaqueWidget { | |||||
Slider *wireOpacitySlider; | |||||
Slider *wireTensionSlider; | |||||
Slider *zoomSlider; | |||||
RadioButton *cpuUsageButton; | |||||
Toolbar(); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,24 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
#include "WireWidget.hpp" | |||||
#include "engine.hpp" | |||||
namespace rack { | |||||
struct WireContainer : TransparentWidget { | |||||
WireWidget *activeWire = NULL; | |||||
/** Takes ownership of `w` and adds it as a child if it isn't already */ | |||||
void setActiveWire(WireWidget *w); | |||||
/** "Drops" the wire onto the port, making an engine connection if successful */ | |||||
void commitActiveWire(); | |||||
void removeTopWire(Port *port); | |||||
void removeAllWires(Port *port); | |||||
/** Returns the most recently added wire connected to the given Port, i.e. the top of the stack */ | |||||
WireWidget *getTopWire(Port *port); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,32 @@ | |||||
#pragma once | |||||
#include "common.hpp" | |||||
namespace rack { | |||||
struct Port; | |||||
struct WireWidget : OpaqueWidget { | |||||
Port *outputPort = NULL; | |||||
Port *inputPort = NULL; | |||||
Port *hoveredOutputPort = NULL; | |||||
Port *hoveredInputPort = NULL; | |||||
Wire *wire = NULL; | |||||
NVGcolor color; | |||||
WireWidget(); | |||||
~WireWidget(); | |||||
/** Synchronizes the plugged state of the widget to the owned wire */ | |||||
void updateWire(); | |||||
math::Vec getOutputPos(); | |||||
math::Vec getInputPos(); | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
void draw(NVGcontext *vg) override; | |||||
void drawPlugs(NVGcontext *vg); | |||||
}; | |||||
} // namespace rack |
@@ -0,0 +1,47 @@ | |||||
#pragma once | |||||
#include "ui.hpp" | |||||
#include <jansson.h> | |||||
namespace rack { | |||||
static const float SVG_DPI = 75.0; | |||||
static const float MM_PER_IN = 25.4; | |||||
/** Converts inch measurements to pixels */ | |||||
inline float in2px(float in) { | |||||
return in * SVG_DPI; | |||||
} | |||||
inline math::Vec in2px(math::Vec in) { | |||||
return in.mult(SVG_DPI); | |||||
} | |||||
/** Converts millimeter measurements to pixels */ | |||||
inline float mm2px(float mm) { | |||||
return mm * (SVG_DPI / MM_PER_IN); | |||||
} | |||||
inline math::Vec mm2px(math::Vec mm) { | |||||
return mm.mult(SVG_DPI / MM_PER_IN); | |||||
} | |||||
// A 1HPx3U module should be 15x380 pixels. Thus the width of a module should be a factor of 15. | |||||
static const float RACK_GRID_WIDTH = 15; | |||||
static const float RACK_GRID_HEIGHT = 380; | |||||
static const math::Vec RACK_GRID_SIZE = math::Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT); | |||||
static const std::string PRESET_FILTERS = "VCV Rack module preset (.vcvm):vcvm"; | |||||
static const std::string PATCH_FILTERS = "VCV Rack patch (.vcv):vcv"; | |||||
/** Deprecated. Will be removed in v1 */ | |||||
json_t *colorToJson(NVGcolor color); | |||||
/** Deprecated. Will be removed in v1 */ | |||||
NVGcolor jsonToColor(json_t *colorJ); | |||||
} // namespace rack |
@@ -12,8 +12,10 @@ struct Widget; | |||||
namespace event { | namespace event { | ||||
/** Base event class */ | |||||
struct Event { | struct Event { | ||||
/** Set this to the Widget that consumes (responds to) the event. | |||||
/** The Widget that consumes the event. | |||||
Set to `this` in your event handler method if consumed. | |||||
This stops propagation of the event if applicable. | This stops propagation of the event if applicable. | ||||
*/ | */ | ||||
Widget *target = NULL; | Widget *target = NULL; | ||||
@@ -46,7 +48,7 @@ struct Text { | |||||
/** Occurs every frame when the mouse is hovering over a Widget. | /** Occurs every frame when the mouse is hovering over a Widget. | ||||
Recurses until consumed. | Recurses until consumed. | ||||
If target is set, other events may occur on that Widget. | |||||
If `target` is set, other events may occur on that Widget. | |||||
*/ | */ | ||||
struct Hover : Event, Position { | struct Hover : Event, Position { | ||||
/** Change in mouse position since the last frame. Can be zero. */ | /** Change in mouse position since the last frame. Can be zero. */ | ||||
@@ -56,7 +58,7 @@ struct Hover : Event, Position { | |||||
/** Occurs each mouse button press or release. | /** Occurs each mouse button press or release. | ||||
Recurses until consumed. | Recurses until consumed. | ||||
If target is set, other events may occur on that Widget. | |||||
If `target` is set, other events may occur on that Widget. | |||||
*/ | */ | ||||
struct Button : Event, Position { | struct Button : Event, Position { | ||||
/** GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE, etc. */ | /** GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE, etc. */ | ||||
@@ -116,6 +118,7 @@ struct Deselect : Event { | |||||
/** Occurs when a key is pressed while a Widget is selected. | /** Occurs when a key is pressed while a Widget is selected. | ||||
If consumed, a HoverKey event will not be triggered. | |||||
*/ | */ | ||||
struct SelectKey : Event, Key { | struct SelectKey : Event, Key { | ||||
}; | }; | ||||
@@ -140,14 +143,22 @@ struct DragEnd : Event { | |||||
}; | }; | ||||
/** Occurs when a dragged Widget is moved. | |||||
Called once per frame, even when mouseDelta is zero. | |||||
/** Occurs every frame on the dragged Widget. | |||||
`mouseDelta` may be zero. | |||||
*/ | */ | ||||
struct DragMove : Event { | struct DragMove : Event { | ||||
math::Vec mouseDelta; | math::Vec mouseDelta; | ||||
}; | }; | ||||
/** Occurs every frame when the mouse is hovering over a Widget while dragging. | |||||
Must consume to allow DragEnter, DragLeave, and DragDrop to occur. | |||||
*/ | |||||
struct DragHover : Event, Position { | |||||
/** Change in mouse position since the last frame. Can be zero. */ | |||||
math::Vec mouseDelta; | |||||
}; | |||||
/** Occurs when the mouse enters a Widget while dragging. | /** Occurs when the mouse enters a Widget while dragging. | ||||
*/ | */ | ||||
struct DragEnter : Event { | struct DragEnter : Event { | ||||
@@ -1,4 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "ui/common.hpp" | |||||
#include "ui/SequentialLayout.hpp" | #include "ui/SequentialLayout.hpp" | ||||
#include "ui/Label.hpp" | #include "ui/Label.hpp" | ||||
#include "ui/List.hpp" | #include "ui/List.hpp" | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "ui/Button.hpp" | |||||
#include "Button.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "ui/Button.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "MenuEntry.hpp" | #include "MenuEntry.hpp" | ||||
#include "blendish.h" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,8 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "ui/MenuOverlay.hpp" | |||||
#include "common.hpp" | |||||
#include "MenuOverlay.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include "ui/TextField.hpp" | |||||
#include "common.hpp" | |||||
#include "TextField.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "logger.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
#include "WidgetState.hpp" | #include "WidgetState.hpp" | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,8 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
#include "WidgetState.hpp" | #include "WidgetState.hpp" | ||||
#include "blendish.h" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#include "common.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -0,0 +1,6 @@ | |||||
#pragma once | |||||
#include "widgets.hpp" | |||||
#include "blendish.h" | |||||
#define CHECKMARK_STRING "âś”" | |||||
#define CHECKMARK(_cond) ((_cond) ? CHECKMARK_STRING : "") |
@@ -1,5 +1,4 @@ | |||||
#pragma once | #pragma once | ||||
#include "widgets/Widget.hpp" | #include "widgets/Widget.hpp" | ||||
#include "widgets/TransparentWidget.hpp" | #include "widgets/TransparentWidget.hpp" | ||||
#include "widgets/OpaqueWidget.hpp" | #include "widgets/OpaqueWidget.hpp" | ||||
@@ -8,7 +7,3 @@ | |||||
#include "widgets/SVGWidget.hpp" | #include "widgets/SVGWidget.hpp" | ||||
#include "widgets/FramebufferWidget.hpp" | #include "widgets/FramebufferWidget.hpp" | ||||
#include "widgets/QuantityWidget.hpp" | #include "widgets/QuantityWidget.hpp" | ||||
#define CHECKMARK_STRING "âś”" | |||||
#define CHECKMARK(_cond) ((_cond) ? CHECKMARK_STRING : "") |
@@ -15,31 +15,31 @@ struct OpaqueWidget : virtual Widget { | |||||
if (!e.target) | if (!e.target) | ||||
e.target = this; | e.target = this; | ||||
} | } | ||||
void onButton(event::Button &e) override { | void onButton(event::Button &e) override { | ||||
Widget::onButton(e); | Widget::onButton(e); | ||||
if (!e.target) | if (!e.target) | ||||
e.target = this; | e.target = this; | ||||
} | } | ||||
void onHoverKey(event::HoverKey &e) override { | void onHoverKey(event::HoverKey &e) override { | ||||
Widget::onHoverKey(e); | Widget::onHoverKey(e); | ||||
if (!e.target) | if (!e.target) | ||||
e.target = this; | e.target = this; | ||||
} | } | ||||
void onHoverText(event::HoverText &e) override { | void onHoverText(event::HoverText &e) override { | ||||
Widget::onHoverText(e); | Widget::onHoverText(e); | ||||
if (!e.target) | if (!e.target) | ||||
e.target = this; | e.target = this; | ||||
} | } | ||||
// void onHoverScroll(event::HoverScroll &e) override { | |||||
// Widget::onHoverScroll(e); | |||||
// if (!e.target) | |||||
// e.target = this; | |||||
// } | |||||
void onHoverScroll(event::HoverScroll &e) override { | |||||
Widget::onHoverScroll(e); | |||||
if (!e.target) | |||||
e.target = this; | |||||
} | |||||
void onDragHover(event::DragHover &e) override { | |||||
Widget::onDragHover(e); | |||||
if (!e.target) | |||||
e.target = this; | |||||
} | |||||
void onPathDrop(event::PathDrop &e) override { | void onPathDrop(event::PathDrop &e) override { | ||||
Widget::onPathDrop(e); | Widget::onPathDrop(e); | ||||
if (!e.target) | if (!e.target) | ||||
@@ -121,6 +121,7 @@ struct Widget { | |||||
virtual void onDragStart(event::DragStart &e) {} | virtual void onDragStart(event::DragStart &e) {} | ||||
virtual void onDragEnd(event::DragEnd &e) {} | virtual void onDragEnd(event::DragEnd &e) {} | ||||
virtual void onDragMove(event::DragMove &e) {} | virtual void onDragMove(event::DragMove &e) {} | ||||
virtual void onDragHover(event::DragHover &e) {recursePositionEvent(&Widget::onDragHover, e);} | |||||
virtual void onDragEnter(event::DragEnter &e) {} | virtual void onDragEnter(event::DragEnter &e) {} | ||||
virtual void onDragLeave(event::DragLeave &e) {} | virtual void onDragLeave(event::DragLeave &e) {} | ||||
virtual void onDragDrop(event::DragDrop &e) {} | virtual void onDragDrop(event::DragDrop &e) {} | ||||
@@ -1,11 +1,14 @@ | |||||
#include "WidgetState.hpp" | #include "WidgetState.hpp" | ||||
#include "event.hpp" | |||||
#include "widgets.hpp" | |||||
#include "logger.hpp" | #include "logger.hpp" | ||||
namespace rack { | namespace rack { | ||||
void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) { | void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) { | ||||
// Button event | |||||
// event::Button | |||||
event::Button eButton; | event::Button eButton; | ||||
eButton.pos = pos; | eButton.pos = pos; | ||||
eButton.button = button; | eButton.button = button; | ||||
@@ -15,28 +18,37 @@ void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) | |||||
Widget *clickedWidget = eButton.target; | Widget *clickedWidget = eButton.target; | ||||
if (button == GLFW_MOUSE_BUTTON_LEFT) { | if (button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
// Drag events | |||||
if (action == GLFW_PRESS && !draggedWidget && clickedWidget) { | if (action == GLFW_PRESS && !draggedWidget && clickedWidget) { | ||||
// event::DragStart | |||||
event::DragStart eDragStart; | event::DragStart eDragStart; | ||||
clickedWidget->onDragStart(eDragStart); | clickedWidget->onDragStart(eDragStart); | ||||
draggedWidget = clickedWidget; | draggedWidget = clickedWidget; | ||||
} | } | ||||
if (action == GLFW_RELEASE && draggedWidget) { | if (action == GLFW_RELEASE && draggedWidget) { | ||||
if (dragHoveredWidget) { | |||||
// event::DragLeave | |||||
event::DragLeave eDragLeave; | |||||
dragHoveredWidget->onDragLeave(eDragLeave); | |||||
} | |||||
if (clickedWidget) { | if (clickedWidget) { | ||||
// event::DragDrop | |||||
event::DragDrop eDragDrop; | event::DragDrop eDragDrop; | ||||
eDragDrop.origin = draggedWidget; | eDragDrop.origin = draggedWidget; | ||||
clickedWidget->onDragDrop(eDragDrop); | clickedWidget->onDragDrop(eDragDrop); | ||||
} | } | ||||
// event::DragEnd | |||||
event::DragEnd eDragEnd; | event::DragEnd eDragEnd; | ||||
draggedWidget->onDragEnd(eDragEnd); | draggedWidget->onDragEnd(eDragEnd); | ||||
draggedWidget = NULL; | draggedWidget = NULL; | ||||
dragHoveredWidget = NULL; | |||||
} | } | ||||
// Select events | |||||
if (action == GLFW_PRESS && clickedWidget != selectedWidget) { | if (action == GLFW_PRESS && clickedWidget != selectedWidget) { | ||||
if (selectedWidget) { | if (selectedWidget) { | ||||
// event::Deselect | |||||
event::Deselect eDeselect; | event::Deselect eDeselect; | ||||
selectedWidget->onDeselect(eDeselect); | selectedWidget->onDeselect(eDeselect); | ||||
} | } | ||||
@@ -44,6 +56,7 @@ void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) | |||||
selectedWidget = clickedWidget; | selectedWidget = clickedWidget; | ||||
if (selectedWidget) { | if (selectedWidget) { | ||||
// event::Select | |||||
event::Select eSelect; | event::Select eSelect; | ||||
selectedWidget->onSelect(eSelect); | selectedWidget->onSelect(eSelect); | ||||
} | } | ||||
@@ -62,22 +75,47 @@ void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) | |||||
void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | ||||
// Drag events | |||||
if (draggedWidget) { | if (draggedWidget) { | ||||
// event::DragMove | |||||
event::DragMove eDragMove; | event::DragMove eDragMove; | ||||
eDragMove.mouseDelta = mouseDelta; | eDragMove.mouseDelta = mouseDelta; | ||||
draggedWidget->onDragMove(eDragMove); | draggedWidget->onDragMove(eDragMove); | ||||
// event::DragHover | |||||
event::DragHover eDragHover; | |||||
eDragHover.pos = pos; | |||||
eDragHover.mouseDelta = mouseDelta; | |||||
rootWidget->onDragHover(eDragHover); | |||||
Widget *newDragHoveredWidget = eDragHover.target; | |||||
if (newDragHoveredWidget != dragHoveredWidget) { | |||||
if (dragHoveredWidget) { | |||||
// event::DragLeave | |||||
event::DragLeave eDragLeave; | |||||
dragHoveredWidget->onDragLeave(eDragLeave); | |||||
} | |||||
dragHoveredWidget = newDragHoveredWidget; | |||||
if (dragHoveredWidget) { | |||||
// event::DragEnter | |||||
event::DragEnter eDragEnter; | |||||
dragHoveredWidget->onDragEnter(eDragEnter); | |||||
} | |||||
} | |||||
return; | return; | ||||
} | } | ||||
// if (scrollWidget) { | // if (scrollWidget) { | ||||
// event::HoverScroll | |||||
// event::HoverScroll eHoverScroll; | // event::HoverScroll eHoverScroll; | ||||
// eHoverScroll.pos = pos; | // eHoverScroll.pos = pos; | ||||
// eHoverScroll.scrollDelta = scrollDelta; | // eHoverScroll.scrollDelta = scrollDelta; | ||||
// rootWidget->onHoverScroll(eHoverScroll); | // rootWidget->onHoverScroll(eHoverScroll); | ||||
// } | // } | ||||
// Hover event | |||||
// event::Hover | |||||
event::Hover eHover; | event::Hover eHover; | ||||
eHover.pos = pos; | eHover.pos = pos; | ||||
eHover.mouseDelta = mouseDelta; | eHover.mouseDelta = mouseDelta; | ||||
@@ -86,6 +124,7 @@ void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
if (newHoveredWidget != hoveredWidget) { | if (newHoveredWidget != hoveredWidget) { | ||||
if (hoveredWidget) { | if (hoveredWidget) { | ||||
// event::Leave | |||||
event::Leave eLeave; | event::Leave eLeave; | ||||
hoveredWidget->onLeave(eLeave); | hoveredWidget->onLeave(eLeave); | ||||
} | } | ||||
@@ -93,6 +132,7 @@ void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
hoveredWidget = newHoveredWidget; | hoveredWidget = newHoveredWidget; | ||||
if (hoveredWidget) { | if (hoveredWidget) { | ||||
// event::Enter | |||||
event::Enter eEnter; | event::Enter eEnter; | ||||
hoveredWidget->onEnter(eEnter); | hoveredWidget->onEnter(eEnter); | ||||
} | } | ||||
@@ -101,7 +141,7 @@ void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
void WidgetState::handleLeave() { | void WidgetState::handleLeave() { | ||||
if (hoveredWidget) { | if (hoveredWidget) { | ||||
// Leave event | |||||
// event::Leave | |||||
event::Leave eLeave; | event::Leave eLeave; | ||||
hoveredWidget->onLeave(eLeave); | hoveredWidget->onLeave(eLeave); | ||||
} | } | ||||
@@ -109,7 +149,7 @@ void WidgetState::handleLeave() { | |||||
} | } | ||||
void WidgetState::handleScroll(math::Vec pos, math::Vec scrollDelta) { | void WidgetState::handleScroll(math::Vec pos, math::Vec scrollDelta) { | ||||
// HoverScroll event | |||||
// event::HoverScroll | |||||
event::HoverScroll eHoverScroll; | event::HoverScroll eHoverScroll; | ||||
eHoverScroll.pos = pos; | eHoverScroll.pos = pos; | ||||
eHoverScroll.scrollDelta = scrollDelta; | eHoverScroll.scrollDelta = scrollDelta; | ||||
@@ -117,7 +157,7 @@ void WidgetState::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||||
} | } | ||||
void WidgetState::handleDrop(math::Vec pos, std::vector<std::string> paths) { | void WidgetState::handleDrop(math::Vec pos, std::vector<std::string> paths) { | ||||
// PathDrop event | |||||
// event::PathDrop | |||||
event::PathDrop ePathDrop; | event::PathDrop ePathDrop; | ||||
ePathDrop.pos = pos; | ePathDrop.pos = pos; | ||||
ePathDrop.paths = paths; | ePathDrop.paths = paths; | ||||
@@ -126,7 +166,7 @@ void WidgetState::handleDrop(math::Vec pos, std::vector<std::string> paths) { | |||||
void WidgetState::handleText(math::Vec pos, int codepoint) { | void WidgetState::handleText(math::Vec pos, int codepoint) { | ||||
if (selectedWidget) { | if (selectedWidget) { | ||||
// SelectText event | |||||
// event::SelectText | |||||
event::SelectText eSelectText; | event::SelectText eSelectText; | ||||
eSelectText.codepoint = codepoint; | eSelectText.codepoint = codepoint; | ||||
selectedWidget->onSelectText(eSelectText); | selectedWidget->onSelectText(eSelectText); | ||||
@@ -134,7 +174,7 @@ void WidgetState::handleText(math::Vec pos, int codepoint) { | |||||
return; | return; | ||||
} | } | ||||
// HoverText event | |||||
// event::HoverText | |||||
event::HoverText eHoverText; | event::HoverText eHoverText; | ||||
eHoverText.pos = pos; | eHoverText.pos = pos; | ||||
eHoverText.codepoint = codepoint; | eHoverText.codepoint = codepoint; | ||||
@@ -143,6 +183,7 @@ void WidgetState::handleText(math::Vec pos, int codepoint) { | |||||
void WidgetState::handleKey(math::Vec pos, int key, int scancode, int action, int mods) { | void WidgetState::handleKey(math::Vec pos, int key, int scancode, int action, int mods) { | ||||
if (selectedWidget) { | if (selectedWidget) { | ||||
// event::SelectKey | |||||
event::SelectKey eSelectKey; | event::SelectKey eSelectKey; | ||||
eSelectKey.key = key; | eSelectKey.key = key; | ||||
eSelectKey.scancode = scancode; | eSelectKey.scancode = scancode; | ||||
@@ -153,6 +194,7 @@ void WidgetState::handleKey(math::Vec pos, int key, int scancode, int action, in | |||||
return; | return; | ||||
} | } | ||||
// event::HoverKey | |||||
event::HoverKey eHoverKey; | event::HoverKey eHoverKey; | ||||
eHoverKey.pos = pos; | eHoverKey.pos = pos; | ||||
eHoverKey.key = key; | eHoverKey.key = key; | ||||
@@ -171,6 +213,7 @@ void WidgetState::finalizeWidget(Widget *w) { | |||||
} | } | ||||
void WidgetState::handleZoom() { | void WidgetState::handleZoom() { | ||||
// event::Zoom | |||||
event::Zoom eZoom; | event::Zoom eZoom; | ||||
rootWidget->onZoom(eZoom); | rootWidget->onZoom(eZoom); | ||||
} | } | ||||