Browse Source

Class-ify window, un-class-ify asset

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
0dec45d970
46 changed files with 607 additions and 547 deletions
  1. +0
    -25
      include/AssetManager.hpp
  2. +4
    -3
      include/app/Knob.hpp
  3. +2
    -1
      include/app/SVGPanel.hpp
  4. +1
    -0
      include/app/Scene.hpp
  5. +26
    -0
      include/asset.hpp
  6. +76
    -76
      include/componentlibrary.hpp
  7. +2
    -4
      include/context.hpp
  8. +1
    -1
      include/helpers.hpp
  9. +1
    -1
      include/logger.hpp
  10. +1
    -1
      include/plugin/PluginManager.hpp
  11. +1
    -1
      include/rack.hpp
  12. +3
    -3
      include/rack0.hpp
  13. +13
    -0
      include/svg.hpp
  14. +15
    -0
      include/ui.hpp
  15. +3
    -3
      include/ui/MenuItem.hpp
  16. +3
    -2
      include/ui/MenuLabel.hpp
  17. +9
    -9
      include/ui/ScrollWidget.hpp
  18. +3
    -2
      include/ui/Slider.hpp
  19. +12
    -12
      include/ui/TextField.hpp
  20. +1
    -0
      include/ui/common.hpp
  21. +1
    -0
      include/widgets/SVGWidget.hpp
  22. +35
    -36
      include/window.hpp
  23. +1
    -1
      src/Core/AudioInterface.cpp
  24. +1
    -1
      src/Core/MIDICCToCVInterface.cpp
  25. +1
    -1
      src/Core/MIDIToCVInterface.cpp
  26. +1
    -1
      src/Core/MIDITriggerToCVInterface.cpp
  27. +1
    -1
      src/Core/Notes.cpp
  28. +1
    -1
      src/Core/QuadMIDIToCVInterface.cpp
  29. +7
    -6
      src/app/LedDisplay.cpp
  30. +16
    -14
      src/app/ModuleWidget.cpp
  31. +1
    -1
      src/app/PluginManagerWidget.cpp
  32. +1
    -1
      src/app/Port.cpp
  33. +1
    -1
      src/app/RackScrollWidget.cpp
  34. +8
    -8
      src/app/RackWidget.cpp
  35. +11
    -11
      src/app/Scene.cpp
  36. +11
    -11
      src/app/Toolbar.cpp
  37. +30
    -25
      src/asset.cpp
  38. +0
    -4
      src/event.cpp
  39. +4
    -5
      src/logger.cpp
  40. +34
    -28
      src/main.cpp
  41. +8
    -8
      src/plugin/PluginManager.cpp
  42. +7
    -7
      src/settings.cpp
  43. +2
    -4
      src/svg.cpp
  44. +64
    -0
      src/ui.cpp
  45. +11
    -9
      src/widgets/FramebufferWidget.cpp
  46. +172
    -218
      src/window.cpp

+ 0
- 25
include/AssetManager.hpp View File

@@ -1,25 +0,0 @@
#pragma once
#include "common.hpp"


namespace rack {


struct Plugin;


struct AssetManager {
std::string systemDir;
std::string userDir;

AssetManager();
/** Returns the path of a system resource. Should only read files from this location. */
std::string system(std::string filename);
/** Returns the path of a user resource. Can read and write files to this location. */
std::string user(std::string filename);
/** Returns the path of a resource in the plugin's folder. Should only read files from this location. */
std::string plugin(Plugin *plugin, std::string filename);
};


} // namespace rack

+ 4
- 3
include/app/Knob.hpp View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "app/common.hpp" #include "app/common.hpp"
#include "app/ParamWidget.hpp" #include "app/ParamWidget.hpp"
#include "context.hpp"




namespace rack { namespace rack {
@@ -15,11 +16,11 @@ struct Knob : ParamWidget {
float speed = 1.0; float speed = 1.0;


void onDragStart(event::DragStart &e) override { void onDragStart(event::DragStart &e) override {
windowCursorLock();
context()->window->cursorLock();
} }


void onDragEnd(event::DragEnd &e) override { void onDragEnd(event::DragEnd &e) override {
windowCursorUnlock();
context()->window->cursorUnlock();
} }


void onDragMove(event::DragMove &e) override { void onDragMove(event::DragMove &e) override {
@@ -35,7 +36,7 @@ struct Knob : ParamWidget {
float delta = KNOB_SENSITIVITY * -e.mouseDelta.y * speed * range; float delta = KNOB_SENSITIVITY * -e.mouseDelta.y * speed * range;


// Drag slower if Mod is held // Drag slower if Mod is held
if (windowIsModPressed())
if (context()->window->isModPressed())
delta /= 16.f; delta /= 16.f;
quantity->moveValue(delta); quantity->moveValue(delta);
} }


+ 2
- 1
include/app/SVGPanel.hpp View File

@@ -3,6 +3,7 @@
#include "widgets/TransparentWidget.hpp" #include "widgets/TransparentWidget.hpp"
#include "widgets/FramebufferWidget.hpp" #include "widgets/FramebufferWidget.hpp"
#include "widgets/SVGWidget.hpp" #include "widgets/SVGWidget.hpp"
#include "context.hpp"




namespace rack { namespace rack {
@@ -22,7 +23,7 @@ struct PanelBorder : TransparentWidget {


struct SVGPanel : FramebufferWidget { struct SVGPanel : FramebufferWidget {
void step() override { void step() override {
if (isNear(gPixelRatio, 1.0)) {
if (isNear(context()->window->pixelRatio, 1.0)) {
// Small details draw poorly at low DPI, so oversample when drawing to the framebuffer // Small details draw poorly at low DPI, so oversample when drawing to the framebuffer
oversample = 2.0; oversample = 2.0;
} }


+ 1
- 0
include/app/Scene.hpp View File

@@ -19,6 +19,7 @@ struct Scene : OpaqueWidget {
Toolbar *toolbar; Toolbar *toolbar;


// Version checking // Version checking
bool devMode = false;
bool checkVersion = true; bool checkVersion = true;
bool checkedVersion = false; bool checkedVersion = false;
std::string latestVersion; std::string latestVersion;


+ 26
- 0
include/asset.hpp View File

@@ -0,0 +1,26 @@
#pragma once
#include "common.hpp"


namespace rack {

struct Plugin;

namespace asset {


void init(bool devMode);
/** Returns the path of a system resource. Should only read files from this location. */
std::string system(std::string filename);
/** Returns the path of a user resource. Can read and write files to this location. */
std::string user(std::string filename);
/** Returns the path of a resource in the plugin's folder. Should only read files from this location. */
std::string plugin(Plugin *plugin, std::string filename);


extern std::string gSystemDir;
extern std::string gUserDir;


} // namespace asset
} // namespace rack

+ 76
- 76
include/componentlibrary.hpp View File

@@ -35,25 +35,25 @@ struct RoundKnob : SVGKnob {


struct RoundBlackKnob : RoundKnob { struct RoundBlackKnob : RoundKnob {
RoundBlackKnob() { RoundBlackKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/RoundBlackKnob.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/RoundBlackKnob.svg")));
} }
}; };


struct RoundSmallBlackKnob : RoundKnob { struct RoundSmallBlackKnob : RoundKnob {
RoundSmallBlackKnob() { RoundSmallBlackKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/RoundSmallBlackKnob.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/RoundSmallBlackKnob.svg")));
} }
}; };


struct RoundLargeBlackKnob : RoundKnob { struct RoundLargeBlackKnob : RoundKnob {
RoundLargeBlackKnob() { RoundLargeBlackKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/RoundLargeBlackKnob.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/RoundLargeBlackKnob.svg")));
} }
}; };


struct RoundHugeBlackKnob : RoundKnob { struct RoundHugeBlackKnob : RoundKnob {
RoundHugeBlackKnob() { RoundHugeBlackKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/RoundHugeBlackKnob.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/RoundHugeBlackKnob.svg")));
} }
}; };


@@ -75,37 +75,37 @@ struct Davies1900hKnob : SVGKnob {


struct Davies1900hWhiteKnob : Davies1900hKnob { struct Davies1900hWhiteKnob : Davies1900hKnob {
Davies1900hWhiteKnob() { Davies1900hWhiteKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Davies1900hWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Davies1900hWhite.svg")));
} }
}; };


struct Davies1900hBlackKnob : Davies1900hKnob { struct Davies1900hBlackKnob : Davies1900hKnob {
Davies1900hBlackKnob() { Davies1900hBlackKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Davies1900hBlack.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Davies1900hBlack.svg")));
} }
}; };


struct Davies1900hRedKnob : Davies1900hKnob { struct Davies1900hRedKnob : Davies1900hKnob {
Davies1900hRedKnob() { Davies1900hRedKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Davies1900hRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Davies1900hRed.svg")));
} }
}; };


struct Davies1900hLargeWhiteKnob : Davies1900hKnob { struct Davies1900hLargeWhiteKnob : Davies1900hKnob {
Davies1900hLargeWhiteKnob() { Davies1900hLargeWhiteKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Davies1900hLargeWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Davies1900hLargeWhite.svg")));
} }
}; };


struct Davies1900hLargeBlackKnob : Davies1900hKnob { struct Davies1900hLargeBlackKnob : Davies1900hKnob {
Davies1900hLargeBlackKnob() { Davies1900hLargeBlackKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Davies1900hLargeBlack.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Davies1900hLargeBlack.svg")));
} }
}; };


struct Davies1900hLargeRedKnob : Davies1900hKnob { struct Davies1900hLargeRedKnob : Davies1900hKnob {
Davies1900hLargeRedKnob() { Davies1900hLargeRedKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Davies1900hLargeRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Davies1900hLargeRed.svg")));
} }
}; };


@@ -119,163 +119,163 @@ struct Rogan : SVGKnob {


struct Rogan6PSWhite : Rogan { struct Rogan6PSWhite : Rogan {
Rogan6PSWhite() { Rogan6PSWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan6PSWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan6PSWhite.svg")));
} }
}; };


struct Rogan5PSGray : Rogan { struct Rogan5PSGray : Rogan {
Rogan5PSGray() { Rogan5PSGray() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan5PSGray.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan5PSGray.svg")));
} }
}; };


struct Rogan3PSBlue : Rogan { struct Rogan3PSBlue : Rogan {
Rogan3PSBlue() { Rogan3PSBlue() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PSBlue.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PSBlue.svg")));
} }
}; };


struct Rogan3PSRed : Rogan { struct Rogan3PSRed : Rogan {
Rogan3PSRed() { Rogan3PSRed() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PSRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PSRed.svg")));
} }
}; };


struct Rogan3PSGreen : Rogan { struct Rogan3PSGreen : Rogan {
Rogan3PSGreen() { Rogan3PSGreen() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PSGreen.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PSGreen.svg")));
} }
}; };


struct Rogan3PSWhite : Rogan { struct Rogan3PSWhite : Rogan {
Rogan3PSWhite() { Rogan3PSWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PSWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PSWhite.svg")));
} }
}; };


struct Rogan3PBlue : Rogan { struct Rogan3PBlue : Rogan {
Rogan3PBlue() { Rogan3PBlue() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PBlue.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PBlue.svg")));
} }
}; };


struct Rogan3PRed : Rogan { struct Rogan3PRed : Rogan {
Rogan3PRed() { Rogan3PRed() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PRed.svg")));
} }
}; };


struct Rogan3PGreen : Rogan { struct Rogan3PGreen : Rogan {
Rogan3PGreen() { Rogan3PGreen() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PGreen.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PGreen.svg")));
} }
}; };


struct Rogan3PWhite : Rogan { struct Rogan3PWhite : Rogan {
Rogan3PWhite() { Rogan3PWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan3PWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan3PWhite.svg")));
} }
}; };


struct Rogan2SGray : Rogan { struct Rogan2SGray : Rogan {
Rogan2SGray() { Rogan2SGray() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2SGray.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2SGray.svg")));
} }
}; };


struct Rogan2PSBlue : Rogan { struct Rogan2PSBlue : Rogan {
Rogan2PSBlue() { Rogan2PSBlue() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PSBlue.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PSBlue.svg")));
} }
}; };


struct Rogan2PSRed : Rogan { struct Rogan2PSRed : Rogan {
Rogan2PSRed() { Rogan2PSRed() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PSRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PSRed.svg")));
} }
}; };


struct Rogan2PSGreen : Rogan { struct Rogan2PSGreen : Rogan {
Rogan2PSGreen() { Rogan2PSGreen() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PSGreen.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PSGreen.svg")));
} }
}; };


struct Rogan2PSWhite : Rogan { struct Rogan2PSWhite : Rogan {
Rogan2PSWhite() { Rogan2PSWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PSWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PSWhite.svg")));
} }
}; };


struct Rogan2PBlue : Rogan { struct Rogan2PBlue : Rogan {
Rogan2PBlue() { Rogan2PBlue() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PBlue.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PBlue.svg")));
} }
}; };


struct Rogan2PRed : Rogan { struct Rogan2PRed : Rogan {
Rogan2PRed() { Rogan2PRed() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PRed.svg")));
} }
}; };


struct Rogan2PGreen : Rogan { struct Rogan2PGreen : Rogan {
Rogan2PGreen() { Rogan2PGreen() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PGreen.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PGreen.svg")));
} }
}; };


struct Rogan2PWhite : Rogan { struct Rogan2PWhite : Rogan {
Rogan2PWhite() { Rogan2PWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan2PWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan2PWhite.svg")));
} }
}; };


struct Rogan1PSBlue : Rogan { struct Rogan1PSBlue : Rogan {
Rogan1PSBlue() { Rogan1PSBlue() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PSBlue.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PSBlue.svg")));
} }
}; };


struct Rogan1PSRed : Rogan { struct Rogan1PSRed : Rogan {
Rogan1PSRed() { Rogan1PSRed() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PSRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PSRed.svg")));
} }
}; };


struct Rogan1PSGreen : Rogan { struct Rogan1PSGreen : Rogan {
Rogan1PSGreen() { Rogan1PSGreen() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PSGreen.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PSGreen.svg")));
} }
}; };


struct Rogan1PSWhite : Rogan { struct Rogan1PSWhite : Rogan {
Rogan1PSWhite() { Rogan1PSWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PSWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PSWhite.svg")));
} }
}; };


