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.

670 lines
17KB

  1. #include <app/RackWidget.hpp>
  2. #include <widget/TransparentWidget.hpp>
  3. #include <app/RackRail.hpp>
  4. #include <app/Scene.hpp>
  5. #include <app/ModuleBrowser.hpp>
  6. #include <settings.hpp>
  7. #include <plugin.hpp>
  8. #include <engine/Engine.hpp>
  9. #include <app.hpp>
  10. #include <asset.hpp>
  11. #include <patch.hpp>
  12. #include <osdialog.h>
  13. #include <map>
  14. #include <algorithm>
  15. #include <queue>
  16. namespace rack {
  17. namespace app {
  18. /** Creates a new Module and ModuleWidget */
  19. ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) {
  20. engine::Module* module = engine::moduleFromJson(moduleJ);
  21. assert(module);
  22. // Create ModuleWidget
  23. ModuleWidget* moduleWidget = module->model->createModuleWidget(module);
  24. assert(moduleWidget);
  25. return moduleWidget;
  26. }
  27. struct ModuleContainer : widget::Widget {
  28. void draw(const DrawArgs& args) override {
  29. // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets.
  30. for (widget::Widget* child : children) {
  31. ModuleWidget* w = dynamic_cast<ModuleWidget*>(child);
  32. assert(w);
  33. nvgSave(args.vg);
  34. nvgTranslate(args.vg, child->box.pos.x, child->box.pos.y);
  35. w->drawShadow(args);
  36. nvgRestore(args.vg);
  37. }
  38. Widget::draw(args);
  39. }
  40. };
  41. struct CableContainer : widget::TransparentWidget {
  42. void draw(const DrawArgs& args) override {
  43. // Draw cable plugs
  44. for (widget::Widget* w : children) {
  45. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  46. assert(cw);
  47. cw->drawPlugs(args);
  48. }
  49. Widget::draw(args);
  50. }
  51. };
  52. RackWidget::RackWidget() {
  53. railFb = new widget::FramebufferWidget;
  54. railFb->box.size = math::Vec();
  55. railFb->oversample = 1.0;
  56. {
  57. RackRail* rail = new RackRail;
  58. rail->box.size = math::Vec();
  59. railFb->addChild(rail);
  60. }
  61. addChild(railFb);
  62. moduleContainer = new ModuleContainer;
  63. addChild(moduleContainer);
  64. cableContainer = new CableContainer;
  65. addChild(cableContainer);
  66. }
  67. RackWidget::~RackWidget() {
  68. clear();
  69. }
  70. void RackWidget::step() {
  71. Widget::step();
  72. }
  73. void RackWidget::draw(const DrawArgs& args) {
  74. // Resize and reposition the RackRail to align on the grid.
  75. math::Rect railBox;
  76. railBox.pos = args.clipBox.pos.div(BUS_BOARD_GRID_SIZE).floor().mult(BUS_BOARD_GRID_SIZE);
  77. railBox.size = args.clipBox.size.div(BUS_BOARD_GRID_SIZE).ceil().plus(math::Vec(1, 1)).mult(BUS_BOARD_GRID_SIZE);
  78. if (!railFb->box.size.isEqual(railBox.size)) {
  79. railFb->dirty = true;
  80. }
  81. railFb->box = railBox;
  82. RackRail* rail = railFb->getFirstDescendantOfType<RackRail>();
  83. rail->box.size = railFb->box.size;
  84. Widget::draw(args);
  85. }
  86. void RackWidget::onHover(const event::Hover& e) {
  87. // Set before calling children's onHover()
  88. mousePos = e.pos;
  89. OpaqueWidget::onHover(e);
  90. }
  91. void RackWidget::onHoverKey(const event::HoverKey& e) {
  92. OpaqueWidget::onHoverKey(e);
  93. if (e.isConsumed())
  94. return;
  95. if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
  96. switch (e.key) {
  97. case GLFW_KEY_V: {
  98. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  99. pastePresetClipboardAction();
  100. e.consume(this);
  101. }
  102. } break;
  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. cw->setCable(cable);
  241. cw->fromJson(cableJ);
  242. addCable(cw);
  243. }
  244. }
  245. void RackWidget::pastePresetClipboardAction() {
  246. const char* moduleJson = glfwGetClipboardString(APP->window->win);
  247. if (!moduleJson) {
  248. WARN("Could not get text from clipboard.");
  249. return;
  250. }
  251. json_error_t error;
  252. json_t* moduleJ = json_loads(moduleJson, 0, &error);
  253. if (!moduleJ) {
  254. WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
  255. return;
  256. }
  257. DEFER({
  258. json_decref(moduleJ);
  259. });
  260. try {
  261. engine::Module* module = engine::moduleFromJson(moduleJ);
  262. // Reset ID so the Engine automatically assigns a new one
  263. module->id = -1;
  264. APP->engine->addModule(module);
  265. ModuleWidget* mw = module->model->createModuleWidget(module);
  266. addModuleAtMouse(mw);
  267. // history::ModuleAdd
  268. history::ModuleAdd* h = new history::ModuleAdd;
  269. h->setModule(mw);
  270. APP->history->push(h);
  271. }
  272. catch (Exception& e) {
  273. WARN("%s", e.what());
  274. return;
  275. }
  276. }
  277. static void RackWidget_updateAdjacent(RackWidget* that) {
  278. for (widget::Widget* w : that->moduleContainer->children) {
  279. math::Vec pLeft = w->box.pos.div(RACK_GRID_SIZE).round();
  280. math::Vec pRight = w->box.getTopRight().div(RACK_GRID_SIZE).round();
  281. ModuleWidget* mwLeft = NULL;
  282. ModuleWidget* mwRight = NULL;
  283. // Find adjacent modules
  284. for (widget::Widget* w2 : that->moduleContainer->children) {
  285. if (w2 == w)
  286. continue;
  287. math::Vec p2Left = w2->box.pos.div(RACK_GRID_SIZE).round();
  288. math::Vec p2Right = w2->box.getTopRight().div(RACK_GRID_SIZE).round();
  289. // Check if this is a left module
  290. if (p2Right.isEqual(pLeft)) {
  291. mwLeft = dynamic_cast<ModuleWidget*>(w2);
  292. }
  293. // Check if this is a right module
  294. if (p2Left.isEqual(pRight)) {
  295. mwRight = dynamic_cast<ModuleWidget*>(w2);
  296. }
  297. }
  298. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  299. mw->module->leftExpander.moduleId = mwLeft ? mwLeft->module->id : -1;
  300. mw->module->rightExpander.moduleId = mwRight ? mwRight->module->id : -1;
  301. }
  302. }
  303. void RackWidget::addModule(ModuleWidget* m) {
  304. // Add module to ModuleContainer
  305. assert(m);
  306. // Module must be 3U high and at least 1HP wide
  307. assert(m->box.size.x >= RACK_GRID_WIDTH);
  308. assert(m->box.size.y == RACK_GRID_HEIGHT);
  309. moduleContainer->addChild(m);
  310. RackWidget_updateAdjacent(this);
  311. }
  312. void RackWidget::addModuleAtMouse(ModuleWidget* mw) {
  313. assert(mw);
  314. // Move module nearest to the mouse position
  315. math::Vec pos = mousePos.minus(mw->box.size.div(2));
  316. setModulePosNearest(mw, pos);
  317. addModule(mw);
  318. }
  319. void RackWidget::removeModule(ModuleWidget* m) {
  320. // Unset touchedParamWidget
  321. if (touchedParam) {
  322. ModuleWidget* touchedModule = touchedParam->getAncestorOfType<ModuleWidget>();
  323. if (touchedModule == m)
  324. touchedParam = NULL;
  325. }
  326. // Disconnect cables
  327. m->disconnect();
  328. // Remove module from ModuleContainer
  329. moduleContainer->removeChild(m);
  330. }
  331. bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) {
  332. // Check intersection with other modules
  333. math::Rect mwBox = math::Rect(pos, mw->box.size);
  334. for (widget::Widget* w2 : moduleContainer->children) {
  335. // Don't intersect with self
  336. if (mw == w2)
  337. continue;
  338. // Don't intersect with invisible modules
  339. if (!w2->visible)
  340. continue;
  341. // Check intersection
  342. if (mwBox.isIntersecting(w2->box)) {
  343. return false;
  344. }
  345. }
  346. // Accept requested position
  347. mw->box = mwBox;
  348. RackWidget_updateAdjacent(this);
  349. return true;
  350. }
  351. void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) {
  352. // Dijkstra's algorithm to generate a sorted list of Vecs closest to `pos`.
  353. // Comparison of distance of Vecs to `pos`
  354. auto cmpNearest = [&](const math::Vec & a, const math::Vec & b) {
  355. return a.minus(pos).square() > b.minus(pos).square();
  356. };
  357. // Comparison of dictionary order of Vecs
  358. auto cmp = [&](const math::Vec & a, const math::Vec & b) {
  359. if (a.x != b.x)
  360. return a.x < b.x;
  361. return a.y < b.y;
  362. };
  363. // Priority queue sorted by distance from `pos`
  364. std::priority_queue<math::Vec, std::vector<math::Vec>, decltype(cmpNearest)> queue(cmpNearest);
  365. // Set of already-tested Vecs
  366. std::set<math::Vec, decltype(cmp)> visited(cmp);
  367. // Seed priority queue with closest Vec
  368. math::Vec closestPos = pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE);
  369. queue.push(closestPos);
  370. while (!queue.empty()) {
  371. math::Vec testPos = queue.top();
  372. // Check testPos
  373. if (requestModulePos(mw, testPos))
  374. return;
  375. // Move testPos to visited set
  376. queue.pop();
  377. visited.insert(testPos);
  378. // Add adjacent Vecs
  379. static const std::vector<math::Vec> deltas = {
  380. math::Vec(-1, 0).mult(RACK_GRID_SIZE),
  381. math::Vec(1, 0).mult(RACK_GRID_SIZE),
  382. math::Vec(0, -1).mult(RACK_GRID_SIZE),
  383. math::Vec(0, 1).mult(RACK_GRID_SIZE),
  384. };
  385. for (math::Vec delta : deltas) {
  386. math::Vec newPos = testPos.plus(delta);
  387. if (visited.find(newPos) == visited.end()) {
  388. queue.push(newPos);
  389. }
  390. }
  391. }
  392. // We failed to find a box. This shouldn't happen on an infinite rack.
  393. assert(0);
  394. }
  395. void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) {
  396. mw->box.pos = pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE);
  397. // Comparison of center X coordinates
  398. auto cmp = [&](const widget::Widget * a, const widget::Widget * b) {
  399. return a->box.pos.x + a->box.size.x / 2 < b->box.pos.x + b->box.size.x / 2;
  400. };
  401. // Collect modules to the left and right of `mw`
  402. std::set<widget::Widget*, decltype(cmp)> leftModules(cmp);
  403. std::set<widget::Widget*, decltype(cmp)> rightModules(cmp);
  404. for (widget::Widget* w2 : moduleContainer->children) {
  405. if (w2 == mw)
  406. continue;
  407. // Modules must be on the same row as `mw`
  408. if (w2->box.pos.y != mw->box.pos.y)
  409. continue;
  410. if (cmp(w2, mw))
  411. leftModules.insert(w2);
  412. else
  413. rightModules.insert(w2);
  414. }
  415. // Shove left modules
  416. float xLimit = mw->box.pos.x;
  417. for (auto it = leftModules.rbegin(); it != leftModules.rend(); it++) {
  418. widget::Widget* w = *it;
  419. float x = xLimit - w->box.size.x;
  420. x = std::round(x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  421. if (w->box.pos.x < x)
  422. break;
  423. w->box.pos.x = x;
  424. xLimit = x;
  425. }
  426. // Shove right modules
  427. xLimit = mw->box.pos.x + mw->box.size.x;
  428. for (auto it = rightModules.begin(); it != rightModules.end(); it++) {
  429. widget::Widget* w = *it;
  430. float x = xLimit;
  431. x = std::round(x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  432. if (w->box.pos.x > x)
  433. break;
  434. w->box.pos.x = x;
  435. xLimit = x + w->box.size.x;
  436. }
  437. RackWidget_updateAdjacent(this);
  438. }
  439. ModuleWidget* RackWidget::getModule(int moduleId) {
  440. for (widget::Widget* w : moduleContainer->children) {
  441. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  442. assert(mw);
  443. if (mw->module->id == moduleId)
  444. return mw;
  445. }
  446. return NULL;
  447. }
  448. bool RackWidget::isEmpty() {
  449. return moduleContainer->children.empty();
  450. }
  451. void RackWidget::updateModuleDragPositions() {
  452. moduleDragPositions.clear();
  453. for (widget::Widget* w : moduleContainer->children) {
  454. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  455. assert(mw);
  456. moduleDragPositions[mw->module->id] = mw->box.pos;
  457. }
  458. }
  459. history::ComplexAction* RackWidget::getModuleDragAction() {
  460. history::ComplexAction* h = new history::ComplexAction;
  461. for (widget::Widget* w : moduleContainer->children) {
  462. ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w);
  463. assert(mw);
  464. // It is possible to add modules to the rack while dragging, so ignore modules that don't exist.
  465. auto it = moduleDragPositions.find(mw->module->id);
  466. if (it == moduleDragPositions.end())
  467. continue;
  468. // Create ModuleMove action if the module was moved.
  469. math::Vec pos = it->second;
  470. if (!pos.isEqual(mw->box.pos)) {
  471. history::ModuleMove* mmh = new history::ModuleMove;
  472. mmh->moduleId = mw->module->id;
  473. mmh->oldPos = pos;
  474. mmh->newPos = mw->box.pos;
  475. h->push(mmh);
  476. }
  477. }
  478. return h;
  479. }
  480. void RackWidget::clearCables() {
  481. incompleteCable = NULL;
  482. cableContainer->clearChildren();
  483. }
  484. void RackWidget::clearCablesAction() {
  485. // Add CableRemove for every cable to a ComplexAction
  486. history::ComplexAction* complexAction = new history::ComplexAction;
  487. complexAction->name = "clear cables";
  488. for (widget::Widget* w : cableContainer->children) {
  489. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  490. assert(cw);
  491. if (!cw->isComplete())
  492. continue;
  493. // history::CableRemove
  494. history::CableRemove* h = new history::CableRemove;
  495. h->setCable(cw);
  496. complexAction->push(h);
  497. }
  498. if (!complexAction->isEmpty())
  499. APP->history->push(complexAction);
  500. else
  501. delete complexAction;
  502. clearCables();
  503. }
  504. void RackWidget::clearCablesOnPort(PortWidget* port) {
  505. for (CableWidget* cw : getCablesOnPort(port)) {
  506. // Check if cable is connected to port
  507. if (cw == incompleteCable) {
  508. incompleteCable = NULL;
  509. cableContainer->removeChild(cw);
  510. }
  511. else {
  512. removeCable(cw);
  513. }
  514. delete cw;
  515. }
  516. }
  517. void RackWidget::addCable(CableWidget* cw) {
  518. assert(cw->isComplete());
  519. cableContainer->addChild(cw);
  520. }
  521. void RackWidget::removeCable(CableWidget* cw) {
  522. assert(cw->isComplete());
  523. cableContainer->removeChild(cw);
  524. }
  525. void RackWidget::setIncompleteCable(CableWidget* cw) {
  526. if (incompleteCable) {
  527. cableContainer->removeChild(incompleteCable);
  528. delete incompleteCable;
  529. incompleteCable = NULL;
  530. }
  531. if (cw) {
  532. cableContainer->addChild(cw);
  533. incompleteCable = cw;
  534. }
  535. }
  536. CableWidget* RackWidget::releaseIncompleteCable() {
  537. if (!incompleteCable)
  538. return NULL;
  539. CableWidget* cw = incompleteCable;
  540. cableContainer->removeChild(incompleteCable);
  541. incompleteCable = NULL;
  542. return cw;
  543. }
  544. CableWidget* RackWidget::getTopCable(PortWidget* port) {
  545. for (auto it = cableContainer->children.rbegin(); it != cableContainer->children.rend(); it++) {
  546. CableWidget* cw = dynamic_cast<CableWidget*>(*it);
  547. assert(cw);
  548. if (cw->inputPort == port || cw->outputPort == port)
  549. return cw;
  550. }
  551. return NULL;
  552. }
  553. CableWidget* RackWidget::getCable(int cableId) {
  554. for (widget::Widget* w : cableContainer->children) {
  555. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  556. assert(cw);
  557. if (!cw->cable)
  558. continue;
  559. if (cw->cable->id == cableId)
  560. return cw;
  561. }
  562. return NULL;
  563. }
  564. std::list<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) {
  565. assert(port);
  566. std::list<CableWidget*> cws;
  567. for (widget::Widget* w : cableContainer->children) {
  568. CableWidget* cw = dynamic_cast<CableWidget*>(w);
  569. assert(cw);
  570. if (cw->inputPort == port || cw->outputPort == port) {
  571. cws.push_back(cw);
  572. }
  573. }
  574. return cws;
  575. }
  576. } // namespace app
  577. } // namespace rack