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