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