| @@ -0,0 +1,25 @@ | |||
| #pragma once | |||
| #include "event.hpp" | |||
| namespace rack { | |||
| struct WidgetState { | |||
| Widget *rootWidget; | |||
| Widget *hoveredWidget; | |||
| Widget *draggedWidget; | |||
| Widget *dragHoveredWidget; | |||
| Widget *selectedWidget; | |||
| WidgetState(); | |||
| }; | |||
| // TODO Move this elsewhere | |||
| extern WidgetState *gWidgetState; | |||
| } // namespace rack | |||
| @@ -3,6 +3,7 @@ | |||
| #include <jansson.h> | |||
| #include "widgets.hpp" | |||
| #include "ui.hpp" | |||
| #include "WidgetState.hpp" | |||
| static const float SVG_DPI = 75.0; | |||
| @@ -234,12 +234,4 @@ struct Zoom : Event { | |||
| } // namespace event | |||
| extern Widget *gHoveredWidget; | |||
| extern Widget *gSelectedWidget; | |||
| extern Widget *gDraggedWidget; | |||
| extern Widget *gDragHoveredWidget; | |||
| } // namespace rack | |||
| @@ -1,6 +1,7 @@ | |||
| #include "plugin.hpp" | |||
| #include "engine.hpp" | |||
| #include "app.hpp" | |||
| #include "WidgetState.hpp" | |||
| namespace rack { | |||
| @@ -136,5 +137,17 @@ TMenuItem *createMenuItem(std::string text, std::string rightText = "") { | |||
| return o; | |||
| } | |||
| // TODO Reevaluate this. Does it belong here? | |||
| inline Menu *createMenu() { | |||
| Menu *o = new Menu(); | |||
| o->box.pos = gMousePos; | |||
| MenuOverlay *menuOverlay = new MenuOverlay(); | |||
| menuOverlay->addChild(o); | |||
| gWidgetState->rootWidget->addChild(menuOverlay); | |||
| return o; | |||
| } | |||
| } // namespace rack | |||
| @@ -2,6 +2,7 @@ | |||
| #include "widgets.hpp" | |||
| #include "blendish.h" | |||
| #include "ui/MenuOverlay.hpp" | |||
| namespace rack { | |||
| @@ -16,7 +17,7 @@ struct MenuItem : MenuEntry { | |||
| void draw(NVGcontext *vg) override { | |||
| // Get state | |||
| BNDwidgetState state = (gHoveredWidget == this) ? BND_HOVER : BND_DEFAULT; | |||
| BNDwidgetState state = (gWidgetState->hoveredWidget == this) ? BND_HOVER : BND_DEFAULT; | |||
| Menu *parentMenu = dynamic_cast<Menu*>(parent); | |||
| if (parentMenu && parentMenu->activeEntry == this) { | |||
| state = BND_ACTIVE; | |||
| @@ -64,10 +65,11 @@ struct MenuItem : MenuEntry { | |||
| // Consume event by default, but allow action to un-consume it to prevent the menu from being removed. | |||
| eAction.target = this; | |||
| handleEvent(eAction); | |||
| if (eAction.target) { | |||
| // deletes `this` | |||
| gScene->setOverlay(NULL); | |||
| } | |||
| if (!eAction.target) | |||
| return; | |||
| Widget *overlay = getAncestorOfType<MenuOverlay>(); | |||
| overlay->requestedDelete = true; | |||
| } | |||
| }; | |||
| @@ -11,50 +11,36 @@ struct MenuOverlay : OpaqueWidget { | |||
| void step() override { | |||
| Widget::step(); | |||
| // Adopt parent's size | |||
| box.size = parent->box.size; | |||
| // Fit all children in the box | |||
| for (Widget *child : children) { | |||
| child->box = child->box.nudge(box.zeroPos()); | |||
| } | |||
| } | |||
| void on(event::Button &e) override; | |||
| void on(event::HoverKey &e) override; | |||
| }; | |||
| } // namespace rack | |||
| #include "ui/Scene.hpp" | |||
| void on(event::Button &e) override { | |||
| EventWidget::on(e); | |||
| namespace rack { | |||
| if (!e.target) { | |||
| e.target = this; | |||
| requestedDelete = true; | |||
| } | |||
| } | |||
| void on(event::HoverKey &e) override { | |||
| switch (e.key) { | |||
| case GLFW_KEY_ESCAPE: { | |||
| e.target = this; | |||
| requestedDelete = true; | |||
| return; | |||
| } break; | |||
| } | |||
| inline void MenuOverlay::on(event::Button &e) { | |||
| EventWidget::on(e); | |||
| if (!e.target) { | |||
| // deletes `this` | |||
| gScene->setOverlay(NULL); | |||
| e.target = this; | |||
| EventWidget::on(e); | |||
| } | |||
| } | |||
| inline void MenuOverlay::on(event::HoverKey &e) { | |||
| switch (e.key) { | |||
| case GLFW_KEY_ESCAPE: { | |||
| gScene->setOverlay(NULL); | |||
| // e.consumed = true; | |||
| return; | |||
| } break; | |||
| } | |||
| // if (!e.consumed) { | |||
| // // Recurse children but consume the event | |||
| // Widget::onHoverKey(e); | |||
| // e.consumed = true; | |||
| // } | |||
| } | |||
| }; | |||
| } // namespace rack | |||
| @@ -1,68 +1,13 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "ui/Menu.hpp" | |||
| namespace rack { | |||
| struct Menu; | |||
| struct Scene : OpaqueWidget { | |||
| Widget *overlay = NULL; | |||
| /** Takes ownership of `w` */ | |||
| void setOverlay(Widget *w) { | |||
| if (overlay) { | |||
| removeChild(overlay); | |||
| delete overlay; | |||
| overlay = NULL; | |||
| } | |||
| if (w) { | |||
| addChild(w); | |||
| overlay = w; | |||
| overlay->box.pos = math::Vec(); | |||
| } | |||
| } | |||
| Menu *createMenu(); | |||
| void step() override { | |||
| if (overlay) { | |||
| overlay->box.pos = math::Vec(0, 0); | |||
| overlay->box.size = box.size; | |||
| } | |||
| Widget::step(); | |||
| } | |||
| }; | |||
| extern Scene *gScene; | |||
| } // namespace rack | |||
| #include "ui/MenuOverlay.hpp" | |||
| namespace rack { | |||
| inline Menu *Scene::createMenu() { | |||
| // Get relative position of the click | |||
| MenuOverlay *overlay = new MenuOverlay(); | |||
| Menu *menu = new Menu(); | |||
| menu->box.pos = gMousePos; | |||
| overlay->addChild(menu); | |||
| gScene->setOverlay(overlay); | |||
| return menu; | |||
| } | |||
| } // namespace rack | |||
| @@ -1,6 +1,7 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "WidgetState.hpp" | |||
| namespace rack { | |||
| @@ -110,7 +111,7 @@ struct ScrollWidget : OpaqueWidget { | |||
| void on(event::Hover &e) override { | |||
| // Scroll with arrow keys | |||
| if (!gSelectedWidget) { | |||
| if (!gWidgetState->selectedWidget) { | |||
| float arrowSpeed = 30.0; | |||
| if (windowIsShiftPressed() && windowIsModPressed()) | |||
| arrowSpeed /= 16.0; | |||
| @@ -1,6 +1,7 @@ | |||
| #pragma once | |||
| #include "widgets.hpp" | |||
| #include "WidgetState.hpp" | |||
| #include "blendish.h" | |||
| @@ -26,9 +27,9 @@ struct TextField : OpaqueWidget { | |||
| nvgScissor(vg, 0, 0, box.size.x, box.size.y); | |||
| BNDwidgetState state; | |||
| if (this == gSelectedWidget) | |||
| if (this == gWidgetState->selectedWidget) | |||
| state = BND_ACTIVE; | |||
| else if (this == gHoveredWidget) | |||
| else if (this == gWidgetState->hoveredWidget) | |||
| state = BND_HOVER; | |||
| else | |||
| state = BND_DEFAULT; | |||
| @@ -52,7 +53,7 @@ struct TextField : OpaqueWidget { | |||
| } | |||
| void on(event::Hover &e) override { | |||
| if (this == gDraggedWidget) { | |||
| if (this == gWidgetState->draggedWidget) { | |||
| int pos = getTextPosition(e.pos); | |||
| if (pos != selection) { | |||
| cursor = pos; | |||
| @@ -10,14 +10,10 @@ namespace rack { | |||
| namespace event { | |||
| struct Event; | |||
| } // namespace event | |||
| struct Event; | |||
| enum PickTarget { | |||
| PICK_MOUSE, | |||
| PICK_SCROLL, | |||
| }; | |||
| } // namespace event | |||
| /** A node in the 2D scene graph */ | |||
| @@ -2,6 +2,7 @@ | |||
| #include "midi.hpp" | |||
| #include "dsp/filter.hpp" | |||
| #include "window.hpp" | |||
| #include "WidgetState.hpp" | |||
| struct MIDICCToCVInterface : Module { | |||
| @@ -129,8 +130,8 @@ struct MidiCcChoice : GridChoice { | |||
| else { | |||
| text = string::stringf("%d", module->learnedCcs[id]); | |||
| color.a = 1.0; | |||
| if (gSelectedWidget == this) | |||
| gSelectedWidget = NULL; | |||
| if (gWidgetState->selectedWidget == this) | |||
| gWidgetState->selectedWidget = NULL; | |||
| } | |||
| } | |||
| @@ -158,11 +159,11 @@ struct MidiCcChoice : GridChoice { | |||
| } | |||
| void on(event::SelectKey &e) override { | |||
| if (gSelectedWidget == this) { | |||
| if (gWidgetState->selectedWidget == this) { | |||
| if (e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) { | |||
| event::Deselect eDeselect; | |||
| handleEvent(eDeselect); | |||
| gSelectedWidget = NULL; | |||
| gWidgetState->selectedWidget = NULL; | |||
| e.target = this; | |||
| } | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| #include "Core.hpp" | |||
| #include "midi.hpp" | |||
| #include "WidgetState.hpp" | |||
| struct MIDITriggerToCVInterface : Module { | |||
| @@ -171,8 +172,8 @@ struct MidiTrigChoice : GridChoice { | |||
| text = string::stringf("%s%d", noteNames[semi], oct); | |||
| color.a = 1.0; | |||
| if (gSelectedWidget == this) | |||
| gSelectedWidget = NULL; | |||
| if (gWidgetState->selectedWidget == this) | |||
| gWidgetState->selectedWidget = NULL; | |||
| } | |||
| } | |||
| @@ -0,0 +1,19 @@ | |||
| #include "WidgetState.hpp" | |||
| namespace rack { | |||
| WidgetState::WidgetState() { | |||
| rootWidget = NULL; | |||
| hoveredWidget = NULL; | |||
| draggedWidget = NULL; | |||
| dragHoveredWidget = NULL; | |||
| selectedWidget = NULL; | |||
| } | |||
| // TODO Move this elsewhere | |||
| WidgetState *gWidgetState = NULL; | |||
| } // namespace rack | |||
| @@ -17,7 +17,7 @@ struct AudioDriverItem : MenuItem { | |||
| struct AudioDriverChoice : LedDisplayChoice { | |||
| AudioWidget *audioWidget; | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->addChild(createMenuLabel("Audio driver")); | |||
| for (int driver : audioWidget->audioIO->getDrivers()) { | |||
| AudioDriverItem *item = new AudioDriverItem(); | |||
| @@ -49,7 +49,7 @@ struct AudioDeviceChoice : LedDisplayChoice { | |||
| int maxTotalChannels = 128; | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->addChild(createMenuLabel("Audio device")); | |||
| int deviceCount = audioWidget->audioIO->getDeviceCount(); | |||
| { | |||
| @@ -97,7 +97,7 @@ struct AudioSampleRateItem : MenuItem { | |||
| struct AudioSampleRateChoice : LedDisplayChoice { | |||
| AudioWidget *audioWidget; | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->addChild(createMenuLabel("Sample rate")); | |||
| std::vector<int> sampleRates = audioWidget->audioIO->getSampleRates(); | |||
| if (sampleRates.empty()) { | |||
| @@ -129,7 +129,7 @@ struct AudioBlockSizeItem : MenuItem { | |||
| struct AudioBlockSizeChoice : LedDisplayChoice { | |||
| AudioWidget *audioWidget; | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->addChild(createMenuLabel("Block size")); | |||
| std::vector<int> blockSizes = audioWidget->audioIO->getBlockSizes(); | |||
| if (blockSizes.empty()) { | |||
| @@ -1,6 +1,7 @@ | |||
| #include "app.hpp" | |||
| #include "asset.hpp" | |||
| #include "window.hpp" | |||
| #include "WidgetState.hpp" | |||
| namespace rack { | |||
| @@ -84,7 +85,7 @@ void LedDisplayTextField::draw(NVGcontext *vg) { | |||
| NVGcolor highlightColor = color; | |||
| highlightColor.a = 0.5; | |||
| int begin = std::min(cursor, selection); | |||
| int end = (this == gSelectedWidget) ? std::max(cursor, selection) : -1; | |||
| int end = (this == gWidgetState->selectedWidget) ? std::max(cursor, selection) : -1; | |||
| bndIconLabelCaret(vg, textOffset.x, textOffset.y, | |||
| box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y, | |||
| -1, color, 12, text.c_str(), highlightColor, begin, end); | |||
| @@ -17,7 +17,7 @@ struct MidiDriverItem : MenuItem { | |||
| struct MidiDriverChoice : LedDisplayChoice { | |||
| MidiWidget *midiWidget; | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->addChild(createMenuLabel("MIDI driver")); | |||
| for (int driverId : midiWidget->midiIO->getDriverIds()) { | |||
| MidiDriverItem *item = new MidiDriverItem(); | |||
| @@ -51,7 +51,7 @@ struct MidiDeviceItem : MenuItem { | |||
| struct MidiDeviceChoice : LedDisplayChoice { | |||
| MidiWidget *midiWidget; | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->addChild(createMenuLabel("MIDI device")); | |||
| { | |||
| MidiDeviceItem *item = new MidiDeviceItem(); | |||
| @@ -93,7 +93,7 @@ struct MidiChannelItem : MenuItem { | |||
| struct MidiChannelChoice : LedDisplayChoice { | |||
| MidiWidget *midiWidget; | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->addChild(createMenuLabel("MIDI channel")); | |||
| for (int channel = -1; channel < 16; channel++) { | |||
| MidiChannelItem *item = new MidiChannelItem(); | |||
| @@ -2,6 +2,7 @@ | |||
| #include "plugin.hpp" | |||
| #include "window.hpp" | |||
| #include "helpers.hpp" | |||
| #include "WidgetState.hpp" | |||
| #include <set> | |||
| #include <algorithm> | |||
| @@ -92,8 +93,8 @@ struct BrowserListItem : OpaqueWidget { | |||
| eAction.target = this; | |||
| handleEvent(eAction); | |||
| if (eAction.target) { | |||
| // deletes `this` | |||
| gScene->setOverlay(NULL); | |||
| MenuOverlay *overlay = getAncestorOfType<MenuOverlay>(); | |||
| overlay->requestedDelete = true; | |||
| } | |||
| } | |||
| }; | |||
| @@ -429,7 +430,7 @@ struct ModuleBrowser : OpaqueWidget { | |||
| moduleScroll->box.size.y = std::min(box.size.y - moduleScroll->box.pos.y, moduleList->box.size.y); | |||
| box.size.y = std::min(box.size.y, moduleScroll->box.getBottomRight().y); | |||
| gSelectedWidget = searchField; | |||
| gWidgetState->selectedWidget = searchField; | |||
| Widget::step(); | |||
| } | |||
| }; | |||
| @@ -492,7 +493,8 @@ void SearchModuleField::on(event::Change &e) { | |||
| void SearchModuleField::on(event::SelectKey &e) { | |||
| switch (e.key) { | |||
| case GLFW_KEY_ESCAPE: { | |||
| gScene->setOverlay(NULL); | |||
| MenuOverlay *overlay = getAncestorOfType<MenuOverlay>(); | |||
| overlay->requestedDelete = true; | |||
| e.target = this; | |||
| return; | |||
| } break; | |||
| @@ -539,7 +541,7 @@ void appModuleBrowserCreate() { | |||
| ModuleBrowser *moduleBrowser = new ModuleBrowser(); | |||
| overlay->addChild(moduleBrowser); | |||
| gScene->setOverlay(overlay); | |||
| gRackScene->addChild(overlay); | |||
| } | |||
| json_t *appModuleBrowserToJson() { | |||
| @@ -483,7 +483,7 @@ struct ModuleDeleteItem : MenuItem { | |||
| }; | |||
| Menu *ModuleWidget::createContextMenu() { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| MenuLabel *menuLabel = new MenuLabel(); | |||
| menuLabel->text = model->author + " " + model->name + " " + model->plugin->version; | |||
| @@ -16,13 +16,13 @@ struct TooltipIconButton : IconButton { | |||
| tooltip = new Tooltip(); | |||
| tooltip->box.pos = getAbsoluteOffset(math::Vec(0, BND_WIDGET_HEIGHT)); | |||
| tooltip->text = tooltipText; | |||
| gScene->addChild(tooltip); | |||
| gRackScene->addChild(tooltip); | |||
| } | |||
| IconButton::on(e); | |||
| } | |||
| void on(event::Leave &e) override { | |||
| if (tooltip) { | |||
| gScene->removeChild(tooltip); | |||
| gRackScene->removeChild(tooltip); | |||
| delete tooltip; | |||
| tooltip = NULL; | |||
| } | |||
| @@ -120,7 +120,7 @@ struct SampleRateButton : TooltipIconButton { | |||
| tooltipText = "Engine sample rate"; | |||
| } | |||
| void on(event::Action &e) override { | |||
| Menu *menu = gScene->createMenu(); | |||
| Menu *menu = createMenu(); | |||
| menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y)); | |||
| menu->box.size.x = box.size.x; | |||
| @@ -2,6 +2,7 @@ | |||
| #include "engine.hpp" | |||
| #include "componentlibrary.hpp" | |||
| #include "window.hpp" | |||
| #include "WidgetState.hpp" | |||
| namespace rack { | |||
| @@ -171,7 +172,7 @@ void WireWidget::draw(NVGcontext *vg) { | |||
| opacity = 1.0; | |||
| } | |||
| else { | |||
| Port *hoveredPort = dynamic_cast<Port*>(gHoveredWidget); | |||
| Port *hoveredPort = dynamic_cast<Port*>(gWidgetState->hoveredWidget); | |||
| if (hoveredPort && (hoveredPort == outputPort || hoveredPort == inputPort)) | |||
| opacity = 1.0; | |||
| } | |||
| @@ -37,7 +37,9 @@ static void checkVersion() { | |||
| void appInit(bool devMode) { | |||
| gRackScene = new RackScene(); | |||
| gScene = gRackScene; | |||
| gWidgetState = new WidgetState(); | |||
| gWidgetState->rootWidget = gRackScene; | |||
| // Request latest version from server | |||
| if (!devMode && gCheckVersion) { | |||
| @@ -46,8 +48,13 @@ void appInit(bool devMode) { | |||
| } | |||
| } | |||
| void appDestroy() { | |||
| delete gRackScene; | |||
| gRackScene = NULL; | |||
| delete gWidgetState; | |||
| gWidgetState = NULL; | |||
| } | |||
| @@ -1,12 +0,0 @@ | |||
| #include "event.hpp" | |||
| namespace rack { | |||
| Widget *gHoveredWidget = NULL; | |||
| Widget *gDraggedWidget = NULL; | |||
| Widget *gDragHoveredWidget = NULL; | |||
| Widget *gSelectedWidget = NULL; | |||
| } // namespace rack | |||
| @@ -69,8 +69,8 @@ int main(int argc, char* argv[]) { | |||
| bridgeInit(); | |||
| keyboard::init(); | |||
| gamepad::init(); | |||
| windowInit(); | |||
| appInit(devMode); | |||
| windowInit(); | |||
| settings::load(asset::local("settings.json")); | |||
| if (patchFile.empty()) { | |||
| @@ -1,9 +0,0 @@ | |||
| #include "ui.hpp" | |||
| namespace rack { | |||
| Scene *gScene = NULL; | |||
| } // namespace rack | |||
| @@ -1,5 +1,6 @@ | |||
| #include "widgets.hpp" | |||
| #include "app.hpp" | |||
| #include "WidgetState.hpp" | |||
| #include <algorithm> | |||
| @@ -9,10 +10,10 @@ Widget::~Widget() { | |||
| // You should only delete orphaned widgets | |||
| assert(!parent); | |||
| // Stop dragging and hovering this widget | |||
| if (gHoveredWidget == this) gHoveredWidget = NULL; | |||
| if (gDraggedWidget == this) gDraggedWidget = NULL; | |||
| if (gDragHoveredWidget == this) gDragHoveredWidget = NULL; | |||
| if (gSelectedWidget == this) gSelectedWidget = NULL; | |||
| if (gWidgetState->hoveredWidget == this) gWidgetState->hoveredWidget = NULL; | |||
| if (gWidgetState->draggedWidget == this) gWidgetState->draggedWidget = NULL; | |||
| if (gWidgetState->hoveredWidget == this) gWidgetState->hoveredWidget = NULL; | |||
| if (gWidgetState->selectedWidget == this) gWidgetState->selectedWidget = NULL; | |||
| clearChildren(); | |||
| } | |||
| @@ -13,6 +13,7 @@ | |||
| #include "rack.hpp" | |||
| #include "keyboard.hpp" | |||
| #include "gamepad.hpp" | |||
| #include "WidgetState.hpp" | |||
| #define NANOVG_GL2_IMPLEMENTATION 1 | |||
| // #define NANOVG_GL3_IMPLEMENTATION 1 | |||
| @@ -45,7 +46,9 @@ math::Vec gMousePos; | |||
| std::string lastWindowTitle; | |||
| static void windowSizeCallback(GLFWwindow* window, int width, int height) {} | |||
| static void windowSizeCallback(GLFWwindow* window, int width, int height) { | |||
| // Do nothing. Window size is reset each frame anyway. | |||
| } | |||
| static void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { | |||
| #ifdef ARCH_MAC | |||
| @@ -62,7 +65,7 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int | |||
| eButton.button = button; | |||
| eButton.action = action; | |||
| eButton.mods = mods; | |||
| gScene->handleEvent(eButton); | |||
| gWidgetState->rootWidget->handleEvent(eButton); | |||
| Widget *clickedWidget = eButton.target; | |||
| // Dragging | |||
| @@ -72,7 +75,7 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int | |||
| event::DragStart eDragStart; | |||
| eDragStart.button = button; | |||
| clickedWidget->handleEvent(eDragStart); | |||
| gDraggedWidget = eDragStart.target; | |||
| gWidgetState->draggedWidget = eDragStart.target; | |||
| } | |||
| if (action == GLFW_RELEASE) { | |||
| @@ -80,23 +83,23 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int | |||
| // TODO Use dragged button | |||
| eDragEnd.button = button; | |||
| clickedWidget->handleEvent(eDragEnd); | |||
| gDraggedWidget = eDragEnd.target; | |||
| gWidgetState->draggedWidget = eDragEnd.target; | |||
| } | |||
| } | |||
| // Selection | |||
| if (action == GLFW_PRESS && button == GLFW_MOUSE_BUTTON_LEFT) { | |||
| if (clickedWidget != gSelectedWidget) { | |||
| if (gSelectedWidget) { | |||
| if (clickedWidget != gWidgetState->selectedWidget) { | |||
| if (gWidgetState->selectedWidget) { | |||
| event::Deselect eDeselect; | |||
| gSelectedWidget->handleEvent(eDeselect); | |||
| gWidgetState->selectedWidget->handleEvent(eDeselect); | |||
| } | |||
| gSelectedWidget = clickedWidget; | |||
| gWidgetState->selectedWidget = clickedWidget; | |||
| if (gSelectedWidget) { | |||
| if (gWidgetState->selectedWidget) { | |||
| event::Select eSelect; | |||
| gSelectedWidget->handleEvent(eSelect); | |||
| gWidgetState->selectedWidget->handleEvent(eSelect); | |||
| } | |||
| } | |||
| } | |||
| @@ -109,21 +112,21 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int | |||
| EventDragStart e; | |||
| gTempWidget->onDragStart(e); | |||
| } | |||
| gDraggedWidget = gTempWidget; | |||
| gWidgetState->draggedWidget = gTempWidget; | |||
| if (gTempWidget != gSelectedWidget) { | |||
| if (gSelectedWidget) { | |||
| if (gTempWidget != gWidgetState->selectedWidget) { | |||
| if (gWidgetState->selectedWidget) { | |||
| // onDefocus | |||
| EventDefocus e; | |||
| gSelectedWidget->onDefocus(e); | |||
| gWidgetState->selectedWidget->onDefocus(e); | |||
| } | |||
| gSelectedWidget = NULL; | |||
| gWidgetState->selectedWidget = NULL; | |||
| if (gTempWidget) { | |||
| // onFocus | |||
| EventFocus e; | |||
| gTempWidget->onFocus(e); | |||
| if (e.consumed) { | |||
| gSelectedWidget = gTempWidget; | |||
| gWidgetState->selectedWidget = gTempWidget; | |||
| } | |||
| } | |||
| } | |||
| @@ -137,25 +140,25 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int | |||
| EventMouseUp e; | |||
| e.pos = gMousePos; | |||
| e.button = button; | |||
| gScene->onMouseUp(e); | |||
| gWidgetState->rootWidget->onMouseUp(e); | |||
| gTempWidget = e.target; | |||
| } | |||
| if (button == GLFW_MOUSE_BUTTON_LEFT) { | |||
| if (gDraggedWidget) { | |||
| if (gWidgetState->draggedWidget) { | |||
| // onDragDrop | |||
| EventDragDrop e; | |||
| e.origin = gDraggedWidget; | |||
| e.origin = gWidgetState->draggedWidget; | |||
| gTempWidget->onDragDrop(e); | |||
| } | |||
| // gDraggedWidget might have been set to null in the last event, recheck here | |||
| if (gDraggedWidget) { | |||
| // gWidgetState->draggedWidget might have been set to null in the last event, recheck here | |||
| if (gWidgetState->draggedWidget) { | |||
| // onDragEnd | |||
| EventDragEnd e; | |||
| gDraggedWidget->onDragEnd(e); | |||
| gWidgetState->draggedWidget->onDragEnd(e); | |||
| } | |||
| gDraggedWidget = NULL; | |||
| gDragHoveredWidget = NULL; | |||
| gWidgetState->draggedWidget = NULL; | |||
| gDragWidgetState->hoveredWidget = NULL; | |||
| } | |||
| gTempWidget = NULL; | |||
| } | |||
| @@ -209,49 +212,49 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||
| event::Hover eHover; | |||
| eHover.pos = mousePos; | |||
| eHover.mouseDelta = mouseDelta; | |||
| gScene->handleEvent(eHover); | |||
| gWidgetState->rootWidget->handleEvent(eHover); | |||
| if (gDraggedWidget) { | |||
| if (gWidgetState->draggedWidget) { | |||
| event::DragMove eDragMove; | |||
| // TODO | |||
| eDragMove.button = 0; | |||
| eDragMove.mouseDelta = mouseDelta; | |||
| gDraggedWidget->handleEvent(eDragMove); | |||
| gWidgetState->draggedWidget->handleEvent(eDragMove); | |||
| } | |||
| /* | |||
| if (gDraggedWidget) { | |||
| if (gWidgetState->draggedWidget) { | |||
| // onDragMove | |||
| EventDragMove e; | |||
| e.mouseDelta = mouseDelta; | |||
| gDraggedWidget->onDragMove(e); | |||
| gWidgetState->draggedWidget->onDragMove(e); | |||
| if (gTempWidget != gDragHoveredWidget) { | |||
| if (gDragHoveredWidget) { | |||
| if (gTempWidget != gDragWidgetState->hoveredWidget) { | |||
| if (gDragWidgetState->hoveredWidget) { | |||
| EventDragEnter e; | |||
| e.origin = gDraggedWidget; | |||
| gDragHoveredWidget->onDragLeave(e); | |||
| e.origin = gWidgetState->draggedWidget; | |||
| gDragWidgetState->hoveredWidget->onDragLeave(e); | |||
| } | |||
| gDragHoveredWidget = gTempWidget; | |||
| if (gDragHoveredWidget) { | |||
| gDragWidgetState->hoveredWidget = gTempWidget; | |||
| if (gDragWidgetState->hoveredWidget) { | |||
| EventDragEnter e; | |||
| e.origin = gDraggedWidget; | |||
| gDragHoveredWidget->onDragEnter(e); | |||
| e.origin = gWidgetState->draggedWidget; | |||
| gDragWidgetState->hoveredWidget->onDragEnter(e); | |||
| } | |||
| } | |||
| } | |||
| else { | |||
| if (gTempWidget != gHoveredWidget) { | |||
| if (gHoveredWidget) { | |||
| if (gTempWidget != gWidgetState->hoveredWidget) { | |||
| if (gWidgetState->hoveredWidget) { | |||
| // onMouseLeave | |||
| EventMouseLeave e; | |||
| gHoveredWidget->onMouseLeave(e); | |||
| gWidgetState->hoveredWidget->onMouseLeave(e); | |||
| } | |||
| gHoveredWidget = gTempWidget; | |||
| if (gHoveredWidget) { | |||
| gWidgetState->hoveredWidget = gTempWidget; | |||
| if (gWidgetState->hoveredWidget) { | |||
| // onMouseEnter | |||
| EventMouseEnter e; | |||
| gHoveredWidget->onMouseEnter(e); | |||
| gWidgetState->hoveredWidget->onMouseEnter(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -262,18 +265,18 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||
| EventScroll e; | |||
| e.pos = mousePos; | |||
| e.scrollRel = mouseDelta; | |||
| gScene->onScroll(e); | |||
| gWidgetState->rootWidget->onScroll(e); | |||
| } | |||
| */ | |||
| } | |||
| void cursorEnterCallback(GLFWwindow* window, int entered) { | |||
| if (!entered) { | |||
| if (gHoveredWidget) { | |||
| if (gWidgetState->hoveredWidget) { | |||
| event::Leave eLeave; | |||
| gHoveredWidget->handleEvent(eLeave); | |||
| gWidgetState->hoveredWidget->handleEvent(eLeave); | |||
| } | |||
| gHoveredWidget = NULL; | |||
| gWidgetState->hoveredWidget = NULL; | |||
| } | |||
| } | |||
| @@ -287,26 +290,26 @@ void scrollCallback(GLFWwindow *window, double x, double y) { | |||
| event::HoverScroll eHoverScroll; | |||
| eHoverScroll.scrollDelta = scrollDelta; | |||
| gScene->handleEvent(eHoverScroll); | |||
| gWidgetState->rootWidget->handleEvent(eHoverScroll); | |||
| } | |||
| void charCallback(GLFWwindow *window, unsigned int codepoint) { | |||
| if (gSelectedWidget) { | |||
| if (gWidgetState->selectedWidget) { | |||
| event::SelectText eSelectText; | |||
| eSelectText.codepoint = codepoint; | |||
| gSelectedWidget->handleEvent(eSelectText); | |||
| gWidgetState->selectedWidget->handleEvent(eSelectText); | |||
| } | |||
| } | |||
| void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) { | |||
| if (action == GLFW_PRESS || action == GLFW_REPEAT) { | |||
| if (gSelectedWidget) { | |||
| if (gWidgetState->selectedWidget) { | |||
| event::SelectKey eSelectKey; | |||
| eSelectKey.key = key; | |||
| eSelectKey.scancode = scancode; | |||
| eSelectKey.action = action; | |||
| eSelectKey.mods = mods; | |||
| gSelectedWidget->handleEvent(eSelectKey); | |||
| gWidgetState->selectedWidget->handleEvent(eSelectKey); | |||
| if (eSelectKey.target) | |||
| return; | |||
| } | |||
| @@ -317,7 +320,7 @@ void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods | |||
| eHoverKey.action = action; | |||
| eHoverKey.mods = mods; | |||
| eHoverKey.pos = gMousePos; | |||
| gScene->handleEvent(eHoverKey); | |||
| gWidgetState->rootWidget->handleEvent(eHoverKey); | |||
| } | |||
| // Keyboard MIDI driver | |||
| @@ -337,7 +340,7 @@ void dropCallback(GLFWwindow *window, int count, const char **paths) { | |||
| for (int i = 0; i < count; i++) { | |||
| ePathDrop.paths.push_back(paths[i]); | |||
| } | |||
| gScene->handleEvent(ePathDrop); | |||
| gWidgetState->rootWidget->handleEvent(ePathDrop); | |||
| } | |||
| void errorCallback(int error, const char *description) { | |||
| @@ -353,7 +356,7 @@ void renderGui() { | |||
| nvgReset(gVg); | |||
| nvgScale(gVg, gPixelRatio, gPixelRatio); | |||
| gScene->draw(gVg); | |||
| gWidgetState->rootWidget->draw(gVg); | |||
| glViewport(0, 0, width, height); | |||
| glClearColor(0.0, 0.0, 0.0, 1.0); | |||
| @@ -507,7 +510,7 @@ void windowRun() { | |||
| pixelRatio = roundf(pixelRatio); | |||
| if (pixelRatio != gPixelRatio) { | |||
| event::Zoom eZoom; | |||
| gScene->handleEvent(eZoom); | |||
| gWidgetState->rootWidget->handleEvent(eZoom); | |||
| gPixelRatio = pixelRatio; | |||
| } | |||
| @@ -518,10 +521,10 @@ void windowRun() { | |||
| glfwGetWindowSize(gWindow, &windowWidth, &windowHeight); | |||
| gWindowRatio = (float)width / windowWidth; | |||
| gScene->box.size = math::Vec(width, height).div(gPixelRatio); | |||
| gWidgetState->rootWidget->box.size = math::Vec(width, height).div(gPixelRatio); | |||
| // Step scene | |||
| gScene->step(); | |||
| gWidgetState->rootWidget->step(); | |||
| // Render | |||
| bool visible = glfwGetWindowAttrib(gWindow, GLFW_VISIBLE) && !glfwGetWindowAttrib(gWindow, GLFW_ICONIFIED); | |||