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.

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