struct Rogan1PBlue : Rogan { struct Rogan1PBlue : Rogan {
Rogan1PBlue() { Rogan1PBlue() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PBlue.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PBlue.svg")));
} }
}; };


struct Rogan1PRed : Rogan { struct Rogan1PRed : Rogan {
Rogan1PRed() { Rogan1PRed() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PRed.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PRed.svg")));
} }
}; };


struct Rogan1PGreen : Rogan { struct Rogan1PGreen : Rogan {
Rogan1PGreen() { Rogan1PGreen() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PGreen.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PGreen.svg")));
} }
}; };


struct Rogan1PWhite : Rogan { struct Rogan1PWhite : Rogan {
Rogan1PWhite() { Rogan1PWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan1PWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan1PWhite.svg")));
} }
}; };


@@ -284,9 +284,9 @@ struct SynthTechAlco : SVGKnob {
SynthTechAlco() { SynthTechAlco() {
minAngle = -0.82*M_PI; minAngle = -0.82*M_PI;
maxAngle = 0.82*M_PI; maxAngle = 0.82*M_PI;
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/SynthTechAlco.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/SynthTechAlco.svg")));
SVGWidget *cap = new SVGWidget; SVGWidget *cap = new SVGWidget;
cap->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/SynthTechAlco_cap.svg")));
cap->setSVG(SVG::load(asset::system("res/ComponentLibrary/SynthTechAlco_cap.svg")));
addChild(cap); addChild(cap);
} }
}; };
@@ -295,7 +295,7 @@ struct Trimpot : SVGKnob {
Trimpot() { Trimpot() {
minAngle = -0.75*M_PI; minAngle = -0.75*M_PI;
maxAngle = 0.75*M_PI; maxAngle = 0.75*M_PI;
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Trimpot.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Trimpot.svg")));
} }
}; };


@@ -303,7 +303,7 @@ struct BefacoBigKnob : SVGKnob {
BefacoBigKnob() { BefacoBigKnob() {
minAngle = -0.75*M_PI; minAngle = -0.75*M_PI;
maxAngle = 0.75*M_PI; maxAngle = 0.75*M_PI;
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoBigKnob.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/BefacoBigKnob.svg")));
} }
}; };


@@ -319,7 +319,7 @@ struct BefacoTinyKnob : SVGKnob {
BefacoTinyKnob() { BefacoTinyKnob() {
minAngle = -0.75*M_PI; minAngle = -0.75*M_PI;
maxAngle = 0.75*M_PI; maxAngle = 0.75*M_PI;
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoTinyKnob.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/BefacoTinyKnob.svg")));
} }
}; };


@@ -328,7 +328,7 @@ struct BefacoSlidePot : SVGSlider {
Vec margin = Vec(3.5, 3.5); Vec margin = Vec(3.5, 3.5);
maxHandlePos = Vec(-1, -2).plus(margin); maxHandlePos = Vec(-1, -2).plus(margin);
minHandlePos = Vec(-1, 87).plus(margin); minHandlePos = Vec(-1, 87).plus(margin);
setSVGs(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoSlidePot.svg")), SVG::load(context()->asset->system("res/ComponentLibrary/BefacoSlidePotHandle.svg")));
setSVGs(SVG::load(asset::system("res/ComponentLibrary/BefacoSlidePot.svg")), SVG::load(asset::system("res/ComponentLibrary/BefacoSlidePotHandle.svg")));
background->box.pos = margin; background->box.pos = margin;
box.size = background->box.size.plus(margin.mult(2)); box.size = background->box.size.plus(margin.mult(2));
} }
@@ -338,38 +338,38 @@ struct LEDSlider : SVGSlider {
LEDSlider() { LEDSlider() {
maxHandlePos = mm2px(Vec(0.738, 0.738).plus(Vec(2, 0))); maxHandlePos = mm2px(Vec(0.738, 0.738).plus(Vec(2, 0)));
minHandlePos = mm2px(Vec(0.738, 22.078).plus(Vec(2, 0))); minHandlePos = mm2px(Vec(0.738, 22.078).plus(Vec(2, 0)));
setSVGs(SVG::load(context()->asset->system("res/ComponentLibrary/LEDSlider.svg")), NULL);
setSVGs(SVG::load(asset::system("res/ComponentLibrary/LEDSlider.svg")), NULL);
} }
}; };


/** API is unstable for LEDSlider. Will add a LightWidget later. */ /** API is unstable for LEDSlider. Will add a LightWidget later. */
struct LEDSliderGreen : LEDSlider { struct LEDSliderGreen : LEDSlider {
LEDSliderGreen() { LEDSliderGreen() {
handle->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/LEDSliderGreenHandle.svg")));
handle->setSVG(SVG::load(asset::system("res/ComponentLibrary/LEDSliderGreenHandle.svg")));
} }
}; };


struct LEDSliderRed : LEDSlider { struct LEDSliderRed : LEDSlider {
LEDSliderRed() { LEDSliderRed() {
handle->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/LEDSliderRedHandle.svg")));
handle->setSVG(SVG::load(asset::system("res/ComponentLibrary/LEDSliderRedHandle.svg")));
} }
}; };


struct LEDSliderYellow : LEDSlider { struct LEDSliderYellow : LEDSlider {
LEDSliderYellow() { LEDSliderYellow() {
handle->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/LEDSliderYellowHandle.svg")));
handle->setSVG(SVG::load(asset::system("res/ComponentLibrary/LEDSliderYellowHandle.svg")));
} }
}; };


struct LEDSliderBlue : LEDSlider { struct LEDSliderBlue : LEDSlider {
LEDSliderBlue() { LEDSliderBlue() {
handle->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/LEDSliderBlueHandle.svg")));
handle->setSVG(SVG::load(asset::system("res/ComponentLibrary/LEDSliderBlueHandle.svg")));
} }
}; };


struct LEDSliderWhite : LEDSlider { struct LEDSliderWhite : LEDSlider {
LEDSliderWhite() { LEDSliderWhite() {
handle->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/LEDSliderWhiteHandle.svg")));
handle->setSVG(SVG::load(asset::system("res/ComponentLibrary/LEDSliderWhiteHandle.svg")));
} }
}; };


@@ -379,19 +379,19 @@ struct LEDSliderWhite : LEDSlider {


struct PJ301MPort : SVGPort { struct PJ301MPort : SVGPort {
PJ301MPort() { PJ301MPort() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/PJ301M.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/PJ301M.svg")));
} }
}; };


struct PJ3410Port : SVGPort { struct PJ3410Port : SVGPort {
PJ3410Port() { PJ3410Port() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/PJ3410.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/PJ3410.svg")));
} }
}; };


struct CL1362Port : SVGPort { struct CL1362Port : SVGPort {
CL1362Port() { CL1362Port() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/CL1362.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/CL1362.svg")));
} }
}; };


@@ -514,83 +514,83 @@ struct PB61303Light : BASE {


struct NKK : SVGSwitch, ToggleSwitch { struct NKK : SVGSwitch, ToggleSwitch {
NKK() { NKK() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/NKK_0.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/NKK_1.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/NKK_2.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/NKK_0.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/NKK_1.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/NKK_2.svg")));
} }
}; };


struct CKSS : SVGSwitch, ToggleSwitch { struct CKSS : SVGSwitch, ToggleSwitch {
CKSS() { CKSS() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/CKSS_0.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/CKSS_1.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/CKSS_0.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/CKSS_1.svg")));
} }
}; };


struct CKSSThree : SVGSwitch, ToggleSwitch { struct CKSSThree : SVGSwitch, ToggleSwitch {
CKSSThree() { CKSSThree() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/CKSSThree_0.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/CKSSThree_1.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/CKSSThree_2.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/CKSSThree_0.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/CKSSThree_1.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/CKSSThree_2.svg")));
} }
}; };


struct CKD6 : SVGSwitch, MomentarySwitch { struct CKD6 : SVGSwitch, MomentarySwitch {
CKD6() { CKD6() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/CKD6_0.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/CKD6_1.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/CKD6_0.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/CKD6_1.svg")));
} }
}; };


struct TL1105 : SVGSwitch, MomentarySwitch { struct TL1105 : SVGSwitch, MomentarySwitch {
TL1105() { TL1105() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/TL1105_0.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/TL1105_1.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/TL1105_0.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/TL1105_1.svg")));
} }
}; };


struct LEDButton : SVGSwitch, MomentarySwitch { struct LEDButton : SVGSwitch, MomentarySwitch {
LEDButton() { LEDButton() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/LEDButton.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/LEDButton.svg")));
} }
}; };


struct BefacoSwitch : SVGSwitch, ToggleSwitch { struct BefacoSwitch : SVGSwitch, ToggleSwitch {
BefacoSwitch() { BefacoSwitch() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoSwitch_0.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoSwitch_1.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoSwitch_2.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/BefacoSwitch_0.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/BefacoSwitch_1.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/BefacoSwitch_2.svg")));
} }
}; };


struct BefacoPush : SVGSwitch, MomentarySwitch { struct BefacoPush : SVGSwitch, MomentarySwitch {
BefacoPush() { BefacoPush() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoPush_0.svg")));
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/BefacoPush_1.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/BefacoPush_0.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/BefacoPush_1.svg")));
} }
}; };


struct LEDBezel : SVGSwitch, MomentarySwitch { struct LEDBezel : SVGSwitch, MomentarySwitch {
LEDBezel() { LEDBezel() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/LEDBezel.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/LEDBezel.svg")));
} }
}; };


struct PB61303 : SVGSwitch, MomentarySwitch { struct PB61303 : SVGSwitch, MomentarySwitch {
PB61303() { PB61303() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/PB61303.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/PB61303.svg")));
} }
}; };


struct PB61303Button : SVGButton { struct PB61303Button : SVGButton {
PB61303Button() { PB61303Button() {
setSVGs(SVG::load(context()->asset->system("res/ComponentLibrary/PB61303.svg")), NULL);
setSVGs(SVG::load(asset::system("res/ComponentLibrary/PB61303.svg")), NULL);
} }
}; };


struct LEDBezelButton : SVGButton { struct LEDBezelButton : SVGButton {
LEDBezelButton() { LEDBezelButton() {
setSVGs(SVG::load(context()->asset->system("res/ComponentLibrary/LEDBezel.svg")), NULL);
setSVGs(SVG::load(asset::system("res/ComponentLibrary/LEDBezel.svg")), NULL);
} }
}; };


