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.

679 lines
17KB

  1. #include <map>
  2. #include <algorithm>
  3. #include <queue>
  4. #include <osdialog.h>
  5. #include <app/RackWidget.hpp>
  6. #include <widget/TransparentWidget.hpp>
  7. #include <app/RackRail.hpp>
  8. #include <app/Scene.hpp>
  9. #include <app/ModuleBrowser.hpp>
  10. #include <settings.hpp>
  11. #include <plugin.hpp>
  12. #include <engine/Engine.hpp>
  13. #include <context.hpp>
  14. #include <asset.hpp>
  15. #include <patch.hpp>
  16. namespace rack {
  17. namespace app {
  18. /** Creates a new Module and ModuleWidget */
  19. ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) {
  20. plugin::Model* model = plugin::modelFromJson(moduleJ);
  21. engine::Module* module = model->createModule();
  22. assert(module);
  23. module->fromJson(moduleJ);
  24. // Create ModuleWidget
  25. ModuleWidget* moduleWidget = module->model->createModuleWidget(module);
  26. assert(moduleWidget);
  27. return moduleWidget;
  28. }
  29. struct ModuleContainer : widget::Widget {
  30. void draw(const DrawArgs& args) override {
  31. // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets.
  32. for (widget::Widget* child : children) {
  33. ModuleWidget* w = dynamic_cast<ModuleWidget*>(child);
  34. assert(w);
  35. nvgSave(args.vg);
  36. nvgTranslate(args.vg, child->box.pos.x, child->box.pos.y);
  37. w->drawShadow(args);
  38. nvgRestore(args.vg);
  39. }
  40. Widget::draw(args);
  41. }
  42. };
  43. struct CableContainer : widget::TransparentWidget {
  44. void draw(const DrawArgs& args) override {
  45. // Draw cable plugs
  46. for (widget::Widget* w : children) {
  47. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  48. assert(cw);
  49. cw->drawPlugs(args);
  50. }
  51. Widget::draw(args);
  52. }
  53. };
  54. RackWidget::RackWidget() {
  55. railFb = new widget::FramebufferWidget;
  56. railFb->box.size = math::Vec();
  57. railFb->oversample = 1.0;
  58. // Don't redraw when the world offset of the rail FramebufferWidget changes its fractional value.
  59. railFb->dirtyOnSubpixelChange = false;
  60. {
  61. RackRail* rail = new RackRail;
  62. rail->box.size = math::Vec();
  63. railFb->addChild(rail);
  64. }
  65. addChild(railFb);
  66. moduleContainer = new ModuleContainer;
  67. addChild(moduleContainer);
  68. cableContainer = new CableContainer;
  69. addChild(cableContainer);
  70. }
  71. RackWidget::~RackWidget() {
  72. clear();
  73. }
  74. void RackWidget::step() {
  75. Widget::step();
  76. }
  77. void RackWidget::draw(const DrawArgs& args) {
  78. // Resize and reposition the RackRail to align on the grid.
  79. math::Rect railBox;
  80. railBox.pos = args.clipBox.pos.div(BUS_BOARD_GRID_SIZE).floor().mult(BUS_BOARD_GRID_SIZE);
  81. railBox.size = args.clipBox.size.div(BUS_BOARD_GRID_SIZE).ceil().plus(math::Vec(1, 1)).mult(BUS_BOARD_GRID_SIZE);
  82. if (!railFb->box.size.isEqual(railBox.size)) {
  83. railFb->dirty = true;
  84. }
  85. railFb->box = railBox;
  86. RackRail* rail = railFb->getFirstDescendantOfType<RackRail>();
  87. rail->box.size = railFb->box.size;
  88. Widget::draw(args);
  89. }
  90. void RackWidget::onHover(const event::Hover& e) {
  91. // Set before calling children's onHover()
  92. mousePos = e.pos;
  93. OpaqueWidget::onHover(e);
  94. }
  95. void RackWidget::onHoverKey(const event::HoverKey& e) {
  96. OpaqueWidget::onHoverKey(e);
  97. if (e.isConsumed())
  98. return;
  99. if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
  100. if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  101. pastePresetClipboardAction();
  102. e.consume(this);
  103. }
  104. }
  105. }
  106. void RackWidget::onDragHover(const event::DragHover& e) {
  107. // Set before calling children's onDragHover()
  108. mousePos = e.pos;
  109. OpaqueWidget::onDragHover(e);
  110. }
  111. void RackWidget::onButton(const event::Button& e) {
  112. Widget::onButton(e);
  113. e.stopPropagating();
  114. if (e.isConsumed())
  115. return;
  116. if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
  117. APP->scene->moduleBrowser->show();
  118. e.consume(this);
  119. }
  120. }
  121. void RackWidget::clear() {
  122. // This isn't required because removing all ModuleWidgets should remove all cables, but do it just in case.
  123. clearCables();
  124. // Remove ModuleWidgets
  125. std::list<widget::Widget*> widgets = moduleContainer->children;
  126. for (widget::Widget* w : widgets) {
  127. ModuleWidget* moduleWidget = dynamic_cast<ModuleWidget*>(w);
  128. assert(moduleWidget);
  129. removeModule(moduleWidget);
  130. delete moduleWidget;
  131. }
  132. }
  133. void RackWidget::mergeJson(json_t* rootJ) {
  134. // Get module offset so modules are aligned to (0, 0) when the patch is loaded.
  135. math::Vec moduleOffset = math::Vec(INFINITY, INFINITY);
  136. for (widget::Widget* w : moduleContainer->children) {
  137. moduleOffset = moduleOffset.min(w->box.pos);
  138. }
  139. if (moduleContainer->children.empty()) {
  140. moduleOffset = RACK_OFFSET;
  141. }
  142. // modules
  143. json_t* modulesJ = json_object_get(rootJ, "modules");
  144. if (!modulesJ)
  145. return;
  146. size_t moduleIndex;
  147. json_t* moduleJ;
  148. json_array_foreach(modulesJ, moduleIndex, moduleJ) {
  149. // module
  150. json_t* idJ = json_object_get(moduleJ, "id");
  151. if (!idJ)
  152. continue;
  153. int id = json_integer_value(idJ);
  154. // TODO Legacy v0.6?
  155. ModuleWidget* moduleWidget = getModule(id);
  156. if (!moduleWidget)
  157. continue;
  158. // pos
  159. math::Vec pos = moduleWidget->box.pos.minus(moduleOffset);
  160. pos = pos.div(RACK_GRID_SIZE).round();
  161. json_t* posJ = json_pack("[i, i]", (int) pos.x, (int) pos.y);
  162. json_object_set_new(moduleJ, "pos", posJ);
  163. }
  164. // cables
  165. json_t* cablesJ = json_object_get(rootJ, "cables");
  166. if (!cablesJ)
  167. return;
  168. size_t cableIndex;
  169. json_t* cableJ;
  170. json_array_foreach(cablesJ, cableIndex, cableJ) {
  171. // cable
  172. json_t* idJ = json_object_get(cableJ, "id");
  173. if (!idJ)
  174. continue;
  175. int id = json_integer_value(idJ);
  176. CableWidget* cw = getCable(id);
  177. if (!cw)
  178. continue;
  179. json_t* cwJ = cw->toJson();
  180. // Merge cable JSON object
  181. json_object_update(cableJ, cwJ);
  182. json_decref(cwJ);
  183. }
  184. }
  185. void RackWidget::fromJson(json_t* rootJ) {
  186. // modules
  187. json_t* modulesJ = json_object_get(rootJ, "modules");
  188. assert(modulesJ);
  189. size_t moduleIndex;
  190. json_t* moduleJ;
  191. json_array_foreach(modulesJ, moduleIndex, moduleJ) {
  192. // module
  193. // Create ModuleWidget and attach it to existing Module from Engine.
  194. json_t* idJ = json_object_get(moduleJ, "id");
  195. if (!idJ)
  196. continue;
  197. int id = json_integer_value(idJ);
  198. engine::Module* module = APP->engine->getModule(id);
  199. if (!module)
  200. continue;
  201. ModuleWidget* moduleWidget = module->model->createModuleWidget(module);
  202. // Before 1.0, the module ID was the index in the "modules" array
  203. if (APP->patch->isLegacy(2)) {
  204. module->id = moduleIndex;
  205. }
  206. // pos
  207. json_t* posJ = json_object_get(moduleJ, "pos");
  208. double x, y;
  209. json_unpack(posJ, "[F, F]", &x, &y);
  210. math::Vec pos = math::Vec(x, y);
  211. if (APP->patch->isLegacy(1)) {
  212. // In <=v0.5, positions were in pixel units
  213. moduleWidget->box.pos = pos;
  214. }
  215. else {
  216. moduleWidget->box.pos = pos.mult(RACK_GRID_SIZE);
  217. }
  218. moduleWidget->box.pos = moduleWidget->box.pos.plus(RACK_OFFSET);
  219. addModule(moduleWidget);
  220. }
  221. // cables
  222. json_t* cablesJ = json_object_get(rootJ, "cables");
  223. // In <=v0.6, cables were called wires
  224. if (!cablesJ)
  225. cablesJ = json_object_get(rootJ, "wires");
  226. assert(cablesJ);
  227. size_t cableIndex;
  228. json_t* cableJ;
  229. json_array_foreach(cablesJ, cableIndex, cableJ) {
  230. // cable
  231. // Get Cable from Engine
  232. json_t* idJ = json_object_get(cableJ, "id");
  233. if (!idJ)
  234. continue;
  235. int id = json_integer_value(idJ);
  236. engine::Cable* cable = APP->engine->getCable(id);
  237. if (!cable)
  238. continue;
  239. CableWidget* cw = new CableWidget;
  240. // Legacy: Before v1, cable colors were not serialized. So we need to initialize the color here.
  241. cw->setNextCableColor();
  242. cw->setCable(cable);
  243. cw->fromJson(cableJ);
  244. addCable(cw);
  245. }
  246. }
  247. void RackWidget::pastePresetClipboardAction() {
  248. const char* moduleJson = glfwGetClipboardString(APP->window->win);
  249. if (!moduleJson) {
  250. WARN("Could not get text from clipboard.");
  251. return;
  252. }
  253. json_error_t error;
  254. json_t* moduleJ = json_loads(moduleJson, 0, &error);
  255. if (!moduleJ) {
  256. WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
  257. return;
  258. }
  259. DEFER({
  260. json_decref(moduleJ);
  261. });
  262. try {
  263. plugin::Model* model = plugin::modelFromJson(moduleJ);
  264. engine::Module* module = model->createModule();
  265. assert(module);
  266. module->fromJson(moduleJ);
  267. // Reset ID so the Engine automatically assigns a new one
  268. module->id = -1;
  269. APP->engine->addModule(module);
  270. ModuleWidget* mw = module->model->createModuleWidget(module);
  271. addModuleAtMouse(mw);
  272. // history::ModuleAdd
  273. history::ModuleAdd* h = new history::ModuleAdd;
  274. h->setModule(mw);
  275. APP->history->push(h);
  276. }
  277. catch (Exception& e) {
  278. WARN("%s", e.what());
  279. return;
  280. }
  281. }
  282. static void RackWidget_updateAdjacent(RackWidget* that) {
  283. for (widget::Widget* w : that->moduleContainer->children) {
  284. math::Vec pLeft = w->box.pos.div(RACK_GRID_SIZE).round();
  285. math::Vec pRight = w->box.getTopRight().div(RACK_GRID_SIZE).round();
  286. ModuleWidget* mwLeft = NULL;
  287. ModuleWidget* mwRight = NULL;
  288. // Find adjacent modules
  289. for (widget::Widget* w2 : that->moduleContainer->children) {
  290. if (w2 == w)
  291. continue;
  292. math::Vec p2Left = w2->box.pos.div(RACK_GRID_SIZE).round();
  293. math::Vec p2Right = w2->box.getTopRight().div(RACK_GRID_SIZE).round();
  294. // Check if this is a left module
  295. if (p2Right.isEqual(pLeft)) {
  296. mwLeft = dynamic_cast<ModuleWidget*>(w2);
  297. }
  298. // Check if this is a right module
  299. if (p2Left.isEqual(pRight)) {
  300. mwRight = dynamic_cast<ModuleWidget*>(w2);
  301. }
  302. }
  303. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  304. mw->module->leftExpander.moduleId = mwLeft ? mwLeft->module->id : -1;
  305. mw->module->rightExpander.moduleId = mwRight ? mwRight->module->id : -1;
  306. }
  307. }
  308. void RackWidget::addModule(ModuleWidget* m) {
  309. // Add module to ModuleContainer
  310. assert(m);
  311. // Module must be 3U high and at least 1HP wide
  312. assert(m->box.size.x >= RACK_GRID_WIDTH);
  313. assert(m->box.size.y == RACK_GRID_HEIGHT);
  314. moduleContainer->addChild(m);
  315. RackWidget_updateAdjacent(this);
  316. }
  317. void RackWidget::addModuleAtMouse(ModuleWidget* mw) {
  318. assert(mw);
  319. // Move module nearest to the mouse position
  320. math::Vec pos = mousePos.minus(mw->box.size.div(2));
  321. setModulePosNearest(mw, pos);
  322. addModule(mw);
  323. }
  324. void RackWidget::removeModule(ModuleWidget* m) {
  325. // Unset touchedParamWidget
  326. if (touchedParam) {
  327. ModuleWidget* touchedModule = touchedParam->getAncestorOfType<ModuleWidget>();
  328. if (touchedModule == m)
  329. touchedParam = NULL;
  330. }
  331. // Disconnect cables
  332. m->disconnect();
  333. // Remove module from ModuleContainer
  334. moduleContainer->removeChild(m);
  335. }
  336. bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) {
  337. // Check intersection with other modules
  338. math::Rect mwBox = math::Rect(pos, mw->box.size);
  339. for (widget::Widget* w2 : moduleContainer->children) {
  340. // Don't intersect with self
  341. if (mw == w2)
  342. continue;
  343. // Don't intersect with invisible modules
  344. if (!w2->visible)
  345. continue;
  346. // Check intersection
  347. if (mwBox.isIntersecting(w2->box))
  348. return false;
  349. }
  350. // Accept requested position
  351. mw->setPosition(mwBox.pos);
  352. RackWidget_updateAdjacent(this);
  353. return true;
  354. }
  355. void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) {
  356. // Dijkstra's algorithm to generate a sorted list of Vecs closest to `pos`.
  357. // Comparison of distance of Vecs to `pos`
  358. auto cmpNearest = [&](const math::Vec & a, const math::Vec & b) {
  359. return a.minus(pos).square() > b.minus(pos).square();
  360. };
  361. // Comparison of dictionary order of Vecs
  362. auto cmp = [&](const math::Vec & a, const math::Vec & b) {
  363. if (a.x != b.x)
  364. return a.x < b.x;
  365. return a.y < b.y;
  366. };
  367. // Priority queue sorted by distance from `pos`
  368. std::priority_queue<math::Vec, std::vector<math::Vec>, decltype(cmpNearest)> queue(cmpNearest);
  369. // Set of already-tested Vecs
  370. std::set<math::Vec, decltype(cmp)> visited(cmp);
  371. // Seed priority queue with closest Vec
  372. math::Vec closestPos = pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE);
  373. queue.push(closestPos);
  374. while (!queue.empty()) {
  375. math::Vec testPos = queue.top();
  376. // Check testPos
  377. if (requestModulePos(mw, testPos))
  378. return;
  379. // Move testPos to visited set
  380. queue.pop();
  381. visited.insert(testPos);
  382. // Add adjacent Vecs
  383. static const std::vector<math::Vec> deltas = {
  384. math::Vec(-1, 0).mult(RACK_GRID_SIZE),
  385. math::Vec(1, 0).mult(RACK_GRID_SIZE),
  386. math::Vec(0, -1).mult(RACK_GRID_SIZE),
  387. math::Vec(0, 1).mult(RACK_GRID_SIZE),
  388. };
  389. for (math::Vec delta : deltas) {
  390. math::Vec newPos = testPos.plus(delta);
  391. if (visited.find(newPos) == visited.end()) {
  392. queue.push(newPos);
  393. }
  394. }
  395. }
  396. // We failed to find a box. This shouldn't happen on an infinite rack.
  397. assert(false);
  398. }
  399. void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) {
  400. mw->setPosition(pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE));
  401. // Comparison of center X coordinates
  402. auto cmp = [&](const widget::Widget * a, const widget::Widget * b) {
  403. return a->box.pos.x + a->box.size.x / 2 < b->box.pos.x + b->box.size.x / 2;
  404. };
  405. // Collect modules to the left and right of `mw`
  406. std::set<widget::Widget*, decltype(cmp)> leftModules(cmp);
  407. std::set<widget::Widget*, decltype(cmp)> rightModules(cmp);
  408. for (widget::Widget* w2 : moduleContainer->children) {
  409. if (w2 == mw)
  410. continue;
  411. // Modules must be on the same row as `mw`
  412. if (w2->box.pos.y != mw->box.pos.y)
  413. continue;
  414. if (cmp(w2, mw))
  415. leftModules.insert(w2);
  416. else
  417. rightModules.insert(w2);
  418. }
  419. // Shove left modules
  420. float xLimit = mw->box.pos.x;
  421. for (auto it = leftModules.rbegin(); it != leftModules.rend(); it++) {
  422. widget::Widget* w = *it;
  423. math::Vec newPos = w->box.pos;
  424. newPos.x = xLimit - w->box.size.x;
  425. newPos.x = std::round(newPos.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  426. if (w->box.pos.x < newPos.x)
  427. break;
  428. w->setPosition(newPos);
  429. xLimit = newPos.x;
  430. }
  431. // Shove right modules
  432. xLimit = mw->box.pos.x + mw->box.size.x;
  433. for (auto it = rightModules.begin(); it != rightModules.end(); it++) {
  434. widget::Widget* w = *it;
  435. math::Vec newPos = w->box.pos;
  436. newPos.x = xLimit;
  437. newPos.x = std::round(newPos.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  438. if (w->box.pos.x > newPos.x)
  439. break;
  440. w->setPosition(newPos);
  441. xLimit = newPos.x + w->box.size.x;
  442. }
  443. RackWidget_updateAdjacent(this);
  444. }
  445. ModuleWidget* RackWidget::getModule(int moduleId) {
  446. for (widget::Widget* w : moduleContainer->children) {
  447. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  448. assert(mw);
  449. if (mw->module->id == moduleId)
  450. return mw;
  451. }
  452. return NULL;
  453. }
  454. bool RackWidget::isEmpty() {
  455. return moduleContainer->children.empty();
  456. }
  457. void RackWidget::updateModuleOldPositions() {
  458. // Set all modules' oldPos field from their current position.
  459. for (widget::Widget* w : moduleContainer->children) {
  460. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  461. assert(mw);
  462. mw->oldPos() = mw->box.pos;
  463. }
  464. }
  465. history::ComplexAction* RackWidget::getModuleDragAction() {
  466. history::ComplexAction* h = new history::ComplexAction;
  467. for (widget::Widget* w : moduleContainer->children) {
  468. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  469. assert(mw);
  470. // Create ModuleMove action if the module was moved.
  471. math::Vec oldPos = mw->oldPos();
  472. if (!oldPos.isEqual(mw->box.pos)) {
  473. history::ModuleMove* mmh = new history::ModuleMove;
  474. mmh->moduleId = mw->module->id;
  475. mmh->oldPos = oldPos;
  476. mmh->newPos = mw->box.pos;
  477. h->push(mmh);
  478. }
  479. }
  480. if (h->isEmpty()) {
  481. delete h;
  482. return NULL;
  483. }
  484. return h;
  485. }
  486. void RackWidget::clearCables() {
  487. incompleteCable = NULL;
  488. cableContainer->clearChildren();
  489. }
  490. void RackWidget::clearCablesAction() {
  491. // Add CableRemove for every cable to a ComplexAction
  492. history::ComplexAction* complexAction = new history::ComplexAction;
  493. complexAction->name = "clear cables";
  494. for (widget::Widget* w : cableContainer->children) {
  495. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  496. assert(cw);
  497. if (!cw->isComplete())
  498. continue;
  499. // history::CableRemove
  500. history::CableRemove* h = new history::CableRemove;
  501. h->setCable(cw);
  502. complexAction->push(h);
  503. }
  504. if (!complexAction->isEmpty())
  505. APP->history->push(complexAction);
  506. else
  507. delete complexAction;
  508. clearCables();
  509. }
  510. void RackWidget::clearCablesOnPort(PortWidget* port) {
  511. for (CableWidget* cw : getCablesOnPort(port)) {
  512. // Check if cable is connected to port
  513. if (cw == incompleteCable) {
  514. incompleteCable = NULL;
  515. cableContainer->removeChild(cw);
  516. }
  517. else {
  518. removeCable(cw);
  519. }
  520. delete cw;
  521. }
  522. }
  523. void RackWidget::addCable(CableWidget* cw) {
  524. assert(cw->isComplete());
  525. cableContainer->addChild(cw);
  526. }
  527. void RackWidget::removeCable(CableWidget* cw) {
  528. assert(cw->isComplete());
  529. cableContainer->removeChild(cw);
  530. }
  531. void RackWidget::setIncompleteCable(CableWidget* cw) {
  532. if (incompleteCable) {
  533. cableContainer->removeChild(incompleteCable);
  534. delete incompleteCable;
  535. incompleteCable = NULL;
  536. }
  537. if (cw) {
  538. cableContainer->addChild(cw);
  539. incompleteCable = cw;
  540. }
  541. }
  542. CableWidget* RackWidget::releaseIncompleteCable() {
  543. if (!incompleteCable)
  544. return NULL;
  545. CableWidget* cw = incompleteCable;
  546. cableContainer->removeChild(incompleteCable);
  547. incompleteCable = NULL;
  548. return cw;
  549. }
  550. CableWidget* RackWidget::getTopCable(PortWidget* port) {
  551. for (auto it = cableContainer->children.rbegin(); it != cableContainer->children.rend(); it++) {
  552. CableWidget* cw = dynamic_cast<CableWidget*>(*it);
  553. assert(cw);
  554. if (cw->inputPort == port || cw->outputPort == port)
  555. return cw;
  556. }
  557. return NULL;
  558. }
  559. CableWidget* RackWidget::getCable(int cableId) {
  560. for (widget::Widget* w : cableContainer->children) {
  561. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  562. assert(cw);
  563. if (!cw->cable)
  564. continue;
  565. if (cw->cable->id == cableId)
  566. return cw;
  567. }
  568. return NULL;
  569. }
  570. std::list<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) {
  571. assert(port);
  572. std::list<CableWidget*> cws;
  573. for (widget::Widget* w : cableContainer->children) {
  574. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  575. assert(cw);
  576. if (cw->inputPort == port || cw->outputPort == port) {
  577. cws.push_back(cw);
  578. }
  579. }
  580. return cws;
  581. }
  582. } // namespace app
  583. } // namespace rack