diff --git a/Makefile b/Makefile index 06ebd028..9881623e 100644 --- a/Makefile +++ b/Makefile @@ -30,9 +30,6 @@ CFLAGS += -DNOC_FILE_DIALOG_OSX CXXFLAGS += -DAPPLE -stdlib=libc++ -I$(HOME)/local/include LDFLAGS += -stdlib=libc++ -L$(HOME)/local/lib -lpthread -lglew -lglfw3 -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo -ldl -ljansson -lportaudio -lportmidi -lsamplerate TARGET = Rack - -Rack.app: $(TARGET) - ./bundle.sh endif # Windows @@ -52,41 +49,13 @@ LDFLAGS += \ -L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows TARGET = Rack.exe -# OBJECTS = Rack.res - -%.res: %.rc - windres $^ -O coff -o $@ -endif - +OBJECTS = Rack.res all: $(TARGET) -dist: $(TARGET) - # Rack - mkdir -p dist/Rack - cp LICENSE* dist/Rack/ -ifeq ($(ARCH), linux) - cp Rack dist/Rack/ -endif -ifeq ($(ARCH), apple) - ./bundle.sh - cp -R Rack.app dist/Rack/ -endif -ifeq ($(ARCH), windows) - cp Rack.exe dist/Rack/ - ./copy_dlls.sh - cp *.dll dist/Rack/ +%.res: %.rc + windres $^ -O coff -o $@ endif - cp -R res dist/Rack/ - mkdir -p dist/Rack/plugins - # Fundamental - $(MAKE) -C plugins/Fundamental dist - cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ - # zip - cd dist && zip -5 -r Rack.zip Rack - -clean: - rm -rfv build $(TARGET) dist include Makefile.inc \ No newline at end of file diff --git a/Rack.rc b/Rack.rc new file mode 100644 index 00000000..5befe687 --- /dev/null +++ b/Rack.rc @@ -0,0 +1 @@ +GLFW_ICON ICON res/icon.ico \ No newline at end of file diff --git a/include/components.hpp b/include/components.hpp new file mode 100644 index 00000000..7f8f06fa --- /dev/null +++ b/include/components.hpp @@ -0,0 +1,97 @@ +#pragma once +#include "scene.hpp" + + +namespace rack { + +//////////////////// +// knobs +//////////////////// + +struct KnobDavies1900h : SpriteKnob { + KnobDavies1900h() { + box.size = Vec(36, 36); + spriteOffset = Vec(-8, -8); + spriteSize = Vec(64, 64); + minIndex = 44; + maxIndex = -46; + spriteCount = 120; + } +}; + +struct KnobDavies1900hWhite : KnobDavies1900h { + KnobDavies1900hWhite() { + spriteImage = Image::load("res/ComponentLibrary/Davies1900hWhite.png"); + } +}; + +struct KnobDavies1900hBlack : KnobDavies1900h { + KnobDavies1900hBlack() { + spriteImage = Image::load("res/ComponentLibrary/Davies1900hBlack.png"); + } +}; + +struct KnobDavies1900hRed : KnobDavies1900h { + KnobDavies1900hRed() { + spriteImage = Image::load("res/ComponentLibrary/Davies1900hRed.png"); + } +}; + +//////////////////// +// ports +//////////////////// + +struct PJ301M : SpriteWidget { + PJ301M() { + box.size = Vec(24, 24); + spriteOffset = Vec(-10, -10); + spriteSize = Vec(48, 48); + spriteImage = Image::load("res/ComponentLibrary/PJ301M.png"); + } +}; +struct InputPortPJ301M : InputPort, PJ301M {}; +struct OutputPortPJ301M: OutputPort, PJ301M {}; + +struct PJ3410 : SpriteWidget { + PJ3410() { + box.size = Vec(31, 31); + spriteOffset = Vec(-9, -9); + spriteSize = Vec(54, 54); + spriteImage = Image::load("res/ComponentLibrary/PJ3410.png"); + } +}; +struct InputPortPJ3410 : InputPort, PJ3410 {}; +struct OutputPortPJ3410: OutputPort, PJ3410 {}; + +struct CL1362 : SpriteWidget { + CL1362() { + box.size = Vec(33, 29); + spriteOffset = Vec(-10, -10); + spriteSize = Vec(57, 54); + spriteImage = Image::load("res/ComponentLibrary/CL1362.png"); + } +}; +struct InputPortCL1362 : InputPort, CL1362 {}; +struct OutputPortCL1362 : OutputPort, CL1362 {}; + + +//////////////////// +// panels +//////////////////// + +struct LightPanel : Panel { + LightPanel() { + backgroundColor = nvgRGB(0xe8, 0xe8, 0xe8); + borderColor = nvgRGB(0xac, 0xac, 0xac); + } +}; + +struct DarkPanel : Panel { + DarkPanel() { + backgroundColor = nvgRGB(0x0f, 0x0f, 0x0f); + borderColor = nvgRGB(0x5e, 0x5e, 0x5e); + } +}; + + +} // namespace rack diff --git a/include/gui.hpp b/include/gui.hpp index bd4e1881..f95c8044 100644 --- a/include/gui.hpp +++ b/include/gui.hpp @@ -13,5 +13,7 @@ void guiCursorUnlock(); const char *guiSaveDialog(const char *filters, const char *filename); const char *guiOpenDialog(const char *filters, const char *filename); +// TODO This should probably go in another file, like resources.hpp? +void drawSVG(NVGcontext *vg, NSVGimage *svg); } // namespace rack diff --git a/include/rack.hpp b/include/rack.hpp index 6628cc6a..fd3eef3f 100644 --- a/include/rack.hpp +++ b/include/rack.hpp @@ -2,6 +2,7 @@ #include "plugin.hpp" #include "engine.hpp" #include "gui.hpp" +#include "components.hpp" namespace rack { @@ -11,14 +12,6 @@ namespace rack { // helpers //////////////////// -inline -Plugin *createPlugin(std::string slug, std::string name) { - Plugin *plugin = new Plugin(); - plugin->slug = slug; - plugin->name = name; - return plugin; -} - template Model *createModel(Plugin *plugin, std::string slug, std::string name) { struct TModel : Model { diff --git a/include/scene.hpp b/include/scene.hpp index ee0bea1b..29c0cbd8 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -93,8 +93,9 @@ struct RackWidget : OpaqueWidget { void onMouseDown(int button); }; -struct ModulePanel : TransparentWidget { +struct Panel : TransparentWidget { NVGcolor backgroundColor; + NVGcolor borderColor; std::shared_ptr backgroundImage; void draw(NVGcontext *vg); }; @@ -109,7 +110,7 @@ struct Light : TransparentWidget, SpriteWidget { }; // If you don't add these to your ModuleWidget, it will fall out of the RackWidget -struct Screw : TransparentWidget, SpriteWidget { +struct Screw : TransparentWidget { Screw(); }; @@ -123,14 +124,17 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { void onChange(); }; -struct Knob : ParamWidget, SpriteWidget { - int minIndex, maxIndex, spriteCount; - void step(); +struct Knob : ParamWidget { void onDragStart(); void onDragMove(Vec mouseRel); void onDragEnd(); }; +struct SpriteKnob : Knob, SpriteWidget { + int minIndex, maxIndex, spriteCount; + void step(); +}; + struct Switch : ParamWidget, SpriteWidget { }; @@ -212,47 +216,9 @@ struct RackScene : Scene { RackScene(); void step(); + void draw(NVGcontext *vg); }; - -//////////////////// -// Component Library -//////////////////// - -struct PJ301M : SpriteWidget { - PJ301M() { - box.size = Vec(24, 24); - spriteOffset = Vec(-10, -10); - spriteSize = Vec(48, 48); - spriteImage = Image::load("res/ComponentLibrary/PJ301M.png"); - } -}; -struct InputPortPJ301M : InputPort, PJ301M {}; -struct OutputPortPJ301M: OutputPort, PJ301M {}; - -struct PJ3410 : SpriteWidget { - PJ3410() { - box.size = Vec(31, 31); - spriteOffset = Vec(-9, -9); - spriteSize = Vec(54, 54); - spriteImage = Image::load("res/ComponentLibrary/PJ3410.png"); - } -}; -struct InputPortPJ3410 : InputPort, PJ3410 {}; -struct OutputPortPJ3410: OutputPort, PJ3410 {}; - -struct CL1362 : SpriteWidget { - CL1362() { - box.size = Vec(33, 29); - spriteOffset = Vec(-10, -10); - spriteSize = Vec(57, 54); - spriteImage = Image::load("res/ComponentLibrary/CL1362.png"); - } -}; -struct InputPortCL1362 : InputPort, CL1362 {}; -struct OutputPortCL1362 : OutputPort, CL1362 {}; - - //////////////////// // globals //////////////////// diff --git a/include/widgets.hpp b/include/widgets.hpp index a50f327c..b1ed63ae 100644 --- a/include/widgets.hpp +++ b/include/widgets.hpp @@ -35,7 +35,7 @@ struct Image { }; struct SVG { - NSVGimage *image; + NSVGimage *handle; SVG(const std::string &filename); ~SVG(); static std::shared_ptr load(const std::string &filename); diff --git a/src/core/AudioInterface.cpp b/src/core/AudioInterface.cpp index e9b24778..53990f10 100644 --- a/src/core/AudioInterface.cpp +++ b/src/core/AudioInterface.cpp @@ -46,7 +46,7 @@ struct AudioInterface : Module { SampleRateConverter<2> outputSrc; // in rack's sample rate - DoubleRingBuffer, 32> inputBuffer; + DoubleRingBuffer, 16> inputBuffer; DoubleRingBuffer, (1<<15)> outputBuffer; // in device's sample rate DoubleRingBuffer, (1<<15)> inputSrcBuffer; @@ -121,7 +121,7 @@ void AudioInterface::step() { err = Pa_ReadStream(stream, (float*) buf, blockSize); if (err) { // Ignore buffer underflows - if (err != paInputOverflowed) { + if (err == paInputOverflowed) { fprintf(stderr, "Audio input buffer underflow\n"); } } @@ -143,7 +143,7 @@ void AudioInterface::step() { inputSrcBuffer.startIncr(blockSize); if (err) { // Ignore buffer underflows - if (err != paOutputUnderflowed) { + if (err == paOutputUnderflowed) { fprintf(stderr, "Audio output buffer underflow\n"); } } @@ -308,7 +308,8 @@ struct SampleRateChoice : ChoiceButton { menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); const float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000}; - for (int i = 0; i < 6; i++) { + int sampleRatesLen = sizeof(sampleRates) / sizeof(sampleRates[0]); + for (int i = 0; i < sampleRatesLen; i++) { SampleRateItem *item = new SampleRateItem(); item->audioInterface = audioInterface; item->sampleRate = sampleRates[i]; @@ -340,8 +341,9 @@ struct BlockSizeChoice : ChoiceButton { Menu *menu = new Menu(); menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); - const int blockSizes[6] = {128, 256, 512, 1024, 2048, 4096}; - for (int i = 0; i < 6; i++) { + const int blockSizes[] = {64, 128, 256, 512, 1024, 2048, 4096}; + int blockSizesLen = sizeof(blockSizes) / sizeof(blockSizes[0]); + for (int i = 0; i < blockSizesLen; i++) { BlockSizeItem *item = new BlockSizeItem(); item->audioInterface = audioInterface; item->blockSize = blockSizes[i]; @@ -362,24 +364,14 @@ AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface() box.size = Vec(15*8, 380); { - ModulePanel *panel = new ModulePanel(); + Panel *panel = new LightPanel(); panel->box.size = box.size; - panel->backgroundColor = nvgRGBf(0.90, 0.90, 0.90); - // panel->imageFilename = ""; addChild(panel); } float margin = 5; float yPos = margin; - { - Label *label = new Label(); - label->box.pos = Vec(margin, yPos); - label->text = "Audio Interface"; - addChild(label); - yPos += label->box.size.y + margin; - } - { Label *label = new Label(); label->box.pos = Vec(margin, yPos); diff --git a/src/core/MidiInterface.cpp b/src/core/MidiInterface.cpp index ebbb3bd2..2dffaf8a 100644 --- a/src/core/MidiInterface.cpp +++ b/src/core/MidiInterface.cpp @@ -225,10 +225,8 @@ MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) { box.size = Vec(15*8, 380); { - ModulePanel *panel = new ModulePanel(); + Panel *panel = new LightPanel(); panel->box.size = box.size; - panel->backgroundColor = nvgRGBf(0.90, 0.90, 0.90); - // panel->imageFilename = ""; addChild(panel); } diff --git a/src/core/core.cpp b/src/core/core.cpp index f1bf4eb2..bc41fd68 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1,9 +1,6 @@ #include "core.hpp" -using namespace rack; - - struct CorePlugin : Plugin { CorePlugin() { slug = "Core"; diff --git a/src/engine.cpp b/src/engine.cpp index ed2b359c..697da5a1 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -129,9 +129,9 @@ static void engineRun() { } } auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::nanoseconds((long) (0.9 * 1e9 * stepSize / gSampleRate)) - (end - start); + auto duration = std::chrono::nanoseconds((long) (0.5 * 1e9 * stepSize / gSampleRate)) - (end - start); // Avoid pegging the CPU at 100% when there are no "blocking" modules like AudioInterface, but still step audio at a reasonable rate - std::this_thread::sleep_for(duration); + // std::this_thread::sleep_for(duration); } } diff --git a/src/gui.cpp b/src/gui.cpp index 52190683..f5106603 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -314,8 +314,8 @@ std::shared_ptr Image::load(const std::string &filename) { //////////////////// SVG::SVG(const std::string &filename) { - image = nsvgParseFromFile(filename.c_str(), "px", 96.0); - if (image) { + handle = nsvgParseFromFile(filename.c_str(), "px", 96.0); + if (handle) { fprintf(stderr, "Loaded SVG %s\n", filename.c_str()); } else { @@ -324,7 +324,7 @@ SVG::SVG(const std::string &filename) { } SVG::~SVG() { - nsvgDelete(image); + nsvgDelete(handle); } std::shared_ptr SVG::load(const std::string &filename) { @@ -336,4 +336,83 @@ std::shared_ptr SVG::load(const std::string &filename) { } +//////////////////// +// drawSVG +//////////////////// + +NVGcolor getNVGColor(int color) { + return nvgRGBA((color >> 0) & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); + // return nvgRGBA((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, (color) & 0xff); +} + +void drawSVG(NVGcontext *vg, NSVGimage *svg) { + for (NSVGshape *shape = svg->shapes; shape; shape = shape->next) { + // printf(" new shape: id \"%s\", fillrule %d\n", shape->id, shape->fillRule); + + if (!(shape->flags & NSVG_FLAGS_VISIBLE)) + continue; + + nvgSave(vg); + nvgGlobalAlpha(vg, shape->opacity); + nvgStrokeWidth(vg, shape->strokeWidth); + // strokeDashOffset, strokeDashArray, strokeDashCount not supported + // strokeLineJoin, strokeLineCap not supported + + // Build path + nvgBeginPath(vg); + for (NSVGpath *path = shape->paths; path; path = path->next) { + // printf(" new path: %d points, %s\n", path->npts, path->closed ? "closed" : "notclosed"); + + nvgMoveTo(vg, path->pts[0], path->pts[1]); + for (int i = 1; i < path->npts; i += 3) { + float *p = &path->pts[2*i]; + nvgBezierTo(vg, p[0], p[1], p[2], p[3], p[4], p[5]); + // nvgLineTo(vg, p[4], p[5]); + } + + if (path->closed) + nvgClosePath(vg); + + + if (path->next) + nvgPathWinding(vg, NVG_HOLE); + } + + // Fill shape + if (shape->fill.type) { + switch (shape->fill.type) { + case NSVG_PAINT_COLOR: { + NVGcolor color = getNVGColor(shape->fill.color); + nvgFillColor(vg, color); + // printf(" fill color (%f %f %f %f)\n", color.r, color.g, color.b, color.a); + } break; + case NSVG_PAINT_LINEAR_GRADIENT: { + NSVGgradient *g = shape->fill.gradient; + // printf(" lin grad: %f\t%f\n", g->fx, g->fy); + } break; + } + nvgFill(vg); + } + + // Stroke shape + if (shape->stroke.type) { + switch (shape->stroke.type) { + case NSVG_PAINT_COLOR: { + NVGcolor color = getNVGColor(shape->stroke.color); + nvgFillColor(vg, color); + // printf(" stroke color (%f %f %f %f)\n", color.r, color.g, color.b, color.a); + } break; + case NSVG_PAINT_LINEAR_GRADIENT: { + NSVGgradient *g = shape->stroke.gradient; + // printf(" lin grad: %f\t%f\n", g->fx, g->fy); + } break; + } + nvgStroke(vg); + } + + nvgRestore(vg); + } +} + + } // namespace rack diff --git a/src/main.cpp b/src/main.cpp index 2612d491..c2bcea07 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,7 @@ int main() { assert(success); CFRelease(bundleURL); - chdir(dirname(path)); + // chdir(dirname(path)); } #endif diff --git a/src/scene.cpp b/src/scene.cpp index cfbafe29..1a7214e1 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -4,7 +4,7 @@ namespace rack { std::string gApplicationName = "VCV Rack"; -std::string gApplicationVersion = "v0.1.0 alpha"; +std::string gApplicationVersion = "v0.2.0 alpha"; RackWidget *gRackWidget = NULL; diff --git a/src/widgets/Knob.cpp b/src/widgets/Knob.cpp index f51de5ee..72628cf4 100644 --- a/src/widgets/Knob.cpp +++ b/src/widgets/Knob.cpp @@ -7,10 +7,6 @@ namespace rack { #define KNOB_SENSITIVITY 0.001 -void Knob::step() { - index = eucmod((int) roundf(mapf(value, minValue, maxValue, minIndex, maxIndex)), spriteCount); -} - void Knob::onDragStart() { guiCursorLock(); } diff --git a/src/widgets/ModulePanel.cpp b/src/widgets/Panel.cpp similarity index 61% rename from src/widgets/ModulePanel.cpp rename to src/widgets/Panel.cpp index ec52523b..6fa111a0 100644 --- a/src/widgets/ModulePanel.cpp +++ b/src/widgets/Panel.cpp @@ -3,10 +3,9 @@ namespace rack { -void ModulePanel::draw(NVGcontext *vg) { +void Panel::draw(NVGcontext *vg) { nvgBeginPath(vg); nvgRect(vg, box.pos.x, box.pos.y, box.size.x, box.size.y); - NVGpaint paint; // Background color nvgFillColor(vg, backgroundColor); @@ -16,10 +15,15 @@ void ModulePanel::draw(NVGcontext *vg) { if (backgroundImage) { int width, height; nvgImageSize(vg, backgroundImage->handle, &width, &height); - paint = nvgImagePattern(vg, box.pos.x, box.pos.y, width, height, 0.0, backgroundImage->handle, 1.0); + NVGpaint paint = nvgImagePattern(vg, box.pos.x, box.pos.y, width, height, 0.0, backgroundImage->handle, 1.0); nvgFillPaint(vg, paint); nvgFill(vg); } + + // Border color + nvgStrokeColor(vg, borderColor); + nvgStrokeWidth(vg, 0.5); + nvgStroke(vg); } } // namespace rack diff --git a/src/widgets/RackScene.cpp b/src/widgets/RackScene.cpp index 20b654a9..6ea612c1 100644 --- a/src/widgets/RackScene.cpp +++ b/src/widgets/RackScene.cpp @@ -1,4 +1,5 @@ #include "scene.hpp" +#include "gui.hpp" namespace rack { @@ -24,5 +25,23 @@ void RackScene::step() { Scene::step(); } +void RackScene::draw(NVGcontext *vg) { + Scene::draw(vg); + + // // Draw custom stuff here + // static std::shared_ptr svg; + // if (!svg) + // svg = SVG::load("res/ComponentLibrary/CL1362.svg"); + + // for (float y = 0.0; y < 1000.0; y += 200.0) + // for (float x = 0.0; x < 1000.0; x += 200.0) { + // nvgSave(vg); + // nvgTranslate(vg, x, y); + // drawSVG(vg, svg->handle); + // nvgRestore(vg); + // } +} + + } // namespace rack diff --git a/src/widgets/RackWidget.cpp b/src/widgets/RackWidget.cpp index 323a4aad..9e762600 100644 --- a/src/widgets/RackWidget.cpp +++ b/src/widgets/RackWidget.cpp @@ -288,23 +288,18 @@ void RackWidget::step() { } void RackWidget::draw(NVGcontext *vg) { - // Draw background nvgBeginPath(vg); nvgRect(vg, box.pos.x, box.pos.y, box.size.x, box.size.y); - NVGpaint paint; - { - // int imageId = loadImage("res/background.png"); - // int imageWidth, imageHeight; - // nvgImageSize(vg, imageId, &imageWidth, &imageHeight); - // paint = nvgImagePattern(vg, box.pos.x, box.pos.y, imageWidth, imageHeight, 0.0, imageId, 1.0); - // nvgFillPaint(vg, paint); - nvgFillColor(vg, nvgRGBf(0.25, 0.25, 0.25)); - nvgFill(vg); - } + + // Background color + nvgFillColor(vg, nvgRGBf(0.2, 0.2, 0.2)); + nvgFill(vg); + + // Rails image { int imageWidth, imageHeight; nvgImageSize(vg, railsImage->handle, &imageWidth, &imageHeight); - paint = nvgImagePattern(vg, box.pos.x, box.pos.y, imageWidth, imageHeight, 0.0, railsImage->handle, 1.0); + NVGpaint paint = nvgImagePattern(vg, box.pos.x, box.pos.y, imageWidth, imageHeight, 0.0, railsImage->handle, 1.0); nvgFillPaint(vg, paint); nvgFill(vg); } diff --git a/src/widgets/Screw.cpp b/src/widgets/Screw.cpp index 973fd6b4..964def2b 100644 --- a/src/widgets/Screw.cpp +++ b/src/widgets/Screw.cpp @@ -4,12 +4,12 @@ namespace rack { Screw::Screw() { - box.size = Vec(15, 15); - spriteOffset = Vec(-7, -7); - spriteSize = Vec(29, 29); - spriteImage = Image::load("res/screw.png"); + // box.size = Vec(15, 15); + // spriteOffset = Vec(-7, -7); + // spriteSize = Vec(29, 29); + // spriteImage = Image::load("res/screw.png"); - index = randomu32() % 5; + // index = randomu32() % 5; } diff --git a/src/widgets/SpriteKnob.cpp b/src/widgets/SpriteKnob.cpp new file mode 100644 index 00000000..8ee6fb34 --- /dev/null +++ b/src/widgets/SpriteKnob.cpp @@ -0,0 +1,10 @@ +#include "scene.hpp" + + +namespace rack { + +void SpriteKnob::step() { + index = eucmod((int) roundf(mapf(value, minValue, maxValue, minIndex, maxIndex)), spriteCount); +} + +} // namespace rack diff --git a/src/widgets/WireWidget.cpp b/src/widgets/WireWidget.cpp index 9caabc77..ee0269d4 100644 --- a/src/widgets/WireWidget.cpp +++ b/src/widgets/WireWidget.cpp @@ -4,10 +4,28 @@ namespace rack { -void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color, float opacity) { - NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.08); +static void drawPlug(NVGcontext *vg, Vec pos, NVGcolor color) { NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); + nvgBeginPath(vg); + nvgCircle(vg, pos.x, pos.y, 10.5); + nvgFillColor(vg, colorOutline); + nvgFill(vg); + + nvgBeginPath(vg); + nvgCircle(vg, pos.x, pos.y, 9.5); + nvgFillColor(vg, color); + nvgFill(vg); + + nvgBeginPath(vg); + nvgCircle(vg, pos.x, pos.y, 5.5); + nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); + nvgFill(vg); +} + +static void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, NVGcolor color, float tension, float opacity) { + NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.08); + NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); // Wire if (opacity > 0.0) { @@ -35,68 +53,36 @@ void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color, nvgMoveTo(vg, pos1.x, pos1.y); nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y); nvgStrokeColor(vg, colorOutline); - nvgStrokeWidth(vg, 6); + nvgStrokeWidth(vg, 5); nvgStroke(vg); // Wire solid nvgStrokeColor(vg, color); - nvgStrokeWidth(vg, 4); + nvgStrokeWidth(vg, 3); nvgStroke(vg); nvgRestore(vg); } - - // First plug - nvgBeginPath(vg); - nvgCircle(vg, pos1.x, pos1.y, 21/2.0); - nvgFillColor(vg, colorOutline); - nvgFill(vg); - - nvgBeginPath(vg); - nvgCircle(vg, pos1.x, pos1.y, 19/2.0); - nvgFillColor(vg, color); - nvgFill(vg); - - nvgBeginPath(vg); - nvgCircle(vg, pos1.x, pos1.y, 11/2.0); - nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); - nvgFill(vg); - - // Second plug - nvgBeginPath(vg); - nvgCircle(vg, pos2.x, pos2.y, 21/2.0); - nvgFillColor(vg, colorOutline); - nvgFill(vg); - - nvgBeginPath(vg); - nvgCircle(vg, pos2.x, pos2.y, 19/2.0); - nvgFillColor(vg, color); - nvgFill(vg); - - nvgBeginPath(vg); - nvgCircle(vg, pos2.x, pos2.y, 11/2.0); - nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); - nvgFill(vg); } static NVGcolor wireColors[8] = { - nvgRGB(0x50, 0x50, 0x50), - nvgRGB(0xac, 0x41, 0x42), - nvgRGB(0x90, 0xa9, 0x59), - nvgRGB(0xf4, 0xbf, 0x75), - nvgRGB(0x6a, 0x9f, 0xb5), - nvgRGB(0xaa, 0x75, 0x9f), - nvgRGB(0x75, 0xb5, 0xaa), - nvgRGB(0xf5, 0xf5, 0xf5), + nvgRGB(0xc9, 0xb7, 0x0e), // yellow + nvgRGB(0xc9, 0x18, 0x47), // red + nvgRGB(0x0c, 0x8e, 0x15), // green + nvgRGB(0x09, 0x86, 0xad), // blue + nvgRGB(0x44, 0x44, 0x44), // black + nvgRGB(0x66, 0x66, 0x66), // gray + nvgRGB(0x88, 0x88, 0x88), // light gray + nvgRGB(0xaa, 0xaa, 0xaa), // white }; -static int wireColorId = 1; +static int nextWireColorId = 1; WireWidget::WireWidget() { - wireColorId = (wireColorId + 1) % 8; - color = wireColors[wireColorId]; + color = wireColors[nextWireColorId]; + nextWireColorId = (nextWireColorId + 1) % 8; } WireWidget::~WireWidget() { @@ -152,8 +138,11 @@ void WireWidget::draw(NVGcontext *vg) { outputPos = outputPos.minus(absolutePos); inputPos = inputPos.minus(absolutePos); - drawWire(vg, outputPos, inputPos, tension, color, opacity); + drawWire(vg, outputPos, inputPos, color, tension, opacity); + drawPlug(vg, outputPos, color); + drawPlug(vg, inputPos, color); } + } // namespace rack