| @@ -348,8 +348,9 @@ struct RackWidget : OpaqueWidget { | |||||
| }; | }; | ||||
| struct ModulePanel : TransparentWidget { | struct ModulePanel : TransparentWidget { | ||||
| std::string imageFilename; | |||||
| NVGcolor backgroundColor; | NVGcolor backgroundColor; | ||||
| NVGcolor highlightColor; | |||||
| std::string imageFilename; | |||||
| void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
| }; | }; | ||||
| @@ -33,9 +33,9 @@ struct MidiInterface : Module { | |||||
| PortMidiStream *stream = NULL; | PortMidiStream *stream = NULL; | ||||
| std::list<int> notes; | std::list<int> notes; | ||||
| bool pedal = false; | bool pedal = false; | ||||
| int note = 64; // C4 | |||||
| int note = 60; // C4, most modules should use 261.63 Hz | |||||
| int pitchWheel = 64; | int pitchWheel = 64; | ||||
| bool retrigger = true; | |||||
| bool retrigger = false; | |||||
| bool retriggered = false; | bool retriggered = false; | ||||
| MidiInterface(); | MidiInterface(); | ||||
| @@ -10,7 +10,7 @@ | |||||
| namespace rack { | namespace rack { | ||||
| std::string gApplicationName = "Virtuoso Rack"; | std::string gApplicationName = "Virtuoso Rack"; | ||||
| std::string gApplicationVersion = "v0.0.0"; | |||||
| std::string gApplicationVersion = "v0.0.0 alpha"; | |||||
| } // namespace rack | } // namespace rack | ||||
| @@ -10,9 +10,7 @@ void ModulePanel::draw(NVGcontext *vg) { | |||||
| // Background gradient | // Background gradient | ||||
| Vec c = box.getTopRight(); | Vec c = box.getTopRight(); | ||||
| float length = box.size.norm(); | float length = box.size.norm(); | ||||
| NVGcolor color1 = nvgLerpRGBA(backgroundColor, nvgRGBf(1.0, 1.0, 1.0), 0.5); | |||||
| NVGcolor color2 = backgroundColor; | |||||
| paint = nvgRadialGradient(vg, c.x, c.y, 0.0, length, color1, color2); | |||||
| paint = nvgRadialGradient(vg, c.x, c.y, 0.0, length, highlightColor, backgroundColor); | |||||
| nvgFillPaint(vg, paint); | nvgFillPaint(vg, paint); | ||||
| nvgFill(vg); | nvgFill(vg); | ||||
| // Background image | // Background image | ||||
| @@ -67,7 +67,9 @@ void ModuleWidget::fromJson(json_t *root) { | |||||
| size_t paramId; | size_t paramId; | ||||
| json_t *paramJ; | json_t *paramJ; | ||||
| json_array_foreach(paramsJ, paramId, paramJ) { | json_array_foreach(paramsJ, paramId, paramJ) { | ||||
| params[paramId]->fromJson(paramJ); | |||||
| if (0 <= paramId && paramId < params.size()) { | |||||
| params[paramId]->fromJson(paramJ); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -60,6 +60,10 @@ json_t *RackWidget::toJson() { | |||||
| // root | // root | ||||
| json_t *root = json_object(); | json_t *root = json_object(); | ||||
| // version | |||||
| json_t *versionJ = json_string(gApplicationVersion.c_str()); | |||||
| json_object_set_new(root, "version", versionJ); | |||||
| // modules | // modules | ||||
| json_t *modulesJ = json_array(); | json_t *modulesJ = json_array(); | ||||
| std::map<ModuleWidget*, int> moduleIds; | std::map<ModuleWidget*, int> moduleIds; | ||||
| @@ -86,16 +90,28 @@ json_t *RackWidget::toJson() { | |||||
| // wire | // wire | ||||
| json_t *wire = json_object(); | json_t *wire = json_object(); | ||||
| { | { | ||||
| // Get the modules at each end of the wire | |||||
| ModuleWidget *outputModuleWidget = wireWidget->outputPort->getAncestorOfType<ModuleWidget>(); | ModuleWidget *outputModuleWidget = wireWidget->outputPort->getAncestorOfType<ModuleWidget>(); | ||||
| assert(outputModuleWidget); | assert(outputModuleWidget); | ||||
| int outputModuleId = moduleIds[outputModuleWidget]; | |||||
| ModuleWidget *inputModuleWidget = wireWidget->inputPort->getAncestorOfType<ModuleWidget>(); | ModuleWidget *inputModuleWidget = wireWidget->inputPort->getAncestorOfType<ModuleWidget>(); | ||||
| assert(inputModuleWidget); | assert(inputModuleWidget); | ||||
| int outputModuleId = moduleIds[outputModuleWidget]; | |||||
| int inputModuleId = moduleIds[inputModuleWidget]; | int inputModuleId = moduleIds[inputModuleWidget]; | ||||
| // Get output/input ports | |||||
| auto outputIt = std::find(outputModuleWidget->outputs.begin(), outputModuleWidget->outputs.end(), wireWidget->outputPort); | |||||
| assert(outputIt != outputModuleWidget->outputs.end()); | |||||
| int outputId = outputIt - outputModuleWidget->outputs.begin(); | |||||
| auto inputIt = std::find(inputModuleWidget->inputs.begin(), inputModuleWidget->inputs.end(), wireWidget->inputPort); | |||||
| assert(inputIt != inputModuleWidget->inputs.end()); | |||||
| int inputId = inputIt - inputModuleWidget->inputs.begin(); | |||||
| json_object_set_new(wire, "outputModuleId", json_integer(outputModuleId)); | json_object_set_new(wire, "outputModuleId", json_integer(outputModuleId)); | ||||
| json_object_set_new(wire, "outputId", json_integer(wireWidget->outputPort->outputId)); | |||||
| json_object_set_new(wire, "outputId", json_integer(outputId)); | |||||
| json_object_set_new(wire, "inputModuleId", json_integer(inputModuleId)); | json_object_set_new(wire, "inputModuleId", json_integer(inputModuleId)); | ||||
| json_object_set_new(wire, "inputId", json_integer(wireWidget->inputPort->inputId)); | |||||
| json_object_set_new(wire, "inputId", json_integer(inputId)); | |||||
| } | } | ||||
| json_array_append_new(wires, wire); | json_array_append_new(wires, wire); | ||||
| } | } | ||||
| @@ -105,7 +105,7 @@ Toolbar::Toolbar() { | |||||
| label->box.pos = Vec(xPos, margin); | label->box.pos = Vec(xPos, margin); | ||||
| label->text = gApplicationName + " " + gApplicationVersion; | label->text = gApplicationName + " " + gApplicationVersion; | ||||
| addChild(label); | addChild(label); | ||||
| xPos += 150; | |||||
| xPos += 175; | |||||
| } | } | ||||
| xPos += margin; | xPos += margin; | ||||
| @@ -5,32 +5,34 @@ namespace rack { | |||||
| void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color) { | void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color) { | ||||
| float dist = pos1.minus(pos2).norm(); | float dist = pos1.minus(pos2).norm(); | ||||
| float slump = (1.0 - tension) * (150.0 + 1.0*dist); | |||||
| Vec pos3 = pos1.plus(pos2).div(2).plus(Vec(0, slump)); | |||||
| NVGcolor colorOutline = nvgRGBf(0, 0, 0); | |||||
| Vec slump; | |||||
| slump.y = (1.0 - tension) * (150.0 + 1.0*dist); | |||||
| Vec pos3 = pos1.plus(pos2).div(2).plus(slump); | |||||
| nvgLineJoin(vg, NVG_ROUND); | nvgLineJoin(vg, NVG_ROUND); | ||||
| nvgStrokeWidth(vg, 4); | |||||
| // Shadow | // Shadow | ||||
| // Vec pos4 = pos3.plus(slump.mult(0.1)); | |||||
| // NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.2); | |||||
| // nvgBeginPath(vg); | |||||
| // nvgMoveTo(vg, pos1.x, pos1.y); | |||||
| // nvgQuadTo(vg, pos4.x, pos4.y, pos2.x, pos2.y); | |||||
| // nvgStrokeColor(vg, colorShadow); | |||||
| // nvgStroke(vg); | |||||
| Vec pos4 = pos3.plus(slump.mult(0.08)); | |||||
| NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.08); | |||||
| nvgBeginPath(vg); | |||||
| nvgMoveTo(vg, pos1.x, pos1.y); | |||||
| nvgQuadTo(vg, pos4.x, pos4.y, pos2.x, pos2.y); | |||||
| nvgStrokeColor(vg, colorShadow); | |||||
| nvgStrokeWidth(vg, 5); | |||||
| nvgStroke(vg); | |||||
| // Wire outline | // Wire outline | ||||
| NVGcolor colorOutline = nvgRGBf(0, 0, 0); | |||||
| nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
| nvgMoveTo(vg, pos1.x, pos1.y); | nvgMoveTo(vg, pos1.x, pos1.y); | ||||
| nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y); | nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y); | ||||
| nvgStrokeColor(vg, colorOutline); | nvgStrokeColor(vg, colorOutline); | ||||
| nvgStrokeWidth(vg, 4); | |||||
| nvgStroke(vg); | nvgStroke(vg); | ||||
| // Wire solid | // Wire solid | ||||
| nvgStrokeWidth(vg, 2); | |||||
| nvgStrokeColor(vg, color); | nvgStrokeColor(vg, color); | ||||
| nvgStrokeWidth(vg, 2); | |||||
| nvgStroke(vg); | nvgStroke(vg); | ||||
| } | } | ||||