@@ -116,6 +116,9 @@ ifeq ($(ARCH), mac) | |||||
mkdir -p $(BUNDLE)/Contents/Resources/plugins | mkdir -p $(BUNDLE)/Contents/Resources/plugins | ||||
cp -R plugins/Fundamental/dist/Fundamental $(BUNDLE)/Contents/Resources/plugins | cp -R plugins/Fundamental/dist/Fundamental $(BUNDLE)/Contents/Resources/plugins | ||||
# Make DMG image | |||||
cd dist && ln -s /Applications Applications | |||||
cd dist && hdiutil create -srcfolder . -volname Rack -ov -format UDZO Rack-$(VERSION)-$(ARCH).dmg | |||||
endif | endif | ||||
ifeq ($(ARCH), win) | ifeq ($(ARCH), win) | ||||
mkdir -p dist/Rack | mkdir -p dist/Rack | ||||
@@ -135,6 +138,11 @@ ifeq ($(ARCH), win) | |||||
cp dep/bin/portaudio_x64.dll dist/Rack/ | cp dep/bin/portaudio_x64.dll dist/Rack/ | ||||
mkdir -p dist/Rack/plugins | mkdir -p dist/Rack/plugins | ||||
cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | ||||
# Make ZIP | |||||
cd dist && zip -5 -r Rack-$(VERSION)-$(ARCH).zip Rack | |||||
# Make NSIS installer | |||||
makensis installer.nsi | |||||
mv Rack-setup.exe dist/Rack-$(VERSION)-$(ARCH).exe | |||||
endif | endif | ||||
ifeq ($(ARCH), lin) | ifeq ($(ARCH), lin) | ||||
mkdir -p dist/Rack | mkdir -p dist/Rack | ||||
@@ -149,16 +157,10 @@ ifeq ($(ARCH), lin) | |||||
cp dep/lib/libportaudio.so.2 dist/Rack/ | cp dep/lib/libportaudio.so.2 dist/Rack/ | ||||
cp dep/lib/librtmidi.so.4 dist/Rack/ | cp dep/lib/librtmidi.so.4 dist/Rack/ | ||||
mkdir -p dist/Rack/plugins | mkdir -p dist/Rack/plugins | ||||
# Make ZIP | |||||
cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | ||||
endif | endif | ||||
ifeq ($(ARCH), mac) | |||||
cd dist && ln -s /Applications Applications | |||||
cd dist && hdiutil create -srcfolder . -volname Rack -ov -format UDZO Rack-$(VERSION)-$(ARCH).dmg | |||||
else | |||||
cd dist && zip -5 -r Rack-$(VERSION)-$(ARCH).zip Rack | |||||
endif | |||||
# Plugin helpers | # Plugin helpers | ||||
@@ -67,12 +67,12 @@ struct ModuleWidget : OpaqueWidget { | |||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
Vec dragPos; | Vec dragPos; | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override; | |||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
void onMouseDownOpaque(int button) override; | |||||
void onMouseDown(EventMouseDown &e) override; | |||||
void onMouseMove(EventMouseMove &e) override; | |||||
void onHoverKey(EventHoverKey &e) override; | |||||
void onDragStart(EventDragStart &e) override; | |||||
void onDragEnd(EventDragEnd &e) override; | |||||
void onDragMove(EventDragMove &e) override; | |||||
}; | }; | ||||
struct ValueLight; | struct ValueLight; | ||||
@@ -144,9 +144,9 @@ struct RackWidget : OpaqueWidget { | |||||
void step() override; | void step() override; | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override; | |||||
void onMouseDownOpaque(int button) override; | |||||
void onZoom() override; | |||||
void onMouseMove(EventMouseMove &e) override; | |||||
void onMouseDown(EventMouseDown &e) override; | |||||
void onZoom(EventZoom &e) override; | |||||
}; | }; | ||||
struct RackRail : TransparentWidget { | struct RackRail : TransparentWidget { | ||||
@@ -184,8 +184,8 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||||
json_t *toJson(); | json_t *toJson(); | ||||
void fromJson(json_t *rootJ); | void fromJson(json_t *rootJ); | ||||
virtual void randomize(); | virtual void randomize(); | ||||
void onMouseDownOpaque(int button) override; | |||||
void onChange() override; | |||||
void onMouseDown(EventMouseDown &e) override; | |||||
void onChange(EventChange &e) override; | |||||
}; | }; | ||||
/** Implements vertical dragging behavior for ParamWidgets */ | /** Implements vertical dragging behavior for ParamWidgets */ | ||||
@@ -193,11 +193,11 @@ struct Knob : ParamWidget { | |||||
/** Snap to nearest integer while dragging */ | /** Snap to nearest integer while dragging */ | ||||
bool snap = false; | bool snap = false; | ||||
float dragValue; | float dragValue; | ||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
void onDragStart(EventDragStart &e) override; | |||||
void onDragMove(EventDragMove &e) override; | |||||
void onDragEnd(EventDragEnd &e) override; | |||||
/** Tell engine to smoothly vary this parameter */ | /** Tell engine to smoothly vary this parameter */ | ||||
void onChange() override; | |||||
void onChange(EventChange &e) override; | |||||
}; | }; | ||||
struct SpriteKnob : virtual Knob, SpriteWidget { | struct SpriteKnob : virtual Knob, SpriteWidget { | ||||
@@ -216,7 +216,7 @@ struct SVGKnob : virtual Knob, FramebufferWidget { | |||||
SVGKnob(); | SVGKnob(); | ||||
void setSVG(std::shared_ptr<SVG> svg); | void setSVG(std::shared_ptr<SVG> svg); | ||||
void step() override; | void step() override; | ||||
void onChange() override; | |||||
void onChange(EventChange &e) override; | |||||
}; | }; | ||||
struct SVGSlider : Knob, FramebufferWidget { | struct SVGSlider : Knob, FramebufferWidget { | ||||
@@ -228,7 +228,7 @@ struct SVGSlider : Knob, FramebufferWidget { | |||||
SVGSlider(); | SVGSlider(); | ||||
void step() override; | void step() override; | ||||
void onChange() override; | |||||
void onChange(EventChange &e) override; | |||||
}; | }; | ||||
struct Switch : ParamWidget { | struct Switch : ParamWidget { | ||||
@@ -243,12 +243,12 @@ struct SVGSwitch : virtual Switch, FramebufferWidget { | |||||
/** Adds an SVG file to represent the next switch position */ | /** Adds an SVG file to represent the next switch position */ | ||||
void addFrame(std::shared_ptr<SVG> svg); | void addFrame(std::shared_ptr<SVG> svg); | ||||
void step() override; | void step() override; | ||||
void onChange() override; | |||||
void onChange(EventChange &e) override; | |||||
}; | }; | ||||
/** A switch that cycles through each mechanical position */ | /** A switch that cycles through each mechanical position */ | ||||
struct ToggleSwitch : virtual Switch { | struct ToggleSwitch : virtual Switch { | ||||
void onDragStart() override { | |||||
void onDragStart(EventDragStart &e) override { | |||||
// Cycle through values | // Cycle through values | ||||
// e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3. | // e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3. | ||||
if (value >= maxValue) | if (value >= maxValue) | ||||
@@ -262,10 +262,10 @@ struct ToggleSwitch : virtual Switch { | |||||
struct MomentarySwitch : virtual Switch { | struct MomentarySwitch : virtual Switch { | ||||
/** Don't randomize state */ | /** Don't randomize state */ | ||||
void randomize() override {} | void randomize() override {} | ||||
void onDragStart() override { | |||||
void onDragStart(EventDragStart &e) override { | |||||
setValue(maxValue); | setValue(maxValue); | ||||
} | } | ||||
void onDragEnd() override { | |||||
void onDragEnd(EventDragEnd &e) override { | |||||
setValue(minValue); | setValue(minValue); | ||||
} | } | ||||
}; | }; | ||||
@@ -286,12 +286,12 @@ struct Port : OpaqueWidget { | |||||
~Port(); | ~Port(); | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
void onMouseDownOpaque(int button) override; | |||||
void onDragEnd() override; | |||||
void onDragStart() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
void onDragEnter(Widget *origin) override; | |||||
void onDragLeave(Widget *origin) override; | |||||
void onMouseDown(EventMouseDown &e) override; | |||||
void onDragStart(EventDragStart &e) override; | |||||
void onDragEnd(EventDragEnd &e) override; | |||||
void onDragDrop(EventDragDrop &e) override; | |||||
void onDragEnter(EventDragEnter &e) override; | |||||
void onDragLeave(EventDragEnter &e) override; | |||||
}; | }; | ||||
struct SVGPort : Port, FramebufferWidget { | struct SVGPort : Port, FramebufferWidget { | ||||
@@ -365,7 +365,8 @@ struct RackScene : Scene { | |||||
RackScene(); | RackScene(); | ||||
void step() override; | void step() override; | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
void onHoverKey(EventHoverKey &e) override; | |||||
void onPathDrop(EventPathDrop &e) override; | |||||
}; | }; | ||||
//////////////////// | //////////////////// | ||||
@@ -409,34 +409,39 @@ struct RedGreenBlueLight : ColorLightWidget { | |||||
}; | }; | ||||
/** Based on the size of 5mm LEDs */ | |||||
template <typename BASE> | template <typename BASE> | ||||
struct LargeLight : BASE { | struct LargeLight : BASE { | ||||
LargeLight() { | LargeLight() { | ||||
this->box.size = Vec(20, 20); | |||||
this->box.size = mm2px(Vec(5.179, 5.179)); | |||||
} | } | ||||
}; | }; | ||||
/** Based on the size of 3mm LEDs */ | |||||
template <typename BASE> | template <typename BASE> | ||||
struct MediumLight : BASE { | struct MediumLight : BASE { | ||||
MediumLight() { | MediumLight() { | ||||
this->box.size = Vec(12, 12); | |||||
this->box.size = mm2px(Vec(3.176, 3.176)); | |||||
} | } | ||||
}; | }; | ||||
/** Based on the size of 2mm LEDs */ | |||||
template <typename BASE> | template <typename BASE> | ||||
struct SmallLight : BASE { | struct SmallLight : BASE { | ||||
SmallLight() { | SmallLight() { | ||||
this->box.size = Vec(8, 8); | |||||
this->box.size = mm2px(Vec(2.176, 2.176)); | |||||
} | } | ||||
}; | }; | ||||
/** Based on the size of 1mm LEDs */ | |||||
template <typename BASE> | template <typename BASE> | ||||
struct TinyLight : BASE { | struct TinyLight : BASE { | ||||
TinyLight() { | TinyLight() { | ||||
this->box.size = Vec(5, 5); | |||||
this->box.size = mm2px(Vec(1.088, 1.088)); | |||||
} | } | ||||
}; | }; | ||||
//////////////////// | //////////////////// | ||||
// Switches and Buttons | // Switches and Buttons | ||||
//////////////////// | //////////////////// | ||||
@@ -497,6 +502,12 @@ struct PB61303 : SVGSwitch, MomentarySwitch { | |||||
} | } | ||||
}; | }; | ||||
struct LEDBezel : SVGSwitch, MomentarySwitch { | |||||
LEDBezel() { | |||||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/LEDBezel.svg"))); | |||||
} | |||||
}; | |||||
//////////////////// | //////////////////// | ||||
// Misc | // Misc | ||||
@@ -63,15 +63,15 @@ struct Module { | |||||
virtual void step() {} | virtual void step() {} | ||||
virtual void onSampleRateChange() {} | virtual void onSampleRateChange() {} | ||||
/** Override these to store extra internal data in the "data" property */ | |||||
virtual json_t *toJson() { return NULL; } | |||||
virtual void fromJson(json_t *root) {} | |||||
/** Override these to implement spacial behavior when user clicks Initialize and Randomize */ | /** Override these to implement spacial behavior when user clicks Initialize and Randomize */ | ||||
virtual void reset() {} | virtual void reset() {} | ||||
virtual void randomize() {} | virtual void randomize() {} | ||||
/** Deprecated */ | /** Deprecated */ | ||||
virtual void initialize() final {} | virtual void initialize() final {} | ||||
/** Override these to store extra internal data in the "data" property */ | |||||
virtual json_t *toJson() { return NULL; } | |||||
virtual void fromJson(json_t *root) {} | |||||
}; | }; | ||||
struct Wire { | struct Wire { | ||||
@@ -0,0 +1,107 @@ | |||||
#pragma once | |||||
#include <list> | |||||
#include "math.hpp" | |||||
namespace rack { | |||||
struct Widget; | |||||
struct Event { | |||||
/** Set this to true to signal that no other widgets should receive the event */ | |||||
bool consumed = false; | |||||
}; | |||||
struct EventPosition : Event { | |||||
Vec pos; | |||||
}; | |||||
/////////// | |||||
struct EventMouseDown : EventPosition { | |||||
int button; | |||||
/** The widget which responded to the click. Set it to `this` if consumed. */ | |||||
Widget *target = NULL; | |||||
}; | |||||
struct EventMouseUp : EventPosition { | |||||
int button; | |||||
Widget *target = NULL; | |||||
}; | |||||
struct EventMouseMove : EventPosition { | |||||
Vec mouseRel; | |||||
Widget *target = NULL; | |||||
}; | |||||
struct EventHoverKey : EventPosition { | |||||
int key; | |||||
Widget *target = NULL; | |||||
}; | |||||
struct EventMouseEnter : Event { | |||||
}; | |||||
struct EventMouseLeave : Event { | |||||
}; | |||||
struct EventFocus : Event { | |||||
}; | |||||
struct EventDefocus : Event { | |||||
}; | |||||
struct EventText : Event { | |||||
int codepoint; | |||||
}; | |||||
struct EventKey : Event { | |||||
int key; | |||||
}; | |||||
struct EventScroll : EventPosition { | |||||
Vec scrollRel; | |||||
}; | |||||
///////////// | |||||
struct EventDragStart : Event { | |||||
}; | |||||
struct EventDragEnd : Event { | |||||
}; | |||||
struct EventDragMove : Event { | |||||
Vec mouseRel; | |||||
}; | |||||
struct EventDragEnter : Event { | |||||
Widget *origin = NULL; | |||||
}; | |||||
struct EventDragLeave : Event { | |||||
Widget *origin = NULL; | |||||
}; | |||||
struct EventDragDrop : Event { | |||||
Widget *origin = NULL; | |||||
}; | |||||
struct EventPathDrop : EventPosition { | |||||
std::list<std::string> paths; | |||||
}; | |||||
struct EventAction : Event { | |||||
}; | |||||
struct EventChange : Event { | |||||
}; | |||||
struct EventZoom : Event { | |||||
}; | |||||
} // namespace rack |
@@ -8,6 +8,7 @@ | |||||
#include "math.hpp" | #include "math.hpp" | ||||
#include "util.hpp" | #include "util.hpp" | ||||
#include "events.hpp" | |||||
#define SVG_DPI 75.0 | #define SVG_DPI 75.0 | ||||
@@ -122,35 +123,36 @@ struct Widget { | |||||
Return `this` to accept the event. | Return `this` to accept the event. | ||||
Return NULL to reject the event and pass it to the widget behind this one. | Return NULL to reject the event and pass it to the widget behind this one. | ||||
*/ | */ | ||||
virtual Widget *onMouseDown(Vec pos, int button); | |||||
virtual Widget *onMouseUp(Vec pos, int button); | |||||
virtual void onMouseDown(EventMouseDown &e); | |||||
virtual void onMouseUp(EventMouseUp &e); | |||||
/** Called on every frame, even if mouseRel = Vec(0, 0) */ | /** Called on every frame, even if mouseRel = Vec(0, 0) */ | ||||
virtual Widget *onMouseMove(Vec pos, Vec mouseRel); | |||||
virtual Widget *onHoverKey(Vec pos, int key); | |||||
virtual void onMouseMove(EventMouseMove &e); | |||||
virtual void onHoverKey(EventHoverKey &e); | |||||
/** Called when this widget begins responding to `onMouseMove` events */ | /** Called when this widget begins responding to `onMouseMove` events */ | ||||
virtual void onMouseEnter() {} | |||||
virtual void onMouseEnter(EventMouseEnter &e) {} | |||||
/** Called when another widget begins responding to `onMouseMove` events */ | /** Called when another widget begins responding to `onMouseMove` events */ | ||||
virtual void onMouseLeave() {} | |||||
virtual bool onFocus() {return false;} | |||||
virtual void onDefocus() {} | |||||
virtual bool onFocusText(int codepoint) {return false;} | |||||
virtual bool onFocusKey(int key) {return false;} | |||||
virtual Widget *onScroll(Vec pos, Vec scrollRel); | |||||
virtual void onMouseLeave(EventMouseLeave &e) {} | |||||
virtual void onFocus(EventFocus &e) {} | |||||
virtual void onDefocus(EventDefocus &e) {} | |||||
virtual void onText(EventText &e) {} | |||||
virtual void onKey(EventKey &e) {} | |||||
virtual void onScroll(EventScroll &e); | |||||
/** Called when a widget responds to `onMouseDown` for a left button press */ | /** Called when a widget responds to `onMouseDown` for a left button press */ | ||||
virtual void onDragStart() {} | |||||
virtual void onDragStart(EventDragStart &e) {} | |||||
/** Called when the left button is released and this widget is being dragged */ | /** Called when the left button is released and this widget is being dragged */ | ||||
virtual void onDragEnd() {} | |||||
virtual void onDragEnd(EventDragEnd &e) {} | |||||
/** Called when a widget responds to `onMouseMove` and is being dragged */ | /** Called when a widget responds to `onMouseMove` and is being dragged */ | ||||
virtual void onDragMove(Vec mouseRel) {} | |||||
virtual void onDragMove(EventDragMove &e) {} | |||||
/** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */ | /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */ | ||||
virtual void onDragEnter(Widget *origin) {} | |||||
virtual void onDragLeave(Widget *origin) {} | |||||
virtual void onDragDrop(Widget *origin) {} | |||||
virtual void onAction() {} | |||||
virtual void onChange() {} | |||||
virtual void onZoom(); | |||||
virtual void onDragEnter(EventDragEnter &e) {} | |||||
virtual void onDragLeave(EventDragEnter &e) {} | |||||
virtual void onDragDrop(EventDragDrop &e) {} | |||||
virtual void onPathDrop(EventPathDrop &e); | |||||
virtual void onAction(EventAction &e) {} | |||||
virtual void onChange(EventChange &e) {} | |||||
virtual void onZoom(EventZoom &e); | |||||
}; | }; | ||||
struct TransformWidget : Widget { | struct TransformWidget : Widget { | ||||
@@ -170,11 +172,11 @@ struct ZoomWidget : Widget { | |||||
Rect getViewport(Rect r) override; | Rect getViewport(Rect r) override; | ||||
void setZoom(float zoom); | void setZoom(float zoom); | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
Widget *onMouseDown(Vec pos, int button) override; | |||||
Widget *onMouseUp(Vec pos, int button) override; | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override; | |||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
Widget *onScroll(Vec pos, Vec scrollRel) override; | |||||
void onMouseDown(EventMouseDown &e) override; | |||||
void onMouseUp(EventMouseUp &e) override; | |||||
void onMouseMove(EventMouseMove &e) override; | |||||
void onHoverKey(EventHoverKey &e) override; | |||||
void onScroll(EventScroll &e) override; | |||||
}; | }; | ||||
//////////////////// | //////////////////// | ||||
@@ -183,47 +185,36 @@ struct ZoomWidget : Widget { | |||||
/** Widget that does not respond to events */ | /** Widget that does not respond to events */ | ||||
struct TransparentWidget : virtual Widget { | struct TransparentWidget : virtual Widget { | ||||
Widget *onMouseDown(Vec pos, int button) override {return NULL;} | |||||
Widget *onMouseUp(Vec pos, int button) override {return NULL;} | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override {return NULL;} | |||||
Widget *onScroll(Vec pos, Vec scrollRel) override {return NULL;} | |||||
void onMouseDown(EventMouseDown &e) override {} | |||||
void onMouseUp(EventMouseUp &e) override {} | |||||
void onMouseMove(EventMouseMove &e) override {} | |||||
void onScroll(EventScroll &e) override {} | |||||
}; | }; | ||||
/** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */ | /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */ | ||||
struct OpaqueWidget : virtual Widget { | struct OpaqueWidget : virtual Widget { | ||||
Widget *onMouseDown(Vec pos, int button) override { | |||||
Widget *w = Widget::onMouseDown(pos, button); | |||||
if (w) return w; | |||||
onMouseDownOpaque(button); | |||||
return this; | |||||
void onMouseDown(EventMouseDown &e) override { | |||||
Widget::onMouseDown(e); | |||||
if (!e.target) | |||||
e.target = this; | |||||
e.consumed = true; | |||||
} | } | ||||
Widget *onMouseUp(Vec pos, int button) override { | |||||
Widget *w = Widget::onMouseUp(pos, button); | |||||
if (w) return w; | |||||
onMouseUpOpaque(button); | |||||
return this; | |||||
void onMouseUp(EventMouseUp &e) override { | |||||
Widget::onMouseUp(e); | |||||
if (!e.target) | |||||
e.target = this; | |||||
e.consumed = true; | |||||
} | } | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override { | |||||
Widget *w = Widget::onMouseMove(pos, mouseRel); | |||||
if (w) return w; | |||||
onMouseMoveOpaque(mouseRel); | |||||
return this; | |||||
void onMouseMove(EventMouseMove &e) override { | |||||
Widget::onMouseMove(e); | |||||
if (!e.target) | |||||
e.target = this; | |||||
e.consumed = true; | |||||
} | } | ||||
Widget *onScroll(Vec pos, Vec scrollRel) override { | |||||
Widget *w = Widget::onScroll(pos, scrollRel); | |||||
if (w) return w; | |||||
if (onScrollOpaque(scrollRel)) | |||||
return this; | |||||
return NULL; | |||||
void onScroll(EventScroll &e) override { | |||||
Widget::onScroll(e); | |||||
e.consumed = true; | |||||
} | } | ||||
/** "High level" events called by the above lower level events. | |||||
Use these if you don't care about the clicked position. | |||||
*/ | |||||
virtual void onMouseDownOpaque(int button) {} | |||||
virtual void onMouseUpOpaque(int button) {} | |||||
virtual void onMouseMoveOpaque(Vec mouseRel) {} | |||||
virtual bool onScrollOpaque(Vec scrollRel) {return false;} | |||||
}; | }; | ||||
struct SpriteWidget : virtual Widget { | struct SpriteWidget : virtual Widget { | ||||
@@ -264,7 +255,7 @@ struct FramebufferWidget : virtual Widget { | |||||
~FramebufferWidget(); | ~FramebufferWidget(); | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
int getImageHandle(); | int getImageHandle(); | ||||
void onZoom() override; | |||||
void onZoom(EventZoom &e) override; | |||||
}; | }; | ||||
struct QuantityWidget : virtual Widget { | struct QuantityWidget : virtual Widget { | ||||
@@ -302,9 +293,9 @@ struct Label : Widget { | |||||
// Deletes itself from parent when clicked | // Deletes itself from parent when clicked | ||||
struct MenuOverlay : OpaqueWidget { | struct MenuOverlay : OpaqueWidget { | ||||
void onDragDrop(Widget *origin) override; | |||||
bool onScrollOpaque(Vec scrollRel) override {return true;} | |||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
void onDragDrop(EventDragDrop &e) override; | |||||
void onScroll(EventScroll &e) override; | |||||
void onHoverKey(EventHoverKey &e) override; | |||||
}; | }; | ||||
struct MenuEntry; | struct MenuEntry; | ||||
@@ -324,7 +315,7 @@ struct Menu : OpaqueWidget { | |||||
void setChildMenu(Menu *menu); | void setChildMenu(Menu *menu); | ||||
void step() override; | void step() override; | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
bool onScrollOpaque(Vec scrollRel) override; | |||||
void onScroll(EventScroll &e) override; | |||||
}; | }; | ||||
struct MenuEntry : OpaqueWidget { | struct MenuEntry : OpaqueWidget { | ||||
@@ -343,8 +334,8 @@ struct MenuLabel : MenuEntry { | |||||
struct MenuItem : MenuEntry { | struct MenuItem : MenuEntry { | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
virtual Menu *createChildMenu() {return NULL;} | virtual Menu *createChildMenu() {return NULL;} | ||||
void onMouseEnter() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
void onMouseEnter(EventMouseEnter &e) override; | |||||
void onDragDrop(EventDragDrop &e) override; | |||||
}; | }; | ||||
struct Button : OpaqueWidget { | struct Button : OpaqueWidget { | ||||
@@ -355,11 +346,11 @@ struct Button : OpaqueWidget { | |||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
void onMouseEnter() override; | |||||
void onMouseLeave() override; | |||||
void onDragStart() override; | |||||
void onDragEnd() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
void onMouseEnter(EventMouseEnter &e) override; | |||||
void onMouseLeave(EventMouseLeave &e) override; | |||||
void onDragStart(EventDragStart &e) override; | |||||
void onDragEnd(EventDragEnd &e) override; | |||||
void onDragDrop(EventDragDrop &e) override; | |||||
}; | }; | ||||
struct ChoiceButton : Button { | struct ChoiceButton : Button { | ||||
@@ -373,9 +364,9 @@ struct RadioButton : OpaqueWidget, QuantityWidget { | |||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
void onMouseEnter() override; | |||||
void onMouseLeave() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
void onMouseEnter(EventMouseEnter &e) override; | |||||
void onMouseLeave(EventMouseLeave &e) override; | |||||
void onDragDrop(EventDragDrop &e) override; | |||||
}; | }; | ||||
struct Slider : OpaqueWidget, QuantityWidget { | struct Slider : OpaqueWidget, QuantityWidget { | ||||
@@ -385,10 +376,10 @@ struct Slider : OpaqueWidget, QuantityWidget { | |||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
void onMouseDownOpaque(int button) override; | |||||
void onDragStart(EventDragStart &e) override; | |||||
void onDragMove(EventDragMove &e) override; | |||||
void onDragEnd(EventDragEnd &e) override; | |||||
void onMouseDown(EventMouseDown &e) override; | |||||
}; | }; | ||||
/** Parent must be a ScrollWidget */ | /** Parent must be a ScrollWidget */ | ||||
@@ -400,9 +391,9 @@ struct ScrollBar : OpaqueWidget { | |||||
box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT); | box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT); | ||||
} | } | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
void onDragStart(EventDragStart &e) override; | |||||
void onDragMove(EventDragMove &e) override; | |||||
void onDragEnd(EventDragEnd &e) override; | |||||
}; | }; | ||||
/** Handles a container with ScrollBar */ | /** Handles a container with ScrollBar */ | ||||
@@ -414,7 +405,7 @@ struct ScrollWidget : OpaqueWidget { | |||||
ScrollWidget(); | ScrollWidget(); | ||||
void step() override; | void step() override; | ||||
bool onScrollOpaque(Vec scrollRel) override; | |||||
void onScroll(EventScroll &e) override; | |||||
}; | }; | ||||
struct TextField : OpaqueWidget { | struct TextField : OpaqueWidget { | ||||
@@ -428,10 +419,10 @@ struct TextField : OpaqueWidget { | |||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
Widget *onMouseDown(Vec pos, int button) override; | |||||
bool onFocusText(int codepoint) override; | |||||
bool onFocusKey(int key) override; | |||||
bool onFocus() override; | |||||
void onMouseDown(EventMouseDown &e) override; | |||||
void onFocus(EventFocus &e) override; | |||||
void onText(EventText &e) override; | |||||
void onKey(EventKey &e) override; | |||||
void insertText(std::string newText); | void insertText(std::string newText); | ||||
virtual void onTextChange() {} | virtual void onTextChange() {} | ||||
}; | }; | ||||
@@ -0,0 +1,88 @@ | |||||
!include "MUI2.nsh" | |||||
Name "VCV Rack" | |||||
OutFile "Rack-setup.exe" | |||||
SetCompressor "bzip2" | |||||
CRCCheck On | |||||
;Default installation folder | |||||
InstallDir "$PROGRAMFILES\VCV" | |||||
;Get installation folder from registry if available | |||||
InstallDirRegKey HKCU "Software\VCV Rack" "" | |||||
;Request application privileges for Windows Vista | |||||
RequestExecutionLevel admin | |||||
!define MUI_ICON "icon.ico" | |||||
!define MUI_HEADERIMAGE | |||||
!define MUI_HEADERIMAGE_BITMAP "installer-banner.bmp" ; 150x57 | |||||
; !define MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\win.bmp" ; 164x314 | |||||
; !define MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\win.bmp" ; 164x314 | |||||
!define MUI_COMPONENTSPAGE_NODESC | |||||
; Pages | |||||
; !insertmacro MUI_PAGE_WELCOME | |||||
!insertmacro MUI_PAGE_COMPONENTS | |||||
!insertmacro MUI_PAGE_DIRECTORY | |||||
;second directory selection | |||||
; Var DbInstDir | |||||
; !define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which to install the database." | |||||
; !define MUI_DIRECTORYPAGE_TEXT_TOP "The installer will install the database(s) in the following folder. To install in a differenct folder, click Browse and select another folder. Click Next to continue." | |||||
; !define MUI_DIRECTORYPAGE_VARIABLE $DbInstDir ; <= the other directory will be stored into that variable | |||||
; !insertmacro MUI_PAGE_DIRECTORY | |||||
!insertmacro MUI_PAGE_INSTFILES | |||||
!insertmacro MUI_UNPAGE_CONFIRM | |||||
!insertmacro MUI_UNPAGE_INSTFILES | |||||
!insertmacro MUI_LANGUAGE "English" | |||||
Section "!VCV Rack" VCVRACK | |||||
SetOutPath "$INSTDIR" | |||||
File /r "dist\Rack" | |||||
;Store installation folder | |||||
WriteRegStr HKCU "Software\VCV Rack" "" $INSTDIR | |||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\VCV Rack" "DisplayName" "VCV Rack" | |||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\VCV Rack" "UninstallString" "$\"$INSTDIR\UninstallRack.exe$\"" | |||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\VCV Rack" "QuietUninstallString" "$\"$INSTDIR\UninstallRack.exe$\" /S" | |||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\VCV Rack" "InstallLocation" "$\"$INSTDIR$\"" | |||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\VCV Rack" "Publisher" "VCV" | |||||
;Create uninstaller | |||||
WriteUninstaller "$INSTDIR\UninstallRack.exe" | |||||
;Create shortcuts | |||||
CreateDirectory "$SMPROGRAMS" | |||||
; Set working directory of shortcut | |||||
SetOutPath "$INSTDIR\Rack" | |||||
CreateShortcut "$SMPROGRAMS\VCV Rack.lnk" "$INSTDIR\Rack\Rack.exe" | |||||
SectionEnd | |||||
; Section "VST Plugin" VST | |||||
; SectionEnd | |||||
Section "Uninstall" | |||||
RMDir /r "$INSTDIR\Rack" | |||||
Delete "$INSTDIR\UninstallRack.exe" | |||||
RMDir "$INSTDIR" | |||||
Delete "$SMPROGRAMS\VCV Rack.lnk" | |||||
DeleteRegKey /ifempty HKCU "Software\VCV Rack" | |||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\VCV Rack" | |||||
SectionEnd |
@@ -0,0 +1,71 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
<!-- Created with Inkscape (http://www.inkscape.org/) --> | |||||
<svg | |||||
xmlns:dc="http://purl.org/dc/elements/1.1/" | |||||
xmlns:cc="http://creativecommons.org/ns#" | |||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||||
xmlns:svg="http://www.w3.org/2000/svg" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||||
width="7.5001564mm" | |||||
height="7.5000095mm" | |||||
viewBox="0 0 7.5001564 7.5000095" | |||||
version="1.1" | |||||
id="svg64581" | |||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06" | |||||
sodipodi:docname="LEDBezel.svg"> | |||||
<defs | |||||
id="defs64575" /> | |||||
<sodipodi:namedview | |||||
id="base" | |||||
pagecolor="#ffffff" | |||||
bordercolor="#666666" | |||||
borderopacity="1.0" | |||||
inkscape:pageopacity="0.0" | |||||
inkscape:pageshadow="2" | |||||
inkscape:zoom="1.979899" | |||||
inkscape:cx="-100.74496" | |||||
inkscape:cy="9.8683694" | |||||
inkscape:document-units="mm" | |||||
inkscape:current-layer="layer1" | |||||
showgrid="false" | |||||
fit-margin-top="0" | |||||
fit-margin-left="0" | |||||
fit-margin-right="0" | |||||
fit-margin-bottom="0" | |||||
inkscape:window-width="2560" | |||||
inkscape:window-height="1422" | |||||
inkscape:window-x="0" | |||||
inkscape:window-y="18" | |||||
inkscape:window-maximized="0" /> | |||||
<metadata | |||||
id="metadata64578"> | |||||
<rdf:RDF> | |||||
<cc:Work | |||||
rdf:about=""> | |||||
<dc:format>image/svg+xml</dc:format> | |||||
<dc:type | |||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||||
<dc:title></dc:title> | |||||
</cc:Work> | |||||
</rdf:RDF> | |||||
</metadata> | |||||
<g | |||||
inkscape:label="Layer 1" | |||||
inkscape:groupmode="layer" | |||||
id="layer1" | |||||
transform="translate(-94.523732,-120.89285)"> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
id="path9729" | |||||
d="m 94.750061,123.36034 c -0.706931,1.94578 0.297674,4.09829 2.240704,4.8066 1.947157,0.70556 4.098285,-0.29626 4.805225,-2.24208 0.70968,-1.94578 -0.29355,-4.09688 -2.239332,-4.80522 -1.945781,-0.70693 -4.096914,0.29355 -4.806597,2.2407" | |||||
style="fill:#2b2b2b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" /> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
id="path64013" | |||||
d="m 99.30033,121.82382 c -1.557161,-0.56497 -3.279704,0.23703 -3.846089,1.79285 -0.565009,1.55716 0.237031,3.27833 1.794192,3.84334 1.557197,0.56776 3.276987,-0.23428 3.844747,-1.79144 0.56498,-1.55582 -0.23565,-3.27837 -1.79285,-3.84475" | |||||
style="clip-rule:nonzero;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" /> | |||||
</g> | |||||
</svg> |
@@ -10,29 +10,30 @@ namespace rack { | |||||
#define KNOB_SENSITIVITY 0.0015 | #define KNOB_SENSITIVITY 0.0015 | ||||
void Knob::onDragStart() { | |||||
void Knob::onDragStart(EventDragStart &e) { | |||||
guiCursorLock(); | guiCursorLock(); | ||||
dragValue = value; | dragValue = value; | ||||
randomizable = false; | randomizable = false; | ||||
} | } | ||||
void Knob::onDragMove(Vec mouseRel) { | |||||
void Knob::onDragMove(EventDragMove &e) { | |||||
// Drag slower if Mod | // Drag slower if Mod | ||||
float delta = KNOB_SENSITIVITY * (maxValue - minValue) * -e.mouseRel.y; | |||||
if (guiIsModPressed()) | if (guiIsModPressed()) | ||||
mouseRel = mouseRel.mult(1/16.0); | |||||
dragValue += KNOB_SENSITIVITY * (maxValue - minValue) * -mouseRel.y; | |||||
delta /= 16.0; | |||||
dragValue += delta; | |||||
if (snap) | if (snap) | ||||
setValue(roundf(dragValue)); | setValue(roundf(dragValue)); | ||||
else | else | ||||
setValue(dragValue); | setValue(dragValue); | ||||
} | } | ||||
void Knob::onDragEnd() { | |||||
void Knob::onDragEnd(EventDragEnd &e) { | |||||
guiCursorUnlock(); | guiCursorUnlock(); | ||||
randomizable = true; | randomizable = true; | ||||
} | } | ||||
void Knob::onChange() { | |||||
void Knob::onChange(EventChange &e) { | |||||
if (!module) | if (!module) | ||||
return; | return; | ||||
@@ -6,7 +6,7 @@ namespace rack { | |||||
void LightWidget::draw(NVGcontext *vg) { | void LightWidget::draw(NVGcontext *vg) { | ||||
float radius = box.size.x / 2.0; | float radius = box.size.x / 2.0; | ||||
float oradius = radius + 20.0; | |||||
float oradius = radius + 15.0; | |||||
color.r = clampf(color.r, 0.0, 1.0); | color.r = clampf(color.r, 0.0, 1.0); | ||||
color.g = clampf(color.g, 0.0, 1.0); | color.g = clampf(color.g, 0.0, 1.0); | ||||
@@ -36,7 +36,7 @@ void LightWidget::draw(NVGcontext *vg) { | |||||
nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | ||||
NVGpaint paint; | NVGpaint paint; | ||||
NVGcolor icol = color; | NVGcolor icol = color; | ||||
icol.a *= 0.15; | |||||
icol.a *= 0.10; | |||||
NVGcolor ocol = color; | NVGcolor ocol = color; | ||||
ocol.a = 0.0; | ocol.a = 0.0; | ||||
paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); | paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); | ||||
@@ -165,7 +165,22 @@ void ModuleWidget::draw(NVGcontext *vg) { | |||||
nvgResetScissor(vg); | nvgResetScissor(vg); | ||||
} | } | ||||
Widget *ModuleWidget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
void ModuleWidget::onMouseDown(EventMouseDown &e) { | |||||
Widget::onMouseDown(e); | |||||
if (e.consumed) | |||||
return; | |||||
if (e.button == 1) { | |||||
createContextMenu(); | |||||
} | |||||
e.consumed = true; | |||||
e.target = this; | |||||
} | |||||
void ModuleWidget::onMouseMove(EventMouseMove &e) { | |||||
OpaqueWidget::onMouseMove(e); | |||||
// Don't delete the ModuleWidget if a TextField is focused | |||||
if (!gFocusedWidget) { | if (!gFocusedWidget) { | ||||
// Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget. | // Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget. | ||||
if (glfwGetKey(gWindow, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_BACKSPACE) == GLFW_PRESS) { | if (glfwGetKey(gWindow, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_BACKSPACE) == GLFW_PRESS) { | ||||
@@ -174,82 +189,85 @@ Widget *ModuleWidget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
this->finalizeEvents(); | this->finalizeEvents(); | ||||
delete this; | delete this; | ||||
// Kinda sketchy because events will be passed further down the tree | // Kinda sketchy because events will be passed further down the tree | ||||
return NULL; | |||||
return; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
return OpaqueWidget::onMouseMove(pos, mouseRel); | |||||
} | } | ||||
Widget *ModuleWidget::onHoverKey(Vec pos, int key) { | |||||
switch (key) { | |||||
void ModuleWidget::onHoverKey(EventHoverKey &e) { | |||||
switch (e.key) { | |||||
case GLFW_KEY_I: | case GLFW_KEY_I: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
reset(); | reset(); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
break; | break; | ||||
case GLFW_KEY_R: | case GLFW_KEY_R: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
randomize(); | randomize(); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
break; | break; | ||||
case GLFW_KEY_D: | case GLFW_KEY_D: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
gRackWidget->cloneModule(this); | gRackWidget->cloneModule(this); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
break; | break; | ||||
} | } | ||||
return Widget::onHoverKey(pos, key); | |||||
Widget::onHoverKey(e); | |||||
} | } | ||||
void ModuleWidget::onDragStart() { | |||||
void ModuleWidget::onDragStart(EventDragStart &e) { | |||||
dragPos = gRackWidget->lastMousePos.minus(box.pos); | dragPos = gRackWidget->lastMousePos.minus(box.pos); | ||||
} | } | ||||
void ModuleWidget::onDragMove(Vec mouseRel) { | |||||
void ModuleWidget::onDragEnd(EventDragEnd &e) { | |||||
} | |||||
void ModuleWidget::onDragMove(EventDragMove &e) { | |||||
Rect newBox = box; | Rect newBox = box; | ||||
newBox.pos = gRackWidget->lastMousePos.minus(dragPos); | newBox.pos = gRackWidget->lastMousePos.minus(dragPos); | ||||
gRackWidget->requestModuleBoxNearest(this, newBox); | gRackWidget->requestModuleBoxNearest(this, newBox); | ||||
} | } | ||||
void ModuleWidget::onDragEnd() { | |||||
} | |||||
struct DisconnectMenuItem : MenuItem { | struct DisconnectMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
moduleWidget->disconnect(); | moduleWidget->disconnect(); | ||||
} | } | ||||
}; | }; | ||||
struct ResetMenuItem : MenuItem { | struct ResetMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
moduleWidget->reset(); | moduleWidget->reset(); | ||||
} | } | ||||
}; | }; | ||||
struct RandomizeMenuItem : MenuItem { | struct RandomizeMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
moduleWidget->randomize(); | moduleWidget->randomize(); | ||||
} | } | ||||
}; | }; | ||||
struct CloneMenuItem : MenuItem { | struct CloneMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
gRackWidget->cloneModule(moduleWidget); | gRackWidget->cloneModule(moduleWidget); | ||||
} | } | ||||
}; | }; | ||||
struct DeleteMenuItem : MenuItem { | struct DeleteMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
gRackWidget->deleteModule(moduleWidget); | gRackWidget->deleteModule(moduleWidget); | ||||
moduleWidget->finalizeEvents(); | moduleWidget->finalizeEvents(); | ||||
delete moduleWidget; | delete moduleWidget; | ||||
@@ -295,11 +313,5 @@ Menu *ModuleWidget::createContextMenu() { | |||||
return menu; | return menu; | ||||
} | } | ||||
void ModuleWidget::onMouseDownOpaque(int button) { | |||||
if (button == 1) { | |||||
createContextMenu(); | |||||
} | |||||
} | |||||
} // namespace rack | } // namespace rack |
@@ -19,13 +19,15 @@ void ParamWidget::randomize() { | |||||
setValue(rescalef(randomf(), 0.0, 1.0, minValue, maxValue)); | setValue(rescalef(randomf(), 0.0, 1.0, minValue, maxValue)); | ||||
} | } | ||||
void ParamWidget::onMouseDownOpaque(int button) { | |||||
if (button == 1) { | |||||
void ParamWidget::onMouseDown(EventMouseDown &e) { | |||||
if (e.button == 1) { | |||||
setValue(defaultValue); | setValue(defaultValue); | ||||
} | } | ||||
e.consumed = true; | |||||
e.target = this; | |||||
} | } | ||||
void ParamWidget::onChange() { | |||||
void ParamWidget::onChange(EventChange &e) { | |||||
if (!module) | if (!module) | ||||
return; | return; | ||||
@@ -15,7 +15,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
Vec pos = Vec(0, 0); | Vec pos = Vec(0, 0); | ||||
struct RegisterButton : Button { | struct RegisterButton : Button { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
std::thread t(openBrowser, "https://vcvrack.com/"); | std::thread t(openBrowser, "https://vcvrack.com/"); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -46,7 +46,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
struct LogInButton : Button { | struct LogInButton : Button { | ||||
TextField *emailField; | TextField *emailField; | ||||
TextField *passwordField; | TextField *passwordField; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
std::thread t(pluginLogIn, emailField->text, passwordField->text); | std::thread t(pluginLogIn, emailField->text, passwordField->text); | ||||
t.detach(); | t.detach(); | ||||
passwordField->text = ""; | passwordField->text = ""; | ||||
@@ -79,7 +79,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
Vec pos = Vec(0, 0); | Vec pos = Vec(0, 0); | ||||
struct ManageButton : Button { | struct ManageButton : Button { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
std::thread t(openBrowser, "https://vcvrack.com/"); | std::thread t(openBrowser, "https://vcvrack.com/"); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -92,7 +92,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
pos.x += manageButton->box.size.x; | pos.x += manageButton->box.size.x; | ||||
struct RefreshButton : Button { | struct RefreshButton : Button { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
std::thread t(pluginRefresh); | std::thread t(pluginRefresh); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -106,7 +106,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
pos.x += refreshButton->box.size.x; | pos.x += refreshButton->box.size.x; | ||||
struct LogOutButton : Button { | struct LogOutButton : Button { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
pluginLogOut(); | pluginLogOut(); | ||||
} | } | ||||
}; | }; | ||||
@@ -142,7 +142,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
pos.x += downloadProgress->box.size.x; | pos.x += downloadProgress->box.size.x; | ||||
// struct CancelButton : Button { | // struct CancelButton : Button { | ||||
// void onAction() override { | |||||
// void onAction(EventAction &e) override { | |||||
// pluginCancelDownload(); | // pluginCancelDownload(); | ||||
// } | // } | ||||
// }; | // }; | ||||
@@ -17,23 +17,20 @@ void Port::draw(NVGcontext *vg) { | |||||
} | } | ||||
} | } | ||||
void Port::onMouseDownOpaque(int button) { | |||||
if (button == 1) { | |||||
void Port::onMouseDown(EventMouseDown &e) { | |||||
if (e.button == 1) { | |||||
gRackWidget->wireContainer->removeTopWire(this); | gRackWidget->wireContainer->removeTopWire(this); | ||||
// HACK | // HACK | ||||
// Update hovered*Port of active wire if applicable | // Update hovered*Port of active wire if applicable | ||||
onDragEnter(NULL); | |||||
EventDragEnter e; | |||||
onDragEnter(e); | |||||
} | } | ||||
e.consumed = true; | |||||
e.target = this; | |||||
} | } | ||||
void Port::onDragEnd() { | |||||
// FIXME | |||||
// If the source Port is deleted, this will be called, removing the cable | |||||
gRackWidget->wireContainer->commitActiveWire(); | |||||
} | |||||
void Port::onDragStart() { | |||||
void Port::onDragStart(EventDragStart &e) { | |||||
// Try to grab wire on top of stack | // Try to grab wire on top of stack | ||||
WireWidget *wire = gRackWidget->wireContainer->getTopWire(this); | WireWidget *wire = gRackWidget->wireContainer->getTopWire(this); | ||||
if (guiIsModPressed()) { | if (guiIsModPressed()) { | ||||
@@ -62,10 +59,16 @@ void Port::onDragStart() { | |||||
gRackWidget->wireContainer->setActiveWire(wire); | gRackWidget->wireContainer->setActiveWire(wire); | ||||
} | } | ||||
void Port::onDragDrop(Widget *origin) { | |||||
void Port::onDragEnd(EventDragEnd &e) { | |||||
// FIXME | |||||
// If the source Port is deleted, this will be called, removing the cable | |||||
gRackWidget->wireContainer->commitActiveWire(); | |||||
} | |||||
void Port::onDragDrop(EventDragDrop &e) { | |||||
} | } | ||||
void Port::onDragEnter(Widget *origin) { | |||||
void Port::onDragEnter(EventDragEnter &e) { | |||||
// Reject ports if this is an input port and something is already plugged into it | // Reject ports if this is an input port and something is already plugged into it | ||||
if (type == INPUT) { | if (type == INPUT) { | ||||
WireWidget *topWire = gRackWidget->wireContainer->getTopWire(this); | WireWidget *topWire = gRackWidget->wireContainer->getTopWire(this); | ||||
@@ -82,7 +85,7 @@ void Port::onDragEnter(Widget *origin) { | |||||
} | } | ||||
} | } | ||||
void Port::onDragLeave(Widget *origin) { | |||||
void Port::onDragLeave(EventDragEnter &e) { | |||||
WireWidget *activeWire = gRackWidget->wireContainer->activeWire; | WireWidget *activeWire = gRackWidget->wireContainer->activeWire; | ||||
if (activeWire) { | if (activeWire) { | ||||
if (type == INPUT) | if (type == INPUT) | ||||
@@ -82,39 +82,55 @@ void RackScene::draw(NVGcontext *vg) { | |||||
Scene::draw(vg); | Scene::draw(vg); | ||||
} | } | ||||
Widget *RackScene::onHoverKey(Vec pos, int key) { | |||||
switch (key) { | |||||
void RackScene::onHoverKey(EventHoverKey &e) { | |||||
switch (e.key) { | |||||
case GLFW_KEY_N: | case GLFW_KEY_N: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
gRackWidget->reset(); | gRackWidget->reset(); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
break; | break; | ||||
case GLFW_KEY_Q: | case GLFW_KEY_Q: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
guiClose(); | guiClose(); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
break; | break; | ||||
case GLFW_KEY_O: | case GLFW_KEY_O: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
gRackWidget->openDialog(); | gRackWidget->openDialog(); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
break; | break; | ||||
case GLFW_KEY_S: | case GLFW_KEY_S: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
gRackWidget->saveDialog(); | gRackWidget->saveDialog(); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
if (guiIsModPressed() && guiIsShiftPressed()) { | if (guiIsModPressed() && guiIsShiftPressed()) { | ||||
gRackWidget->saveAsDialog(); | gRackWidget->saveAsDialog(); | ||||
return this; | |||||
e.consumed = true; | |||||
return; | |||||
} | } | ||||
break; | break; | ||||
} | } | ||||
return Widget::onHoverKey(pos, key); | |||||
Widget::onHoverKey(e); | |||||
} | |||||
void RackScene::onPathDrop(EventPathDrop &e) { | |||||
if (e.paths.size() >= 1) { | |||||
const std::string& firstPath = e.paths.front(); | |||||
if (extractExtension(firstPath) == "vcv") { | |||||
gRackWidget->loadPatch(firstPath); | |||||
e.consumed = true; | |||||
} | |||||
} | |||||
} | } | ||||
@@ -375,7 +375,7 @@ void RackWidget::draw(NVGcontext *vg) { | |||||
struct AddModuleMenuItem : MenuItem { | struct AddModuleMenuItem : MenuItem { | ||||
Model *model; | Model *model; | ||||
Vec modulePos; | Vec modulePos; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
ModuleWidget *moduleWidget = model->createModuleWidget(); | ModuleWidget *moduleWidget = model->createModuleWidget(); | ||||
gRackWidget->moduleContainer->addChild(moduleWidget); | gRackWidget->moduleContainer->addChild(moduleWidget); | ||||
// Move module nearest to the mouse position | // Move module nearest to the mouse position | ||||
@@ -388,7 +388,7 @@ struct AddModuleMenuItem : MenuItem { | |||||
struct UrlItem : MenuItem { | struct UrlItem : MenuItem { | ||||
std::string url; | std::string url; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
std::thread t(openBrowser, url); | std::thread t(openBrowser, url); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -487,13 +487,17 @@ struct SearchModuleField : TextField { | |||||
} | } | ||||
}; | }; | ||||
Widget *RackWidget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
lastMousePos = pos; | |||||
return OpaqueWidget::onMouseMove(pos, mouseRel); | |||||
void RackWidget::onMouseMove(EventMouseMove &e) { | |||||
OpaqueWidget::onMouseMove(e); | |||||
lastMousePos = e.pos; | |||||
} | } | ||||
void RackWidget::onMouseDownOpaque(int button) { | |||||
if (button == 1) { | |||||
void RackWidget::onMouseDown(EventMouseDown &e) { | |||||
Widget::onMouseDown(e); | |||||
if (e.consumed) | |||||
return; | |||||
if (e.button == 1) { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->pushChild(construct<MenuLabel>(&MenuLabel::text, "Add module")); | menu->pushChild(construct<MenuLabel>(&MenuLabel::text, "Add module")); | ||||
@@ -519,15 +523,17 @@ void RackWidget::onMouseDownOpaque(int button) { | |||||
AddManufacturerMenuItem *item = new AddManufacturerMenuItem(); | AddManufacturerMenuItem *item = new AddManufacturerMenuItem(); | ||||
item->text = manufacturerName; | item->text = manufacturerName; | ||||
item->manufacturerName = manufacturerName; | item->manufacturerName = manufacturerName; | ||||
item->modulePos = lastMousePos; | |||||
item->modulePos = e.pos; | |||||
menu->pushChild(item); | menu->pushChild(item); | ||||
} | } | ||||
} | } | ||||
e.consumed = true; | |||||
e.target = this; | |||||
} | } | ||||
void RackWidget::onZoom() { | |||||
void RackWidget::onZoom(EventZoom &e) { | |||||
rails->box.size = Vec(); | rails->box.size = Vec(); | ||||
Widget::onZoom(); | |||||
Widget::onZoom(e); | |||||
} | } | ||||
@@ -35,9 +35,9 @@ void SVGKnob::step() { | |||||
FramebufferWidget::step(); | FramebufferWidget::step(); | ||||
} | } | ||||
void SVGKnob::onChange() { | |||||
void SVGKnob::onChange(EventChange &e) { | |||||
dirty = true; | dirty = true; | ||||
Knob::onChange(); | |||||
Knob::onChange(e); | |||||
} | } | ||||
@@ -21,9 +21,9 @@ void SVGSlider::step() { | |||||
FramebufferWidget::step(); | FramebufferWidget::step(); | ||||
} | } | ||||
void SVGSlider::onChange() { | |||||
void SVGSlider::onChange(EventChange &e) { | |||||
dirty = true; | dirty = true; | ||||
ParamWidget::onChange(); | |||||
ParamWidget::onChange(e); | |||||
} | } | ||||
@@ -22,12 +22,12 @@ void SVGSwitch::step() { | |||||
FramebufferWidget::step(); | FramebufferWidget::step(); | ||||
} | } | ||||
void SVGSwitch::onChange() { | |||||
void SVGSwitch::onChange(EventChange &e) { | |||||
assert(frames.size() > 0); | assert(frames.size() > 0); | ||||
int index = clampi((int) roundf(value), 0, frames.size() - 1); | int index = clampi((int) roundf(value), 0, frames.size() - 1); | ||||
sw->setSVG(frames[index]); | sw->setSVG(frames[index]); | ||||
dirty = true; | dirty = true; | ||||
Switch::onChange(); | |||||
Switch::onChange(e); | |||||
} | } | ||||
@@ -7,37 +7,37 @@ namespace rack { | |||||
struct NewItem : MenuItem { | struct NewItem : MenuItem { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
gRackWidget->reset(); | gRackWidget->reset(); | ||||
} | } | ||||
}; | }; | ||||
struct OpenItem : MenuItem { | struct OpenItem : MenuItem { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
gRackWidget->openDialog(); | gRackWidget->openDialog(); | ||||
} | } | ||||
}; | }; | ||||
struct SaveItem : MenuItem { | struct SaveItem : MenuItem { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
gRackWidget->saveDialog(); | gRackWidget->saveDialog(); | ||||
} | } | ||||
}; | }; | ||||
struct SaveAsItem : MenuItem { | struct SaveAsItem : MenuItem { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
gRackWidget->saveAsDialog(); | gRackWidget->saveAsDialog(); | ||||
} | } | ||||
}; | }; | ||||
struct QuitItem : MenuItem { | struct QuitItem : MenuItem { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
guiClose(); | guiClose(); | ||||
} | } | ||||
}; | }; | ||||
struct FileChoice : ChoiceButton { | struct FileChoice : ChoiceButton { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)); | menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -54,21 +54,21 @@ struct FileChoice : ChoiceButton { | |||||
struct PauseItem : MenuItem { | struct PauseItem : MenuItem { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
gPaused = !gPaused; | gPaused = !gPaused; | ||||
} | } | ||||
}; | }; | ||||
struct SampleRateItem : MenuItem { | struct SampleRateItem : MenuItem { | ||||
float sampleRate; | float sampleRate; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
engineSetSampleRate(sampleRate); | engineSetSampleRate(sampleRate); | ||||
gPaused = false; | gPaused = false; | ||||
} | } | ||||
}; | }; | ||||
struct SampleRateChoice : ChoiceButton { | struct SampleRateChoice : ChoiceButton { | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)); | menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -149,8 +149,8 @@ Toolbar::Toolbar() { | |||||
xPos += margin; | xPos += margin; | ||||
{ | { | ||||
struct ZoomSlider : Slider { | struct ZoomSlider : Slider { | ||||
void onAction() override { | |||||
Slider::onAction(); | |||||
void onAction(EventAction &e) override { | |||||
Slider::onAction(e); | |||||
gRackScene->zoomWidget->setZoom(value / 100.0); | gRackScene->zoomWidget->setZoom(value / 100.0); | ||||
} | } | ||||
}; | }; | ||||
@@ -9,6 +9,11 @@ | |||||
#include <pwd.h> | #include <pwd.h> | ||||
#endif | #endif | ||||
#if ARCH_WIN | |||||
#include <Windows.h> | |||||
#include <Shlobj.h> | |||||
#endif | |||||
namespace rack { | namespace rack { | ||||
@@ -76,9 +81,14 @@ std::string assetLocal(std::string filename) { | |||||
path += "/" + filename; | path += "/" + filename; | ||||
#endif | #endif | ||||
#if ARCH_WIN | #if ARCH_WIN | ||||
// TODO | |||||
// Use ~/My Documents/Rack or something | |||||
path = "./" + filename; | |||||
// Get My Documents folder | |||||
char buf[MAX_PATH]; | |||||
HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, buf); | |||||
assert(result == S_OK); | |||||
path = buf; | |||||
path += "/Rack"; | |||||
CreateDirectory(path.c_str(), NULL); | |||||
path += "/" + filename; | |||||
#endif | #endif | ||||
#if ARCH_LIN | #if ARCH_LIN | ||||
// TODO | // TODO | ||||
@@ -326,14 +326,14 @@ void AudioInterface::closeDevice() { | |||||
struct AudioItem : MenuItem { | struct AudioItem : MenuItem { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
int deviceId; | int deviceId; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
audioInterface->setDeviceId(deviceId); | audioInterface->setDeviceId(deviceId); | ||||
} | } | ||||
}; | }; | ||||
struct AudioChoice : ChoiceButton { | struct AudioChoice : ChoiceButton { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); | menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -364,14 +364,14 @@ struct AudioChoice : ChoiceButton { | |||||
struct SampleRateItem : MenuItem { | struct SampleRateItem : MenuItem { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
float sampleRate; | float sampleRate; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
audioInterface->setSampleRate(sampleRate); | audioInterface->setSampleRate(sampleRate); | ||||
} | } | ||||
}; | }; | ||||
struct SampleRateChoice : ChoiceButton { | struct SampleRateChoice : ChoiceButton { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); | menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -395,14 +395,14 @@ struct SampleRateChoice : ChoiceButton { | |||||
struct BlockSizeItem : MenuItem { | struct BlockSizeItem : MenuItem { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
int blockSize; | int blockSize; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
audioInterface->setBlockSize(blockSize); | audioInterface->setBlockSize(blockSize); | ||||
} | } | ||||
}; | }; | ||||
struct BlockSizeChoice : ChoiceButton { | struct BlockSizeChoice : ChoiceButton { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
void onAction() override { | |||||
void onAction(EventAction &e) override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); | menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round(); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -10,20 +10,21 @@ struct ModuleResizeHandle : Widget { | |||||
ModuleResizeHandle() { | ModuleResizeHandle() { | ||||
box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); | box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); | ||||
} | } | ||||
Widget *onMouseDown(Vec pos, int button) override { | |||||
if (button == 0) | |||||
return this; | |||||
return NULL; | |||||
void onMouseDown(EventMouseDown &e) override { | |||||
if (e.button == 0) { | |||||
e.consumed = true; | |||||
e.target = this; | |||||
} | |||||
} | } | ||||
void onDragStart() override { | |||||
void onDragStart(EventDragStart &e) override { | |||||
assert(parent); | assert(parent); | ||||
originalWidth = parent->box.size.x; | originalWidth = parent->box.size.x; | ||||
totalX = 0.0; | totalX = 0.0; | ||||
} | } | ||||
void onDragMove(Vec mouseRel) override { | |||||
void onDragMove(EventDragMove &e) override { | |||||
ModuleWidget *m = dynamic_cast<ModuleWidget*>(parent); | ModuleWidget *m = dynamic_cast<ModuleWidget*>(parent); | ||||
assert(m); | assert(m); | ||||
totalX += mouseRel.x; | |||||
totalX += e.mouseRel.x; | |||||
float targetWidth = originalWidth; | float targetWidth = originalWidth; | ||||
if (right) | if (right) | ||||
targetWidth += totalX; | targetWidth += totalX; | ||||
@@ -41,8 +41,8 @@ float Light::getBrightness() { | |||||
void Light::setBrightnessSmooth(float brightness) { | void Light::setBrightnessSmooth(float brightness) { | ||||
float v = brightness * brightness; | float v = brightness * brightness; | ||||
if (v < value) { | if (v < value) { | ||||
// Fade out light with lambda = 3 * framerate | |||||
value += (v - value) * sampleTime * (60.0 * 3.0); | |||||
// Fade out light with lambda = 2 * framerate | |||||
value += (v - value) * sampleTime * (60.0 * 2.0); | |||||
} | } | ||||
else { | else { | ||||
// Immediately illuminate light | // Immediately illuminate light | ||||
@@ -54,25 +54,36 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { | |||||
#endif | #endif | ||||
if (action == GLFW_PRESS) { | if (action == GLFW_PRESS) { | ||||
Widget *w = NULL; | |||||
// onMouseDown | // onMouseDown | ||||
Widget *w = gScene->onMouseDown(gMousePos, button); | |||||
{ | |||||
EventMouseDown e; | |||||
e.pos = gMousePos; | |||||
e.button = button; | |||||
gScene->onMouseDown(e); | |||||
w = e.target; | |||||
} | |||||
if (button == GLFW_MOUSE_BUTTON_LEFT) { | if (button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
if (w) { | if (w) { | ||||
// onDragStart | // onDragStart | ||||
w->onDragStart(); | |||||
EventDragStart e; | |||||
w->onDragStart(e); | |||||
} | } | ||||
gDraggedWidget = w; | gDraggedWidget = w; | ||||
if (w != gFocusedWidget) { | if (w != gFocusedWidget) { | ||||
if (gFocusedWidget) { | if (gFocusedWidget) { | ||||
// onDefocus | // onDefocus | ||||
w->onDefocus(); | |||||
EventDefocus e; | |||||
w->onDefocus(e); | |||||
} | } | ||||
gFocusedWidget = NULL; | gFocusedWidget = NULL; | ||||
if (w) { | if (w) { | ||||
// onFocus | // onFocus | ||||
if (w->onFocus()) { | |||||
EventFocus e; | |||||
w->onFocus(e); | |||||
if (e.consumed) { | |||||
gFocusedWidget = w; | gFocusedWidget = w; | ||||
} | } | ||||
} | } | ||||
@@ -81,17 +92,27 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { | |||||
} | } | ||||
else if (action == GLFW_RELEASE) { | else if (action == GLFW_RELEASE) { | ||||
// onMouseUp | // onMouseUp | ||||
Widget *w = gScene->onMouseUp(gMousePos, button); | |||||
Widget *w = NULL; | |||||
{ | |||||
EventMouseUp e; | |||||
e.pos = gMousePos; | |||||
e.button = button; | |||||
gScene->onMouseUp(e); | |||||
w = e.target; | |||||
} | |||||
if (button == GLFW_MOUSE_BUTTON_LEFT) { | if (button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
if (gDraggedWidget) { | if (gDraggedWidget) { | ||||
// onDragDrop | // onDragDrop | ||||
w->onDragDrop(gDraggedWidget); | |||||
EventDragDrop e; | |||||
e.origin = gDraggedWidget; | |||||
w->onDragDrop(e); | |||||
} | } | ||||
// gDraggedWidget might have been set to null in the last event, recheck here | // gDraggedWidget might have been set to null in the last event, recheck here | ||||
if (gDraggedWidget) { | if (gDraggedWidget) { | ||||
// onDragEnd | // onDragEnd | ||||
gDraggedWidget->onDragEnd(); | |||||
EventDragEnd e; | |||||
gDraggedWidget->onDragEnd(e); | |||||
} | } | ||||
gDraggedWidget = NULL; | gDraggedWidget = NULL; | ||||
gDragHoveredWidget = NULL; | gDragHoveredWidget = NULL; | ||||
@@ -141,19 +162,32 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||||
gMousePos = mousePos; | gMousePos = mousePos; | ||||
Widget *hovered = NULL; | |||||
// onMouseMove | // onMouseMove | ||||
Widget *hovered = gScene->onMouseMove(gMousePos, mouseRel); | |||||
{ | |||||
EventMouseMove e; | |||||
e.pos = mousePos; | |||||
e.mouseRel = mouseRel; | |||||
gScene->onMouseMove(e); | |||||
hovered = e.target; | |||||
} | |||||
if (gDraggedWidget) { | if (gDraggedWidget) { | ||||
// onDragMove | // onDragMove | ||||
gDraggedWidget->onDragMove(mouseRel); | |||||
EventDragMove e; | |||||
e.mouseRel = mouseRel; | |||||
gDraggedWidget->onDragMove(e); | |||||
if (hovered != gDragHoveredWidget) { | if (hovered != gDragHoveredWidget) { | ||||
if (gDragHoveredWidget) { | if (gDragHoveredWidget) { | ||||
gDragHoveredWidget->onDragLeave(gDraggedWidget); | |||||
EventDragEnter e; | |||||
e.origin = gDraggedWidget; | |||||
gDragHoveredWidget->onDragLeave(e); | |||||
} | } | ||||
if (hovered) { | if (hovered) { | ||||
hovered->onDragEnter(gDraggedWidget); | |||||
EventDragEnter e; | |||||
e.origin = gDraggedWidget; | |||||
hovered->onDragEnter(e); | |||||
} | } | ||||
gDragHoveredWidget = hovered; | gDragHoveredWidget = hovered; | ||||
} | } | ||||
@@ -162,11 +196,13 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||||
if (hovered != gHoveredWidget) { | if (hovered != gHoveredWidget) { | ||||
if (gHoveredWidget) { | if (gHoveredWidget) { | ||||
// onMouseLeave | // onMouseLeave | ||||
gHoveredWidget->onMouseLeave(); | |||||
EventMouseLeave e; | |||||
gHoveredWidget->onMouseLeave(e); | |||||
} | } | ||||
if (hovered) { | if (hovered) { | ||||
// onMouseEnter | |||||
hovered->onMouseEnter(); | |||||
// onMouseEnter | |||||
EventMouseEnter e; | |||||
hovered->onMouseEnter(e); | |||||
} | } | ||||
gHoveredWidget = hovered; | gHoveredWidget = hovered; | ||||
} | } | ||||
@@ -174,14 +210,19 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||||
if (glfwGetMouseButton(gWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) { | if (glfwGetMouseButton(gWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) { | ||||
// TODO | // TODO | ||||
// Define a new global called gScrollWidget, which remembers the widget where middle-click was first pressed | // Define a new global called gScrollWidget, which remembers the widget where middle-click was first pressed | ||||
gScene->onScroll(mousePos, mouseRel); | |||||
EventScroll e; | |||||
e.pos = mousePos; | |||||
e.scrollRel = mouseRel; | |||||
gScene->onScroll(e); | |||||
} | } | ||||
} | } | ||||
void cursorEnterCallback(GLFWwindow* window, int entered) { | void cursorEnterCallback(GLFWwindow* window, int entered) { | ||||
if (!entered) { | if (!entered) { | ||||
if (gHoveredWidget) { | if (gHoveredWidget) { | ||||
gHoveredWidget->onMouseLeave(); | |||||
// onMouseLeave | |||||
EventMouseLeave e; | |||||
gHoveredWidget->onMouseLeave(e); | |||||
} | } | ||||
gHoveredWidget = NULL; | gHoveredWidget = NULL; | ||||
} | } | ||||
@@ -194,23 +235,47 @@ void scrollCallback(GLFWwindow *window, double x, double y) { | |||||
scrollRel = Vec(y, x); | scrollRel = Vec(y, x); | ||||
#endif | #endif | ||||
// onScroll | // onScroll | ||||
gScene->onScroll(gMousePos, scrollRel.mult(50.0)); | |||||
EventScroll e; | |||||
e.pos = gMousePos; | |||||
e.scrollRel = scrollRel.mult(50.0); | |||||
gScene->onScroll(e); | |||||
} | } | ||||
void charCallback(GLFWwindow *window, unsigned int codepoint) { | void charCallback(GLFWwindow *window, unsigned int codepoint) { | ||||
if (gFocusedWidget) { | if (gFocusedWidget) { | ||||
gFocusedWidget->onFocusText(codepoint); | |||||
// onText | |||||
EventText e; | |||||
e.codepoint = codepoint; | |||||
gFocusedWidget->onText(e); | |||||
} | } | ||||
} | } | ||||
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { | |||||
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) { | |||||
if (action == GLFW_PRESS || action == GLFW_REPEAT) { | if (action == GLFW_PRESS || action == GLFW_REPEAT) { | ||||
// onFocusKey | |||||
if (gFocusedWidget && gFocusedWidget->onFocusKey(key)) | |||||
return; | |||||
if (gFocusedWidget) { | |||||
// onKey | |||||
EventKey e; | |||||
e.key = key; | |||||
gFocusedWidget->onKey(e); | |||||
if (e.consumed) | |||||
return; | |||||
} | |||||
// onHoverKey | // onHoverKey | ||||
gScene->onHoverKey(gMousePos, key); | |||||
EventHoverKey e; | |||||
e.pos = gMousePos; | |||||
e.key = key; | |||||
gScene->onHoverKey(e); | |||||
} | |||||
} | |||||
void dropCallback(GLFWwindow *window, int count, const char **paths) { | |||||
// onPathDrop | |||||
EventPathDrop e; | |||||
e.pos = gMousePos; | |||||
for (int i = 0; i < count; i++) { | |||||
e.paths.push_back(paths[i]); | |||||
} | } | ||||
gScene->onPathDrop(e); | |||||
} | } | ||||
void errorCallback(int error, const char *description) { | void errorCallback(int error, const char *description) { | ||||
@@ -272,6 +337,7 @@ void guiInit() { | |||||
glfwSetScrollCallback(gWindow, scrollCallback); | glfwSetScrollCallback(gWindow, scrollCallback); | ||||
glfwSetCharCallback(gWindow, charCallback); | glfwSetCharCallback(gWindow, charCallback); | ||||
glfwSetKeyCallback(gWindow, keyCallback); | glfwSetKeyCallback(gWindow, keyCallback); | ||||
glfwSetDropCallback(gWindow, dropCallback); | |||||
// Set up GLEW | // Set up GLEW | ||||
glewExperimental = GL_TRUE; | glewExperimental = GL_TRUE; | ||||
@@ -10,9 +10,15 @@ | |||||
using namespace rack; | using namespace rack; | ||||
int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||
char *cwd = getcwd(NULL, 0); | |||||
printf("Current working directory is %s\n", cwd); | |||||
free(cwd); | |||||
{ | |||||
char *cwd = getcwd(NULL, 0); | |||||
printf("Current working directory: %s\n", cwd); | |||||
free(cwd); | |||||
std::string globalDir = assetGlobal(""); | |||||
std::string localDir = assetLocal(""); | |||||
printf("Global directory: %s\n", globalDir.c_str()); | |||||
printf("Local directory: %s\n", localDir.c_str()); | |||||
} | |||||
pluginInit(); | pluginInit(); | ||||
engineInit(); | engineInit(); | ||||
@@ -7,25 +7,26 @@ void Button::draw(NVGcontext *vg) { | |||||
bndToolButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | bndToolButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | ||||
} | } | ||||
void Button::onMouseEnter() { | |||||
void Button::onMouseEnter(EventMouseEnter &e) { | |||||
state = BND_HOVER; | state = BND_HOVER; | ||||
} | } | ||||
void Button::onMouseLeave() { | |||||
void Button::onMouseLeave(EventMouseLeave &e) { | |||||
state = BND_DEFAULT; | state = BND_DEFAULT; | ||||
} | } | ||||
void Button::onDragStart() { | |||||
void Button::onDragStart(EventDragStart &e) { | |||||
state = BND_ACTIVE; | state = BND_ACTIVE; | ||||
} | } | ||||
void Button::onDragEnd() { | |||||
void Button::onDragEnd(EventDragEnd &e) { | |||||
state = BND_HOVER; | state = BND_HOVER; | ||||
} | } | ||||
void Button::onDragDrop(Widget *origin) { | |||||
if (origin == this) { | |||||
onAction(); | |||||
void Button::onDragDrop(EventDragDrop &e) { | |||||
if (e.origin == this) { | |||||
EventAction eAction; | |||||
onAction(eAction); | |||||
} | } | ||||
} | } | ||||
@@ -117,7 +117,7 @@ int FramebufferWidget::getImageHandle() { | |||||
return internal->fb->image; | return internal->fb->image; | ||||
} | } | ||||
void FramebufferWidget::onZoom() { | |||||
void FramebufferWidget::onZoom(EventZoom &e) { | |||||
dirty = true; | dirty = true; | ||||
} | } | ||||
@@ -52,12 +52,12 @@ void Menu::draw(NVGcontext *vg) { | |||||
} | } | ||||
bool Menu::onScrollOpaque(Vec scrollRel) { | |||||
void Menu::onScroll(EventScroll &e) { | |||||
if (!parent) | if (!parent) | ||||
return true; | |||||
return; | |||||
if (!parent->box.contains(box)) | if (!parent->box.contains(box)) | ||||
box.pos = box.pos.plus(scrollRel); | |||||
return true; | |||||
box.pos = box.pos.plus(e.scrollRel); | |||||
e.consumed = true; | |||||
} | } | ||||
@@ -22,7 +22,7 @@ void MenuItem::draw(NVGcontext *vg) { | |||||
bndIconLabelValue(vg, x, 0.0, box.size.x, box.size.y, -1, rightColor, BND_LEFT, BND_LABEL_FONT_SIZE, rightText.c_str(), NULL); | bndIconLabelValue(vg, x, 0.0, box.size.x, box.size.y, -1, rightColor, BND_LEFT, BND_LABEL_FONT_SIZE, rightText.c_str(), NULL); | ||||
} | } | ||||
void MenuItem::onMouseEnter() { | |||||
void MenuItem::onMouseEnter(EventMouseEnter &e) { | |||||
Menu *parentMenu = dynamic_cast<Menu*>(parent); | Menu *parentMenu = dynamic_cast<Menu*>(parent); | ||||
if (!parentMenu) | if (!parentMenu) | ||||
return; | return; | ||||
@@ -38,11 +38,12 @@ void MenuItem::onMouseEnter() { | |||||
parentMenu->setChildMenu(childMenu); | parentMenu->setChildMenu(childMenu); | ||||
} | } | ||||
void MenuItem::onDragDrop(Widget *origin) { | |||||
if (origin != this) | |||||
void MenuItem::onDragDrop(EventDragDrop &e) { | |||||
if (e.origin != this) | |||||
return; | return; | ||||
onAction(); | |||||
EventAction eAction; | |||||
onAction(eAction); | |||||
// deletes `this` | // deletes `this` | ||||
gScene->setOverlay(NULL); | gScene->setOverlay(NULL); | ||||
} | } | ||||
@@ -3,18 +3,22 @@ | |||||
namespace rack { | namespace rack { | ||||
void MenuOverlay::onDragDrop(Widget *origin) { | |||||
if (origin == this) { | |||||
void MenuOverlay::onDragDrop(EventDragDrop &e) { | |||||
if (e.origin == this) { | |||||
// deletes `this` | // deletes `this` | ||||
gScene->setOverlay(NULL); | gScene->setOverlay(NULL); | ||||
} | } | ||||
} | } | ||||
Widget *MenuOverlay::onHoverKey(Vec pos, int key) { | |||||
Widget *w = Widget::onHoverKey(pos, key); | |||||
if (w) return w; | |||||
// Steal all keys | |||||
return this; | |||||
void MenuOverlay::onScroll(EventScroll &e) { | |||||
// Don't recurse children, consume the event | |||||
e.consumed = true; | |||||
} | |||||
void MenuOverlay::onHoverKey(EventHoverKey &e) { | |||||
// Recurse children but consume the event | |||||
Widget::onHoverKey(e); | |||||
e.consumed = true; | |||||
} | } | ||||
@@ -4,12 +4,14 @@ | |||||
namespace rack { | namespace rack { | ||||
QuantityWidget::QuantityWidget() { | QuantityWidget::QuantityWidget() { | ||||
onChange(); | |||||
EventChange e; | |||||
onChange(e); | |||||
} | } | ||||
void QuantityWidget::setValue(float value) { | void QuantityWidget::setValue(float value) { | ||||
this->value = clampf(value, fminf(minValue, maxValue), fmaxf(minValue, maxValue)); | this->value = clampf(value, fminf(minValue, maxValue), fmaxf(minValue, maxValue)); | ||||
onChange(); | |||||
EventChange e; | |||||
onChange(e); | |||||
} | } | ||||
void QuantityWidget::setLimits(float minValue, float maxValue) { | void QuantityWidget::setLimits(float minValue, float maxValue) { | ||||
@@ -7,22 +7,23 @@ void RadioButton::draw(NVGcontext *vg) { | |||||
bndRadioButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, value == 0.0 ? state : BND_ACTIVE, -1, label.c_str()); | bndRadioButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, value == 0.0 ? state : BND_ACTIVE, -1, label.c_str()); | ||||
} | } | ||||
void RadioButton::onMouseEnter() { | |||||
void RadioButton::onMouseEnter(EventMouseEnter &e) { | |||||
state = BND_HOVER; | state = BND_HOVER; | ||||
} | } | ||||
void RadioButton::onMouseLeave() { | |||||
void RadioButton::onMouseLeave(EventMouseLeave &e) { | |||||
state = BND_DEFAULT; | state = BND_DEFAULT; | ||||
} | } | ||||
void RadioButton::onDragDrop(Widget *origin) { | |||||
if (origin == this) { | |||||
void RadioButton::onDragDrop(EventDragDrop &e) { | |||||
if (e.origin == this) { | |||||
if (value == 0.0) | if (value == 0.0) | ||||
value = 1.0; | value = 1.0; | ||||
else | else | ||||
value = 0.0; | value = 0.0; | ||||
onAction(); | |||||
EventAction eAction; | |||||
onAction(eAction); | |||||
} | } | ||||
} | } | ||||
@@ -19,21 +19,21 @@ void ScrollBar::draw(NVGcontext *vg) { | |||||
bndScrollBar(vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size); | bndScrollBar(vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size); | ||||
} | } | ||||
void ScrollBar::onDragStart() { | |||||
void ScrollBar::onDragStart(EventDragStart &e) { | |||||
state = BND_ACTIVE; | state = BND_ACTIVE; | ||||
guiCursorLock(); | guiCursorLock(); | ||||
} | } | ||||
void ScrollBar::onDragMove(Vec mouseRel) { | |||||
void ScrollBar::onDragMove(EventDragMove &e) { | |||||
ScrollWidget *scrollWidget = dynamic_cast<ScrollWidget*>(parent); | ScrollWidget *scrollWidget = dynamic_cast<ScrollWidget*>(parent); | ||||
assert(scrollWidget); | assert(scrollWidget); | ||||
if (orientation == HORIZONTAL) | if (orientation == HORIZONTAL) | ||||
scrollWidget->offset.x += mouseRel.x; | |||||
scrollWidget->offset.x += e.mouseRel.x; | |||||
else | else | ||||
scrollWidget->offset.y += mouseRel.y; | |||||
scrollWidget->offset.y += e.mouseRel.y; | |||||
} | } | ||||
void ScrollBar::onDragEnd() { | |||||
void ScrollBar::onDragEnd(EventDragEnd &e) { | |||||
state = BND_DEFAULT; | state = BND_DEFAULT; | ||||
guiCursorUnlock(); | guiCursorUnlock(); | ||||
} | } | ||||
@@ -58,9 +58,9 @@ void ScrollWidget::step() { | |||||
Widget::step(); | Widget::step(); | ||||
} | } | ||||
bool ScrollWidget::onScrollOpaque(Vec scrollRel) { | |||||
offset = offset.minus(scrollRel); | |||||
return true; | |||||
void ScrollWidget::onScroll(EventScroll &e) { | |||||
offset = offset.minus(e.scrollRel); | |||||
e.consumed = true; | |||||
} | } | ||||
@@ -11,26 +11,30 @@ void Slider::draw(NVGcontext *vg) { | |||||
bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, getText().c_str(), NULL); | bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, getText().c_str(), NULL); | ||||
} | } | ||||
void Slider::onDragStart() { | |||||
void Slider::onDragStart(EventDragStart &e) { | |||||
state = BND_ACTIVE; | state = BND_ACTIVE; | ||||
guiCursorLock(); | guiCursorLock(); | ||||
} | } | ||||
void Slider::onDragMove(Vec mouseRel) { | |||||
setValue(value + SLIDER_SENSITIVITY * (maxValue - minValue) * mouseRel.x); | |||||
void Slider::onDragMove(EventDragMove &e) { | |||||
setValue(value + SLIDER_SENSITIVITY * (maxValue - minValue) * e.mouseRel.x); | |||||
} | } | ||||
void Slider::onDragEnd() { | |||||
void Slider::onDragEnd(EventDragEnd &e) { | |||||
state = BND_DEFAULT; | state = BND_DEFAULT; | ||||
guiCursorUnlock(); | guiCursorUnlock(); | ||||
onAction(); | |||||
EventAction eAction; | |||||
onAction(eAction); | |||||
} | } | ||||
void Slider::onMouseDownOpaque(int button) { | |||||
if (button == 1) { | |||||
void Slider::onMouseDown(EventMouseDown &e) { | |||||
if (e.button == 1) { | |||||
setValue(defaultValue); | setValue(defaultValue); | ||||
onAction(); | |||||
EventAction eAction; | |||||
onAction(eAction); | |||||
} | } | ||||
e.consumed = true; | |||||
e.target = this; | |||||
} | } | ||||
@@ -24,21 +24,25 @@ void TextField::draw(NVGcontext *vg) { | |||||
} | } | ||||
} | } | ||||
Widget *TextField::onMouseDown(Vec pos, int button) { | |||||
end = begin = bndTextFieldTextPosition(gVg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), pos.x, pos.y); | |||||
return OpaqueWidget::onMouseDown(pos, button); | |||||
void TextField::onMouseDown(EventMouseDown &e) { | |||||
end = begin = bndTextFieldTextPosition(gVg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), e.pos.x, e.pos.y); | |||||
OpaqueWidget::onMouseDown(e); | |||||
} | } | ||||
void TextField::onFocus(EventFocus &e) { | |||||
begin = 0; | |||||
end = text.size(); | |||||
e.consumed = true; | |||||
} | |||||
bool TextField::onFocusText(int codepoint) { | |||||
char c = codepoint; | |||||
std::string newText(1, c); | |||||
void TextField::onText(EventText &e) { | |||||
std::string newText(1, (char) e.codepoint); | |||||
insertText(newText); | insertText(newText); | ||||
return true; | |||||
e.consumed = true; | |||||
} | } | ||||
bool TextField::onFocusKey(int key) { | |||||
switch (key) { | |||||
void TextField::onKey(EventKey &e) { | |||||
switch (e.key) { | |||||
case GLFW_KEY_BACKSPACE: | case GLFW_KEY_BACKSPACE: | ||||
if (begin < end) { | if (begin < end) { | ||||
text.erase(begin, end - begin); | text.erase(begin, end - begin); | ||||
@@ -107,20 +111,15 @@ bool TextField::onFocusKey(int key) { | |||||
insertText("\n"); | insertText("\n"); | ||||
} | } | ||||
else { | else { | ||||
onAction(); | |||||
EventAction e; | |||||
onAction(e); | |||||
} | } | ||||
break; | break; | ||||
} | } | ||||
begin = mini(maxi(begin, 0), text.size()); | begin = mini(maxi(begin, 0), text.size()); | ||||
end = mini(maxi(end, 0), text.size()); | end = mini(maxi(end, 0), text.size()); | ||||
return true; | |||||
} | |||||
bool TextField::onFocus() { | |||||
begin = 0; | |||||
end = text.size(); | |||||
return true; | |||||
e.consumed = true; | |||||
} | } | ||||
void TextField::insertText(std::string newText) { | void TextField::insertText(std::string newText) { | ||||
@@ -78,18 +78,21 @@ void Widget::clearChildren() { | |||||
void Widget::finalizeEvents() { | void Widget::finalizeEvents() { | ||||
// Stop dragging and hovering this widget | // Stop dragging and hovering this widget | ||||
if (gHoveredWidget == this) { | if (gHoveredWidget == this) { | ||||
gHoveredWidget->onMouseLeave(); | |||||
EventMouseLeave e; | |||||
gHoveredWidget->onMouseLeave(e); | |||||
gHoveredWidget = NULL; | gHoveredWidget = NULL; | ||||
} | } | ||||
if (gDraggedWidget == this) { | if (gDraggedWidget == this) { | ||||
gDraggedWidget->onDragEnd(); | |||||
EventDragEnd e; | |||||
gDraggedWidget->onDragEnd(e); | |||||
gDraggedWidget = NULL; | gDraggedWidget = NULL; | ||||
} | } | ||||
if (gDragHoveredWidget == this) { | if (gDragHoveredWidget == this) { | ||||
gDragHoveredWidget = NULL; | gDragHoveredWidget = NULL; | ||||
} | } | ||||
if (gFocusedWidget == this) { | if (gFocusedWidget == this) { | ||||
gFocusedWidget->onDefocus(); | |||||
EventDefocus e; | |||||
gFocusedWidget->onDefocus(e); | |||||
gFocusedWidget = NULL; | gFocusedWidget = NULL; | ||||
} | } | ||||
for (Widget *child : children) { | for (Widget *child : children) { | ||||
@@ -114,80 +117,51 @@ void Widget::draw(NVGcontext *vg) { | |||||
} | } | ||||
} | } | ||||
Widget *Widget::onMouseDown(Vec pos, int button) { | |||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | |||||
Widget *child = *it; | |||||
if (!child->visible) | |||||
continue; | |||||
if (child->box.contains(pos)) { | |||||
Widget *w = child->onMouseDown(pos.minus(child->box.pos), button); | |||||
if (w) | |||||
return w; | |||||
} | |||||
} | |||||
return NULL; | |||||
#define RECURSE_EVENT_POSITION(_method) { \ | |||||
Vec pos = e.pos; \ | |||||
for (auto it = children.rbegin(); it != children.rend(); it++) { \ | |||||
Widget *child = *it; \ | |||||
if (!child->visible) \ | |||||
continue; \ | |||||
if (child->box.contains(pos)) { \ | |||||
e.pos = pos.minus(child->box.pos); \ | |||||
child->_method(e); \ | |||||
if (e.consumed) \ | |||||
break; \ | |||||
} \ | |||||
} \ | |||||
e.pos = pos; \ | |||||
} | } | ||||
Widget *Widget::onMouseUp(Vec pos, int button) { | |||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | |||||
Widget *child = *it; | |||||
if (!child->visible) | |||||
continue; | |||||
if (child->box.contains(pos)) { | |||||
Widget *w = child->onMouseUp(pos.minus(child->box.pos), button); | |||||
if (w) | |||||
return w; | |||||
} | |||||
} | |||||
return NULL; | |||||
void Widget::onMouseDown(EventMouseDown &e) { | |||||
RECURSE_EVENT_POSITION(onMouseDown); | |||||
} | } | ||||
Widget *Widget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | |||||
Widget *child = *it; | |||||
if (!child->visible) | |||||
continue; | |||||
if (child->box.contains(pos)) { | |||||
Widget *w = child->onMouseMove(pos.minus(child->box.pos), mouseRel); | |||||
if (w) | |||||
return w; | |||||
} | |||||
} | |||||
return NULL; | |||||
void Widget::onMouseUp(EventMouseUp &e) { | |||||
RECURSE_EVENT_POSITION(onMouseUp); | |||||
} | } | ||||
Widget *Widget::onHoverKey(Vec pos, int key) { | |||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | |||||
Widget *child = *it; | |||||
if (!child->visible) | |||||
continue; | |||||
if (child->box.contains(pos)) { | |||||
Widget *w = child->onHoverKey(pos.minus(child->box.pos), key); | |||||
if (w) | |||||
return w; | |||||
} | |||||
} | |||||
return NULL; | |||||
void Widget::onMouseMove(EventMouseMove &e) { | |||||
RECURSE_EVENT_POSITION(onMouseMove); | |||||
} | } | ||||
Widget *Widget::onScroll(Vec pos, Vec scrollRel) { | |||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | |||||
Widget *child = *it; | |||||
if (!child->visible) | |||||
continue; | |||||
if (child->box.contains(pos)) { | |||||
Widget *w = child->onScroll(pos.minus(child->box.pos), scrollRel); | |||||
if (w) | |||||
return w; | |||||
} | |||||
} | |||||
return NULL; | |||||
void Widget::onHoverKey(EventHoverKey &e) { | |||||
RECURSE_EVENT_POSITION(onHoverKey); | |||||
} | |||||
void Widget::onScroll(EventScroll &e) { | |||||
RECURSE_EVENT_POSITION(onScroll); | |||||
} | |||||
void Widget::onPathDrop(EventPathDrop &e) { | |||||
RECURSE_EVENT_POSITION(onPathDrop); | |||||
} | } | ||||
void Widget::onZoom() { | |||||
void Widget::onZoom(EventZoom &e) { | |||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | for (auto it = children.rbegin(); it != children.rend(); it++) { | ||||
Widget *child = *it; | Widget *child = *it; | ||||
child->onZoom(); | |||||
child->onZoom(e); | |||||
} | } | ||||
} | } | ||||
@@ -18,8 +18,10 @@ Rect ZoomWidget::getViewport(Rect r) { | |||||
} | } | ||||
void ZoomWidget::setZoom(float zoom) { | void ZoomWidget::setZoom(float zoom) { | ||||
if (zoom != this->zoom) | |||||
onZoom(); | |||||
if (zoom != this->zoom) { | |||||
EventZoom e; | |||||
onZoom(e); | |||||
} | |||||
this->zoom = zoom; | this->zoom = zoom; | ||||
} | } | ||||
@@ -28,24 +30,39 @@ void ZoomWidget::draw(NVGcontext *vg) { | |||||
Widget::draw(vg); | Widget::draw(vg); | ||||
} | } | ||||
Widget *ZoomWidget::onMouseDown(Vec pos, int button) { | |||||
return Widget::onMouseDown(pos.div(zoom), button); | |||||
void ZoomWidget::onMouseDown(EventMouseDown &e) { | |||||
Vec pos = e.pos; | |||||
e.pos = e.pos.div(zoom); | |||||
Widget::onMouseDown(e); | |||||
e.pos = pos; | |||||
} | } | ||||
Widget *ZoomWidget::onMouseUp(Vec pos, int button) { | |||||
return Widget::onMouseUp(pos.div(zoom), button); | |||||
void ZoomWidget::onMouseUp(EventMouseUp &e) { | |||||
Vec pos = e.pos; | |||||
e.pos = e.pos.div(zoom); | |||||
Widget::onMouseUp(e); | |||||
e.pos = pos; | |||||
} | } | ||||
Widget *ZoomWidget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
return Widget::onMouseMove(pos.div(zoom), mouseRel); | |||||
void ZoomWidget::onMouseMove(EventMouseMove &e) { | |||||
Vec pos = e.pos; | |||||
e.pos = e.pos.div(zoom); | |||||
Widget::onMouseMove(e); | |||||
e.pos = pos; | |||||
} | } | ||||
Widget *ZoomWidget::onHoverKey(Vec pos, int key) { | |||||
return Widget::onHoverKey(pos.div(zoom), key); | |||||
void ZoomWidget::onHoverKey(EventHoverKey &e) { | |||||
Vec pos = e.pos; | |||||
e.pos = e.pos.div(zoom); | |||||
Widget::onHoverKey(e); | |||||
e.pos = pos; | |||||
} | } | ||||
Widget *ZoomWidget::onScroll(Vec pos, Vec scrollRel) { | |||||
return Widget::onScroll(pos.div(zoom), scrollRel); | |||||
void ZoomWidget::onScroll(EventScroll &e) { | |||||
Vec pos = e.pos; | |||||
e.pos = e.pos.div(zoom); | |||||
Widget::onScroll(e); | |||||
e.pos = pos; | |||||
} | } | ||||