You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1359 lines
35KB

  1. #include <map>
  2. #include <algorithm>
  3. #include <queue>
  4. #include <functional>
  5. #include <osdialog.h>
  6. #include <app/RackWidget.hpp>
  7. #include <widget/TransparentWidget.hpp>
  8. #include <app/RailWidget.hpp>
  9. #include <app/Scene.hpp>
  10. #include <settings.hpp>
  11. #include <plugin.hpp>
  12. #include <engine/Engine.hpp>
  13. #include <context.hpp>
  14. #include <system.hpp>
  15. #include <asset.hpp>
  16. #include <patch.hpp>
  17. #include <helpers.hpp>
  18. namespace rack {
  19. namespace app {
  20. /** Creates a new Module and ModuleWidget */
  21. static ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) {
  22. plugin::Model* model = plugin::modelFromJson(moduleJ);
  23. assert(model);
  24. engine::Module* module = model->createModule();
  25. assert(module);
  26. module->fromJson(moduleJ);
  27. // Create ModuleWidget
  28. ModuleWidget* moduleWidget = module->model->createModuleWidget(module);
  29. assert(moduleWidget);
  30. return moduleWidget;
  31. }
  32. struct ModuleContainer : widget::Widget {
  33. void draw(const DrawArgs& args) override {
  34. // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets.
  35. for (widget::Widget* child : children) {
  36. ModuleWidget* w = dynamic_cast<ModuleWidget*>(child);
  37. assert(w);
  38. nvgSave(args.vg);
  39. nvgTranslate(args.vg, child->box.pos.x, child->box.pos.y);
  40. w->drawShadow(args);
  41. nvgRestore(args.vg);
  42. }
  43. Widget::draw(args);
  44. }
  45. };
  46. struct CableContainer : widget::TransparentWidget {
  47. void draw(const DrawArgs& args) override {
  48. // Draw Plugs
  49. Widget::draw(args);
  50. // Draw cable shadows
  51. DrawArgs args1 = args;
  52. args1.layer = 1;
  53. Widget::draw(args1);
  54. // Draw cables
  55. DrawArgs args2 = args;
  56. args2.layer = 2;
  57. Widget::draw(args2);
  58. }
  59. };
  60. struct RackWidget::Internal {
  61. RailWidget* rail = NULL;
  62. widget::Widget* moduleContainer = NULL;
  63. widget::Widget* cableContainer = NULL;
  64. /** The last mouse position in the RackWidget */
  65. math::Vec mousePos;
  66. bool selecting = false;
  67. math::Vec selectionStart;
  68. math::Vec selectionEnd;
  69. std::set<ModuleWidget*> selectedModules;
  70. };
  71. RackWidget::RackWidget() {
  72. internal = new Internal;
  73. internal->rail = new RailWidget;
  74. addChild(internal->rail);
  75. internal->moduleContainer = new ModuleContainer;
  76. addChild(internal->moduleContainer);
  77. internal->cableContainer = new CableContainer;
  78. addChild(internal->cableContainer);
  79. }
  80. RackWidget::~RackWidget() {
  81. clear();
  82. delete internal;
  83. }
  84. void RackWidget::step() {
  85. Widget::step();
  86. }
  87. void RackWidget::draw(const DrawArgs& args) {
  88. // Darken all children by user setting
  89. float b = settings::rackBrightness;
  90. nvgGlobalTint(args.vg, nvgRGBAf(b, b, b, 1));
  91. Widget::draw(args);
  92. // Draw selection rectangle
  93. if (internal->selecting) {
  94. nvgBeginPath(args.vg);
  95. math::Rect selectionBox = math::Rect::fromCorners(internal->selectionStart, internal->selectionEnd);
  96. nvgRect(args.vg, RECT_ARGS(selectionBox));
  97. nvgFillColor(args.vg, nvgRGBAf(1, 0, 0, 0.25));
  98. nvgFill(args.vg);
  99. nvgStrokeWidth(args.vg, 2.0);
  100. nvgStrokeColor(args.vg, nvgRGBAf(1, 0, 0, 0.5));
  101. nvgStroke(args.vg);
  102. }
  103. }
  104. void RackWidget::onHover(const HoverEvent& e) {
  105. // Set before calling children's onHover()
  106. internal->mousePos = e.pos;
  107. OpaqueWidget::onHover(e);
  108. }
  109. void RackWidget::onHoverKey(const HoverKeyEvent& e) {
  110. OpaqueWidget::onHoverKey(e);
  111. }
  112. void RackWidget::onButton(const ButtonEvent& e) {
  113. Widget::onButton(e);
  114. e.stopPropagating();
  115. if (e.isConsumed())
  116. return;
  117. if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
  118. APP->scene->browser->show();
  119. e.consume(this);
  120. }
  121. if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
  122. e.consume(this);
  123. }
  124. }
  125. void RackWidget::onDragStart(const DragStartEvent& e) {
  126. if (e.button == GLFW_MOUSE_BUTTON_LEFT) {
  127. // Deselect all modules
  128. updateSelectionFromRect();
  129. internal->selecting = true;
  130. internal->selectionStart = internal->mousePos;
  131. internal->selectionEnd = internal->mousePos;
  132. }
  133. }
  134. void RackWidget::onDragEnd(const DragEndEvent& e) {
  135. if (e.button == GLFW_MOUSE_BUTTON_LEFT) {
  136. internal->selecting = false;
  137. }
  138. }
  139. void RackWidget::onDragHover(const DragHoverEvent& e) {
  140. // Set before calling children's onDragHover()
  141. internal->mousePos = e.pos;
  142. if (internal->selecting) {
  143. internal->selectionEnd = internal->mousePos;
  144. updateSelectionFromRect();
  145. }
  146. OpaqueWidget::onDragHover(e);
  147. }
  148. widget::Widget* RackWidget::getModuleContainer() {
  149. return internal->moduleContainer;
  150. }
  151. widget::Widget* RackWidget::getCableContainer() {
  152. return internal->cableContainer;
  153. }
  154. math::Vec RackWidget::getMousePos() {
  155. return internal->mousePos;
  156. }
  157. void RackWidget::clear() {
  158. // This isn't required because removing all ModuleWidgets should remove all cables, but do it just in case.
  159. clearCables();
  160. // Remove ModuleWidgets
  161. for (ModuleWidget* mw : getModules()) {
  162. removeModule(mw);
  163. delete mw;
  164. }
  165. }
  166. static void RackWidget_updateExpanders(RackWidget* that) {
  167. for (widget::Widget* w : that->internal->moduleContainer->children) {
  168. math::Vec pLeft = w->box.pos.div(RACK_GRID_SIZE).round();
  169. math::Vec pRight = w->box.getTopRight().div(RACK_GRID_SIZE).round();
  170. ModuleWidget* mwLeft = NULL;
  171. ModuleWidget* mwRight = NULL;
  172. // Find adjacent modules
  173. for (widget::Widget* w2 : that->internal->moduleContainer->children) {
  174. if (w2 == w)
  175. continue;
  176. math::Vec p2Left = w2->box.pos.div(RACK_GRID_SIZE).round();
  177. math::Vec p2Right = w2->box.getTopRight().div(RACK_GRID_SIZE).round();
  178. // Check if this is a left module
  179. if (p2Right.equals(pLeft)) {
  180. mwLeft = dynamic_cast<ModuleWidget*>(w2);
  181. }
  182. // Check if this is a right module
  183. if (p2Left.equals(pRight)) {
  184. mwRight = dynamic_cast<ModuleWidget*>(w2);
  185. }
  186. }
  187. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  188. mw->module->leftExpander.moduleId = mwLeft ? mwLeft->module->id : -1;
  189. mw->module->rightExpander.moduleId = mwRight ? mwRight->module->id : -1;
  190. }
  191. }
  192. void RackWidget::mergeJson(json_t* rootJ) {
  193. // Get module offset so modules are aligned to (0, 0) when the patch is loaded.
  194. math::Vec moduleOffset = internal->moduleContainer->getChildrenBoundingBox().pos;
  195. if (!moduleOffset.isFinite()) {
  196. moduleOffset = RACK_OFFSET;
  197. }
  198. // modules
  199. json_t* modulesJ = json_object_get(rootJ, "modules");
  200. if (!modulesJ)
  201. return;
  202. size_t moduleIndex;
  203. json_t* moduleJ;
  204. json_array_foreach(modulesJ, moduleIndex, moduleJ) {
  205. // module
  206. json_t* idJ = json_object_get(moduleJ, "id");
  207. if (!idJ)
  208. continue;
  209. int64_t id = json_integer_value(idJ);
  210. // TODO Legacy v0.6?
  211. ModuleWidget* mw = getModule(id);
  212. if (!mw) {
  213. WARN("Cannot find ModuleWidget %" PRId64, id);
  214. continue;
  215. }
  216. // pos
  217. math::Vec pos = mw->box.pos.minus(moduleOffset);
  218. pos = pos.div(RACK_GRID_SIZE).round();
  219. json_t* posJ = json_pack("[i, i]", (int) pos.x, (int) pos.y);
  220. json_object_set_new(moduleJ, "pos", posJ);
  221. }
  222. // cables
  223. json_t* cablesJ = json_object_get(rootJ, "cables");
  224. if (!cablesJ)
  225. return;
  226. size_t cableIndex;
  227. json_t* cableJ;
  228. json_array_foreach(cablesJ, cableIndex, cableJ) {
  229. // cable
  230. json_t* idJ = json_object_get(cableJ, "id");
  231. if (!idJ)
  232. continue;
  233. int64_t id = json_integer_value(idJ);
  234. CableWidget* cw = getCable(id);
  235. if (!cw) {
  236. WARN("Cannot find CableWidget %" PRId64, id);
  237. continue;
  238. }
  239. cw->mergeJson(cableJ);
  240. }
  241. }
  242. void RackWidget::fromJson(json_t* rootJ) {
  243. // version
  244. std::string version;
  245. json_t* versionJ = json_object_get(rootJ, "version");
  246. if (versionJ)
  247. version = json_string_value(versionJ);
  248. bool legacyV05 = false;
  249. if (string::startsWith(version, "0.3.") || string::startsWith(version, "0.4.") || string::startsWith(version, "0.5.") || version == "dev") {
  250. legacyV05 = true;
  251. }
  252. // modules
  253. json_t* modulesJ = json_object_get(rootJ, "modules");
  254. if (!modulesJ)
  255. return;
  256. size_t moduleIndex;
  257. json_t* moduleJ;
  258. json_array_foreach(modulesJ, moduleIndex, moduleJ) {
  259. // Get module ID
  260. json_t* idJ = json_object_get(moduleJ, "id");
  261. int64_t id;
  262. if (idJ)
  263. id = json_integer_value(idJ);
  264. else
  265. id = moduleIndex;
  266. // Get Module
  267. engine::Module* module = APP->engine->getModule(id);
  268. if (!module) {
  269. WARN("Cannot find Module %" PRId64, id);
  270. continue;
  271. }
  272. // Create ModuleWidget
  273. ModuleWidget* mw = module->model->createModuleWidget(module);
  274. // pos
  275. json_t* posJ = json_object_get(moduleJ, "pos");
  276. double x = 0.0, y = 0.0;
  277. json_unpack(posJ, "[F, F]", &x, &y);
  278. math::Vec pos = math::Vec(x, y);
  279. if (legacyV05) {
  280. // In <=v0.5, positions were in pixel units
  281. }
  282. else {
  283. pos = pos.mult(RACK_GRID_SIZE);
  284. }
  285. pos = pos.plus(RACK_OFFSET);
  286. setModulePosNearest(mw, pos);
  287. internal->moduleContainer->addChild(mw);
  288. }
  289. RackWidget_updateExpanders(this);
  290. // cables
  291. json_t* cablesJ = json_object_get(rootJ, "cables");
  292. // In <=v0.6, cables were called wires
  293. if (!cablesJ)
  294. cablesJ = json_object_get(rootJ, "wires");
  295. if (!cablesJ)
  296. return;
  297. size_t cableIndex;
  298. json_t* cableJ;
  299. json_array_foreach(cablesJ, cableIndex, cableJ) {
  300. // Get cable ID
  301. json_t* idJ = json_object_get(cableJ, "id");
  302. int64_t id;
  303. if (idJ)
  304. id = json_integer_value(idJ);
  305. else
  306. id = cableIndex;
  307. // Get Cable
  308. engine::Cable* cable = APP->engine->getCable(id);
  309. if (!cable) {
  310. WARN("Cannot find Cable %" PRId64, id);
  311. continue;
  312. }
  313. // Create CableWidget
  314. CableWidget* cw = new CableWidget;
  315. cw->setCable(cable);
  316. cw->fromJson(cableJ);
  317. // In <=v1, cable colors were not serialized, so choose one from the available colors.
  318. if (cw->color.a == 0.f) {
  319. cw->setNextCableColor();
  320. }
  321. addCable(cw);
  322. }
  323. }
  324. struct PasteJsonReturn {
  325. std::map<int64_t, int64_t> newModuleIds;
  326. };
  327. static PasteJsonReturn RackWidget_pasteJson(RackWidget* that, json_t* rootJ, history::ComplexAction* complexAction) {
  328. that->deselectAll();
  329. std::map<int64_t, int64_t> newModuleIds;
  330. // modules
  331. json_t* modulesJ = json_object_get(rootJ, "modules");
  332. if (!modulesJ)
  333. return {};
  334. size_t moduleIndex;
  335. json_t* moduleJ;
  336. json_array_foreach(modulesJ, moduleIndex, moduleJ) {
  337. json_t* idJ = json_object_get(moduleJ, "id");
  338. if (!idJ)
  339. continue;
  340. int64_t id = json_integer_value(idJ);
  341. engine::Module::jsonStripIds(moduleJ);
  342. ModuleWidget* mw;
  343. try {
  344. mw = moduleWidgetFromJson(moduleJ);
  345. }
  346. catch (Exception& e) {
  347. WARN("%s", e.what());
  348. continue;
  349. }
  350. assert(mw);
  351. assert(mw->module);
  352. APP->engine->addModule(mw->module);
  353. // pos
  354. json_t* posJ = json_object_get(moduleJ, "pos");
  355. double x = 0.0, y = 0.0;
  356. json_unpack(posJ, "[F, F]", &x, &y);
  357. math::Vec pos = math::Vec(x, y);
  358. pos = pos.mult(RACK_GRID_SIZE);
  359. mw->box.pos = pos.plus(RACK_OFFSET);
  360. that->internal->moduleContainer->addChild(mw);
  361. that->select(mw);
  362. newModuleIds[id] = mw->module->id;
  363. }
  364. // This calls RackWidget_updateExpanders()
  365. that->setSelectionPosNearest(math::Vec(0, 0));
  366. // Add positioned selected modules to history
  367. for (ModuleWidget* mw : that->getSelected()) {
  368. // history::ModuleAdd
  369. history::ModuleAdd* h = new history::ModuleAdd;
  370. h->setModule(mw);
  371. complexAction->push(h);
  372. }
  373. // cables
  374. json_t* cablesJ = json_object_get(rootJ, "cables");
  375. if (cablesJ) {
  376. size_t cableIndex;
  377. json_t* cableJ;
  378. json_array_foreach(cablesJ, cableIndex, cableJ) {
  379. engine::Cable::jsonStripIds(cableJ);
  380. // Remap old module IDs to new IDs
  381. json_t* inputModuleIdJ = json_object_get(cableJ, "inputModuleId");
  382. if (!inputModuleIdJ)
  383. continue;
  384. int64_t inputModuleId = json_integer_value(inputModuleIdJ);
  385. inputModuleId = get(newModuleIds, inputModuleId, -1);
  386. if (inputModuleId < 0)
  387. continue;
  388. json_object_set(cableJ, "inputModuleId", json_integer(inputModuleId));
  389. json_t* outputModuleIdJ = json_object_get(cableJ, "outputModuleId");
  390. if (!outputModuleIdJ)
  391. continue;
  392. int64_t outputModuleId = json_integer_value(outputModuleIdJ);
  393. outputModuleId = get(newModuleIds, outputModuleId, -1);
  394. if (outputModuleId < 0)
  395. continue;
  396. json_object_set(cableJ, "outputModuleId", json_integer(outputModuleId));
  397. // Create Cable
  398. engine::Cable* cable = new engine::Cable;
  399. try {
  400. cable->fromJson(cableJ);
  401. APP->engine->addCable(cable);
  402. }
  403. catch (Exception& e) {
  404. WARN("Cannot paste cable: %s", e.what());
  405. delete cable;
  406. continue;
  407. }
  408. // Create CableWidget
  409. app::CableWidget* cw = new app::CableWidget;
  410. cw->setCable(cable);
  411. cw->fromJson(cableJ);
  412. that->addCable(cw);
  413. // history::CableAdd
  414. history::CableAdd* h = new history::CableAdd;
  415. h->setCable(cw);
  416. complexAction->push(h);
  417. }
  418. }
  419. return {newModuleIds};
  420. }
  421. void RackWidget::pasteJsonAction(json_t* rootJ) {
  422. history::ComplexAction* complexAction = new history::ComplexAction;
  423. complexAction->name = "paste modules";
  424. DEFER({
  425. if (!complexAction->isEmpty())
  426. APP->history->push(complexAction);
  427. else
  428. delete complexAction;
  429. });
  430. RackWidget_pasteJson(this, rootJ, complexAction);
  431. }
  432. void RackWidget::pasteModuleJsonAction(json_t* moduleJ) {
  433. engine::Module::jsonStripIds(moduleJ);
  434. ModuleWidget* mw;
  435. try {
  436. mw = moduleWidgetFromJson(moduleJ);
  437. }
  438. catch (Exception& e) {
  439. WARN("%s", e.what());
  440. return;
  441. }
  442. assert(mw);
  443. assert(mw->module);
  444. APP->engine->addModule(mw->module);
  445. addModuleAtMouse(mw);
  446. // history::ModuleAdd
  447. history::ModuleAdd* h = new history::ModuleAdd;
  448. h->name = "paste module";
  449. h->setModule(mw);
  450. APP->history->push(h);
  451. }
  452. void RackWidget::pasteClipboardAction() {
  453. const char* json = glfwGetClipboardString(APP->window->win);
  454. if (!json) {
  455. WARN("Could not get text from clipboard.");
  456. return;
  457. }
  458. json_error_t error;
  459. json_t* rootJ = json_loads(json, 0, &error);
  460. if (!rootJ) {
  461. WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
  462. return;
  463. }
  464. DEFER({json_decref(rootJ);});
  465. json_t* modulesJ = json_object_get(rootJ, "modules");
  466. if (modulesJ) {
  467. // JSON is a selection of modules
  468. pasteJsonAction(rootJ);
  469. }
  470. else {
  471. // JSON is a single module
  472. pasteModuleJsonAction(rootJ);
  473. }
  474. }
  475. void RackWidget::addModule(ModuleWidget* m) {
  476. assert(m);
  477. // Module must be 3U high and at least 1HP wide
  478. if (m->box.size.x < RACK_GRID_WIDTH / 2)
  479. throw Exception("Module %s width is %g px, must be at least %g px", m->model->getFullName().c_str(), m->box.size.x, RACK_GRID_WIDTH);
  480. if (m->box.size.y != RACK_GRID_HEIGHT)
  481. throw Exception("Module %s height is %g px, must be %g px", m->model->getFullName().c_str(), m->box.size.y, RACK_GRID_HEIGHT);
  482. internal->moduleContainer->addChild(m);
  483. RackWidget_updateExpanders(this);
  484. }
  485. void RackWidget::addModuleAtMouse(ModuleWidget* mw) {
  486. assert(mw);
  487. // Move module nearest to the mouse position
  488. math::Vec pos = internal->mousePos.minus(mw->box.size.div(2));
  489. setModulePosNearest(mw, pos);
  490. addModule(mw);
  491. }
  492. void RackWidget::removeModule(ModuleWidget* m) {
  493. // Unset touchedParamWidget
  494. if (touchedParam) {
  495. ModuleWidget* touchedModule = touchedParam->getAncestorOfType<ModuleWidget>();
  496. if (touchedModule == m)
  497. touchedParam = NULL;
  498. }
  499. // Disconnect cables
  500. m->disconnect();
  501. // Deselect module if selected
  502. internal->selectedModules.erase(m);
  503. // Remove module from ModuleContainer
  504. internal->moduleContainer->removeChild(m);
  505. }
  506. bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) {
  507. // Check intersection with other modules
  508. math::Rect mwBox = math::Rect(pos, mw->box.size);
  509. for (widget::Widget* w2 : internal->moduleContainer->children) {
  510. // Don't intersect with self
  511. if (mw == w2)
  512. continue;
  513. // Check intersection
  514. math::Rect w2Box = w2->box;
  515. if (mwBox.intersects(w2Box))
  516. return false;
  517. }
  518. // Accept requested position
  519. mw->setPosition(mwBox.pos);
  520. RackWidget_updateExpanders(this);
  521. return true;
  522. }
  523. static math::Vec eachNearestGridPos(math::Vec pos, std::function<bool(math::Vec pos)> f) {
  524. // Dijkstra's algorithm to generate a sorted list of Vecs closest to `pos`.
  525. // Comparison of distance of Vecs to `pos`
  526. auto cmpNearest = [&](const math::Vec& a, const math::Vec& b) {
  527. return a.minus(pos).square() > b.minus(pos).square();
  528. };
  529. // Comparison of dictionary order of Vecs
  530. auto cmp = [](const math::Vec& a, const math::Vec& b) {
  531. if (a.y != b.y)
  532. return a.y < b.y;
  533. return a.x < b.x;
  534. };
  535. // Priority queue sorted by distance from `pos`
  536. std::priority_queue<math::Vec, std::vector<math::Vec>, decltype(cmpNearest)> queue(cmpNearest);
  537. // Set of already-tested Vecs
  538. std::set<math::Vec, decltype(cmp)> visited(cmp);
  539. // Seed priority queue with closest Vec
  540. math::Vec closestPos = pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE);
  541. queue.push(closestPos);
  542. while (!queue.empty()) {
  543. math::Vec testPos = queue.top();
  544. // Check testPos
  545. if (f(testPos))
  546. return testPos;
  547. // Move testPos to visited set
  548. queue.pop();
  549. visited.insert(testPos);
  550. // Add adjacent Vecs
  551. static const std::vector<math::Vec> deltas = {
  552. math::Vec(1, 0).mult(RACK_GRID_SIZE),
  553. math::Vec(0, 1).mult(RACK_GRID_SIZE),
  554. math::Vec(-1, 0).mult(RACK_GRID_SIZE),
  555. math::Vec(0, -1).mult(RACK_GRID_SIZE),
  556. };
  557. for (math::Vec delta : deltas) {
  558. math::Vec newPos = testPos.plus(delta);
  559. if (visited.find(newPos) == visited.end()) {
  560. queue.push(newPos);
  561. }
  562. }
  563. }
  564. // We failed to find a box. This shouldn't happen on an infinite rack.
  565. assert(false);
  566. return math::Vec();
  567. }
  568. void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) {
  569. eachNearestGridPos(pos, [&](math::Vec pos) -> bool {
  570. return requestModulePos(mw, pos);
  571. });
  572. }
  573. void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) {
  574. mw->setPosition(pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE));
  575. // Comparison of center X coordinates
  576. auto cmp = [&](const widget::Widget * a, const widget::Widget * b) {
  577. return a->box.pos.x + a->box.size.x / 2 < b->box.pos.x + b->box.size.x / 2;
  578. };
  579. // Collect modules to the left and right of `mw`
  580. std::set<widget::Widget*, decltype(cmp)> leftModules(cmp);
  581. std::set<widget::Widget*, decltype(cmp)> rightModules(cmp);
  582. for (widget::Widget* w2 : internal->moduleContainer->children) {
  583. if (w2 == mw)
  584. continue;
  585. // Modules must be on the same row as `mw`
  586. if (w2->box.pos.y != mw->box.pos.y)
  587. continue;
  588. if (cmp(w2, mw))
  589. leftModules.insert(w2);
  590. else
  591. rightModules.insert(w2);
  592. }
  593. // Shove left modules
  594. float xLimit = mw->box.pos.x;
  595. for (auto it = leftModules.rbegin(); it != leftModules.rend(); it++) {
  596. widget::Widget* w = *it;
  597. math::Vec newPos = w->box.pos;
  598. newPos.x = xLimit - w->box.size.x;
  599. newPos.x = std::round(newPos.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  600. if (w->box.pos.x < newPos.x)
  601. break;
  602. w->setPosition(newPos);
  603. xLimit = newPos.x;
  604. }
  605. // Shove right modules
  606. xLimit = mw->box.pos.x + mw->box.size.x;
  607. for (auto it = rightModules.begin(); it != rightModules.end(); it++) {
  608. widget::Widget* w = *it;
  609. math::Vec newPos = w->box.pos;
  610. newPos.x = xLimit;
  611. newPos.x = std::round(newPos.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  612. if (w->box.pos.x > newPos.x)
  613. break;
  614. w->setPosition(newPos);
  615. xLimit = newPos.x + w->box.size.x;
  616. }
  617. RackWidget_updateExpanders(this);
  618. }
  619. ModuleWidget* RackWidget::getModule(int64_t moduleId) {
  620. for (widget::Widget* w : internal->moduleContainer->children) {
  621. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  622. assert(mw);
  623. if (mw->module->id == moduleId)
  624. return mw;
  625. }
  626. return NULL;
  627. }
  628. std::vector<ModuleWidget*> RackWidget::getModules() {
  629. std::vector<ModuleWidget*> mws;
  630. mws.reserve(internal->moduleContainer->children.size());
  631. for (widget::Widget* w : internal->moduleContainer->children) {
  632. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  633. assert(mw);
  634. mws.push_back(mw);
  635. }
  636. mws.shrink_to_fit();
  637. return mws;
  638. }
  639. bool RackWidget::hasModules() {
  640. return internal->moduleContainer->children.empty();
  641. }
  642. void RackWidget::updateModuleOldPositions() {
  643. // Set all modules' oldPos field from their current position.
  644. for (ModuleWidget* mw : getModules()) {
  645. mw->oldPos() = mw->box.pos;
  646. }
  647. }
  648. history::ComplexAction* RackWidget::getModuleDragAction() {
  649. history::ComplexAction* h = new history::ComplexAction;
  650. h->name = "move modules";
  651. for (ModuleWidget* mw : getModules()) {
  652. // Create ModuleMove action if the module was moved.
  653. math::Vec oldPos = mw->oldPos();
  654. if (!oldPos.equals(mw->box.pos)) {
  655. history::ModuleMove* mmh = new history::ModuleMove;
  656. mmh->moduleId = mw->module->id;
  657. mmh->oldPos = oldPos;
  658. mmh->newPos = mw->box.pos;
  659. h->push(mmh);
  660. }
  661. }
  662. return h;
  663. }
  664. void RackWidget::updateSelectionFromRect() {
  665. math::Rect selectionBox = math::Rect::fromCorners(internal->selectionStart, internal->selectionEnd);
  666. deselectAll();
  667. for (ModuleWidget* mw : getModules()) {
  668. bool selected = internal->selecting && selectionBox.intersects(mw->box);
  669. if (selected)
  670. select(mw);
  671. }
  672. }
  673. void RackWidget::selectAll() {
  674. internal->selectedModules.clear();
  675. for (widget::Widget* w : internal->moduleContainer->children) {
  676. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  677. assert(mw);
  678. internal->selectedModules.insert(mw);
  679. }
  680. }
  681. void RackWidget::deselectAll() {
  682. internal->selectedModules.clear();
  683. }
  684. void RackWidget::select(ModuleWidget* mw, bool selected) {
  685. if (selected) {
  686. internal->selectedModules.insert(mw);
  687. }
  688. else {
  689. auto it = internal->selectedModules.find(mw);
  690. if (it != internal->selectedModules.end())
  691. internal->selectedModules.erase(it);
  692. }
  693. }
  694. bool RackWidget::hasSelection() {
  695. return !internal->selectedModules.empty();
  696. }
  697. const std::set<ModuleWidget*>& RackWidget::getSelected() {
  698. return internal->selectedModules;
  699. }
  700. bool RackWidget::isSelected(ModuleWidget* mw) {
  701. auto it = internal->selectedModules.find(mw);
  702. return (it != internal->selectedModules.end());
  703. }
  704. json_t* RackWidget::selectionToJson() {
  705. json_t* rootJ = json_object();
  706. std::set<engine::Module*> modules;
  707. // modules
  708. json_t* modulesJ = json_array();
  709. for (ModuleWidget* mw : getSelected()) {
  710. json_t* moduleJ = mw->toJson();
  711. // pos
  712. math::Vec pos = mw->box.pos.minus(RACK_OFFSET);
  713. pos = pos.div(RACK_GRID_SIZE).round();
  714. json_t* posJ = json_pack("[i, i]", (int) pos.x, (int) pos.y);
  715. json_object_set_new(moduleJ, "pos", posJ);
  716. json_array_append_new(modulesJ, moduleJ);
  717. modules.insert(mw->getModule());
  718. }
  719. json_object_set_new(rootJ, "modules", modulesJ);
  720. // cables
  721. json_t* cablesJ = json_array();
  722. for (CableWidget* cw : getCompleteCables()) {
  723. // Only add cables attached on both ends to selected modules
  724. engine::Cable* cable = cw->getCable();
  725. if (!cable || !cable->inputModule || !cable->outputModule)
  726. continue;
  727. const auto inputIt = modules.find(cable->inputModule);
  728. if (inputIt == modules.end())
  729. continue;
  730. const auto outputIt = modules.find(cable->outputModule);
  731. if (outputIt == modules.end())
  732. continue;
  733. json_t* cableJ = cable->toJson();
  734. cw->mergeJson(cableJ);
  735. json_array_append_new(cablesJ, cableJ);
  736. }
  737. json_object_set_new(rootJ, "cables", cablesJ);
  738. return rootJ;
  739. }
  740. static const char SELECTION_FILTERS[] = "VCV Rack module selection (.vcvs):vcvs";
  741. void RackWidget::loadSelection(std::string path) {
  742. FILE* file = std::fopen(path.c_str(), "r");
  743. if (!file)
  744. throw Exception("Could not load selection file %s", path.c_str());
  745. DEFER({std::fclose(file);});
  746. INFO("Loading selection %s", path.c_str());
  747. json_error_t error;
  748. json_t* rootJ = json_loadf(file, 0, &error);
  749. if (!rootJ)
  750. throw Exception("File is not a valid selection file. JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
  751. DEFER({json_decref(rootJ);});
  752. pasteJsonAction(rootJ);
  753. }
  754. void RackWidget::loadSelectionDialog() {
  755. std::string selectionDir = asset::user("selections");
  756. system::createDirectories(selectionDir);
  757. osdialog_filters* filters = osdialog_filters_parse(SELECTION_FILTERS);
  758. DEFER({osdialog_filters_free(filters);});
  759. char* pathC = osdialog_file(OSDIALOG_OPEN, selectionDir.c_str(), NULL, filters);
  760. if (!pathC) {
  761. // No path selected
  762. return;
  763. }
  764. DEFER({std::free(pathC);});
  765. try {
  766. loadSelection(pathC);
  767. }
  768. catch (Exception& e) {
  769. osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, e.what());
  770. }
  771. }
  772. void RackWidget::saveSelection(std::string path) {
  773. INFO("Saving selection %s", path.c_str());
  774. json_t* rootJ = selectionToJson();
  775. assert(rootJ);
  776. DEFER({json_decref(rootJ);});
  777. engine::Module::jsonStripIds(rootJ);
  778. FILE* file = std::fopen(path.c_str(), "w");
  779. if (!file) {
  780. std::string message = string::f("Could not save selection to file %s", path.c_str());
  781. osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, message.c_str());
  782. return;
  783. }
  784. DEFER({std::fclose(file);});
  785. json_dumpf(rootJ, file, JSON_INDENT(2));
  786. }
  787. void RackWidget::saveSelectionDialog() {
  788. std::string selectionDir = asset::user("selections");
  789. system::createDirectories(selectionDir);
  790. osdialog_filters* filters = osdialog_filters_parse(SELECTION_FILTERS);
  791. DEFER({osdialog_filters_free(filters);});
  792. char* pathC = osdialog_file(OSDIALOG_SAVE, selectionDir.c_str(), "Untitled.vcvs", filters);
  793. if (!pathC) {
  794. // No path selected
  795. return;
  796. }
  797. DEFER({std::free(pathC);});
  798. std::string path = pathC;
  799. // Automatically append .vcvs extension
  800. if (system::getExtension(path) != ".vcvs")
  801. path += ".vcvs";
  802. saveSelection(path);
  803. }
  804. void RackWidget::copyClipboardSelection() {
  805. json_t* rootJ = selectionToJson();
  806. DEFER({json_decref(rootJ);});
  807. char* moduleJson = json_dumps(rootJ, JSON_INDENT(2));
  808. DEFER({std::free(moduleJson);});
  809. glfwSetClipboardString(APP->window->win, moduleJson);
  810. }
  811. void RackWidget::resetSelectionAction() {
  812. history::ComplexAction* complexAction = new history::ComplexAction;
  813. complexAction->name = "reset modules";
  814. for (ModuleWidget* mw : getSelected()) {
  815. assert(mw->module);
  816. // history::ModuleChange
  817. history::ModuleChange* h = new history::ModuleChange;
  818. h->moduleId = mw->module->id;
  819. h->oldModuleJ = mw->toJson();
  820. APP->engine->resetModule(mw->module);
  821. h->newModuleJ = mw->toJson();
  822. complexAction->push(h);
  823. }
  824. APP->history->push(complexAction);
  825. }
  826. void RackWidget::randomizeSelectionAction() {
  827. history::ComplexAction* complexAction = new history::ComplexAction;
  828. complexAction->name = "randomize modules";
  829. for (ModuleWidget* mw : getSelected()) {
  830. assert(mw->module);
  831. // history::ModuleChange
  832. history::ModuleChange* h = new history::ModuleChange;
  833. h->moduleId = mw->module->id;
  834. h->oldModuleJ = mw->toJson();
  835. APP->engine->randomizeModule(mw->module);
  836. h->newModuleJ = mw->toJson();
  837. complexAction->push(h);
  838. }
  839. APP->history->push(complexAction);
  840. }
  841. void RackWidget::disconnectSelectionAction() {
  842. history::ComplexAction* complexAction = new history::ComplexAction;
  843. complexAction->name = "disconnect cables";
  844. for (ModuleWidget* mw : getSelected()) {
  845. mw->appendDisconnectActions(complexAction);
  846. }
  847. if (!complexAction->isEmpty())
  848. APP->history->push(complexAction);
  849. else
  850. delete complexAction;
  851. }
  852. void RackWidget::cloneSelectionAction() {
  853. json_t* rootJ = selectionToJson();
  854. DEFER({json_decref(rootJ);});
  855. history::ComplexAction* complexAction = new history::ComplexAction;
  856. complexAction->name = "duplicate modules";
  857. DEFER({
  858. if (!complexAction->isEmpty())
  859. APP->history->push(complexAction);
  860. else
  861. delete complexAction;
  862. });
  863. auto p = RackWidget_pasteJson(this, rootJ, complexAction);
  864. // Clone cables attached to inputs of selected modules but outputs of non-selected modules
  865. for (CableWidget* cw : getCompleteCables()) {
  866. auto inputIt = p.newModuleIds.find(cw->getCable()->inputModule->id);
  867. if (inputIt == p.newModuleIds.end())
  868. continue;
  869. auto outputIt = p.newModuleIds.find(cw->getCable()->outputModule->id);
  870. if (outputIt != p.newModuleIds.end())
  871. continue;
  872. int64_t clonedInputModuleId = inputIt->second;
  873. engine::Module* clonedInputModule = APP->engine->getModule(clonedInputModuleId);
  874. // Create cable attached to cloned ModuleWidget's input
  875. engine::Cable* clonedCable = new engine::Cable;
  876. clonedCable->inputModule = clonedInputModule;
  877. clonedCable->inputId = cw->cable->inputId;
  878. clonedCable->outputModule = cw->cable->outputModule;
  879. clonedCable->outputId = cw->cable->outputId;
  880. APP->engine->addCable(clonedCable);
  881. app::CableWidget* clonedCw = new app::CableWidget;
  882. clonedCw->setCable(clonedCable);
  883. clonedCw->color = cw->color;
  884. APP->scene->rack->addCable(clonedCw);
  885. // history::CableAdd
  886. history::CableAdd* hca = new history::CableAdd;
  887. hca->setCable(clonedCw);
  888. complexAction->push(hca);
  889. }
  890. }
  891. void RackWidget::bypassSelectionAction(bool bypassed) {
  892. history::ComplexAction* complexAction = new history::ComplexAction;
  893. complexAction->name = bypassed ? "bypass modules" : "un-bypass modules";
  894. for (ModuleWidget* mw : getSelected()) {
  895. assert(mw->module);
  896. if (mw->module->isBypassed() == bypassed)
  897. continue;
  898. // history::ModuleBypass
  899. history::ModuleBypass* h = new history::ModuleBypass;
  900. h->moduleId = mw->module->id;
  901. h->bypassed = bypassed;
  902. complexAction->push(h);
  903. APP->engine->bypassModule(mw->module, bypassed);
  904. }
  905. if (!complexAction->isEmpty())
  906. APP->history->push(complexAction);
  907. else
  908. delete complexAction;
  909. }
  910. bool RackWidget::isSelectionBypassed() {
  911. for (ModuleWidget* mw : getSelected()) {
  912. if (!mw->getModule()->isBypassed())
  913. return false;
  914. }
  915. return true;
  916. }
  917. void RackWidget::deleteSelectionAction() {
  918. history::ComplexAction* complexAction = new history::ComplexAction;
  919. complexAction->name = "remove modules";
  920. // Copy selected set since removing ModuleWidgets modifies it.
  921. std::set<ModuleWidget*> selectedModules = getSelected();
  922. for (ModuleWidget* mw : selectedModules) {
  923. mw->appendDisconnectActions(complexAction);
  924. // history::ModuleRemove
  925. history::ModuleRemove* moduleRemove = new history::ModuleRemove;
  926. moduleRemove->setModule(mw);
  927. complexAction->push(moduleRemove);
  928. removeModule(mw);
  929. delete mw;
  930. }
  931. APP->history->push(complexAction);
  932. }
  933. bool RackWidget::requestSelectionPos(math::Vec delta) {
  934. // Calculate new positions
  935. std::map<widget::Widget*, math::Rect> mwBoxes;
  936. for (ModuleWidget* mw : getSelected()) {
  937. math::Rect mwBox = mw->box;
  938. mwBox.pos += delta;
  939. mwBoxes[mw] = mwBox;
  940. }
  941. // Check intersection with other modules
  942. for (widget::Widget* w2 : internal->moduleContainer->children) {
  943. // Don't intersect with selected modules
  944. auto it = mwBoxes.find(w2);
  945. if (it != mwBoxes.end())
  946. continue;
  947. math::Rect w2Box = w2->box;
  948. // Check intersection with all selected modules
  949. for (const auto& pair : mwBoxes) {
  950. if (pair.second.intersects(w2Box))
  951. return false;
  952. }
  953. }
  954. // Accept requested position
  955. for (const auto& pair : mwBoxes) {
  956. pair.first->setPosition(pair.second.pos);
  957. }
  958. RackWidget_updateExpanders(this);
  959. return true;
  960. }
  961. void RackWidget::setSelectionPosNearest(math::Vec delta) {
  962. eachNearestGridPos(delta, [&](math::Vec delta) -> bool {
  963. return requestSelectionPos(delta);
  964. });
  965. }
  966. void RackWidget::appendSelectionContextMenu(ui::Menu* menu) {
  967. int n = getSelected().size();
  968. menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules")));
  969. // Enable alwaysConsume of menu items if the number of selected modules changes
  970. // Select all
  971. menu->addChild(createMenuItem("Select all", RACK_MOD_CTRL_NAME "+A", [=]() {
  972. selectAll();
  973. }, false, true));
  974. // Deselect
  975. menu->addChild(createMenuItem("Deselect", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+A", [=]() {
  976. deselectAll();
  977. }, n == 0, true));
  978. // Copy
  979. menu->addChild(createMenuItem("Copy", RACK_MOD_CTRL_NAME "+C", [=]() {
  980. copyClipboardSelection();
  981. }, n == 0));
  982. // Paste
  983. menu->addChild(createMenuItem("Paste", RACK_MOD_CTRL_NAME "+V", [=]() {
  984. pasteClipboardAction();
  985. }, false, true));
  986. // Load
  987. menu->addChild(createMenuItem("Import selection", "", [=]() {
  988. loadSelectionDialog();
  989. }, false, true));
  990. // Save
  991. menu->addChild(createMenuItem("Save selection as", "", [=]() {
  992. saveSelectionDialog();
  993. }, n == 0));
  994. // Initialize
  995. menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [=]() {
  996. resetSelectionAction();
  997. }, n == 0));
  998. // Randomize
  999. menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [=]() {
  1000. randomizeSelectionAction();
  1001. }, n == 0));
  1002. // Disconnect cables
  1003. menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [=]() {
  1004. disconnectSelectionAction();
  1005. }, n == 0));
  1006. // Bypass
  1007. std::string bypassText = RACK_MOD_CTRL_NAME "+E";
  1008. bool bypassed = (n > 0) && isSelectionBypassed();
  1009. if (bypassed)
  1010. bypassText += " " CHECKMARK_STRING;
  1011. menu->addChild(createMenuItem("Bypass", bypassText, [=]() {
  1012. bypassSelectionAction(!bypassed);
  1013. }, n == 0, true));
  1014. // Duplicate
  1015. menu->addChild(createMenuItem("Duplicate", RACK_MOD_CTRL_NAME "+D", [=]() {
  1016. cloneSelectionAction();
  1017. }, n == 0));
  1018. // Delete
  1019. menu->addChild(createMenuItem("Delete", "Backspace/Delete", [=]() {
  1020. deleteSelectionAction();
  1021. }, n == 0, true));
  1022. }
  1023. void RackWidget::clearCables() {
  1024. incompleteCable = NULL;
  1025. internal->cableContainer->clearChildren();
  1026. }
  1027. void RackWidget::clearCablesAction() {
  1028. // Add CableRemove for every cable to a ComplexAction
  1029. history::ComplexAction* complexAction = new history::ComplexAction;
  1030. complexAction->name = "clear cables";
  1031. for (CableWidget* cw : getCompleteCables()) {
  1032. // history::CableRemove
  1033. history::CableRemove* h = new history::CableRemove;
  1034. h->setCable(cw);
  1035. complexAction->push(h);
  1036. }
  1037. if (!complexAction->isEmpty())
  1038. APP->history->push(complexAction);
  1039. else
  1040. delete complexAction;
  1041. clearCables();
  1042. }
  1043. void RackWidget::clearCablesOnPort(PortWidget* port) {
  1044. for (CableWidget* cw : getCablesOnPort(port)) {
  1045. // Check if cable is connected to port
  1046. if (cw == incompleteCable) {
  1047. incompleteCable = NULL;
  1048. internal->cableContainer->removeChild(cw);
  1049. }
  1050. else {
  1051. removeCable(cw);
  1052. }
  1053. delete cw;
  1054. }
  1055. }
  1056. void RackWidget::addCable(CableWidget* cw) {
  1057. assert(cw->isComplete());
  1058. internal->cableContainer->addChild(cw);
  1059. }
  1060. void RackWidget::removeCable(CableWidget* cw) {
  1061. assert(cw->isComplete());
  1062. internal->cableContainer->removeChild(cw);
  1063. }
  1064. void RackWidget::setIncompleteCable(CableWidget* cw) {
  1065. if (incompleteCable) {
  1066. internal->cableContainer->removeChild(incompleteCable);
  1067. delete incompleteCable;
  1068. incompleteCable = NULL;
  1069. }
  1070. if (cw) {
  1071. internal->cableContainer->addChild(cw);
  1072. incompleteCable = cw;
  1073. }
  1074. }
  1075. CableWidget* RackWidget::releaseIncompleteCable() {
  1076. if (!incompleteCable)
  1077. return NULL;
  1078. CableWidget* cw = incompleteCable;
  1079. internal->cableContainer->removeChild(incompleteCable);
  1080. incompleteCable = NULL;
  1081. return cw;
  1082. }
  1083. CableWidget* RackWidget::getTopCable(PortWidget* port) {
  1084. for (auto it = internal->cableContainer->children.rbegin(); it != internal->cableContainer->children.rend(); it++) {
  1085. CableWidget* cw = dynamic_cast<CableWidget*>(*it);
  1086. assert(cw);
  1087. if (cw->inputPort == port || cw->outputPort == port)
  1088. return cw;
  1089. }
  1090. return NULL;
  1091. }
  1092. CableWidget* RackWidget::getCable(int64_t cableId) {
  1093. for (widget::Widget* w : internal->cableContainer->children) {
  1094. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  1095. assert(cw);
  1096. if (!cw->cable)
  1097. continue;
  1098. if (cw->cable->id == cableId)
  1099. return cw;
  1100. }
  1101. return NULL;
  1102. }
  1103. std::vector<CableWidget*> RackWidget::getCompleteCables() {
  1104. std::vector<CableWidget*> cws;
  1105. cws.reserve(internal->cableContainer->children.size());
  1106. for (widget::Widget* w : internal->cableContainer->children) {
  1107. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  1108. assert(cw);
  1109. if (cw->isComplete())
  1110. cws.push_back(cw);
  1111. }
  1112. cws.shrink_to_fit();
  1113. return cws;
  1114. }
  1115. std::vector<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) {
  1116. assert(port);
  1117. std::vector<CableWidget*> cws;
  1118. for (widget::Widget* w : internal->cableContainer->children) {
  1119. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  1120. assert(cw);
  1121. if (cw->inputPort == port || cw->outputPort == port) {
  1122. cws.push_back(cw);
  1123. }
  1124. }
  1125. return cws;
  1126. }
  1127. } // namespace app
  1128. } // namespace rack