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