| @@ -1,11 +1,13 @@ | |||
| #pragma once | |||
| #include "event.hpp" | |||
| #include "widgets/Widget.hpp" | |||
| #include "math.hpp" | |||
| #include <vector> | |||
| namespace rack { | |||
| struct Widget; | |||
| struct WidgetState { | |||
| Widget *rootWidget = NULL; | |||
| @@ -1,441 +1,38 @@ | |||
| #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/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 { | |||
| 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 gApplicationVersion; | |||
| extern std::string gApiHost; | |||
| @@ -453,11 +50,4 @@ void appModuleBrowserCreate(); | |||
| json_t *appModuleBrowserToJson(); | |||
| 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 | |||
| @@ -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 | |||
| #include "widgets/OpaqueWidget.hpp" | |||
| #include "app/SVGPanel.hpp" | |||
| #include "common.hpp" | |||
| #include "plugin.hpp" | |||
| #include "engine.hpp" | |||
| @@ -8,6 +7,10 @@ | |||
| namespace rack { | |||
| struct SVGPanel; | |||
| struct Port; | |||
| struct ModuleWidget : OpaqueWidget { | |||
| Model *model = NULL; | |||
| /** 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 | |||
| #include "app.hpp" | |||
| #include "widgets/FramebufferWidget.hpp" | |||
| #include "widgets/SVGWidget.hpp" | |||
| #include "common.hpp" | |||
| 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 { | |||
| /** Base event class */ | |||
| 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. | |||
| */ | |||
| Widget *target = NULL; | |||
| @@ -46,7 +48,7 @@ struct Text { | |||
| /** Occurs every frame when the mouse is hovering over a Widget. | |||
| 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 { | |||
| /** 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. | |||
| 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 { | |||
| /** 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. | |||
| If consumed, a HoverKey event will not be triggered. | |||
| */ | |||
| 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 { | |||
| 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. | |||
| */ | |||
| struct DragEnter : Event { | |||
| @@ -1,4 +1,5 @@ | |||
| #pragma once | |||
| #include "ui/common.hpp" | |||
| #include "ui/SequentialLayout.hpp" | |||
| #include "ui/Label.hpp" | |||
| #include "ui/List.hpp" | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "ui/Button.hpp" | |||
| #include "Button.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "ui/Button.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "MenuEntry.hpp" | |||
| #include "blendish.h" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,8 +1,6 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "ui/MenuOverlay.hpp" | |||
| #include "common.hpp" | |||
| #include "MenuOverlay.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,6 @@ | |||
| #pragma once | |||
| #include "ui/TextField.hpp" | |||
| #include "common.hpp" | |||
| #include "TextField.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "logger.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| #include "WidgetState.hpp" | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,8 +1,6 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| #include "WidgetState.hpp" | |||
| #include "blendish.h" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| @@ -1,7 +1,5 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "common.hpp" | |||
| 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 | |||
| #include "widgets/Widget.hpp" | |||
| #include "widgets/TransparentWidget.hpp" | |||
| #include "widgets/OpaqueWidget.hpp" | |||
| @@ -8,7 +7,3 @@ | |||
| #include "widgets/SVGWidget.hpp" | |||
| #include "widgets/FramebufferWidget.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) | |||
| e.target = this; | |||
| } | |||
| void onButton(event::Button &e) override { | |||
| Widget::onButton(e); | |||
| if (!e.target) | |||
| e.target = this; | |||
| } | |||
| void onHoverKey(event::HoverKey &e) override { | |||
| Widget::onHoverKey(e); | |||
| if (!e.target) | |||
| e.target = this; | |||
| } | |||
| void onHoverText(event::HoverText &e) override { | |||
| Widget::onHoverText(e); | |||
| if (!e.target) | |||
| 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 { | |||
| Widget::onPathDrop(e); | |||
| if (!e.target) | |||
| @@ -121,6 +121,7 @@ struct Widget { | |||
| virtual void onDragStart(event::DragStart &e) {} | |||
| virtual void onDragEnd(event::DragEnd &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 onDragLeave(event::DragLeave &e) {} | |||
| virtual void onDragDrop(event::DragDrop &e) {} | |||
| @@ -1,11 +1,14 @@ | |||
| #include "WidgetState.hpp" | |||
| #include "event.hpp" | |||
| #include "widgets.hpp" | |||
| #include "logger.hpp" | |||
| namespace rack { | |||
| void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| // Button event | |||
| // event::Button | |||
| event::Button eButton; | |||
| eButton.pos = pos; | |||
| eButton.button = button; | |||
| @@ -15,28 +18,37 @@ void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) | |||
| Widget *clickedWidget = eButton.target; | |||
| if (button == GLFW_MOUSE_BUTTON_LEFT) { | |||
| // Drag events | |||
| if (action == GLFW_PRESS && !draggedWidget && clickedWidget) { | |||
| // event::DragStart | |||
| event::DragStart eDragStart; | |||
| clickedWidget->onDragStart(eDragStart); | |||
| draggedWidget = clickedWidget; | |||
| } | |||
| if (action == GLFW_RELEASE && draggedWidget) { | |||
| if (dragHoveredWidget) { | |||
| // event::DragLeave | |||
| event::DragLeave eDragLeave; | |||
| dragHoveredWidget->onDragLeave(eDragLeave); | |||
| } | |||
| if (clickedWidget) { | |||
| // event::DragDrop | |||
| event::DragDrop eDragDrop; | |||
| eDragDrop.origin = draggedWidget; | |||
| clickedWidget->onDragDrop(eDragDrop); | |||
| } | |||
| // event::DragEnd | |||
| event::DragEnd eDragEnd; | |||
| draggedWidget->onDragEnd(eDragEnd); | |||
| draggedWidget = NULL; | |||
| dragHoveredWidget = NULL; | |||
| } | |||
| // Select events | |||
| if (action == GLFW_PRESS && clickedWidget != selectedWidget) { | |||
| if (selectedWidget) { | |||
| // event::Deselect | |||
| event::Deselect eDeselect; | |||
| selectedWidget->onDeselect(eDeselect); | |||
| } | |||
| @@ -44,6 +56,7 @@ void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) | |||
| selectedWidget = clickedWidget; | |||
| if (selectedWidget) { | |||
| // event::Select | |||
| event::Select 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) { | |||
| // Drag events | |||
| if (draggedWidget) { | |||
| // event::DragMove | |||
| event::DragMove eDragMove; | |||
| eDragMove.mouseDelta = mouseDelta; | |||
| 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; | |||
| } | |||
| // if (scrollWidget) { | |||
| // event::HoverScroll | |||
| // event::HoverScroll eHoverScroll; | |||
| // eHoverScroll.pos = pos; | |||
| // eHoverScroll.scrollDelta = scrollDelta; | |||
| // rootWidget->onHoverScroll(eHoverScroll); | |||
| // } | |||
| // Hover event | |||
| // event::Hover | |||
| event::Hover eHover; | |||
| eHover.pos = pos; | |||
| eHover.mouseDelta = mouseDelta; | |||
| @@ -86,6 +124,7 @@ void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| if (newHoveredWidget != hoveredWidget) { | |||
| if (hoveredWidget) { | |||
| // event::Leave | |||
| event::Leave eLeave; | |||
| hoveredWidget->onLeave(eLeave); | |||
| } | |||
| @@ -93,6 +132,7 @@ void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| hoveredWidget = newHoveredWidget; | |||
| if (hoveredWidget) { | |||
| // event::Enter | |||
| event::Enter eEnter; | |||
| hoveredWidget->onEnter(eEnter); | |||
| } | |||
| @@ -101,7 +141,7 @@ void WidgetState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| void WidgetState::handleLeave() { | |||
| if (hoveredWidget) { | |||
| // Leave event | |||
| // event::Leave | |||
| event::Leave eLeave; | |||
| hoveredWidget->onLeave(eLeave); | |||
| } | |||
| @@ -109,7 +149,7 @@ void WidgetState::handleLeave() { | |||
| } | |||
| void WidgetState::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||
| // HoverScroll event | |||
| // event::HoverScroll | |||
| event::HoverScroll eHoverScroll; | |||
| eHoverScroll.pos = pos; | |||
| 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) { | |||
| // PathDrop event | |||
| // event::PathDrop | |||
| event::PathDrop ePathDrop; | |||
| ePathDrop.pos = pos; | |||
| 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) { | |||
| if (selectedWidget) { | |||
| // SelectText event | |||
| // event::SelectText | |||
| event::SelectText eSelectText; | |||
| eSelectText.codepoint = codepoint; | |||
| selectedWidget->onSelectText(eSelectText); | |||
| @@ -134,7 +174,7 @@ void WidgetState::handleText(math::Vec pos, int codepoint) { | |||
| return; | |||
| } | |||
| // HoverText event | |||
| // event::HoverText | |||
| event::HoverText eHoverText; | |||
| eHoverText.pos = pos; | |||
| 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) { | |||
| if (selectedWidget) { | |||
| // event::SelectKey | |||
| event::SelectKey eSelectKey; | |||
| eSelectKey.key = key; | |||
| eSelectKey.scancode = scancode; | |||
| @@ -153,6 +194,7 @@ void WidgetState::handleKey(math::Vec pos, int key, int scancode, int action, in | |||
| return; | |||
| } | |||
| // event::HoverKey | |||
| event::HoverKey eHoverKey; | |||
| eHoverKey.pos = pos; | |||
| eHoverKey.key = key; | |||
| @@ -171,6 +213,7 @@ void WidgetState::finalizeWidget(Widget *w) { | |||
| } | |||
| void WidgetState::handleZoom() { | |||
| // event::Zoom | |||
| event::Zoom eZoom; | |||
| rootWidget->onZoom(eZoom); | |||
| } | |||