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