@@ -600,14 +600,14 @@ struct LEDBezelButton : SVGButton {


struct ScrewSilver : SVGScrew { struct ScrewSilver : SVGScrew {
ScrewSilver() { ScrewSilver() {
sw->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/ScrewSilver.svg")));
sw->setSVG(SVG::load(asset::system("res/ComponentLibrary/ScrewSilver.svg")));
box.size = sw->box.size; box.size = sw->box.size;
} }
}; };


struct ScrewBlack : SVGScrew { struct ScrewBlack : SVGScrew {
ScrewBlack() { ScrewBlack() {
sw->setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/ScrewBlack.svg")));
sw->setSVG(SVG::load(asset::system("res/ComponentLibrary/ScrewBlack.svg")));
box.size = sw->box.size; box.size = sw->box.size;
} }
}; };


+ 2
- 4
include/context.hpp View File

@@ -12,17 +12,15 @@ namespace event {
struct Scene; struct Scene;
struct Engine; struct Engine;
struct PluginManager; struct PluginManager;
struct AssetManager;
struct Window;




struct Context { struct Context {
bool devMode = false;

event::Context *event = NULL; event::Context *event = NULL;
Scene *scene = NULL; Scene *scene = NULL;
Engine *engine = NULL; Engine *engine = NULL;
PluginManager *plugin = NULL; PluginManager *plugin = NULL;
AssetManager *asset = NULL;
Window *window = NULL;
}; };






+ 1
- 1
include/helpers.hpp View File

@@ -144,7 +144,7 @@ TMenuItem *createMenuItem(std::string text, std::string rightText = "") {
// TODO Reevaluate this. Does it belong here? // TODO Reevaluate this. Does it belong here?
inline Menu *createMenu() { inline Menu *createMenu() {
Menu *o = new Menu; Menu *o = new Menu;
o->box.pos = gMousePos;
o->box.pos = context()->window->mousePos;


MenuOverlay *menuOverlay = new MenuOverlay; MenuOverlay *menuOverlay = new MenuOverlay;
menuOverlay->addChild(o); menuOverlay->addChild(o);


+ 1
- 1
include/logger.hpp View File

@@ -24,7 +24,7 @@ enum Level {
FATAL_LEVEL FATAL_LEVEL
}; };


void init();
void init(bool devMode);
void destroy(); void destroy();
/** Do not use this function directly. Use the macros below. */ /** Do not use this function directly. Use the macros below. */
void log(Level level, const char *filename, int line, const char *format, ...); void log(Level level, const char *filename, int line, const char *format, ...);


+ 1
- 1
include/plugin/PluginManager.hpp View File

@@ -17,7 +17,7 @@ struct PluginManager {
std::string downloadName; std::string downloadName;
std::string loginStatus; std::string loginStatus;


PluginManager();
PluginManager(bool devMode);
~PluginManager(); ~PluginManager();
void logIn(std::string email, std::string password); void logIn(std::string email, std::string password);
void logOut(); void logOut();


+ 1
- 1
include/rack.hpp View File

@@ -7,7 +7,7 @@
#include "system.hpp" #include "system.hpp"
#include "random.hpp" #include "random.hpp"
#include "network.hpp" #include "network.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "window.hpp" #include "window.hpp"
#include "context.hpp" #include "context.hpp"
#include "helpers.hpp" #include "helpers.hpp"


+ 3
- 3
include/rack0.hpp View File

@@ -69,9 +69,9 @@ DEPRECATED inline float randomf() {return random::uniform();}
// asset // asset
//////////////////// ////////////////////


DEPRECATED inline std::string assetGlobal(std::string filename) {return context()->asset->system(filename);}
DEPRECATED inline std::string assetLocal(std::string filename) {return context()->asset->user(filename);}
DEPRECATED inline std::string assetPlugin(Plugin *plugin, std::string filename) {return context()->asset->plugin(plugin, filename);}
DEPRECATED inline std::string assetGlobal(std::string filename) {return asset::system(filename);}
DEPRECATED inline std::string assetLocal(std::string filename) {return asset::user(filename);}
DEPRECATED inline std::string assetPlugin(Plugin *plugin, std::string filename) {return asset::plugin(plugin, filename);}


//////////////////// ////////////////////
// color // color


+ 13
- 0
include/svg.hpp View File

@@ -0,0 +1,13 @@
#pragma once
#include "common.hpp"
#include <nanovg.h>
#include <nanosvg.h>


namespace rack {


void svgDraw(NVGcontext *vg, NSVGimage *svg);


} // namespace rack

+ 15
- 0
include/ui.hpp View File

@@ -0,0 +1,15 @@
#pragma once
#include "ui/common.hpp"
#include "color.hpp"
#include "window.hpp"


namespace rack {


void uiInit();
void uiDestroy();
void uiSetTheme(NVGcolor bg, NVGcolor fg);


} // namespace rack

+ 3
- 3
include/ui/MenuItem.hpp View File

@@ -34,9 +34,9 @@ struct MenuItem : MenuEntry {
void step() override { void step() override {
// Add 10 more pixels because measurements on high-DPI screens are sometimes too small for some reason // Add 10 more pixels because measurements on high-DPI screens are sometimes too small for some reason
const float rightPadding = 10.0; const float rightPadding = 10.0;
// HACK use gVg from the window.
// All this does is inspect the font, so it shouldn't modify gVg and should work when called from a FramebufferWidget for example.
box.size.x = bndLabelWidth(gVg, -1, text.c_str()) + bndLabelWidth(gVg, -1, rightText.c_str()) + rightPadding;
// HACK use context()->window->vg from the window.
// All this does is inspect the font, so it shouldn't modify context()->window->vg and should work when called from a FramebufferWidget for example.
box.size.x = bndLabelWidth(context()->window->vg, -1, text.c_str()) + bndLabelWidth(context()->window->vg, -1, rightText.c_str()) + rightPadding;
Widget::step(); Widget::step();
} }




+ 3
- 2
include/ui/MenuLabel.hpp View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "ui/common.hpp" #include "ui/common.hpp"
#include "ui/MenuEntry.hpp" #include "ui/MenuEntry.hpp"
#include "context.hpp"




namespace rack { namespace rack {
@@ -16,8 +17,8 @@ struct MenuLabel : MenuEntry {
void step() override { void step() override {
// Add 10 more pixels because Retina measurements are sometimes too small // Add 10 more pixels because Retina measurements are sometimes too small
const float rightPadding = 10.0; const float rightPadding = 10.0;
// HACK use gVg from the window.
box.size.x = bndLabelWidth(gVg, -1, text.c_str()) + rightPadding;
// HACK use context()->window->vg from the window.
box.size.x = bndLabelWidth(context()->window->vg, -1, text.c_str()) + rightPadding;
Widget::step(); Widget::step();
} }
}; };


+ 9
- 9
include/ui/ScrollWidget.hpp View File

@@ -29,14 +29,14 @@ struct ScrollBar : OpaqueWidget {


void onDragStart(event::DragStart &e) override { void onDragStart(event::DragStart &e) override {
state = BND_ACTIVE; state = BND_ACTIVE;
windowCursorLock();
context()->window->cursorLock();
} }


void onDragMove(event::DragMove &e) override; void onDragMove(event::DragMove &e) override;


void onDragEnd(event::DragEnd &e) override { void onDragEnd(event::DragEnd &e) override {
state = BND_DEFAULT; state = BND_DEFAULT;
windowCursorUnlock();
context()->window->cursorUnlock();
} }
}; };


@@ -114,23 +114,23 @@ struct ScrollWidget : OpaqueWidget {
// Scroll with arrow keys // Scroll with arrow keys
if (!context()->event->selectedWidget) { if (!context()->event->selectedWidget) {
float arrowSpeed = 30.0; float arrowSpeed = 30.0;
if (windowIsShiftPressed() && windowIsModPressed())
if (context()->window->isShiftPressed() && context()->window->isModPressed())
arrowSpeed /= 16.0; arrowSpeed /= 16.0;
else if (windowIsShiftPressed())
else if (context()->window->isShiftPressed())
arrowSpeed *= 4.0; arrowSpeed *= 4.0;
else if (windowIsModPressed())
else if (context()->window->isModPressed())
arrowSpeed /= 4.0; arrowSpeed /= 4.0;


if (glfwGetKey(gWindow, GLFW_KEY_LEFT) == GLFW_PRESS) {
if (glfwGetKey(context()->window->win, GLFW_KEY_LEFT) == GLFW_PRESS) {
offset.x -= arrowSpeed; offset.x -= arrowSpeed;
} }
if (glfwGetKey(gWindow, GLFW_KEY_RIGHT) == GLFW_PRESS) {
if (glfwGetKey(context()->window->win, GLFW_KEY_RIGHT) == GLFW_PRESS) {
offset.x += arrowSpeed; offset.x += arrowSpeed;
} }
if (glfwGetKey(gWindow, GLFW_KEY_UP) == GLFW_PRESS) {
if (glfwGetKey(context()->window->win, GLFW_KEY_UP) == GLFW_PRESS) {
offset.y -= arrowSpeed; offset.y -= arrowSpeed;
} }
if (glfwGetKey(gWindow, GLFW_KEY_DOWN) == GLFW_PRESS) {
if (glfwGetKey(context()->window->win, GLFW_KEY_DOWN) == GLFW_PRESS) {
offset.y += arrowSpeed; offset.y += arrowSpeed;
} }
} }


+ 3
- 2
include/ui/Slider.hpp View File

@@ -2,6 +2,7 @@
#include "widgets/OpaqueWidget.hpp" #include "widgets/OpaqueWidget.hpp"
#include "ui/Quantity.hpp" #include "ui/Quantity.hpp"
#include "ui/common.hpp" #include "ui/common.hpp"
#include "context.hpp"




namespace rack { namespace rack {
@@ -31,7 +32,7 @@ struct Slider : OpaqueWidget {


void onDragStart(event::DragStart &e) override { void onDragStart(event::DragStart &e) override {
state = BND_ACTIVE; state = BND_ACTIVE;
windowCursorLock();
context()->window->cursorLock();
} }


void onDragMove(event::DragMove &e) override { void onDragMove(event::DragMove &e) override {
@@ -42,7 +43,7 @@ struct Slider : OpaqueWidget {


void onDragEnd(event::DragEnd &e) override { void onDragEnd(event::DragEnd &e) override {
state = BND_DEFAULT; state = BND_DEFAULT;
windowCursorUnlock();
context()->window->cursorUnlock();
} }


void onButton(event::Button &e) override { void onButton(event::Button &e) override {


+ 12
- 12
include/ui/TextField.hpp View File

@@ -109,7 +109,7 @@ struct TextField : OpaqueWidget {
} }
} break; } break;
case GLFW_KEY_LEFT: { case GLFW_KEY_LEFT: {
if (windowIsModPressed()) {
if (context()->window->isModPressed()) {
while (--cursor > 0) { while (--cursor > 0) {
if (text[cursor] == ' ') if (text[cursor] == ' ')
break; break;
@@ -118,12 +118,12 @@ struct TextField : OpaqueWidget {
else { else {
cursor--; cursor--;
} }
if (!windowIsShiftPressed()) {
if (!context()->window->isShiftPressed()) {
selection = cursor; selection = cursor;
} }
} break; } break;
case GLFW_KEY_RIGHT: { case GLFW_KEY_RIGHT: {
if (windowIsModPressed()) {
if (context()->window->isModPressed()) {
while (++cursor < (int) text.size()) { while (++cursor < (int) text.size()) {
if (text[cursor] == ' ') if (text[cursor] == ' ')
break; break;
@@ -132,7 +132,7 @@ struct TextField : OpaqueWidget {
else { else {
cursor++; cursor++;
} }
if (!windowIsShiftPressed()) {
if (!context()->window->isShiftPressed()) {
selection = cursor; selection = cursor;
} }
} break; } break;
@@ -143,33 +143,33 @@ struct TextField : OpaqueWidget {
selection = cursor = text.size(); selection = cursor = text.size();
} break; } break;
case GLFW_KEY_V: { case GLFW_KEY_V: {
if (windowIsModPressed()) {
const char *newText = glfwGetClipboardString(gWindow);
if (context()->window->isModPressed()) {
const char *newText = glfwGetClipboardString(context()->window->win);
if (newText) if (newText)
insertText(newText); insertText(newText);
} }
} break; } break;
case GLFW_KEY_X: { case GLFW_KEY_X: {
if (windowIsModPressed()) {
if (context()->window->isModPressed()) {
if (cursor != selection) { if (cursor != selection) {
int begin = std::min(cursor, selection); int begin = std::min(cursor, selection);
std::string selectedText = text.substr(begin, std::abs(selection - cursor)); std::string selectedText = text.substr(begin, std::abs(selection - cursor));
glfwSetClipboardString(gWindow, selectedText.c_str());
glfwSetClipboardString(context()->window->win, selectedText.c_str());
insertText(""); insertText("");
} }
} }
} break; } break;
case GLFW_KEY_C: { case GLFW_KEY_C: {
if (windowIsModPressed()) {
if (context()->window->isModPressed()) {
if (cursor != selection) { if (cursor != selection) {
int begin = std::min(cursor, selection); int begin = std::min(cursor, selection);
std::string selectedText = text.substr(begin, std::abs(selection - cursor)); std::string selectedText = text.substr(begin, std::abs(selection - cursor));
glfwSetClipboardString(gWindow, selectedText.c_str());
glfwSetClipboardString(context()->window->win, selectedText.c_str());
} }
} }
} break; } break;
case GLFW_KEY_A: { case GLFW_KEY_A: {
if (windowIsModPressed()) {
if (context()->window->isModPressed()) {
selection = 0; selection = 0;
cursor = text.size(); cursor = text.size();
} }
@@ -213,7 +213,7 @@ struct TextField : OpaqueWidget {
} }


virtual int getTextPosition(Vec mousePos) { virtual int getTextPosition(Vec mousePos) {
return bndTextFieldTextPosition(gVg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), mousePos.x, mousePos.y);
return bndTextFieldTextPosition(context()->window->vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), mousePos.x, mousePos.y);
} }
}; };




+ 1
- 0
include/ui/common.hpp View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "../common.hpp" #include "../common.hpp"
#include <nanovg.h>
#include <blendish.h> #include <blendish.h>


#define CHECKMARK_STRING "âś”" #define CHECKMARK_STRING "âś”"


+ 1
- 0
include/widgets/SVGWidget.hpp View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "widgets/Widget.hpp" #include "widgets/Widget.hpp"
#include "svg.hpp"




namespace rack { namespace rack {


+ 35
- 36
include/window.hpp View File

@@ -43,42 +43,41 @@ struct SVG {
static std::shared_ptr<SVG> load(const std::string &filename); static std::shared_ptr<SVG> load(const std::string &filename);
}; };



extern GLFWwindow *gWindow;
extern NVGcontext *gVg;
extern NVGcontext *gFramebufferVg;
/** The default font to use for GUI elements */
extern std::shared_ptr<Font> gGuiFont;
/** The scaling ratio */
extern float gPixelRatio;
/* The ratio between the framebuffer size and the window size reported by the OS.
This is not equal to gPixelRatio in general.
*/
extern float gWindowRatio;
extern bool gAllowCursorLock;
extern int gGuiFrame;
extern Vec gMousePos;


void windowInit();
void windowDestroy();
void windowRun();
void windowClose();
void windowCursorLock();
void windowCursorUnlock();
bool windowIsModPressed();
bool windowIsShiftPressed();
Vec windowGetWindowSize();
void windowSetWindowSize(Vec size);
Vec windowGetWindowPos();
void windowSetWindowPos(Vec pos);
bool windowIsMaximized();
void windowSetTheme(NVGcolor bg, NVGcolor fg);
void windowSetFullScreen(bool fullScreen);
bool windowGetFullScreen();

// In svg.cpp
void svgDraw(NVGcontext *vg, NSVGimage *svg);
struct Window {
GLFWwindow *win = NULL;
NVGcontext *vg = NULL;
NVGcontext *framebufferVg = NULL;
/** The scaling ratio */
float pixelRatio = 1.f;
/* The ratio between the framebuffer size and the window size reported by the OS.
This is not equal to gPixelRatio in general.
*/
float windowRatio = 1.f;
bool allowCursorLock = true;
int frame = 0;
/** The last known absolute mouse position in the window */
Vec mousePos;
std::shared_ptr<Font> uiFont;

struct Internal;
Internal *internal;

Window();
~Window();
void run();
void close();
void cursorLock();
void cursorUnlock();
bool isModPressed();
bool isShiftPressed();
Vec getWindowSize();
void setWindowSize(Vec size);
Vec getWindowPos();
void setWindowPos(Vec pos);
bool isMaximized();
void setFullScreen(bool fullScreen);
bool isFullScreen();
};




} // namespace rack } // namespace rack

+ 1
- 1
src/Core/AudioInterface.cpp View File

@@ -240,7 +240,7 @@ void AudioInterface::step() {


struct AudioInterfaceWidget : ModuleWidget { struct AudioInterfaceWidget : ModuleWidget {
AudioInterfaceWidget(AudioInterface *module) : ModuleWidget(module) { AudioInterfaceWidget(AudioInterface *module) : ModuleWidget(module) {
setPanel(SVG::load(context()->asset->system("res/Core/AudioInterface.svg")));
setPanel(SVG::load(asset::system("res/Core/AudioInterface.svg")));


addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));


+ 1
- 1
src/Core/MIDICCToCVInterface.cpp View File

@@ -182,7 +182,7 @@ struct MidiCcWidget : Grid16MidiWidget {


struct MIDICCToCVInterfaceWidget : ModuleWidget { struct MIDICCToCVInterfaceWidget : ModuleWidget {
MIDICCToCVInterfaceWidget(MIDICCToCVInterface *module) : ModuleWidget(module) { MIDICCToCVInterfaceWidget(MIDICCToCVInterface *module) : ModuleWidget(module) {
setPanel(SVG::load(context()->asset->system("res/Core/MIDICCToCVInterface.svg")));
setPanel(SVG::load(asset::system("res/Core/MIDICCToCVInterface.svg")));


addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));


+ 1
- 1
src/Core/MIDIToCVInterface.cpp View File

@@ -261,7 +261,7 @@ struct MIDIToCVInterface : Module {


struct MIDIToCVInterfaceWidget : ModuleWidget { struct MIDIToCVInterfaceWidget : ModuleWidget {
MIDIToCVInterfaceWidget(MIDIToCVInterface *module) : ModuleWidget(module) { MIDIToCVInterfaceWidget(MIDIToCVInterface *module) : ModuleWidget(module) {
setPanel(SVG::load(context()->asset->system("res/Core/MIDIToCVInterface.svg")));
setPanel(SVG::load(asset::system("res/Core/MIDIToCVInterface.svg")));


addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));


+ 1
- 1
src/Core/MIDITriggerToCVInterface.cpp View File

@@ -201,7 +201,7 @@ struct MidiTrigWidget : Grid16MidiWidget {


struct MIDITriggerToCVInterfaceWidget : ModuleWidget { struct MIDITriggerToCVInterfaceWidget : ModuleWidget {
MIDITriggerToCVInterfaceWidget(MIDITriggerToCVInterface *module) : ModuleWidget(module) { MIDITriggerToCVInterfaceWidget(MIDITriggerToCVInterface *module) : ModuleWidget(module) {
setPanel(SVG::load(context()->asset->system("res/Core/MIDITriggerToCVInterface.svg")));
setPanel(SVG::load(asset::system("res/Core/MIDITriggerToCVInterface.svg")));


addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));


+ 1
- 1
src/Core/Notes.cpp View File

@@ -8,7 +8,7 @@ struct NotesWidget : ModuleWidget {
TextField *textField; TextField *textField;


NotesWidget(Module *module) : ModuleWidget(module) { NotesWidget(Module *module) : ModuleWidget(module) {
setPanel(SVG::load(context()->asset->system("res/Core/Notes.svg")));
setPanel(SVG::load(asset::system("res/Core/Notes.svg")));


addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));


+ 1
- 1
src/Core/QuadMIDIToCVInterface.cpp View File

@@ -303,7 +303,7 @@ struct QuadMIDIToCVInterface : Module {


struct QuadMIDIToCVInterfaceWidget : ModuleWidget { struct QuadMIDIToCVInterfaceWidget : ModuleWidget {
QuadMIDIToCVInterfaceWidget(QuadMIDIToCVInterface *module) : ModuleWidget(module) { QuadMIDIToCVInterfaceWidget(QuadMIDIToCVInterface *module) : ModuleWidget(module) {
setPanel(SVG::load(context()->asset->system("res/Core/QuadMIDIToCVInterface.svg")));
setPanel(SVG::load(asset::system("res/Core/QuadMIDIToCVInterface.svg")));


addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));


+ 7
- 6
src/app/LedDisplay.cpp View File

@@ -1,8 +1,9 @@
#include "app/LedDisplay.hpp" #include "app/LedDisplay.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "window.hpp" #include "window.hpp"
#include "event.hpp" #include "event.hpp"
#include "context.hpp" #include "context.hpp"
#include "ui.hpp"




namespace rack { namespace rack {
@@ -34,7 +35,7 @@ void LedDisplaySeparator::draw(NVGcontext *vg) {


LedDisplayChoice::LedDisplayChoice() { LedDisplayChoice::LedDisplayChoice() {
box.size = mm2px(Vec(0, 28.0 / 3)); box.size = mm2px(Vec(0, 28.0 / 3));
font = Font::load(context()->asset->system("res/fonts/ShareTechMono-Regular.ttf"));
font = Font::load(asset::system("res/fonts/ShareTechMono-Regular.ttf"));
color = nvgRGB(0xff, 0xd7, 0x14); color = nvgRGB(0xff, 0xd7, 0x14);
textOffset = Vec(10, 18); textOffset = Vec(10, 18);
} }
@@ -64,7 +65,7 @@ void LedDisplayChoice::onButton(event::Button &e) {




LedDisplayTextField::LedDisplayTextField() { LedDisplayTextField::LedDisplayTextField() {
font = Font::load(context()->asset->system("res/fonts/ShareTechMono-Regular.ttf"));
font = Font::load(asset::system("res/fonts/ShareTechMono-Regular.ttf"));
color = nvgRGB(0xff, 0xd7, 0x14); color = nvgRGB(0xff, 0xd7, 0x14);
textOffset = Vec(5, 5); textOffset = Vec(5, 5);
} }
@@ -91,7 +92,7 @@ void LedDisplayTextField::draw(NVGcontext *vg) {
box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y, box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y,
-1, color, 12, text.c_str(), highlightColor, begin, end); -1, color, 12, text.c_str(), highlightColor, begin, end);


bndSetFont(gGuiFont->handle);
bndSetFont(context()->window->uiFont->handle);
} }


nvgResetScissor(vg); nvgResetScissor(vg);
@@ -99,10 +100,10 @@ void LedDisplayTextField::draw(NVGcontext *vg) {


int LedDisplayTextField::getTextPosition(Vec mousePos) { int LedDisplayTextField::getTextPosition(Vec mousePos) {
bndSetFont(font->handle); bndSetFont(font->handle);
int textPos = bndIconLabelTextPosition(gVg, textOffset.x, textOffset.y,
int textPos = bndIconLabelTextPosition(context()->window->vg, textOffset.x, textOffset.y,
box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y, box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y,
-1, 12, text.c_str(), mousePos.x, mousePos.y); -1, 12, text.c_str(), mousePos.x, mousePos.y);
bndSetFont(gGuiFont->handle);
bndSetFont(context()->window->uiFont->handle);
return textPos; return textPos;
} }




+ 16
- 14
src/app/ModuleWidget.cpp View File

@@ -2,10 +2,11 @@
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "system.hpp" #include "system.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "app/Scene.hpp" #include "app/Scene.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "context.hpp" #include "context.hpp"
#include "ui.hpp"


#include "osdialog.h" #include "osdialog.h"


@@ -124,13 +125,13 @@ void ModuleWidget::fromJson(json_t *rootJ) {
void ModuleWidget::copyClipboard() { void ModuleWidget::copyClipboard() {
json_t *moduleJ = toJson(); json_t *moduleJ = toJson();
char *moduleJson = json_dumps(moduleJ, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); char *moduleJson = json_dumps(moduleJ, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
glfwSetClipboardString(gWindow, moduleJson);
glfwSetClipboardString(context()->window->win, moduleJson);
free(moduleJson); free(moduleJson);
json_decref(moduleJ); json_decref(moduleJ);
} }


void ModuleWidget::pasteClipboard() { void ModuleWidget::pasteClipboard() {
const char *moduleJson = glfwGetClipboardString(gWindow);
const char *moduleJson = glfwGetClipboardString(context()->window->win);
if (!moduleJson) { if (!moduleJson) {
WARN("Could not get text from clipboard."); WARN("Could not get text from clipboard.");
return; return;
@@ -185,7 +186,7 @@ void ModuleWidget::save(std::string filename) {
} }


void ModuleWidget::loadDialog() { void ModuleWidget::loadDialog() {
std::string dir = context()->asset->user("presets");
std::string dir = asset::user("presets");
system::createDirectory(dir); system::createDirectory(dir);


osdialog_filters *filters = osdialog_filters_parse(PRESET_FILTERS.c_str()); osdialog_filters *filters = osdialog_filters_parse(PRESET_FILTERS.c_str());
@@ -198,7 +199,7 @@ void ModuleWidget::loadDialog() {
} }


void ModuleWidget::saveDialog() { void ModuleWidget::saveDialog() {
std::string dir = context()->asset->user("presets");
std::string dir = asset::user("presets");
system::createDirectory(dir); system::createDirectory(dir);


osdialog_filters *filters = osdialog_filters_parse(PRESET_FILTERS.c_str()); osdialog_filters *filters = osdialog_filters_parse(PRESET_FILTERS.c_str());
@@ -264,7 +265,8 @@ void ModuleWidget::draw(NVGcontext *vg) {
nvgFill(vg); nvgFill(vg);


std::string cpuText = string::f("%.0f mS", module->cpuTime * 1000.f); std::string cpuText = string::f("%.0f mS", module->cpuTime * 1000.f);
nvgFontFaceId(vg, gGuiFont->handle);
// TODO Use blendish text function
nvgFontFaceId(vg, context()->window->uiFont->handle);
nvgFontSize(vg, 12); nvgFontSize(vg, 12);
nvgFillColor(vg, nvgRGBf(1, 1, 1)); nvgFillColor(vg, nvgRGBf(1, 1, 1));
nvgText(vg, 10.0, box.size.y - 6.0, cpuText.c_str(), NULL); nvgText(vg, 10.0, box.size.y - 6.0, cpuText.c_str(), NULL);
@@ -297,8 +299,8 @@ void ModuleWidget::onHover(event::Hover &e) {
OpaqueWidget::onHover(e); OpaqueWidget::onHover(e);


// 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 (!windowIsModPressed() && !windowIsShiftPressed()) {
if (glfwGetKey(context()->window->win, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(context()->window->win, GLFW_KEY_BACKSPACE) == GLFW_PRESS) {
if (!context()->window->isModPressed() && !context()->window->isShiftPressed()) {
context()->scene->rackWidget->deleteModule(this); context()->scene->rackWidget->deleteModule(this);
delete this; delete this;
// e.target = this; // e.target = this;
@@ -319,42 +321,42 @@ void ModuleWidget::onButton(event::Button &e) {
void ModuleWidget::onHoverKey(event::HoverKey &e) { void ModuleWidget::onHoverKey(event::HoverKey &e) {
switch (e.key) { switch (e.key) {
case GLFW_KEY_I: { case GLFW_KEY_I: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
reset(); reset();
e.target = this; e.target = this;
return; return;
} }
} break; } break;
case GLFW_KEY_R: { case GLFW_KEY_R: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
randomize(); randomize();
e.target = this; e.target = this;
return; return;
} }
} break; } break;
case GLFW_KEY_C: { case GLFW_KEY_C: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
copyClipboard(); copyClipboard();
e.target = this; e.target = this;
return; return;
} }
} break; } break;
case GLFW_KEY_V: { case GLFW_KEY_V: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
pasteClipboard(); pasteClipboard();
e.target = this; e.target = this;
return; return;
} }
} break; } break;
case GLFW_KEY_D: { case GLFW_KEY_D: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
context()->scene->rackWidget->cloneModule(this); context()->scene->rackWidget->cloneModule(this);
e.target = this; e.target = this;
return; return;
} }
} break; } break;
case GLFW_KEY_U: { case GLFW_KEY_U: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
disconnect(); disconnect();
e.target = this; e.target = this;
return; return;


+ 1
- 1
src/app/PluginManagerWidget.cpp View File

@@ -77,7 +77,7 @@ struct SyncButton : Button {
// Display message if we've completed updates // Display message if we've completed updates
if (completed) { if (completed) {
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "All plugins have been updated. Close Rack and re-launch it to load new updates.")) { if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "All plugins have been updated. Close Rack and re-launch it to load new updates.")) {
windowClose();
context()->window->close();
} }
completed = false; completed = false;
} }


+ 1
- 1
src/app/Port.cpp View File

@@ -65,7 +65,7 @@ void Port::onButton(event::Button &e) {
void Port::onDragStart(event::DragStart &e) { void Port::onDragStart(event::DragStart &e) {
// Try to grab wire on top of stack // Try to grab wire on top of stack
WireWidget *wire = context()->scene->rackWidget->wireContainer->getTopWire(this); WireWidget *wire = context()->scene->rackWidget->wireContainer->getTopWire(this);
if (type == OUTPUT && windowIsModPressed()) {
if (type == OUTPUT && context()->window->isModPressed()) {
wire = NULL; wire = NULL;
} }




+ 1
- 1
src/app/RackScrollWidget.cpp View File

@@ -8,7 +8,7 @@ namespace rack {




void RackScrollWidget::step() { void RackScrollWidget::step() {
Vec pos = gMousePos;
Vec pos = context()->window->mousePos;
Rect viewport = getViewport(box.zeroPos()); Rect viewport = getViewport(box.zeroPos());
// Scroll rack if dragging cable near the edge of the screen // Scroll rack if dragging cable near the edge of the screen
if (context()->scene->rackWidget->wireContainer->activeWire) { if (context()->scene->rackWidget->wireContainer->activeWire) {


+ 8
- 8
src/app/RackWidget.cpp View File

@@ -6,7 +6,7 @@
#include "app/ModuleBrowser.hpp" #include "app/ModuleBrowser.hpp"
#include "osdialog.h" #include "osdialog.h"
#include "settings.hpp" #include "settings.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "system.hpp" #include "system.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "plugin/PluginManager.hpp" #include "plugin/PluginManager.hpp"
@@ -67,7 +67,7 @@ void RackWidget::reset() {
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "Clear patch and start over?")) { if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "Clear patch and start over?")) {
clear(); clear();
// Fails silently if file does not exist // Fails silently if file does not exist
load(context()->asset->user("template.vcv"));
load(asset::user("template.vcv"));
lastPath = ""; lastPath = "";
} }
} }
@@ -75,7 +75,7 @@ void RackWidget::reset() {
void RackWidget::loadDialog() { void RackWidget::loadDialog() {
std::string dir; std::string dir;
if (lastPath.empty()) { if (lastPath.empty()) {
dir = context()->asset->user("patches");
dir = asset::user("patches");
system::createDirectory(dir); system::createDirectory(dir);
} }
else { else {
@@ -104,7 +104,7 @@ void RackWidget::saveAsDialog() {
std::string dir; std::string dir;
std::string filename; std::string filename;
if (lastPath.empty()) { if (lastPath.empty()) {
dir = context()->asset->user("patches");
dir = asset::user("patches");
system::createDirectory(dir); system::createDirectory(dir);
} }
else { else {
@@ -392,7 +392,7 @@ ModuleWidget *RackWidget::moduleFromJson(json_t *moduleJ) {
} }


void RackWidget::pastePresetClipboard() { void RackWidget::pastePresetClipboard() {
const char *moduleJson = glfwGetClipboardString(gWindow);
const char *moduleJson = glfwGetClipboardString(context()->window->win);
if (!moduleJson) { if (!moduleJson) {
WARN("Could not get text from clipboard."); WARN("Could not get text from clipboard.");
return; return;
@@ -493,9 +493,9 @@ void RackWidget::step() {
} }


// Autosave every 15 seconds // Autosave every 15 seconds
if (gGuiFrame % (60 * 15) == 0) {
save(context()->asset->user("autosave.vcv"));
settings::save(context()->asset->user("settings.json"));
if (context()->window->frame % (60 * 15) == 0) {
save(asset::user("autosave.vcv"));
settings::save(asset::user("settings.json"));
} }


Widget::step(); Widget::step();


+ 11
- 11
src/app/Scene.cpp View File

@@ -44,7 +44,7 @@ void Scene::step() {
zoomWidget->box.size = rackWidget->box.size.mult(zoomWidget->zoom); zoomWidget->box.size = rackWidget->box.size.mult(zoomWidget->zoom);


// Request latest version from server // Request latest version from server
if (!context()->devMode && checkVersion && !checkedVersion) {
if (!devMode && checkVersion && !checkedVersion) {
std::thread t(&Scene::runCheckVersion, this); std::thread t(&Scene::runCheckVersion, this);
t.detach(); t.detach();
checkedVersion = true; checkedVersion = true;
@@ -56,7 +56,7 @@ void Scene::step() {
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, versionMessage.c_str())) { if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, versionMessage.c_str())) {
std::thread t(system::openBrowser, "https://vcvrack.com/"); std::thread t(system::openBrowser, "https://vcvrack.com/");
t.detach(); t.detach();
windowClose();
context()->window->close();
} }
latestVersion = ""; latestVersion = "";
} }
@@ -72,39 +72,39 @@ void Scene::onHoverKey(event::HoverKey &e) {
if (!e.target) { if (!e.target) {
switch (e.key) { switch (e.key) {
case GLFW_KEY_N: { case GLFW_KEY_N: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->reset(); rackWidget->reset();
e.target = this; e.target = this;
} }
} break; } break;
case GLFW_KEY_Q: { case GLFW_KEY_Q: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
windowClose();
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
context()->window->close();
e.target = this; e.target = this;
} }
} break; } break;
case GLFW_KEY_O: { case GLFW_KEY_O: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->loadDialog(); rackWidget->loadDialog();
e.target = this; e.target = this;
} }
if (windowIsModPressed() && windowIsShiftPressed()) {
if (context()->window->isModPressed() && context()->window->isShiftPressed()) {
rackWidget->revert(); rackWidget->revert();
e.target = this; e.target = this;
} }
} break; } break;
case GLFW_KEY_S: { case GLFW_KEY_S: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->saveDialog(); rackWidget->saveDialog();
e.target = this; e.target = this;
} }
if (windowIsModPressed() && windowIsShiftPressed()) {
if (context()->window->isModPressed() && context()->window->isShiftPressed()) {
rackWidget->saveAsDialog(); rackWidget->saveAsDialog();
e.target = this; e.target = this;
} }
} break; } break;
case GLFW_KEY_V: { case GLFW_KEY_V: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->pastePresetClipboard(); rackWidget->pastePresetClipboard();
e.target = this; e.target = this;
} }
@@ -115,7 +115,7 @@ void Scene::onHoverKey(event::HoverKey &e) {
e.target = this; e.target = this;
} break; } break;
case GLFW_KEY_F11: { case GLFW_KEY_F11: {
windowSetFullScreen(!windowGetFullScreen());
context()->window->setFullScreen(!context()->window->isFullScreen());
} }
} }
} }


+ 11
- 11
src/app/Toolbar.cpp View File

@@ -1,7 +1,7 @@
#include "app/Toolbar.hpp" #include "app/Toolbar.hpp"
#include "window.hpp" #include "window.hpp"
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "ui/Tooltip.hpp" #include "ui/Tooltip.hpp"
#include "ui/IconButton.hpp" #include "ui/IconButton.hpp"
#include "ui/SequentialLayout.hpp" #include "ui/SequentialLayout.hpp"
@@ -39,7 +39,7 @@ struct TooltipIconButton : IconButton {


struct NewButton : TooltipIconButton { struct NewButton : TooltipIconButton {
NewButton() { NewButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_146097_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_146097_cc.svg")));
} }
std::string getTooltipText() override {return "New patch (" WINDOW_MOD_KEY_NAME "+N)";} std::string getTooltipText() override {return "New patch (" WINDOW_MOD_KEY_NAME "+N)";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -49,7 +49,7 @@ struct NewButton : TooltipIconButton {


struct OpenButton : TooltipIconButton { struct OpenButton : TooltipIconButton {
OpenButton() { OpenButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_31859_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_31859_cc.svg")));
} }
std::string getTooltipText() override {return "Open patch (" WINDOW_MOD_KEY_NAME "+O)";} std::string getTooltipText() override {return "Open patch (" WINDOW_MOD_KEY_NAME "+O)";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -59,7 +59,7 @@ struct OpenButton : TooltipIconButton {


struct SaveButton : TooltipIconButton { struct SaveButton : TooltipIconButton {
SaveButton() { SaveButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_1343816_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_1343816_cc.svg")));
} }
std::string getTooltipText() override {return "Save patch (" WINDOW_MOD_KEY_NAME "+S)";} std::string getTooltipText() override {return "Save patch (" WINDOW_MOD_KEY_NAME "+S)";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -69,7 +69,7 @@ struct SaveButton : TooltipIconButton {


struct SaveAsButton : TooltipIconButton { struct SaveAsButton : TooltipIconButton {
SaveAsButton() { SaveAsButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_1343811_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_1343811_cc.svg")));
} }
std::string getTooltipText() override {return "Save patch as (" WINDOW_MOD_KEY_NAME "+Shift+S)";} std::string getTooltipText() override {return "Save patch as (" WINDOW_MOD_KEY_NAME "+Shift+S)";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -79,7 +79,7 @@ struct SaveAsButton : TooltipIconButton {


struct RevertButton : TooltipIconButton { struct RevertButton : TooltipIconButton {
RevertButton() { RevertButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_1084369_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_1084369_cc.svg")));
} }
std::string getTooltipText() override {return "Revert patch";} std::string getTooltipText() override {return "Revert patch";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -89,7 +89,7 @@ struct RevertButton : TooltipIconButton {


struct DisconnectCablesButton : TooltipIconButton { struct DisconnectCablesButton : TooltipIconButton {
DisconnectCablesButton() { DisconnectCablesButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_1745061_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_1745061_cc.svg")));
} }
std::string getTooltipText() override {return "Disconnect cables";} std::string getTooltipText() override {return "Disconnect cables";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -99,7 +99,7 @@ struct DisconnectCablesButton : TooltipIconButton {


struct PowerMeterButton : TooltipIconButton { struct PowerMeterButton : TooltipIconButton {
PowerMeterButton() { PowerMeterButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_305536_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_305536_cc.svg")));
} }
std::string getTooltipText() override {return "Toggle power meter (see manual for explanation)";} std::string getTooltipText() override {return "Toggle power meter (see manual for explanation)";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -123,7 +123,7 @@ struct SampleRateItem : MenuItem {


struct SampleRateButton : TooltipIconButton { struct SampleRateButton : TooltipIconButton {
SampleRateButton() { SampleRateButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_1240789_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_1240789_cc.svg")));
} }
std::string getTooltipText() override {return "Engine sample rate";} std::string getTooltipText() override {return "Engine sample rate";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -150,7 +150,7 @@ struct SampleRateButton : TooltipIconButton {


struct RackLockButton : TooltipIconButton { struct RackLockButton : TooltipIconButton {
RackLockButton() { RackLockButton() {
setSVG(SVG::load(context()->asset->system("res/icons/noun_468341_cc.svg")));
setSVG(SVG::load(asset::system("res/icons/noun_468341_cc.svg")));
} }
std::string getTooltipText() override {return "Lock modules";} std::string getTooltipText() override {return "Lock modules";}
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
@@ -238,7 +238,7 @@ Toolbar::Toolbar() {
layout->addChild(zoomSlider); layout->addChild(zoomSlider);


// Kind of hacky, but display the PluginManagerWidget only if the user directory is not the development directory // Kind of hacky, but display the PluginManagerWidget only if the user directory is not the development directory
if (context()->asset->user("") != "./") {
if (asset::user("") != "./") {
Widget *pluginManager = new PluginManagerWidget; Widget *pluginManager = new PluginManagerWidget;
layout->addChild(pluginManager); layout->addChild(pluginManager);
} }


src/AssetManager.cpp → src/asset.cpp View File

@@ -1,6 +1,5 @@
#include "AssetManager.hpp"
#include "asset.hpp"
#include "system.hpp" #include "system.hpp"
#include "context.hpp"
#include "plugin/Plugin.hpp" #include "plugin/Plugin.hpp"


#if ARCH_MAC #if ARCH_MAC
@@ -22,13 +21,14 @@




namespace rack { namespace rack {
namespace asset {




AssetManager::AssetManager() {
void init(bool devMode) {
// Get system dir // Get system dir
if (systemDir.empty()) {
if (context()->devMode) {
systemDir = ".";
if (gSystemDir.empty()) {
if (devMode) {
gSystemDir = ".";
} }
else { else {
#if ARCH_MAC #if ARCH_MAC
@@ -39,26 +39,26 @@ AssetManager::AssetManager() {
Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) resourcesBuf, sizeof(resourcesBuf)); Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) resourcesBuf, sizeof(resourcesBuf));
assert(success); assert(success);
CFRelease(resourcesUrl); CFRelease(resourcesUrl);
systemDir = resourcesBuf;
gSystemDir = resourcesBuf;
#endif #endif
#if ARCH_WIN #if ARCH_WIN
char moduleBuf[MAX_PATH]; char moduleBuf[MAX_PATH];
DWORD length = GetModuleFileName(NULL, moduleBuf, sizeof(moduleBuf)); DWORD length = GetModuleFileName(NULL, moduleBuf, sizeof(moduleBuf));
assert(length > 0); assert(length > 0);
PathRemoveFileSpec(moduleBuf); PathRemoveFileSpec(moduleBuf);
systemDir = moduleBuf;
gSystemDir = moduleBuf;
#endif #endif
#if ARCH_LIN #if ARCH_LIN
// TODO For now, users should launch Rack from their terminal in the system directory // TODO For now, users should launch Rack from their terminal in the system directory
systemDir = ".";
gSystemDir = ".";
#endif #endif
} }
} }


// Get user dir // Get user dir
if (userDir.empty()) {
if (context()->devMode) {
userDir = ".";
if (gUserDir.empty()) {
if (devMode) {
gUserDir = ".";
} }
else { else {
#if ARCH_WIN #if ARCH_WIN
@@ -66,15 +66,15 @@ AssetManager::AssetManager() {
char documentsBuf[MAX_PATH]; char documentsBuf[MAX_PATH];
HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBuf); HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBuf);
assert(result == S_OK); assert(result == S_OK);
userDir = documentsBuf;
userDir += "/Rack";
gUserDir = documentsBuf;
gUserDir += "/Rack";
#endif #endif
#if ARCH_MAC #if ARCH_MAC
// Get home directory // Get home directory
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
assert(pw); assert(pw);
userDir = pw->pw_dir;
userDir += "/Documents/Rack";
gUserDir = pw->pw_dir;
gUserDir += "/Documents/Rack";
#endif #endif
#if ARCH_LIN #if ARCH_LIN
// Get home directory // Get home directory
@@ -84,31 +84,36 @@ AssetManager::AssetManager() {
assert(pw); assert(pw);
homeBuf = pw->pw_dir; homeBuf = pw->pw_dir;
} }
userDir = homeBuf;
userDir += "/.Rack";
gUserDir = homeBuf;
gUserDir += "/.Rack";
#endif #endif
} }
} }


system::createDirectory(systemDir);
system::createDirectory(userDir);
system::createDirectory(gSystemDir);
system::createDirectory(gUserDir);
} }




std::string AssetManager::system(std::string filename) {
return systemDir + "/" + filename;
std::string system(std::string filename) {
return gSystemDir + "/" + filename;
} }




std::string AssetManager::user(std::string filename) {
return userDir + "/" + filename;
std::string user(std::string filename) {
return gUserDir + "/" + filename;
} }




std::string AssetManager::plugin(Plugin *plugin, std::string filename) {
std::string plugin(Plugin *plugin, std::string filename) {
assert(plugin); assert(plugin);
return plugin->path + "/" + filename; return plugin->path + "/" + filename;
} }




std::string gSystemDir;
std::string gUserDir;


} // namespace asset
} // namespace rack } // namespace rack

+ 0
- 4
src/event.cpp View File

@@ -219,9 +219,5 @@ void Context::handleZoom() {
} }




// TODO Move this elsewhere
Context *gContext = NULL;


} // namespace event } // namespace event
} // namespace rack } // namespace rack

+ 4
- 5
src/logger.cpp View File

@@ -1,6 +1,5 @@
#include "logger.hpp" #include "logger.hpp"
#include "AssetManager.hpp"
#include "context.hpp"
#include "asset.hpp"
#include <chrono> #include <chrono>




@@ -12,13 +11,13 @@ static FILE *outputFile = NULL;
static std::chrono::high_resolution_clock::time_point startTime; static std::chrono::high_resolution_clock::time_point startTime;




void init() {
void init(bool devMode) {
startTime = std::chrono::high_resolution_clock::now(); startTime = std::chrono::high_resolution_clock::now();
if (context()->devMode) {
if (devMode) {
outputFile = stderr; outputFile = stderr;
} }
else { else {
std::string logFilename = context()->asset->user("log.txt");
std::string logFilename = asset::user("log.txt");
outputFile = fopen(logFilename.c_str(), "w"); outputFile = fopen(logFilename.c_str(), "w");
} }
} }


+ 34
- 28
src/main.cpp View File

@@ -1,7 +1,7 @@
#include "common.hpp" #include "common.hpp"
#include "random.hpp" #include "random.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "rtmidi.hpp" #include "rtmidi.hpp"
#include "keyboard.hpp" #include "keyboard.hpp"
#include "gamepad.hpp" #include "gamepad.hpp"
@@ -12,6 +12,7 @@
#include "tags.hpp" #include "tags.hpp"
#include "plugin/PluginManager.hpp" #include "plugin/PluginManager.hpp"
#include "context.hpp" #include "context.hpp"
#include "ui.hpp"


#include <unistd.h> #include <unistd.h>
#include <osdialog.h> #include <osdialog.h>
@@ -35,6 +36,7 @@ int main(int argc, char *argv[]) {
(void) instanceMutex; (void) instanceMutex;
#endif #endif


bool devMode = false;
std::string patchFile; std::string patchFile;


// Parse command line arguments // Parse command line arguments
@@ -43,13 +45,13 @@ int main(int argc, char *argv[]) {
while ((c = getopt(argc, argv, "ds:u:")) != -1) { while ((c = getopt(argc, argv, "ds:u:")) != -1) {
switch (c) { switch (c) {
case 'd': { case 'd': {
context()->devMode = true;
devMode = true;
} break; } break;
case 's': { case 's': {
context()->asset->systemDir = optarg;
asset::gSystemDir = optarg;
} break; } break;
case 'u': { case 'u': {
context()->asset->userDir = optarg;
asset::gUserDir = optarg;
} break; } break;
default: break; default: break;
} }
@@ -60,35 +62,37 @@ int main(int argc, char *argv[]) {


// Initialize environment // Initialize environment
random::init(); random::init();
context()->asset = new AssetManager;
logger::init();
asset::init(devMode);
logger::init(devMode);
tagsInit();
rtmidiInit();
bridgeInit();
keyboard::init();
gamepad::init();
uiInit();


// Log environment // Log environment
INFO("%s %s", APP_NAME.c_str(), APP_VERSION.c_str()); INFO("%s %s", APP_NAME.c_str(), APP_VERSION.c_str());
if (context()->devMode)
if (devMode)
INFO("Development mode"); INFO("Development mode");
INFO("System directory: %s", context()->asset->system("").c_str());
INFO("User directory: %s", context()->asset->user("").c_str());
INFO("System directory: %s", asset::gSystemDir.c_str());
INFO("User directory: %s", asset::gUserDir.c_str());


// Initialize app // Initialize app
tagsInit();
context()->plugin = new PluginManager;
context()->plugin = new PluginManager(devMode);
context()->engine = new Engine; context()->engine = new Engine;
rtmidiInit();
bridgeInit();
keyboard::init();
gamepad::init();
context()->event = new event::Context; context()->event = new event::Context;
context()->scene = new Scene; context()->scene = new Scene;
context()->scene->devMode = devMode;
context()->event->rootWidget = context()->scene; context()->event->rootWidget = context()->scene;
windowInit();
settings::load(context()->asset->user("settings.json"));
context()->window = new Window;
settings::load(asset::user("settings.json"));


if (patchFile.empty()) { if (patchFile.empty()) {
// To prevent launch crashes, if Rack crashes between now and 15 seconds from now, the "skipAutosaveOnLaunch" property will remain in settings.json, so that in the next launch, the broken autosave will not be loaded. // To prevent launch crashes, if Rack crashes between now and 15 seconds from now, the "skipAutosaveOnLaunch" property will remain in settings.json, so that in the next launch, the broken autosave will not be loaded.
bool oldSkipAutosaveOnLaunch = settings::gSkipAutosaveOnLaunch; bool oldSkipAutosaveOnLaunch = settings::gSkipAutosaveOnLaunch;
settings::gSkipAutosaveOnLaunch = true; settings::gSkipAutosaveOnLaunch = true;
settings::save(context()->asset->user("settings.json"));
settings::save(asset::user("settings.json"));
settings::gSkipAutosaveOnLaunch = false; settings::gSkipAutosaveOnLaunch = false;
if (oldSkipAutosaveOnLaunch && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack has recovered from a crash, possibly caused by a faulty module in your patch. Clear your patch and start over?")) { if (oldSkipAutosaveOnLaunch && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack has recovered from a crash, possibly caused by a faulty module in your patch. Clear your patch and start over?")) {
context()->scene->rackWidget->lastPath = ""; context()->scene->rackWidget->lastPath = "";
@@ -96,7 +100,7 @@ int main(int argc, char *argv[]) {
else { else {
// Load autosave // Load autosave
std::string oldLastPath = context()->scene->rackWidget->lastPath; std::string oldLastPath = context()->scene->rackWidget->lastPath;
context()->scene->rackWidget->load(context()->asset->user("autosave.vcv"));
context()->scene->rackWidget->load(asset::user("autosave.vcv"));
context()->scene->rackWidget->lastPath = oldLastPath; context()->scene->rackWidget->lastPath = oldLastPath;
} }
} }
@@ -107,25 +111,27 @@ int main(int argc, char *argv[]) {
} }


context()->engine->start(); context()->engine->start();
windowRun();
context()->window->run();
context()->engine->stop(); context()->engine->stop();


// Destroy namespaces
context()->scene->rackWidget->save(context()->asset->user("autosave.vcv"));
settings::save(context()->asset->user("settings.json"));
// Destroy app
context()->scene->rackWidget->save(asset::user("autosave.vcv"));
settings::save(asset::user("settings.json"));
delete context()->scene; delete context()->scene;
context()->scene = NULL; context()->scene = NULL;
delete context()->event; delete context()->event;
context()->event = NULL; context()->event = NULL;
windowDestroy();
bridgeDestroy();
delete context()->window;
context()->window = NULL;
delete context()->engine; delete context()->engine;
context()->engine = NULL; context()->engine = NULL;
midiDestroy();
delete context()->plugin; delete context()->plugin;
context()->plugin = NULL; context()->plugin = NULL;
delete context()->asset;
context()->asset = NULL;

// Destroy environment
uiDestroy();
bridgeDestroy();
midiDestroy();
logger::destroy(); logger::destroy();


return 0; return 0;


+ 8
- 8
src/plugin/PluginManager.cpp View File

@@ -2,7 +2,7 @@
#include "system.hpp" #include "system.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "network.hpp" #include "network.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "string.hpp" #include "string.hpp"
#include "context.hpp" #include "context.hpp"
#include "app/common.hpp" #include "app/common.hpp"
@@ -178,7 +178,7 @@ static bool PluginManager_syncPlugin(PluginManager *pluginManager, std::string s
INFO("Downloading plugin %s %s %s", slug.c_str(), latestVersion.c_str(), arch.c_str()); INFO("Downloading plugin %s %s %s", slug.c_str(), latestVersion.c_str(), arch.c_str());


// Download zip // Download zip
std::string pluginDest = context()->asset->user("plugins/" + slug + ".zip");
std::string pluginDest = asset::user("plugins/" + slug + ".zip");
if (!network::requestDownload(downloadUrl, pluginDest, &pluginManager->downloadProgress)) { if (!network::requestDownload(downloadUrl, pluginDest, &pluginManager->downloadProgress)) {
WARN("Plugin %s download was unsuccessful", slug.c_str()); WARN("Plugin %s download was unsuccessful", slug.c_str());
return false; return false;
@@ -300,7 +300,7 @@ static void extractPackages(std::string path) {
// public API // public API
//////////////////// ////////////////////


PluginManager::PluginManager() {
PluginManager::PluginManager(bool devMode) {
// Load core // Load core
// This function is defined in core.cpp // This function is defined in core.cpp
Plugin *corePlugin = new Plugin; Plugin *corePlugin = new Plugin;
@@ -308,14 +308,14 @@ PluginManager::PluginManager() {
plugins.push_back(corePlugin); plugins.push_back(corePlugin);


// Get user plugins directory // Get user plugins directory
std::string userPlugins = context()->asset->user("plugins");
std::string userPlugins = asset::user("plugins");
mkdir(userPlugins.c_str(), 0755); mkdir(userPlugins.c_str(), 0755);


if (!context()->devMode) {
if (devMode) {
// Copy Fundamental package to plugins directory if folder does not exist // Copy Fundamental package to plugins directory if folder does not exist
std::string fundamentalSrc = context()->asset->system("Fundamental.zip");
std::string fundamentalDest = context()->asset->user("plugins/Fundamental.zip");
std::string fundamentalDir = context()->asset->user("plugins/Fundamental");
std::string fundamentalSrc = asset::system("Fundamental.zip");
std::string fundamentalDest = asset::user("plugins/Fundamental.zip");
std::string fundamentalDir = asset::user("plugins/Fundamental");
if (system::isFile(fundamentalSrc) && !system::isFile(fundamentalDest) && !system::isDirectory(fundamentalDir)) { if (system::isFile(fundamentalSrc) && !system::isFile(fundamentalDest) && !system::isDirectory(fundamentalDir)) {
system::copyFile(fundamentalSrc, fundamentalDest); system::copyFile(fundamentalSrc, fundamentalDest);
} }


+ 7
- 7
src/settings.cpp View File

@@ -24,14 +24,14 @@ static json_t *settingsToJson() {
json_t *tokenJ = json_string(context()->plugin->token.c_str()); json_t *tokenJ = json_string(context()->plugin->token.c_str());
json_object_set_new(rootJ, "token", tokenJ); json_object_set_new(rootJ, "token", tokenJ);


if (!windowIsMaximized()) {
if (!context()->window->isMaximized()) {
// windowSize // windowSize
Vec windowSize = windowGetWindowSize();
Vec windowSize = context()->window->getWindowSize();
json_t *windowSizeJ = json_pack("[f, f]", windowSize.x, windowSize.y); json_t *windowSizeJ = json_pack("[f, f]", windowSize.x, windowSize.y);
json_object_set_new(rootJ, "windowSize", windowSizeJ); json_object_set_new(rootJ, "windowSize", windowSizeJ);


// windowPos // windowPos
Vec windowPos = windowGetWindowPos();
Vec windowPos = context()->window->getWindowPos();
json_t *windowPosJ = json_pack("[f, f]", windowPos.x, windowPos.y); json_t *windowPosJ = json_pack("[f, f]", windowPos.x, windowPos.y);
json_object_set_new(rootJ, "windowPos", windowPosJ); json_object_set_new(rootJ, "windowPos", windowPosJ);
} }
@@ -52,7 +52,7 @@ static json_t *settingsToJson() {
json_object_set_new(rootJ, "zoom", zoomJ); json_object_set_new(rootJ, "zoom", zoomJ);


// allowCursorLock // allowCursorLock
json_t *allowCursorLockJ = json_boolean(gAllowCursorLock);
json_t *allowCursorLockJ = json_boolean(context()->window->allowCursorLock);
json_object_set_new(rootJ, "allowCursorLock", allowCursorLockJ); json_object_set_new(rootJ, "allowCursorLock", allowCursorLockJ);


// sampleRate // sampleRate
@@ -91,7 +91,7 @@ static void settingsFromJson(json_t *rootJ) {
if (windowSizeJ) { if (windowSizeJ) {
double width, height; double width, height;
json_unpack(windowSizeJ, "[F, F]", &width, &height); json_unpack(windowSizeJ, "[F, F]", &width, &height);
windowSetWindowSize(Vec(width, height));
context()->window->setWindowSize(Vec(width, height));
} }


// windowPos // windowPos
@@ -99,7 +99,7 @@ static void settingsFromJson(json_t *rootJ) {
if (windowPosJ) { if (windowPosJ) {
double x, y; double x, y;
json_unpack(windowPosJ, "[F, F]", &x, &y); json_unpack(windowPosJ, "[F, F]", &x, &y);
windowSetWindowPos(Vec(x, y));
context()->window->setWindowPos(Vec(x, y));
} }


// opacity // opacity
@@ -121,7 +121,7 @@ static void settingsFromJson(json_t *rootJ) {
// allowCursorLock // allowCursorLock
json_t *allowCursorLockJ = json_object_get(rootJ, "allowCursorLock"); json_t *allowCursorLockJ = json_object_get(rootJ, "allowCursorLock");
if (allowCursorLockJ) if (allowCursorLockJ)
gAllowCursorLock = json_is_true(allowCursorLockJ);
context()->window->allowCursorLock = json_is_true(allowCursorLockJ);


// sampleRate // sampleRate
json_t *sampleRateJ = json_object_get(rootJ, "sampleRate"); json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");


+ 2
- 4
src/svg.cpp View File

@@ -1,4 +1,5 @@
#include "window.hpp"
#include "svg.hpp"
#include "math.hpp"




// #define DEBUG_ONLY(x) x // #define DEBUG_ONLY(x) x
@@ -186,9 +187,6 @@ void svgDraw(NVGcontext *vg, NSVGimage *svg) {
} }


nvgRestore(vg); nvgRestore(vg);

// if (std::string(shape->id) == "rect19347")
// exit(0);
} }


DEBUG_ONLY(printf("\n");) DEBUG_ONLY(printf("\n");)


+ 64
- 0
src/ui.cpp View File

@@ -0,0 +1,64 @@
#include "ui.hpp"


namespace rack {


void uiInit(){
uiSetTheme(nvgRGB(0x33, 0x33, 0x33), nvgRGB(0xf0, 0xf0, 0xf0));
}

void uiDestroy() {
}

void uiSetTheme(NVGcolor bg, NVGcolor fg) {
// Assume dark background and light foreground

BNDwidgetTheme w;
w.outlineColor = bg;
w.itemColor = fg;
w.innerColor = bg;
w.innerSelectedColor = color::plus(bg, nvgRGB(0x30, 0x30, 0x30));
w.textColor = fg;
w.textSelectedColor = fg;
w.shadeTop = 0;
w.shadeDown = 0;

BNDtheme t;
t.backgroundColor = color::plus(bg, nvgRGB(0x30, 0x30, 0x30));
t.regularTheme = w;
t.toolTheme = w;
t.radioTheme = w;
t.textFieldTheme = w;
t.optionTheme = w;
t.choiceTheme = w;
t.numberFieldTheme = w;
t.sliderTheme = w;
t.scrollBarTheme = w;
t.tooltipTheme = w;
t.menuTheme = w;
t.menuItemTheme = w;

t.sliderTheme.itemColor = bg;
t.sliderTheme.innerColor = color::plus(bg, nvgRGB(0x50, 0x50, 0x50));
t.sliderTheme.innerSelectedColor = color::plus(bg, nvgRGB(0x60, 0x60, 0x60));

t.textFieldTheme = t.sliderTheme;
t.textFieldTheme.textColor = color::minus(bg, nvgRGB(0x20, 0x20, 0x20));
t.textFieldTheme.textSelectedColor = t.textFieldTheme.textColor;

t.scrollBarTheme.itemColor = color::plus(bg, nvgRGB(0x50, 0x50, 0x50));
t.scrollBarTheme.innerColor = bg;

t.menuTheme.innerColor = color::minus(bg, nvgRGB(0x10, 0x10, 0x10));
t.menuTheme.textColor = color::minus(fg, nvgRGB(0x50, 0x50, 0x50));
t.menuTheme.textSelectedColor = t.menuTheme.textColor;

bndSetTheme(t);
}


std::shared_ptr<Font> gGuiFont;


} // namespace rack

+ 11
- 9
src/widgets/FramebufferWidget.cpp View File

@@ -1,4 +1,5 @@
#include "widgets/FramebufferWidget.hpp" #include "widgets/FramebufferWidget.hpp"
#include "context.hpp"
#include <nanovg_gl.h> #include <nanovg_gl.h>
#include <nanovg_gl_utils.h> #include <nanovg_gl_utils.h>


@@ -54,7 +55,7 @@ void FramebufferWidget::draw(NVGcontext *vg) {
internal->box.pos = internal->box.pos.mult(s).floor(); internal->box.pos = internal->box.pos.mult(s).floor();
internal->box.size = internal->box.size.mult(s).ceil().plus(Vec(1, 1)); internal->box.size = internal->box.size.mult(s).ceil().plus(Vec(1, 1));


Vec fbSize = internal->box.size.mult(gPixelRatio * oversample);
Vec fbSize = internal->box.size.mult(context()->window->pixelRatio * oversample);


if (!fbSize.isFinite()) if (!fbSize.isFinite())
return; return;
@@ -65,7 +66,7 @@ void FramebufferWidget::draw(NVGcontext *vg) {
// Delete old one first to free up GPU memory // Delete old one first to free up GPU memory
internal->setFramebuffer(NULL); internal->setFramebuffer(NULL);
// Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context. // Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context.
NVGLUframebuffer *fb = nvgluCreateFramebuffer(gVg, fbSize.x, fbSize.y, 0);
NVGLUframebuffer *fb = nvgluCreateFramebuffer(context()->window->vg, fbSize.x, fbSize.y, 0);
if (!fb) if (!fb)
return; return;
internal->setFramebuffer(fb); internal->setFramebuffer(fb);
@@ -75,16 +76,17 @@ void FramebufferWidget::draw(NVGcontext *vg) {
glClearColor(0.0, 0.0, 0.0, 0.0); glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


nvgBeginFrame(gFramebufferVg, fbSize.x, fbSize.y, gPixelRatio * oversample);
NVGcontext *framebufferVg = context()->window->framebufferVg;
nvgBeginFrame(framebufferVg, fbSize.x, fbSize.y, context()->window->pixelRatio * oversample);


nvgScale(gFramebufferVg, gPixelRatio * oversample, gPixelRatio * oversample);
nvgScale(framebufferVg, context()->window->pixelRatio * oversample, context()->window->pixelRatio * oversample);
// Use local scaling // Use local scaling
nvgTranslate(gFramebufferVg, bf.x, bf.y);
nvgTranslate(gFramebufferVg, -internal->box.pos.x, -internal->box.pos.y);
nvgScale(gFramebufferVg, s.x, s.y);
Widget::draw(gFramebufferVg);
nvgTranslate(framebufferVg, bf.x, bf.y);
nvgTranslate(framebufferVg, -internal->box.pos.x, -internal->box.pos.y);
nvgScale(framebufferVg, s.x, s.y);
Widget::draw(framebufferVg);


nvgEndFrame(gFramebufferVg);
nvgEndFrame(framebufferVg);
nvgluBindFramebuffer(NULL); nvgluBindFramebuffer(NULL);
} }




+ 172
- 218
src/window.cpp View File

@@ -1,6 +1,6 @@
#include "window.hpp" #include "window.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "app/Scene.hpp" #include "app/Scene.hpp"
#include "keyboard.hpp" #include "keyboard.hpp"
#include "gamepad.hpp" #include "gamepad.hpp"
@@ -36,24 +36,32 @@
namespace rack { namespace rack {




GLFWwindow *gWindow = NULL;
NVGcontext *gVg = NULL;
NVGcontext *gFramebufferVg = NULL;
std::shared_ptr<Font> gGuiFont;
float gPixelRatio = 1.0;
float gWindowRatio = 1.0;
bool gAllowCursorLock = true;
int gGuiFrame;
Vec gMousePos;
struct MouseButtonArguments {
GLFWwindow *win;
int button;
int action;
int mods;
};



std::string lastWindowTitle;
struct Window::Internal {
std::string lastWindowTitle;


int lastWindowX = 0;
int lastWindowY = 0;
int lastWindowWidth = 0;
int lastWindowHeight = 0;


static void windowSizeCallback(GLFWwindow* window, int width, int height) {
std::queue<MouseButtonArguments> mouseButtonQueue;
};


static void windowSizeCallback(GLFWwindow *win, int width, int height) {
// Do nothing. Window size is reset each frame anyway. // Do nothing. Window size is reset each frame anyway.
} }


static void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) {
static void mouseButtonCallback(GLFWwindow *win, int button, int action, int mods) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
#ifdef ARCH_MAC #ifdef ARCH_MAC
// Remap Ctrl-left click to right click on Mac // Remap Ctrl-left click to right click on Mac
if (button == GLFW_MOUSE_BUTTON_LEFT) { if (button == GLFW_MOUSE_BUTTON_LEFT) {
@@ -63,36 +71,30 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int
} }
#endif #endif


context()->event->handleButton(gMousePos, button, action, mods);
context()->event->handleButton(window->mousePos, button, action, mods);
} }


struct MouseButtonArguments {
GLFWwindow *window;
int button;
int action;
int mods;
};

static std::queue<MouseButtonArguments> mouseButtonQueue;
void mouseButtonStickyPop() {
if (!mouseButtonQueue.empty()) {
MouseButtonArguments args = mouseButtonQueue.front();
mouseButtonQueue.pop();
mouseButtonCallback(args.window, args.button, args.action, args.mods);
static void Window_mouseButtonStickyPop(Window *window) {
if (!window->internal->mouseButtonQueue.empty()) {
MouseButtonArguments args = window->internal->mouseButtonQueue.front();
window->internal->mouseButtonQueue.pop();
mouseButtonCallback(args.win, args.button, args.action, args.mods);
} }
} }


void mouseButtonStickyCallback(GLFWwindow *window, int button, int action, int mods) {
static void mouseButtonStickyCallback(GLFWwindow *win, int button, int action, int mods) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
// Defer multiple clicks per frame to future frames // Defer multiple clicks per frame to future frames
MouseButtonArguments args = {window, button, action, mods};
mouseButtonQueue.push(args);
MouseButtonArguments args = {win, button, action, mods};
window->internal->mouseButtonQueue.push(args);
} }


void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) {
Vec mousePos = Vec(xpos, ypos).div(gPixelRatio / gWindowRatio).round();
Vec mouseDelta = mousePos.minus(gMousePos);
static void cursorPosCallback(GLFWwindow *win, double xpos, double ypos) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
Vec mousePos = Vec(xpos, ypos).div(window->pixelRatio / window->windowRatio).round();
Vec mouseDelta = mousePos.minus(window->mousePos);


int cursorMode = glfwGetInputMode(gWindow, GLFW_CURSOR);
int cursorMode = glfwGetInputMode(win, GLFW_CURSOR);
(void) cursorMode; (void) cursorMode;


#ifdef ARCH_MAC #ifdef ARCH_MAC
@@ -100,42 +102,45 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) {
// This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped. // This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped.
if (cursorMode == GLFW_CURSOR_HIDDEN) { if (cursorMode == GLFW_CURSOR_HIDDEN) {
// CGSetLocalEventsSuppressionInterval(0.0); // CGSetLocalEventsSuppressionInterval(0.0);
glfwSetCursorPos(gWindow, gMousePos.x, gMousePos.y);
glfwSetCursorPos(win, window->mousePos.x, window->mousePos.y);
CGAssociateMouseAndMouseCursorPosition(true); CGAssociateMouseAndMouseCursorPosition(true);
mousePos = gMousePos;
mousePos = window->mousePos;
} }
// Because sometimes the cursor turns into an arrow when its position is on the boundary of the window // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window
glfwSetCursor(gWindow, NULL);
glfwSetCursor(win, NULL);
#endif #endif


gMousePos = mousePos;
window->mousePos = mousePos;


context()->event->handleHover(mousePos, mouseDelta); context()->event->handleHover(mousePos, mouseDelta);
} }


void cursorEnterCallback(GLFWwindow* window, int entered) {
static void cursorEnterCallback(GLFWwindow *win, int entered) {
if (!entered) { if (!entered) {
context()->event->handleLeave(); context()->event->handleLeave();
} }
} }


void scrollCallback(GLFWwindow *window, double x, double y) {
static void scrollCallback(GLFWwindow *win, double x, double y) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
Vec scrollDelta = Vec(x, y); Vec scrollDelta = Vec(x, y);
#if ARCH_LIN || ARCH_WIN #if ARCH_LIN || ARCH_WIN
if (windowIsShiftPressed())
if (window->isShiftPressed())
scrollDelta = Vec(y, x); scrollDelta = Vec(y, x);
#endif #endif
scrollDelta = scrollDelta.mult(50.0); scrollDelta = scrollDelta.mult(50.0);


context()->event->handleScroll(gMousePos, scrollDelta);
context()->event->handleScroll(window->mousePos, scrollDelta);
} }


void charCallback(GLFWwindow *window, unsigned int codepoint) {
context()->event->handleText(gMousePos, codepoint);
static void charCallback(GLFWwindow *win, unsigned int codepoint) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
context()->event->handleText(window->mousePos, codepoint);
} }


void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
context()->event->handleKey(gMousePos, key, scancode, action, mods);
static void keyCallback(GLFWwindow *win, int key, int scancode, int action, int mods) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
context()->event->handleKey(window->mousePos, key, scancode, action, mods);


// Keyboard MIDI driver // Keyboard MIDI driver
if (!(mods & (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER))) { if (!(mods & (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER))) {
@@ -148,37 +153,22 @@ void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods
} }
} }


void dropCallback(GLFWwindow *window, int count, const char **paths) {
static void dropCallback(GLFWwindow *win, int count, const char **paths) {
Window *window = (Window*) glfwGetWindowUserPointer(win);
std::vector<std::string> pathsVec; std::vector<std::string> pathsVec;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
pathsVec.push_back(paths[i]); pathsVec.push_back(paths[i]);
} }
context()->event->handleDrop(gMousePos, pathsVec);
context()->event->handleDrop(window->mousePos, pathsVec);
} }


void errorCallback(int error, const char *description) {
static void errorCallback(int error, const char *description) {
WARN("GLFW error %d: %s", error, description); WARN("GLFW error %d: %s", error, description);
} }


void renderGui() {
int width, height;
glfwGetFramebufferSize(gWindow, &width, &height);

// Update and render
nvgBeginFrame(gVg, width, height, gPixelRatio);
Window::Window() {
internal = new Internal;


nvgReset(gVg);
nvgScale(gVg, gPixelRatio, gPixelRatio);
context()->event->rootWidget->draw(gVg);

glViewport(0, 0, width, height);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgEndFrame(gVg);
glfwSwapBuffers(gWindow);
}

void windowInit() {
int err; int err;


// Set up GLFW // Set up GLFW
@@ -200,28 +190,29 @@ void windowInit() {
#endif #endif
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE); glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
lastWindowTitle = "";
gWindow = glfwCreateWindow(640, 480, lastWindowTitle.c_str(), NULL, NULL);
if (!gWindow) {
internal->lastWindowTitle = "";
win = glfwCreateWindow(640, 480, internal->lastWindowTitle.c_str(), NULL, NULL);

if (!win) {
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Cannot open window with OpenGL 2.0 renderer. Does your graphics card support OpenGL 2.0 or greater? If so, make sure you have the latest graphics drivers installed."); osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Cannot open window with OpenGL 2.0 renderer. Does your graphics card support OpenGL 2.0 or greater? If so, make sure you have the latest graphics drivers installed.");
exit(1); exit(1);
} }


glfwMakeContextCurrent(gWindow);
glfwSetWindowUserPointer(win, this);
glfwSetInputMode(win, GLFW_LOCK_KEY_MODS, 1);


glfwMakeContextCurrent(win);
glfwSwapInterval(1); glfwSwapInterval(1);


glfwSetInputMode(gWindow, GLFW_LOCK_KEY_MODS, 1);

glfwSetWindowSizeCallback(gWindow, windowSizeCallback);
glfwSetMouseButtonCallback(gWindow, mouseButtonStickyCallback);
glfwSetWindowSizeCallback(win, windowSizeCallback);
glfwSetMouseButtonCallback(win, mouseButtonStickyCallback);
// Call this ourselves, but on every frame instead of only when the mouse moves // Call this ourselves, but on every frame instead of only when the mouse moves
// glfwSetCursorPosCallback(gWindow, cursorPosCallback);
glfwSetCursorEnterCallback(gWindow, cursorEnterCallback);
glfwSetScrollCallback(gWindow, scrollCallback);
glfwSetCharCallback(gWindow, charCallback);
glfwSetKeyCallback(gWindow, keyCallback);
glfwSetDropCallback(gWindow, dropCallback);
// glfwSetCursorPosCallback(win, cursorPosCallback);
glfwSetCursorEnterCallback(win, cursorEnterCallback);
glfwSetScrollCallback(win, scrollCallback);
glfwSetCharCallback(win, charCallback);
glfwSetKeyCallback(win, keyCallback);
glfwSetDropCallback(win, dropCallback);


// Set up GLEW // Set up GLEW
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
@@ -234,73 +225,87 @@ void windowInit() {
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
glGetError(); glGetError();


glfwSetWindowSizeLimits(gWindow, 640, 480, GLFW_DONT_CARE, GLFW_DONT_CARE);
glfwSetWindowSizeLimits(win, 640, 480, GLFW_DONT_CARE, GLFW_DONT_CARE);


// Set up NanoVG // Set up NanoVG
int nvgFlags = NVG_ANTIALIAS; int nvgFlags = NVG_ANTIALIAS;
#if defined NANOVG_GL2 #if defined NANOVG_GL2
gVg = nvgCreateGL2(nvgFlags);
vg = nvgCreateGL2(nvgFlags);
#elif defined NANOVG_GL3 #elif defined NANOVG_GL3
gVg = nvgCreateGL3(nvgFlags);
vg = nvgCreateGL3(nvgFlags);
#elif defined NANOVG_GLES2 #elif defined NANOVG_GLES2
gVg = nvgCreateGLES2(nvgFlags);
vg = nvgCreateGLES2(nvgFlags);
#endif #endif
assert(gVg);
assert(vg);


#if defined NANOVG_GL2 #if defined NANOVG_GL2
gFramebufferVg = nvgCreateGL2(nvgFlags);
framebufferVg = nvgCreateGL2(nvgFlags);
#elif defined NANOVG_GL3 #elif defined NANOVG_GL3
gFramebufferVg = nvgCreateGL3(nvgFlags);
framebufferVg = nvgCreateGL3(nvgFlags);
#elif defined NANOVG_GLES2 #elif defined NANOVG_GLES2
gFramebufferVg = nvgCreateGLES2(nvgFlags);
framebufferVg = nvgCreateGLES2(nvgFlags);
#endif #endif
assert(gFramebufferVg);

// Set up Blendish
gGuiFont = Font::load(context()->asset->system("res/fonts/DejaVuSans.ttf"));
bndSetFont(gGuiFont->handle);

windowSetTheme(nvgRGB(0x33, 0x33, 0x33), nvgRGB(0xf0, 0xf0, 0xf0));
assert(framebufferVg);
} }


void windowDestroy() {
gGuiFont.reset();

Window::~Window() {
#if defined NANOVG_GL2 #if defined NANOVG_GL2
nvgDeleteGL2(gVg);
nvgDeleteGL2(vg);
#elif defined NANOVG_GL3 #elif defined NANOVG_GL3
nvgDeleteGL3(gVg);
nvgDeleteGL3(vg);
#elif defined NANOVG_GLES2 #elif defined NANOVG_GLES2
nvgDeleteGLES2(gVg);
nvgDeleteGLES2(vg);
#endif #endif


#if defined NANOVG_GL2 #if defined NANOVG_GL2
nvgDeleteGL2(gFramebufferVg);
nvgDeleteGL2(framebufferVg);
#elif defined NANOVG_GL3 #elif defined NANOVG_GL3
nvgDeleteGL3(gFramebufferVg);
nvgDeleteGL3(framebufferVg);
#elif defined NANOVG_GLES2 #elif defined NANOVG_GLES2
nvgDeleteGLES2(gFramebufferVg);
nvgDeleteGLES2(framebufferVg);
#endif #endif


glfwDestroyWindow(gWindow);
glfwDestroyWindow(win);
glfwTerminate(); glfwTerminate();
delete internal;
}

static void Window_renderGui(Window *window) {
int width, height;
glfwGetFramebufferSize(window->win, &width, &height);

bndSetFont(window->uiFont->handle);

// Update and render
nvgBeginFrame(window->vg, width, height, window->pixelRatio);

nvgReset(window->vg);
nvgScale(window->vg, window->pixelRatio, window->pixelRatio);
context()->event->rootWidget->draw(window->vg);

glViewport(0, 0, width, height);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgEndFrame(window->vg);
glfwSwapBuffers(window->win);
} }


void windowRun() {
assert(gWindow);
gGuiFrame = 0;
while(!glfwWindowShouldClose(gWindow)) {
void Window::run() {
uiFont = Font::load(asset::system("res/fonts/DejaVuSans.ttf"));

frame = 0;
while(!glfwWindowShouldClose(win)) {
double startTime = glfwGetTime(); double startTime = glfwGetTime();
gGuiFrame++;
frame++;


// Poll events // Poll events
glfwPollEvents(); glfwPollEvents();
{ {
double xpos, ypos; double xpos, ypos;
glfwGetCursorPos(gWindow, &xpos, &ypos);
cursorPosCallback(gWindow, xpos, ypos);
glfwGetCursorPos(win, &xpos, &ypos);
cursorPosCallback(win, xpos, ypos);
} }
mouseButtonStickyPop();
Window_mouseButtonStickyPop(this);
gamepad::step(); gamepad::step();


// Set window title // Set window title
@@ -312,36 +317,36 @@ void windowRun() {
windowTitle += " - "; windowTitle += " - ";
windowTitle += string::filename(context()->scene->rackWidget->lastPath); windowTitle += string::filename(context()->scene->rackWidget->lastPath);
} }
if (windowTitle != lastWindowTitle) {
glfwSetWindowTitle(gWindow, windowTitle.c_str());
lastWindowTitle = windowTitle;
if (windowTitle != internal->lastWindowTitle) {
glfwSetWindowTitle(win, windowTitle.c_str());
internal->lastWindowTitle = windowTitle;
} }


// Get desired scaling // Get desired scaling
float pixelRatio;
glfwGetWindowContentScale(gWindow, &pixelRatio, NULL);
pixelRatio = roundf(pixelRatio);
if (pixelRatio != gPixelRatio) {
float newPixelRatio;
glfwGetWindowContentScale(win, &newPixelRatio, NULL);
newPixelRatio = std::round(newPixelRatio);
if (newPixelRatio != pixelRatio) {
context()->event->handleZoom(); context()->event->handleZoom();
gPixelRatio = pixelRatio;
pixelRatio = newPixelRatio;
} }


// Get framebuffer/window ratio // Get framebuffer/window ratio
int width, height; int width, height;
glfwGetFramebufferSize(gWindow, &width, &height);
glfwGetFramebufferSize(win, &width, &height);
int windowWidth, windowHeight; int windowWidth, windowHeight;
glfwGetWindowSize(gWindow, &windowWidth, &windowHeight);
gWindowRatio = (float)width / windowWidth;
glfwGetWindowSize(win, &windowWidth, &windowHeight);
windowRatio = (float)width / windowWidth;


context()->event->rootWidget->box.size = Vec(width, height).div(gPixelRatio);
context()->event->rootWidget->box.size = Vec(width, height).div(pixelRatio);


// Step scene // Step scene
context()->event->rootWidget->step(); context()->event->rootWidget->step();


// Render // Render
bool visible = glfwGetWindowAttrib(gWindow, GLFW_VISIBLE) && !glfwGetWindowAttrib(gWindow, GLFW_ICONIFIED);
bool visible = glfwGetWindowAttrib(win, GLFW_VISIBLE) && !glfwGetWindowAttrib(win, GLFW_ICONIFIED);
if (visible) { if (visible) {
renderGui();
Window_renderGui(this);
} }


// Limit framerate manually if vsync isn't working // Limit framerate manually if vsync isn't working
@@ -356,132 +361,81 @@ void windowRun() {
} }
} }


void windowClose() {
glfwSetWindowShouldClose(gWindow, GLFW_TRUE);
void Window::close() {
glfwSetWindowShouldClose(win, GLFW_TRUE);
} }


void windowCursorLock() {
if (gAllowCursorLock) {
void Window::cursorLock() {
if (allowCursorLock) {
#ifdef ARCH_MAC #ifdef ARCH_MAC
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#else #else
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif #endif
} }
} }


void windowCursorUnlock() {
if (gAllowCursorLock) {
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
void Window::cursorUnlock() {
if (allowCursorLock) {
glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
} }
} }


bool windowIsModPressed() {
bool Window::isModPressed() {
#ifdef ARCH_MAC #ifdef ARCH_MAC
return glfwGetKey(gWindow, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS;
return glfwGetKey(win, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS;
#else #else
return glfwGetKey(gWindow, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS;
return glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS;
#endif #endif
} }


bool windowIsShiftPressed() {
return glfwGetKey(gWindow, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS;
bool Window::isShiftPressed() {
return glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS;
} }


Vec windowGetWindowSize() {
Vec Window::getWindowSize() {
int width, height; int width, height;
glfwGetWindowSize(gWindow, &width, &height);
glfwGetWindowSize(win, &width, &height);
return Vec(width, height); return Vec(width, height);
} }


void windowSetWindowSize(Vec size) {
void Window::setWindowSize(Vec size) {
int width = size.x; int width = size.x;
int height = size.y; int height = size.y;
glfwSetWindowSize(gWindow, width, height);
glfwSetWindowSize(win, width, height);
} }


Vec windowGetWindowPos() {
Vec Window::getWindowPos() {
int x, y; int x, y;
glfwGetWindowPos(gWindow, &x, &y);
glfwGetWindowPos(win, &x, &y);
return Vec(x, y); return Vec(x, y);
} }


void windowSetWindowPos(Vec pos) {
void Window::setWindowPos(Vec pos) {
int x = pos.x; int x = pos.x;
int y = pos.y; int y = pos.y;
glfwSetWindowPos(gWindow, x, y);
}

bool windowIsMaximized() {
return glfwGetWindowAttrib(gWindow, GLFW_MAXIMIZED);
}

void windowSetTheme(NVGcolor bg, NVGcolor fg) {
// Assume dark background and light foreground

BNDwidgetTheme w;
w.outlineColor = bg;
w.itemColor = fg;
w.innerColor = bg;
w.innerSelectedColor = color::plus(bg, nvgRGB(0x30, 0x30, 0x30));
w.textColor = fg;
w.textSelectedColor = fg;
w.shadeTop = 0;
w.shadeDown = 0;

BNDtheme t;
t.backgroundColor = color::plus(bg, nvgRGB(0x30, 0x30, 0x30));
t.regularTheme = w;
t.toolTheme = w;
t.radioTheme = w;
t.textFieldTheme = w;
t.optionTheme = w;
t.choiceTheme = w;
t.numberFieldTheme = w;
t.sliderTheme = w;
t.scrollBarTheme = w;
t.tooltipTheme = w;
t.menuTheme = w;
t.menuItemTheme = w;

t.sliderTheme.itemColor = bg;
t.sliderTheme.innerColor = color::plus(bg, nvgRGB(0x50, 0x50, 0x50));
t.sliderTheme.innerSelectedColor = color::plus(bg, nvgRGB(0x60, 0x60, 0x60));

t.textFieldTheme = t.sliderTheme;
t.textFieldTheme.textColor = color::minus(bg, nvgRGB(0x20, 0x20, 0x20));
t.textFieldTheme.textSelectedColor = t.textFieldTheme.textColor;

t.scrollBarTheme.itemColor = color::plus(bg, nvgRGB(0x50, 0x50, 0x50));
t.scrollBarTheme.innerColor = bg;

t.menuTheme.innerColor = color::minus(bg, nvgRGB(0x10, 0x10, 0x10));
t.menuTheme.textColor = color::minus(fg, nvgRGB(0x50, 0x50, 0x50));
t.menuTheme.textSelectedColor = t.menuTheme.textColor;

bndSetTheme(t);
}

static int windowX = 0;
static int windowY = 0;
static int windowWidth = 0;
static int windowHeight = 0;

void windowSetFullScreen(bool fullScreen) {
if (windowGetFullScreen()) {
glfwSetWindowMonitor(gWindow, NULL, windowX, windowY, windowWidth, windowHeight, GLFW_DONT_CARE);
glfwSetWindowPos(win, x, y);
}

bool Window::isMaximized() {
return glfwGetWindowAttrib(win, GLFW_MAXIMIZED);
}

void Window::setFullScreen(bool fullScreen) {
if (isFullScreen()) {
glfwSetWindowMonitor(win, NULL, internal->lastWindowX, internal->lastWindowY, internal->lastWindowWidth, internal->lastWindowHeight, GLFW_DONT_CARE);
} }
else { else {
glfwGetWindowPos(gWindow, &windowX, &windowY);
glfwGetWindowSize(gWindow, &windowWidth, &windowHeight);
glfwGetWindowPos(win, &internal->lastWindowX, &internal->lastWindowY);
glfwGetWindowSize(win, &internal->lastWindowWidth, &internal->lastWindowHeight);
GLFWmonitor *monitor = glfwGetPrimaryMonitor(); GLFWmonitor *monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor); const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(gWindow, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
glfwSetWindowMonitor(win, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
} }
} }


bool windowGetFullScreen() {
GLFWmonitor *monitor = glfwGetWindowMonitor(gWindow);
bool Window::isFullScreen() {
GLFWmonitor *monitor = glfwGetWindowMonitor(win);
return monitor != NULL; return monitor != NULL;
} }


@@ -491,7 +445,7 @@ bool windowGetFullScreen() {
//////////////////// ////////////////////


Font::Font(const std::string &filename) { Font::Font(const std::string &filename) {
handle = nvgCreateFont(gVg, filename.c_str(), filename.c_str());
handle = nvgCreateFont(context()->window->vg, filename.c_str(), filename.c_str());
if (handle >= 0) { if (handle >= 0) {
INFO("Loaded font %s", filename.c_str()); INFO("Loaded font %s", filename.c_str());
} }
@@ -517,7 +471,7 @@ std::shared_ptr<Font> Font::load(const std::string &filename) {
//////////////////// ////////////////////


Image::Image(const std::string &filename) { Image::Image(const std::string &filename) {
handle = nvgCreateImage(gVg, filename.c_str(), NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
handle = nvgCreateImage(context()->window->vg, filename.c_str(), NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
if (handle > 0) { if (handle > 0) {
INFO("Loaded image %s", filename.c_str()); INFO("Loaded image %s", filename.c_str());
} }
@@ -528,7 +482,7 @@ Image::Image(const std::string &filename) {


Image::~Image() { Image::~Image() {
// TODO What if handle is invalid? // TODO What if handle is invalid?
nvgDeleteImage(gVg, handle);
nvgDeleteImage(context()->window->vg, handle);
} }


std::shared_ptr<Image> Image::load(const std::string &filename) { std::shared_ptr<Image> Image::load(const std::string &filename) {


Loading…
Cancel
Save