@@ -30,6 +30,7 @@ struct Engine { | |||||
void removeModule(Module *module); | void removeModule(Module *module); | ||||
void resetModule(Module *module); | void resetModule(Module *module); | ||||
void randomizeModule(Module *module); | void randomizeModule(Module *module); | ||||
void bypassModule(Module *module, bool bypass); | |||||
/** Does not transfer pointer ownership */ | /** Does not transfer pointer ownership */ | ||||
void addCable(Cable *cable); | void addCable(Cable *cable); | ||||
void removeCable(Cable *cable); | void removeCable(Cable *cable); | ||||
@@ -37,16 +37,16 @@ struct Port { | |||||
return voltages[channel]; | return voltages[channel]; | ||||
} | } | ||||
/** Returns the voltage if a cable is plugged in, otherwise returns the given normal voltage */ | |||||
float getNormalVoltage(float normalVoltage, int channel = 0) { | |||||
return isConnected() ? getVoltage(channel) : normalVoltage; | |||||
} | |||||
/** Returns the voltage if there are enough channels, otherwise returns the first voltage (channel 0) */ | |||||
/** Returns the voltage if `channel` is a valid channel, otherwise returns the first voltage (channel 0) */ | |||||
float getPolyVoltage(int channel) { | float getPolyVoltage(int channel) { | ||||
return (channel < channels) ? getVoltage(channel) : getVoltage(0); | return (channel < channels) ? getVoltage(channel) : getVoltage(0); | ||||
} | } | ||||
/** Returns the voltage if a cable is connected, otherwise returns the given normal voltage */ | |||||
float getNormalVoltage(float normalVoltage, int channel = 0) { | |||||
return isConnected() ? getVoltage(channel) : normalVoltage; | |||||
} | |||||
float getNormalPolyVoltage(float normalVoltage, int channel) { | float getNormalPolyVoltage(float normalVoltage, int channel) { | ||||
return isConnected() ? getPolyVoltage(channel) : normalVoltage; | return isConnected() ? getPolyVoltage(channel) : normalVoltage; | ||||
} | } | ||||
@@ -221,7 +221,7 @@ void CableWidget::draw(NVGcontext *vg) { | |||||
} | } | ||||
float thickness = 5; | float thickness = 5; | ||||
if (cable->outputModule) { | |||||
if (isComplete()) { | |||||
Output *output = &cable->outputModule->outputs[cable->outputId]; | Output *output = &cable->outputModule->outputs[cable->outputId]; | ||||
if (output->channels > 1) { | if (output->channels > 1) { | ||||
// Increase thickness if output port is polyphonic | // Increase thickness if output port is polyphonic | ||||
@@ -246,7 +246,7 @@ void CableWidget::drawPlugs(NVGcontext *vg) { | |||||
// Draw plug if the cable is on top, or if the cable is incomplete | // Draw plug if the cable is on top, or if the cable is incomplete | ||||
if (!isComplete() || app()->scene->rackWidget->getTopCable(outputPort) == this) { | if (!isComplete() || app()->scene->rackWidget->getTopCable(outputPort) == this) { | ||||
drawPlug(vg, outputPos, color); | drawPlug(vg, outputPos, color); | ||||
if (outputPort) { | |||||
if (isComplete()) { | |||||
// Draw plug light | // Draw plug light | ||||
nvgSave(vg); | nvgSave(vg); | ||||
nvgTranslate(vg, outputPos.x - 4, outputPos.y - 4); | nvgTranslate(vg, outputPos.x - 4, outputPos.y - 4); | ||||
@@ -257,7 +257,7 @@ void CableWidget::drawPlugs(NVGcontext *vg) { | |||||
if (!isComplete() || app()->scene->rackWidget->getTopCable(inputPort) == this) { | if (!isComplete() || app()->scene->rackWidget->getTopCable(inputPort) == this) { | ||||
drawPlug(vg, inputPos, color); | drawPlug(vg, inputPos, color); | ||||
if (inputPort) { | |||||
if (isComplete()) { | |||||
nvgSave(vg); | nvgSave(vg); | ||||
nvgTranslate(vg, inputPos.x - 4, inputPos.y - 4); | nvgTranslate(vg, inputPos.x - 4, inputPos.y - 4); | ||||
inputPort->plugLight->draw(vg); | inputPort->plugLight->draw(vg); | ||||
@@ -117,22 +117,7 @@ static void Engine_step(Engine *engine) { | |||||
// Iterate modules | // Iterate modules | ||||
for (Module *module : engine->modules) { | for (Module *module : engine->modules) { | ||||
if (module->bypass) { | |||||
// Bypass module | |||||
for (Output &output : module->outputs) { | |||||
// This also zeros all voltages | |||||
output.setChannels(0); | |||||
} | |||||
if (settings::powerMeter) { | |||||
module->cpuTime = 0.f; | |||||
} | |||||
} | |||||
else { | |||||
// Set all outputs to 1 channel so that modules are forced to specify 0 or >2 channels every frame | |||||
for (Output &output : module->outputs) { | |||||
// Don't use Port::setChannels() so we maintain all previous voltages | |||||
output.channels = 1; | |||||
} | |||||
if (!module->bypass) { | |||||
// Step module | // Step module | ||||
if (settings::powerMeter) { | if (settings::powerMeter) { | ||||
auto startTime = std::chrono::high_resolution_clock::now(); | auto startTime = std::chrono::high_resolution_clock::now(); | ||||
@@ -263,6 +248,7 @@ void Engine::resetModule(Module *module) { | |||||
assert(module); | assert(module); | ||||
VIPLock vipLock(internal->vipMutex); | VIPLock vipLock(internal->vipMutex); | ||||
std::lock_guard<std::mutex> lock(internal->mutex); | std::lock_guard<std::mutex> lock(internal->mutex); | ||||
module->reset(); | module->reset(); | ||||
} | } | ||||
@@ -270,9 +256,31 @@ void Engine::randomizeModule(Module *module) { | |||||
assert(module); | assert(module); | ||||
VIPLock vipLock(internal->vipMutex); | VIPLock vipLock(internal->vipMutex); | ||||
std::lock_guard<std::mutex> lock(internal->mutex); | std::lock_guard<std::mutex> lock(internal->mutex); | ||||
module->randomize(); | module->randomize(); | ||||
} | } | ||||
void Engine::bypassModule(Module *module, bool bypass) { | |||||
assert(module); | |||||
VIPLock vipLock(internal->vipMutex); | |||||
std::lock_guard<std::mutex> lock(internal->mutex); | |||||
if (bypass) { | |||||
for (Output &output : module->outputs) { | |||||
// This also zeros all voltages | |||||
output.setChannels(0); | |||||
} | |||||
module->cpuTime = 0.f; | |||||
} | |||||
else { | |||||
// Set all outputs to 1 channel | |||||
for (Output &output : module->outputs) { | |||||
// Don't use Port::setChannels() so we maintain all previous voltages | |||||
output.channels = 1; | |||||
} | |||||
} | |||||
module->bypass = bypass; | |||||
} | |||||
static void Engine_updateConnected(Engine *engine) { | static void Engine_updateConnected(Engine *engine) { | ||||
// Set everything to unconnected | // Set everything to unconnected | ||||
for (Module *module : engine->modules) { | for (Module *module : engine->modules) { | ||||
@@ -2,6 +2,7 @@ | |||||
#include "app.hpp" | #include "app.hpp" | ||||
#include "app/Scene.hpp" | #include "app/Scene.hpp" | ||||
#include "engine/Cable.hpp" | #include "engine/Cable.hpp" | ||||
#include "engine/Engine.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -80,13 +81,13 @@ void ModuleMove::redo() { | |||||
void ModuleBypass::undo() { | void ModuleBypass::undo() { | ||||
ModuleWidget *mw = app()->scene->rackWidget->getModule(moduleId); | ModuleWidget *mw = app()->scene->rackWidget->getModule(moduleId); | ||||
assert(mw); | assert(mw); | ||||
mw->module->bypass = !bypass; | |||||
app()->engine->bypassModule(mw->module, !bypass); | |||||
} | } | ||||
void ModuleBypass::redo() { | void ModuleBypass::redo() { | ||||
ModuleWidget *mw = app()->scene->rackWidget->getModule(moduleId); | ModuleWidget *mw = app()->scene->rackWidget->getModule(moduleId); | ||||
assert(mw); | assert(mw); | ||||
mw->module->bypass = bypass; | |||||
app()->engine->bypassModule(mw->module, bypass); | |||||
} | } | ||||