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.

569 lines
14KB

  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. namespace rack {
  16. namespace app {
  17. static ModuleWidget *moduleFromJson(json_t *moduleJ) {
  18. // Get slugs
  19. json_t *pluginSlugJ = json_object_get(moduleJ, "plugin");
  20. if (!pluginSlugJ)
  21. return NULL;
  22. json_t *modelSlugJ = json_object_get(moduleJ, "model");
  23. if (!modelSlugJ)
  24. return NULL;
  25. std::string pluginSlug = json_string_value(pluginSlugJ);
  26. std::string modelSlug = json_string_value(modelSlugJ);
  27. // Get Model
  28. plugin::Model *model = plugin::getModel(pluginSlug, modelSlug);
  29. if (!model)
  30. return NULL;
  31. // Create ModuleWidget
  32. ModuleWidget *moduleWidget = model->createModuleWidget();
  33. assert(moduleWidget);
  34. moduleWidget->fromJson(moduleJ);
  35. return moduleWidget;
  36. }
  37. struct ModuleContainer : widget::Widget {
  38. void draw(const DrawArgs &args) override {
  39. // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets.
  40. for (widget::Widget *child : children) {
  41. ModuleWidget *w = dynamic_cast<ModuleWidget*>(child);
  42. assert(w);
  43. nvgSave(args.vg);
  44. nvgTranslate(args.vg, child->box.pos.x, child->box.pos.y);
  45. w->drawShadow(args);
  46. nvgRestore(args.vg);
  47. }
  48. Widget::draw(args);
  49. }
  50. };
  51. struct CableContainer : widget::TransparentWidget {
  52. void draw(const DrawArgs &args) override {
  53. Widget::draw(args);
  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. }
  61. };
  62. RackWidget::RackWidget() {
  63. rails = new widget::FramebufferWidget;
  64. rails->box.size = math::Vec();
  65. rails->oversample = 1.0;
  66. {
  67. RackRail *rail = new RackRail;
  68. rail->box.size = math::Vec();
  69. rails->addChild(rail);
  70. }
  71. addChild(rails);
  72. moduleContainer = new ModuleContainer;
  73. addChild(moduleContainer);
  74. cableContainer = new CableContainer;
  75. addChild(cableContainer);
  76. }
  77. RackWidget::~RackWidget() {
  78. clear();
  79. }
  80. void RackWidget::step() {
  81. // Expand size to fit modules
  82. math::Vec moduleSize = moduleContainer->getChildrenBoundingBox().getBottomRight();
  83. // We assume that the size is reset by a parent before calling step(). Otherwise it will grow unbounded.
  84. box.size = box.size.max(moduleSize);
  85. // Adjust size and position of rails
  86. widget::Widget *rail = rails->children.front();
  87. math::Rect bound = getViewport(math::Rect(math::Vec(), box.size));
  88. if (!rails->box.isContaining(bound)) {
  89. math::Vec cellMargin = math::Vec(20, 1);
  90. rails->box.pos = bound.pos.div(RACK_GRID_SIZE).floor().minus(cellMargin).mult(RACK_GRID_SIZE);
  91. rails->box.size = bound.size.plus(cellMargin.mult(RACK_GRID_SIZE).mult(2));
  92. rails->dirty = true;
  93. rail->box.size = rails->box.size;
  94. }
  95. Widget::step();
  96. }
  97. void RackWidget::draw(const DrawArgs &args) {
  98. Widget::draw(args);
  99. }
  100. void RackWidget::onHover(const widget::HoverEvent &e) {
  101. mousePos = e.pos;
  102. OpaqueWidget::onHover(e);
  103. }
  104. void RackWidget::onHoverKey(const widget::HoverKeyEvent &e) {
  105. OpaqueWidget::onHoverKey(e);
  106. if (e.getConsumed() != this)
  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 & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  112. pastePresetClipboardAction();
  113. }
  114. } break;
  115. }
  116. }
  117. }
  118. void RackWidget::onDragHover(const widget::DragHoverEvent &e) {
  119. OpaqueWidget::onDragHover(e);
  120. mousePos = e.pos;
  121. }
  122. void RackWidget::onButton(const widget::ButtonEvent &e) {
  123. OpaqueWidget::onButton(e);
  124. if (e.getConsumed() == this) {
  125. if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
  126. APP->scene->moduleBrowser->show();
  127. }
  128. }
  129. }
  130. void RackWidget::onZoom(const widget::ZoomEvent &e) {
  131. rails->box.size = math::Vec();
  132. OpaqueWidget::onZoom(e);
  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. // modules
  150. json_t *modulesJ = json_array();
  151. for (widget::Widget *w : moduleContainer->children) {
  152. ModuleWidget *moduleWidget = dynamic_cast<ModuleWidget*>(w);
  153. assert(moduleWidget);
  154. // module
  155. json_t *moduleJ = moduleWidget->toJson();
  156. {
  157. // id
  158. json_object_set_new(moduleJ, "id", json_integer(moduleWidget->module->id));
  159. // pos
  160. math::Vec pos = moduleWidget->box.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. json_array_append_new(modulesJ, moduleJ);
  165. }
  166. json_object_set_new(rootJ, "modules", modulesJ);
  167. // cables
  168. json_t *cablesJ = json_array();
  169. for (widget::Widget *w : cableContainer->children) {
  170. CableWidget *cw = dynamic_cast<CableWidget*>(w);
  171. assert(cw);
  172. // Only serialize complete cables
  173. if (!cw->isComplete())
  174. continue;
  175. json_t *cableJ = cw->toJson();
  176. {
  177. // id
  178. json_object_set_new(rootJ, "id", json_integer(cw->cable->id));
  179. }
  180. json_array_append_new(cablesJ, cableJ);
  181. }
  182. json_object_set_new(rootJ, "cables", cablesJ);
  183. return rootJ;
  184. }
  185. void RackWidget::fromJson(json_t *rootJ) {
  186. // modules
  187. json_t *modulesJ = json_object_get(rootJ, "modules");
  188. if (!modulesJ)
  189. return;
  190. size_t moduleIndex;
  191. json_t *moduleJ;
  192. json_array_foreach(modulesJ, moduleIndex, moduleJ) {
  193. ModuleWidget *moduleWidget = moduleFromJson(moduleJ);
  194. if (moduleWidget) {
  195. // Before 1.0, the module ID was the index in the "modules" array
  196. if (APP->patch->isLegacy(2)) {
  197. moduleWidget->module->id = moduleIndex;
  198. }
  199. // id
  200. json_t *idJ = json_object_get(moduleJ, "id");
  201. if (idJ)
  202. moduleWidget->module->id = json_integer_value(idJ);
  203. // pos
  204. json_t *posJ = json_object_get(moduleJ, "pos");
  205. double x, y;
  206. json_unpack(posJ, "[F, F]", &x, &y);
  207. math::Vec pos = math::Vec(x, y);
  208. if (APP->patch->isLegacy(1)) {
  209. // Before 0.6, positions were in pixel units
  210. moduleWidget->box.pos = pos;
  211. }
  212. else {
  213. moduleWidget->box.pos = pos.mult(RACK_GRID_SIZE);
  214. }
  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. // Before 1.0, cables IDs were not used, so just use the index of the "cables" array.
  242. if (APP->patch->isLegacy(2)) {
  243. cw->cable->id = cableIndex;
  244. }
  245. // id
  246. json_t *idJ = json_object_get(cableJ, "id");
  247. if (idJ)
  248. cw->cable->id = json_integer_value(idJ);
  249. addCable(cw);
  250. }
  251. }
  252. void RackWidget::pastePresetClipboardAction() {
  253. const char *moduleJson = glfwGetClipboardString(APP->window->win);
  254. if (!moduleJson) {
  255. WARN("Could not get text from clipboard.");
  256. return;
  257. }
  258. json_error_t error;
  259. json_t *moduleJ = json_loads(moduleJson, 0, &error);
  260. if (moduleJ) {
  261. ModuleWidget *mw = moduleFromJson(moduleJ);
  262. json_decref(moduleJ);
  263. addModuleAtMouse(mw);
  264. // history::ModuleAdd
  265. history::ModuleAdd *h = new history::ModuleAdd;
  266. h->setModule(mw);
  267. APP->history->push(h);
  268. }
  269. else {
  270. WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
  271. }
  272. }
  273. static void RackWidget_updateAdjacent(RackWidget *that) {
  274. // TODO This can be better than O(n^2)
  275. for (widget::Widget *w : that->moduleContainer->children) {
  276. ModuleWidget *m = dynamic_cast<ModuleWidget*>(w);
  277. math::Vec pRight = m->box.getTopRight().div(RACK_GRID_SIZE).round();
  278. bool found = false;
  279. for (widget::Widget *w2 : that->moduleContainer->children) {
  280. ModuleWidget *m2 = dynamic_cast<ModuleWidget*>(w2);
  281. if (m == m2)
  282. continue;
  283. math::Vec p2 = m2->box.pos.div(RACK_GRID_SIZE).round();
  284. // Check if m is to the left of m2
  285. if (pRight.isEqual(p2)) {
  286. m->module->rightModuleId = m2->module->id;
  287. m2->module->leftModuleId = m->module->id;
  288. found = true;
  289. break;
  290. }
  291. }
  292. if (!found) {
  293. m->module->rightModuleId = -1;
  294. }
  295. }
  296. }
  297. void RackWidget::addModule(ModuleWidget *m) {
  298. // Add module to ModuleContainer
  299. assert(m);
  300. moduleContainer->addChild(m);
  301. if (m->module) {
  302. // Add module to Engine
  303. APP->engine->addModule(m->module);
  304. }
  305. RackWidget_updateAdjacent(this);
  306. }
  307. void RackWidget::addModuleAtMouse(ModuleWidget *m) {
  308. assert(m);
  309. // Move module nearest to the mouse position
  310. m->box.pos = mousePos.minus(m->box.size.div(2));
  311. requestModuleBoxNearest(m, m->box);
  312. addModule(m);
  313. }
  314. void RackWidget::removeModule(ModuleWidget *m) {
  315. // Unset touchedParamWidget
  316. if (touchedParam) {
  317. ModuleWidget *touchedModule = touchedParam->getAncestorOfType<ModuleWidget>();
  318. if (touchedModule == m)
  319. touchedParam = NULL;
  320. }
  321. // Disconnect cables
  322. m->disconnect();
  323. if (m->module) {
  324. // Remove module from Engine
  325. APP->engine->removeModule(m->module);
  326. }
  327. // Remove module from ModuleContainer
  328. moduleContainer->removeChild(m);
  329. }
  330. bool RackWidget::requestModuleBox(ModuleWidget *m, math::Rect requestedBox) {
  331. // Check bounds
  332. if (requestedBox.pos.x < 0 || requestedBox.pos.y < 0)
  333. return false;
  334. // Check intersection with other modules
  335. for (widget::Widget *m2 : moduleContainer->children) {
  336. // Don't intersect with self
  337. if (m == m2)
  338. continue;
  339. if (requestedBox.isIntersecting(m2->box)) {
  340. return false;
  341. }
  342. }
  343. // Accept requested position
  344. m->box = requestedBox;
  345. RackWidget_updateAdjacent(this);
  346. return true;
  347. }
  348. bool RackWidget::requestModuleBoxNearest(ModuleWidget *m, math::Rect requestedBox) {
  349. // Create possible positions
  350. int x0 = std::round(requestedBox.pos.x / RACK_GRID_WIDTH);
  351. int y0 = std::round(requestedBox.pos.y / RACK_GRID_HEIGHT);
  352. std::vector<math::Vec> positions;
  353. for (int y = std::max(0, y0 - 8); y < y0 + 8; y++) {
  354. for (int x = std::max(0, x0 - 400); x < x0 + 400; x++) {
  355. positions.push_back(math::Vec(x * RACK_GRID_WIDTH, y * RACK_GRID_HEIGHT));
  356. }
  357. }
  358. // Sort possible positions by distance to the requested position
  359. std::sort(positions.begin(), positions.end(), [requestedBox](math::Vec a, math::Vec b) {
  360. return a.minus(requestedBox.pos).norm() < b.minus(requestedBox.pos).norm();
  361. });
  362. // Find a position that does not collide
  363. for (math::Vec position : positions) {
  364. math::Rect newBox = requestedBox;
  365. newBox.pos = position;
  366. if (requestModuleBox(m, newBox))
  367. return true;
  368. }
  369. // We failed to find a box with this brute force algorithm.
  370. return false;
  371. }
  372. ModuleWidget *RackWidget::getModule(int moduleId) {
  373. for (widget::Widget *w : moduleContainer->children) {
  374. ModuleWidget *moduleWidget = dynamic_cast<ModuleWidget*>(w);
  375. assert(moduleWidget);
  376. if (moduleWidget->module->id == moduleId)
  377. return moduleWidget;
  378. }
  379. return NULL;
  380. }
  381. bool RackWidget::isEmpty() {
  382. return moduleContainer->children.empty();
  383. }
  384. void RackWidget::clearCables() {
  385. for (widget::Widget *w : cableContainer->children) {
  386. CableWidget *cw = dynamic_cast<CableWidget*>(w);
  387. assert(cw);
  388. if (!cw->isComplete())
  389. continue;
  390. APP->engine->removeCable(cw->cable);
  391. }
  392. incompleteCable = NULL;
  393. cableContainer->clearChildren();
  394. }
  395. void RackWidget::clearCablesAction() {
  396. // Add CableRemove for every cable to a ComplexAction
  397. history::ComplexAction *complexAction = new history::ComplexAction;
  398. complexAction->name = "clear cables";
  399. for (widget::Widget *w : cableContainer->children) {
  400. CableWidget *cw = dynamic_cast<CableWidget*>(w);
  401. assert(cw);
  402. if (!cw->isComplete())
  403. continue;
  404. // history::CableRemove
  405. history::CableRemove *h = new history::CableRemove;
  406. h->setCable(cw);
  407. complexAction->push(h);
  408. }
  409. APP->history->push(complexAction);
  410. clearCables();
  411. }
  412. void RackWidget::clearCablesOnPort(PortWidget *port) {
  413. for (CableWidget *cw : getCablesOnPort(port)) {
  414. // Check if cable is connected to port
  415. if (cw == incompleteCable) {
  416. incompleteCable = NULL;
  417. cableContainer->removeChild(cw);
  418. }
  419. else {
  420. removeCable(cw);
  421. }
  422. delete cw;
  423. }
  424. }
  425. void RackWidget::addCable(CableWidget *w) {
  426. assert(w->isComplete());
  427. APP->engine->addCable(w->cable);
  428. cableContainer->addChild(w);
  429. }
  430. void RackWidget::removeCable(CableWidget *w) {
  431. assert(w->isComplete());
  432. APP->engine->removeCable(w->cable);
  433. cableContainer->removeChild(w);
  434. }
  435. void RackWidget::setIncompleteCable(CableWidget *w) {
  436. if (incompleteCable) {
  437. cableContainer->removeChild(incompleteCable);
  438. delete incompleteCable;
  439. incompleteCable = NULL;
  440. }
  441. if (w) {
  442. cableContainer->addChild(w);
  443. incompleteCable = w;
  444. }
  445. }
  446. CableWidget *RackWidget::releaseIncompleteCable() {
  447. CableWidget *cw = incompleteCable;
  448. cableContainer->removeChild(incompleteCable);
  449. incompleteCable = NULL;
  450. return cw;
  451. }
  452. CableWidget *RackWidget::getTopCable(PortWidget *port) {
  453. for (auto it = cableContainer->children.rbegin(); it != cableContainer->children.rend(); it++) {
  454. CableWidget *cw = dynamic_cast<CableWidget*>(*it);
  455. assert(cw);
  456. // Ignore incomplete cables
  457. if (!cw->isComplete())
  458. continue;
  459. if (cw->inputPort == port || cw->outputPort == port)
  460. return cw;
  461. }
  462. return NULL;
  463. }
  464. CableWidget *RackWidget::getCable(int cableId) {
  465. for (widget::Widget *w : cableContainer->children) {
  466. CableWidget *cw = dynamic_cast<CableWidget*>(w);
  467. assert(cw);
  468. if (cw->cable->id == cableId)
  469. return cw;
  470. }
  471. return NULL;
  472. }
  473. std::list<CableWidget*> RackWidget::getCablesOnPort(PortWidget *port) {
  474. assert(port);
  475. std::list<CableWidget*> cables;
  476. for (widget::Widget *w : cableContainer->children) {
  477. CableWidget *cw = dynamic_cast<CableWidget*>(w);
  478. assert(cw);
  479. if (cw->inputPort == port || cw->outputPort == port) {
  480. cables.push_back(cw);
  481. }
  482. }
  483. return cables;
  484. }
  485. } // namespace app
  486. } // namespace rack