Browse Source

Class-ify window, un-class-ify asset

tags/v1.0.0
Andrew Belt 5 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
#include "app/common.hpp"
#include "app/ParamWidget.hpp"
#include "context.hpp"


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

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

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

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

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


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

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


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

struct SVGPanel : FramebufferWidget {
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
oversample = 2.0;
}


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

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

// Version checking
bool devMode = false;
bool checkVersion = true;
bool checkedVersion = false;
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 {
RoundBlackKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/RoundBlackKnob.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/RoundBlackKnob.svg")));
}
};

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

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

struct RoundHugeBlackKnob : RoundKnob {
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 {
Davies1900hWhiteKnob() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Davies1900hWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Davies1900hWhite.svg")));
}
};

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

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

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

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

struct Davies1900hLargeRedKnob : Davies1900hKnob {
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 {
Rogan6PSWhite() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/Rogan6PSWhite.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/Rogan6PSWhite.svg")));
}
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

struct Rogan1PWhite : Rogan {
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() {
minAngle = -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;
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);
}
};
@@ -295,7 +295,7 @@ struct Trimpot : SVGKnob {
Trimpot() {
minAngle = -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() {
minAngle = -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() {
minAngle = -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);
maxHandlePos = Vec(-1, -2).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;
box.size = background->box.size.plus(margin.mult(2));
}
@@ -338,38 +338,38 @@ struct LEDSlider : SVGSlider {
LEDSlider() {
maxHandlePos = mm2px(Vec(0.738, 0.738).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. */
struct LEDSliderGreen : LEDSlider {
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 {
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 {
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 {
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 {
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 {
PJ301MPort() {
setSVG(SVG::load(context()->asset->system("res/ComponentLibrary/PJ301M.svg")));
setSVG(SVG::load(asset::system("res/ComponentLibrary/PJ301M.svg")));
}
};

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

struct CL1362Port : SVGPort {
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 {
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 {
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 {
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 {
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 {
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 {
LEDButton() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/LEDButton.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/LEDButton.svg")));
}
};

struct BefacoSwitch : SVGSwitch, ToggleSwitch {
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 {
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 {
LEDBezel() {
addFrame(SVG::load(context()->asset->system("res/ComponentLibrary/LEDBezel.svg")));
addFrame(SVG::load(asset::system("res/ComponentLibrary/LEDBezel.svg")));
}
};

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

struct PB61303Button : SVGButton {
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 {
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 {
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;
}
};

struct ScrewBlack : SVGScrew {
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;
}
};


+ 2
- 4
include/context.hpp View File

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


struct Context {
bool devMode = false;

event::Context *event = NULL;
Scene *scene = NULL;
Engine *engine = 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?
inline Menu *createMenu() {
Menu *o = new Menu;
o->box.pos = gMousePos;
o->box.pos = context()->window->mousePos;

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


+ 1
- 1
include/logger.hpp View File

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

void init();
void init(bool devMode);
void destroy();
/** Do not use this function directly. Use the macros below. */
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 loginStatus;

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


+ 1
- 1
include/rack.hpp View File

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


+ 3
- 3
include/rack0.hpp View File

@@ -69,9 +69,9 @@ DEPRECATED inline float randomf() {return random::uniform();}
// 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


+ 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 {
// Add 10 more pixels because measurements on high-DPI screens are sometimes too small for some reason
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();
}



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

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


namespace rack {
@@ -16,8 +17,8 @@ struct MenuLabel : MenuEntry {
void step() override {
// Add 10 more pixels because Retina measurements are sometimes too small
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();
}
};


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

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

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

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

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

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

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


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

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


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

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

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

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

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


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

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

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
#include "../common.hpp"
#include <nanovg.h>
#include <blendish.h>

#define CHECKMARK_STRING "âś”"


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

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


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


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

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

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

struct AudioInterfaceWidget : ModuleWidget {
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(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 {
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(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 {
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(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 {
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(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;

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(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 {
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(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 "AssetManager.hpp"
#include "asset.hpp"
#include "window.hpp"
#include "event.hpp"
#include "context.hpp"
#include "ui.hpp"


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

LedDisplayChoice::LedDisplayChoice() {
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);
textOffset = Vec(10, 18);
}
@@ -64,7 +65,7 @@ void LedDisplayChoice::onButton(event::Button &e) {


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);
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,
-1, color, 12, text.c_str(), highlightColor, begin, end);

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

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

int LedDisplayTextField::getTextPosition(Vec mousePos) {
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,
-1, 12, text.c_str(), mousePos.x, mousePos.y);
bndSetFont(gGuiFont->handle);
bndSetFont(context()->window->uiFont->handle);
return textPos;
}



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

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

#include "osdialog.h"

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

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

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

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

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

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

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);
nvgFillColor(vg, nvgRGBf(1, 1, 1));
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);

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


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

@@ -77,7 +77,7 @@ struct SyncButton : Button {
// Display message if we've completed updates
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.")) {
windowClose();
context()->window->close();
}
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) {
// Try to grab wire on top of stack
WireWidget *wire = context()->scene->rackWidget->wireContainer->getTopWire(this);
if (type == OUTPUT && windowIsModPressed()) {
if (type == OUTPUT && context()->window->isModPressed()) {
wire = NULL;
}



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

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


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


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

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

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

// 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();


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

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

// Request latest version from server
if (!context()->devMode && checkVersion && !checkedVersion) {
if (!devMode && checkVersion && !checkedVersion) {
std::thread t(&Scene::runCheckVersion, this);
t.detach();
checkedVersion = true;
@@ -56,7 +56,7 @@ void Scene::step() {
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, versionMessage.c_str())) {
std::thread t(system::openBrowser, "https://vcvrack.com/");
t.detach();
windowClose();
context()->window->close();
}
latestVersion = "";
}
@@ -72,39 +72,39 @@ void Scene::onHoverKey(event::HoverKey &e) {
if (!e.target) {
switch (e.key) {
case GLFW_KEY_N: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->reset();
e.target = this;
}
} break;
case GLFW_KEY_Q: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
windowClose();
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
context()->window->close();
e.target = this;
}
} break;
case GLFW_KEY_O: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->loadDialog();
e.target = this;
}
if (windowIsModPressed() && windowIsShiftPressed()) {
if (context()->window->isModPressed() && context()->window->isShiftPressed()) {
rackWidget->revert();
e.target = this;
}
} break;
case GLFW_KEY_S: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->saveDialog();
e.target = this;
}
if (windowIsModPressed() && windowIsShiftPressed()) {
if (context()->window->isModPressed() && context()->window->isShiftPressed()) {
rackWidget->saveAsDialog();
e.target = this;
}
} break;
case GLFW_KEY_V: {
if (windowIsModPressed() && !windowIsShiftPressed()) {
if (context()->window->isModPressed() && !context()->window->isShiftPressed()) {
rackWidget->pastePresetClipboard();
e.target = this;
}
@@ -115,7 +115,7 @@ void Scene::onHoverKey(event::HoverKey &e) {
e.target = this;
} break;
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 "window.hpp"
#include "engine/Engine.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "ui/Tooltip.hpp"
#include "ui/IconButton.hpp"
#include "ui/SequentialLayout.hpp"
@@ -39,7 +39,7 @@ struct TooltipIconButton : IconButton {

struct NewButton : TooltipIconButton {
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)";}
void onAction(event::Action &e) override {
@@ -49,7 +49,7 @@ struct NewButton : TooltipIconButton {

struct OpenButton : TooltipIconButton {
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)";}
void onAction(event::Action &e) override {
@@ -59,7 +59,7 @@ struct OpenButton : TooltipIconButton {

struct SaveButton : TooltipIconButton {
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)";}
void onAction(event::Action &e) override {
@@ -69,7 +69,7 @@ struct SaveButton : TooltipIconButton {

struct SaveAsButton : TooltipIconButton {
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)";}
void onAction(event::Action &e) override {
@@ -79,7 +79,7 @@ struct SaveAsButton : TooltipIconButton {

struct RevertButton : TooltipIconButton {
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";}
void onAction(event::Action &e) override {
@@ -89,7 +89,7 @@ struct RevertButton : TooltipIconButton {

struct DisconnectCablesButton : TooltipIconButton {
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";}
void onAction(event::Action &e) override {
@@ -99,7 +99,7 @@ struct DisconnectCablesButton : TooltipIconButton {

struct PowerMeterButton : TooltipIconButton {
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)";}
void onAction(event::Action &e) override {
@@ -123,7 +123,7 @@ struct SampleRateItem : MenuItem {

struct SampleRateButton : TooltipIconButton {
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";}
void onAction(event::Action &e) override {
@@ -150,7 +150,7 @@ struct SampleRateButton : TooltipIconButton {

struct RackLockButton : TooltipIconButton {
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";}
void onAction(event::Action &e) override {
@@ -238,7 +238,7 @@ Toolbar::Toolbar() {
layout->addChild(zoomSlider);

// 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;
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 "context.hpp"
#include "plugin/Plugin.hpp"

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


namespace rack {
namespace asset {


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

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


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


} // namespace asset
} // 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 rack

+ 4
- 5
src/logger.cpp View File

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


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


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


+ 34
- 28
src/main.cpp View File

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

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

bool devMode = false;
std::string patchFile;

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

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

// Log environment
INFO("%s %s", APP_NAME.c_str(), APP_VERSION.c_str());
if (context()->devMode)
if (devMode)
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
tagsInit();
context()->plugin = new PluginManager;
context()->plugin = new PluginManager(devMode);
context()->engine = new Engine;
rtmidiInit();
bridgeInit();
keyboard::init();
gamepad::init();
context()->event = new event::Context;
context()->scene = new Scene;
context()->scene->devMode = devMode;
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()) {
// 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;
settings::gSkipAutosaveOnLaunch = true;
settings::save(context()->asset->user("settings.json"));
settings::save(asset::user("settings.json"));
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?")) {
context()->scene->rackWidget->lastPath = "";
@@ -96,7 +100,7 @@ int main(int argc, char *argv[]) {
else {
// Load autosave
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;
}
}
@@ -107,25 +111,27 @@ int main(int argc, char *argv[]) {
}

context()->engine->start();
windowRun();
context()->window->run();
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;
context()->scene = NULL;
delete context()->event;
context()->event = NULL;
windowDestroy();
bridgeDestroy();
delete context()->window;
context()->window = NULL;
delete context()->engine;
context()->engine = NULL;
midiDestroy();
delete context()->plugin;
context()->plugin = NULL;
delete context()->asset;
context()->asset = NULL;

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

return 0;


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

@@ -2,7 +2,7 @@
#include "system.hpp"
#include "logger.hpp"
#include "network.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "string.hpp"
#include "context.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());

// 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)) {
WARN("Plugin %s download was unsuccessful", slug.c_str());
return false;
@@ -300,7 +300,7 @@ static void extractPackages(std::string path) {
// public API
////////////////////

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

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

if (!context()->devMode) {
if (devMode) {
// 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)) {
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_object_set_new(rootJ, "token", tokenJ);

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

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

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

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

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

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

// 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
@@ -186,9 +187,6 @@ void svgDraw(NVGcontext *vg, NSVGimage *svg) {
}

nvgRestore(vg);

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

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 "context.hpp"
#include <nanovg_gl.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.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())
return;
@@ -65,7 +66,7 @@ void FramebufferWidget::draw(NVGcontext *vg) {
// Delete old one first to free up GPU memory
internal->setFramebuffer(NULL);
// 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)
return;
internal->setFramebuffer(fb);
@@ -75,16 +76,17 @@ void FramebufferWidget::draw(NVGcontext *vg) {
glClearColor(0.0, 0.0, 0.0, 0.0);
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
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);
}



+ 172
- 218
src/window.cpp View File

@@ -1,6 +1,6 @@
#include "window.hpp"
#include "logger.hpp"
#include "AssetManager.hpp"
#include "asset.hpp"
#include "app/Scene.hpp"
#include "keyboard.hpp"
#include "gamepad.hpp"
@@ -36,24 +36,32 @@
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.
}

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
// Remap Ctrl-left click to right click on Mac
if (button == GLFW_MOUSE_BUTTON_LEFT) {
@@ -63,36 +71,30 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int
}
#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
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;

#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.
if (cursorMode == GLFW_CURSOR_HIDDEN) {
// CGSetLocalEventsSuppressionInterval(0.0);
glfwSetCursorPos(gWindow, gMousePos.x, gMousePos.y);
glfwSetCursorPos(win, window->mousePos.x, window->mousePos.y);
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
glfwSetCursor(gWindow, NULL);
glfwSetCursor(win, NULL);
#endif

gMousePos = mousePos;
window->mousePos = mousePos;

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

void cursorEnterCallback(GLFWwindow* window, int entered) {
static void cursorEnterCallback(GLFWwindow *win, int entered) {
if (!entered) {
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);
#if ARCH_LIN || ARCH_WIN
if (windowIsShiftPressed())
if (window->isShiftPressed())
scrollDelta = Vec(y, x);
#endif
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
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;
for (int i = 0; i < count; 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);
}

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;

// Set up GLFW
@@ -200,28 +190,29 @@ void windowInit() {
#endif
glfwWindowHint(GLFW_MAXIMIZED, 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.");
exit(1);
}

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

glfwMakeContextCurrent(win);
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
// 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
glewExperimental = GL_TRUE;
@@ -234,73 +225,87 @@ void windowInit() {
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
glGetError();

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

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

#if defined NANOVG_GL2
gFramebufferVg = nvgCreateGL2(nvgFlags);
framebufferVg = nvgCreateGL2(nvgFlags);
#elif defined NANOVG_GL3
gFramebufferVg = nvgCreateGL3(nvgFlags);
framebufferVg = nvgCreateGL3(nvgFlags);
#elif defined NANOVG_GLES2
gFramebufferVg = nvgCreateGLES2(nvgFlags);
framebufferVg = nvgCreateGLES2(nvgFlags);
#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
nvgDeleteGL2(gVg);
nvgDeleteGL2(vg);
#elif defined NANOVG_GL3
nvgDeleteGL3(gVg);
nvgDeleteGL3(vg);
#elif defined NANOVG_GLES2
nvgDeleteGLES2(gVg);
nvgDeleteGLES2(vg);
#endif

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

glfwDestroyWindow(gWindow);
glfwDestroyWindow(win);
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();
gGuiFrame++;
frame++;

// Poll events
glfwPollEvents();
{
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();

// Set window title
@@ -312,36 +317,36 @@ void windowRun() {
windowTitle += " - ";
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
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();
gPixelRatio = pixelRatio;
pixelRatio = newPixelRatio;
}

// Get framebuffer/window ratio
int width, height;
glfwGetFramebufferSize(gWindow, &width, &height);
glfwGetFramebufferSize(win, &width, &height);
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
context()->event->rootWidget->step();

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

// 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
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#else
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#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
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
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
}

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;
glfwGetWindowSize(gWindow, &width, &height);
glfwGetWindowSize(win, &width, &height);
return Vec(width, height);
}

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

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

void windowSetWindowPos(Vec pos) {
void Window::setWindowPos(Vec pos) {
int x = pos.x;
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 {
glfwGetWindowPos(gWindow, &windowX, &windowY);
glfwGetWindowSize(gWindow, &windowWidth, &windowHeight);
glfwGetWindowPos(win, &internal->lastWindowX, &internal->lastWindowY);
glfwGetWindowSize(win, &internal->lastWindowWidth, &internal->lastWindowHeight);
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
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;
}

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

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) {
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) {
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) {
INFO("Loaded image %s", filename.c_str());
}
@@ -528,7 +482,7 @@ Image::Image(const std::string &filename) {

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

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


Loading…
Cancel
Save