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.

325 lines
9.8KB

  1. --- ../Rack/src/app/Scene.cpp 2023-06-11 21:02:02.640002965 +0200
  2. +++ Scene.cpp 2023-06-11 20:56:09.476002797 +0200
  3. @@ -1,12 +1,36 @@
  4. -#include <thread>
  5. -
  6. -#include <osdialog.h>
  7. +/*
  8. + * DISTRHO Cardinal Plugin
  9. + * Copyright (C) 2021-2023 Filipe Coelho <falktx@falktx.com>
  10. + *
  11. + * This program is free software; you can redistribute it and/or
  12. + * modify it under the terms of the GNU General Public License as
  13. + * published by the Free Software Foundation; either version 3 of
  14. + * the License, or any later version.
  15. + *
  16. + * This program is distributed in the hope that it will be useful,
  17. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. + * GNU General Public License for more details.
  20. + *
  21. + * For a full copy of the GNU General Public License see the LICENSE file.
  22. + */
  23. +
  24. +/**
  25. + * This file is an edited version of VCVRack's app/Scene.cpp
  26. + * Copyright (C) 2016-2023 VCV.
  27. + *
  28. + * This program is free software: you can redistribute it and/or
  29. + * modify it under the terms of the GNU General Public License as
  30. + * published by the Free Software Foundation; either version 3 of
  31. + * the License, or (at your option) any later version.
  32. + */
  33. #include <app/Scene.hpp>
  34. #include <app/Browser.hpp>
  35. #include <app/TipWindow.hpp>
  36. #include <app/MenuBar.hpp>
  37. #include <context.hpp>
  38. +#include <engine/Engine.hpp>
  39. #include <system.hpp>
  40. #include <network.hpp>
  41. #include <history.hpp>
  42. @@ -14,6 +38,14 @@
  43. #include <patch.hpp>
  44. #include <asset.hpp>
  45. +#ifdef NDEBUG
  46. +# undef DEBUG
  47. +#endif
  48. +
  49. +#include "../CardinalCommon.hpp"
  50. +#include "../CardinalRemote.hpp"
  51. +
  52. +#include <algorithm>
  53. namespace rack {
  54. namespace app {
  55. @@ -23,32 +55,72 @@
  56. math::Vec size;
  57. void draw(const DrawArgs& args) override {
  58. + nvgStrokeColor(args.vg, nvgRGBf(1, 1, 1));
  59. + nvgStrokeWidth(args.vg, 1);
  60. +
  61. nvgBeginPath(args.vg);
  62. - nvgMoveTo(args.vg, box.size.x, box.size.y);
  63. + nvgMoveTo(args.vg, box.size.x, 0);
  64. nvgLineTo(args.vg, 0, box.size.y);
  65. - nvgLineTo(args.vg, box.size.x, 0);
  66. - nvgClosePath(args.vg);
  67. - nvgFillColor(args.vg, nvgRGBAf(1, 1, 1, 0.15));
  68. - nvgFill(args.vg);
  69. + nvgStroke(args.vg);
  70. +
  71. + nvgBeginPath(args.vg);
  72. + nvgMoveTo(args.vg, box.size.x + 5, 0);
  73. + nvgLineTo(args.vg, 0, box.size.y + 5);
  74. + nvgStroke(args.vg);
  75. +
  76. + nvgBeginPath(args.vg);
  77. + nvgMoveTo(args.vg, box.size.x + 10, 0);
  78. + nvgLineTo(args.vg, 0, box.size.y + 10);
  79. + nvgStroke(args.vg);
  80. +
  81. + nvgStrokeColor(args.vg, nvgRGBf(0, 0, 0));
  82. +
  83. + nvgBeginPath(args.vg);
  84. + nvgMoveTo(args.vg, box.size.x+1, 0);
  85. + nvgLineTo(args.vg, 0, box.size.y+1);
  86. + nvgStroke(args.vg);
  87. +
  88. + nvgBeginPath(args.vg);
  89. + nvgMoveTo(args.vg, box.size.x + 6, 0);
  90. + nvgLineTo(args.vg, 0, box.size.y + 6);
  91. + nvgStroke(args.vg);
  92. +
  93. + nvgBeginPath(args.vg);
  94. + nvgMoveTo(args.vg, box.size.x + 11, 0);
  95. + nvgLineTo(args.vg, 0, box.size.y + 11);
  96. + nvgStroke(args.vg);
  97. + }
  98. +
  99. + void onHover(const HoverEvent& e) override {
  100. + e.consume(this);
  101. }
  102. - void onDragStart(const DragStartEvent& e) override {
  103. + void onEnter(const EnterEvent& e) override {
  104. + glfwSetCursor(APP->window->win, glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR));
  105. + }
  106. +
  107. + void onLeave(const LeaveEvent& e) override {
  108. + glfwSetCursor(APP->window->win, nullptr);
  109. + }
  110. +
  111. + void onDragStart(const DragStartEvent&) override {
  112. size = APP->window->getSize();
  113. }
  114. void onDragMove(const DragMoveEvent& e) override {
  115. - size = size.plus(e.mouseDelta);
  116. + size = size.plus(e.mouseDelta.mult(APP->window->pixelRatio));
  117. APP->window->setSize(size.round());
  118. }
  119. };
  120. struct Scene::Internal {
  121. - ResizeHandle* resizeHandle;
  122. -
  123. - double lastAutosaveTime = 0.0;
  124. + ResizeHandle* resizeHandle = nullptr;
  125. bool heldArrowKeys[4] = {};
  126. +
  127. + double lastSceneChangeTime = 0.0;
  128. + int historyActionIndex = -1;
  129. };
  130. @@ -67,13 +139,11 @@
  131. browser->hide();
  132. addChild(browser);
  133. - if (settings::showTipsOnLaunch) {
  134. - addChild(tipWindowCreate());
  135. - }
  136. + if (isStandalone() || isMini())
  137. + return;
  138. internal->resizeHandle = new ResizeHandle;
  139. - internal->resizeHandle->box.size = math::Vec(15, 15);
  140. - internal->resizeHandle->hide();
  141. + internal->resizeHandle->box.size = math::Vec(16, 16);
  142. addChild(internal->resizeHandle);
  143. }
  144. @@ -99,22 +169,13 @@
  145. rackScroll->box.pos.y = menuBar->box.size.y;
  146. }
  147. - internal->resizeHandle->box.pos = box.size.minus(internal->resizeHandle->box.size);
  148. + if (internal->resizeHandle != nullptr)
  149. + internal->resizeHandle->box.pos = box.size.minus(internal->resizeHandle->box.size);
  150. // Resize owned descendants
  151. menuBar->box.size.x = box.size.x;
  152. rackScroll->box.size = box.size.minus(rackScroll->box.pos);
  153. - // Autosave periodically
  154. - if (settings::autosaveInterval > 0.0) {
  155. - double time = system::getTime();
  156. - if (time - internal->lastAutosaveTime >= settings::autosaveInterval) {
  157. - internal->lastAutosaveTime = time;
  158. - APP->patch->saveAutosave();
  159. - settings::save();
  160. - }
  161. - }
  162. -
  163. // Scroll RackScrollWidget with arrow keys
  164. math::Vec arrowDelta;
  165. if (internal->heldArrowKeys[0]) {
  166. @@ -143,6 +204,34 @@
  167. rackScroll->offset += arrowDelta * arrowSpeed;
  168. }
  169. + if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) {
  170. + idleRemote(remoteDetails);
  171. +
  172. + if (remoteDetails->autoDeploy) {
  173. + const int actionIndex = APP->history->actionIndex;
  174. + const double time = system::getTime();
  175. +
  176. + if (internal->historyActionIndex == -1) {
  177. + internal->historyActionIndex = actionIndex;
  178. + internal->lastSceneChangeTime = time;
  179. + } else if (internal->historyActionIndex != actionIndex && actionIndex > 0 && time - internal->lastSceneChangeTime >= 1.0) {
  180. + const std::string& name(APP->history->actions[actionIndex - 1]->name);
  181. + static const std::vector<std::string> ignoredNames = {
  182. + "move knob",
  183. + "move modules",
  184. + "move switch",
  185. + };
  186. + if (std::find(ignoredNames.cbegin(), ignoredNames.cend(), name) == ignoredNames.cend()) {
  187. + printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str());
  188. + remoteUtils::sendFullPatchToRemote(remoteDetails);
  189. + window::generateScreenshot();
  190. + }
  191. + internal->historyActionIndex = actionIndex;
  192. + internal->lastSceneChangeTime = time;
  193. + }
  194. + }
  195. + }
  196. +
  197. Widget::step();
  198. }
  199. @@ -172,7 +261,7 @@
  200. if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
  201. // DEBUG("key '%d '%c' scancode %d '%c' keyName '%s'", e.key, e.key, e.scancode, e.scancode, e.keyName.c_str());
  202. if (e.keyName == "n" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  203. - APP->patch->loadTemplateDialog();
  204. + patchUtils::loadTemplateDialog(false);
  205. e.consume(this);
  206. }
  207. if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  208. @@ -180,19 +269,25 @@
  209. e.consume(this);
  210. }
  211. if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  212. - APP->patch->loadDialog();
  213. + patchUtils::loadDialog();
  214. e.consume(this);
  215. }
  216. if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
  217. - APP->patch->revertDialog();
  218. + patchUtils::revertDialog();
  219. e.consume(this);
  220. }
  221. if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  222. - APP->patch->saveDialog();
  223. + // NOTE: for plugin versions it will do nothing if path is empty, intentionally
  224. + if (APP->patch->path.empty()) {
  225. + if (isStandalone())
  226. + patchUtils::saveAsDialog();
  227. + } else {
  228. + patchUtils::saveDialog(APP->patch->path);
  229. + }
  230. e.consume(this);
  231. }
  232. if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
  233. - APP->patch->saveAsDialog();
  234. + patchUtils::saveAsDialog();
  235. e.consume(this);
  236. }
  237. if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  238. @@ -220,24 +315,42 @@
  239. APP->scene->rackScroll->setZoom(std::pow(2.f, zoom));
  240. e.consume(this);
  241. }
  242. - if ((e.keyName == "0") && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  243. + if ((e.keyName == "0" || e.keyName == "1") && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  244. APP->scene->rackScroll->setZoom(1.f);
  245. e.consume(this);
  246. }
  247. + if (e.keyName == "2" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  248. + APP->scene->rackScroll->setZoom(2.f);
  249. + e.consume(this);
  250. + }
  251. if (e.key == GLFW_KEY_F1 && (e.mods & RACK_MOD_MASK) == 0) {
  252. - system::openBrowser("https://vcvrack.com/manual/");
  253. + patchUtils::openBrowser("https://vcvrack.com/manual/");
  254. e.consume(this);
  255. }
  256. if (e.key == GLFW_KEY_F3 && (e.mods & RACK_MOD_MASK) == 0) {
  257. settings::cpuMeter ^= true;
  258. e.consume(this);
  259. }
  260. + if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) {
  261. + if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote())
  262. + {
  263. + remoteUtils::sendFullPatchToRemote(remoteDetails);
  264. + window::generateScreenshot();
  265. + }
  266. + e.consume(this);
  267. + }
  268. + if (e.key == GLFW_KEY_F9 && (e.mods & RACK_MOD_MASK) == 0) {
  269. + window::generateScreenshot();
  270. + e.consume(this);
  271. + }
  272. +#ifdef DISTRHO_OS_WASM
  273. if (e.key == GLFW_KEY_F11 && (e.mods & RACK_MOD_MASK) == 0) {
  274. APP->window->setFullScreen(!APP->window->isFullScreen());
  275. // The MenuBar will be hidden when the mouse moves over the RackScrollWidget.
  276. // menuBar->hide();
  277. e.consume(this);
  278. }
  279. +#endif
  280. // Module selections
  281. if (e.keyName == "a" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  282. @@ -326,13 +439,6 @@
  283. // Key commands that can be overridden by children
  284. if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
  285. - // Alternative key command for exiting fullscreen, since F11 doesn't work reliably on Mac due to "Show desktop" OS binding.
  286. - if (e.key == GLFW_KEY_ESCAPE && (e.mods & RACK_MOD_MASK) == 0) {
  287. - if (APP->window->isFullScreen()) {
  288. - APP->window->setFullScreen(false);
  289. - e.consume(this);
  290. - }
  291. - }
  292. if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  293. rack->pasteClipboardAction();
  294. e.consume(this);
  295. @@ -351,7 +457,7 @@
  296. std::string extension = system::getExtension(path);
  297. if (extension == ".vcv") {
  298. - APP->patch->loadPathDialog(path);
  299. + patchUtils::loadPathDialog(path);
  300. e.consume(this);
  301. return;
  302. }