| @@ -8,6 +8,7 @@ namespace rack { | |||||
| struct RackScrollWidget : ScrollWidget { | struct RackScrollWidget : ScrollWidget { | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| }; | }; | ||||
| @@ -50,6 +50,7 @@ struct RackWidget : OpaqueWidget { | |||||
| /** Moves a module to the closest non-colliding position */ | /** Moves a module to the closest non-colliding position */ | ||||
| bool requestModuleBoxNearest(ModuleWidget *mw, math::Rect requestedBox); | bool requestModuleBoxNearest(ModuleWidget *mw, math::Rect requestedBox); | ||||
| ModuleWidget *getModule(int moduleId); | ModuleWidget *getModule(int moduleId); | ||||
| bool isEmpty(); | |||||
| // Cable methods | // Cable methods | ||||
| @@ -27,4 +27,22 @@ void RackScrollWidget::step() { | |||||
| } | } | ||||
| void RackScrollWidget::draw(NVGcontext *vg) { | |||||
| ScrollWidget::draw(vg); | |||||
| if (app()->scene->rackWidget->isEmpty()) { | |||||
| math::Rect b; | |||||
| b.size = math::Vec(600, 300); | |||||
| b.pos = box.size.minus(b.size).div(2); | |||||
| NVGcolor bg = nvgRGBAf(0, 0, 0, 0.4); | |||||
| bndInnerBox(vg, b.pos.x, b.pos.y, b.size.x, b.size.y, | |||||
| 0, 0, 0, 0, bg, bg); | |||||
| NVGcolor fg = nvgRGBAf(1, 1, 1, 0.25); | |||||
| std::string text = "Right-click or press Enter to add modules"; | |||||
| bndIconLabelValue(vg, b.pos.x, b.pos.y + 80, b.size.x, b.size.y, -1, fg, BND_CENTER, 80, text.c_str(), NULL); | |||||
| } | |||||
| } | |||||
| } // namespace rack | } // namespace rack | ||||
| @@ -416,6 +416,10 @@ ModuleWidget *RackWidget::getModule(int moduleId) { | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| bool RackWidget::isEmpty() { | |||||
| return moduleContainer->children.empty(); | |||||
| } | |||||
| void RackWidget::clearCables() { | void RackWidget::clearCables() { | ||||
| for (Widget *w : cableContainer->children) { | for (Widget *w : cableContainer->children) { | ||||
| CableWidget *cw = dynamic_cast<CableWidget*>(w); | CableWidget *cw = dynamic_cast<CableWidget*>(w); | ||||
| @@ -64,7 +64,7 @@ void Scene::step() { | |||||
| // Set zoom every few frames | // Set zoom every few frames | ||||
| if (app()->window->frame % 10 == 0) | if (app()->window->frame % 10 == 0) | ||||
| zoomWidget->setZoom(settings::zoom); | |||||
| zoomWidget->setZoom(std::round(settings::zoom * 100) / 100); | |||||
| // Request latest version from server | // Request latest version from server | ||||
| if (!devMode && checkVersion && !checkedVersion) { | if (!devMode && checkVersion && !checkedVersion) { | ||||
| @@ -187,8 +187,8 @@ struct ZoomQuantity : Quantity { | |||||
| float getMinValue() override {return 0.25;} | float getMinValue() override {return 0.25;} | ||||
| float getMaxValue() override {return 2.0;} | float getMaxValue() override {return 2.0;} | ||||
| float getDefaultValue() override {return 1.0;} | float getDefaultValue() override {return 1.0;} | ||||
| float getDisplayValue() override {return getValue() * 100.0;} | |||||
| void setDisplayValue(float displayValue) override {setValue(displayValue / 100.0);} | |||||
| float getDisplayValue() override {return std::round(getValue() * 100);} | |||||
| void setDisplayValue(float displayValue) override {setValue(displayValue / 100);} | |||||
| std::string getLabel() override {return "Zoom";} | std::string getLabel() override {return "Zoom";} | ||||
| std::string getUnit() override {return "%";} | std::string getUnit() override {return "%";} | ||||
| }; | }; | ||||
| @@ -202,8 +202,8 @@ struct CableOpacityQuantity : Quantity { | |||||
| return settings::cableOpacity; | return settings::cableOpacity; | ||||
| } | } | ||||
| float getDefaultValue() override {return 0.5;} | float getDefaultValue() override {return 0.5;} | ||||
| float getDisplayValue() override {return getValue() * 100.0;} | |||||
| void setDisplayValue(float displayValue) override {setValue(displayValue / 100.0);} | |||||
| float getDisplayValue() override {return getValue() * 100;} | |||||
| void setDisplayValue(float displayValue) override {setValue(displayValue / 100);} | |||||
| std::string getLabel() override {return "Cable opacity";} | std::string getLabel() override {return "Cable opacity";} | ||||
| std::string getUnit() override {return "%";} | std::string getUnit() override {return "%";} | ||||
| }; | }; | ||||
| @@ -225,7 +225,7 @@ struct CableTensionQuantity : Quantity { | |||||
| struct PowerMeterItem : MenuItem { | struct PowerMeterItem : MenuItem { | ||||
| PowerMeterItem() { | PowerMeterItem() { | ||||
| text = "Power meter"; | |||||
| text = "CPU meter"; | |||||
| rightText = CHECKMARK(settings::powerMeter); | rightText = CHECKMARK(settings::powerMeter); | ||||
| } | } | ||||
| void onAction(const event::Action &e) override { | void onAction(const event::Action &e) override { | ||||
| @@ -1,6 +1,7 @@ | |||||
| #include "engine/Engine.hpp" | #include "engine/Engine.hpp" | ||||
| #include "settings.hpp" | #include "settings.hpp" | ||||
| #include "system.hpp" | #include "system.hpp" | ||||
| #include "random.hpp" | |||||
| #include <algorithm> | #include <algorithm> | ||||
| #include <chrono> | #include <chrono> | ||||
| @@ -150,6 +151,16 @@ static void Engine_step(Engine *engine) { | |||||
| } | } | ||||
| } | } | ||||
| #if 0 | |||||
| if (random::u32() % 1000 == 0 && settings::powerMeter) { | |||||
| float cpuTotal = 0.f; | |||||
| for (Module *module : engine->modules) { | |||||
| cpuTotal += module->cpuTime; | |||||
| } | |||||
| DEBUG("%fus %f%% CPU", cpuTotal * 1e6, cpuTotal * engine->internal->sampleRate * 100); | |||||
| } | |||||
| #endif | |||||
| // Step cables | // Step cables | ||||
| for (Cable *cable : engine->cables) { | for (Cable *cable : engine->cables) { | ||||
| cable->step(); | cable->step(); | ||||