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.

189 lines
4.6KB

  1. #include "system.hpp"
  2. #include "network.hpp"
  3. #include "app/Scene.hpp"
  4. #include "app/ModuleBrowser.hpp"
  5. #include "app/RackScrollWidget.hpp"
  6. #include "app.hpp"
  7. #include "history.hpp"
  8. #include "settings.hpp"
  9. #include "patch.hpp"
  10. #include "asset.hpp"
  11. #include "osdialog.h"
  12. #include <thread>
  13. namespace rack {
  14. Scene::Scene() {
  15. scrollWidget = new RackScrollWidget;
  16. {
  17. zoomWidget = new ZoomWidget;
  18. {
  19. rackWidget = new RackWidget;
  20. zoomWidget->addChild(rackWidget);
  21. }
  22. scrollWidget->container->addChild(zoomWidget);
  23. }
  24. addChild(scrollWidget);
  25. toolbar = new Toolbar;
  26. addChild(toolbar);
  27. scrollWidget->box.pos.y = toolbar->box.size.y;
  28. moduleBrowser = new ModuleBrowser;
  29. moduleBrowser->visible = false;
  30. addChild(moduleBrowser);
  31. }
  32. Scene::~Scene() {
  33. }
  34. void Scene::step() {
  35. // Resize owned descendants
  36. toolbar->box.size.x = box.size.x;
  37. scrollWidget->box.size = box.size.minus(scrollWidget->box.pos);
  38. // Resize to be a bit larger than the ScrollWidget viewport
  39. rackWidget->box.size = scrollWidget->box.size
  40. .minus(scrollWidget->container->box.pos)
  41. .plus(math::Vec(500, 500))
  42. .div(zoomWidget->zoom);
  43. OpaqueWidget::step();
  44. zoomWidget->box.size = rackWidget->box.size.mult(zoomWidget->zoom);
  45. moduleBrowser->box.size = box.size;
  46. // Autosave every 15 seconds
  47. int frame = app()->window->frame;
  48. if (frame > 0 && frame % (60 * 15) == 0) {
  49. app()->patch->save(asset::user("autosave.vcv"));
  50. settings::save(asset::user("settings.json"));
  51. }
  52. // Set zoom every few frames
  53. if (app()->window->frame % 10 == 0)
  54. zoomWidget->setZoom(settings::zoom);
  55. // Request latest version from server
  56. if (!devMode && checkVersion && !checkedVersion) {
  57. std::thread t(&Scene::runCheckVersion, this);
  58. t.detach();
  59. checkedVersion = true;
  60. }
  61. // Version popup message
  62. if (!latestVersion.empty()) {
  63. std::string versionMessage = string::f("Rack %s is available.\n\nYou have Rack %s.\n\nClose Rack and download new version on the website?", latestVersion.c_str(), APP_VERSION.c_str());
  64. if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, versionMessage.c_str())) {
  65. std::thread t(system::openBrowser, "https://vcvrack.com/");
  66. t.detach();
  67. app()->window->close();
  68. }
  69. latestVersion = "";
  70. }
  71. }
  72. void Scene::draw(NVGcontext *vg) {
  73. OpaqueWidget::draw(vg);
  74. }
  75. void Scene::onHoverKey(const event::HoverKey &e) {
  76. if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
  77. switch (e.key) {
  78. case GLFW_KEY_N: {
  79. if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  80. app()->patch->resetDialog();
  81. e.consume(this);
  82. }
  83. } break;
  84. case GLFW_KEY_Q: {
  85. if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  86. app()->window->close();
  87. e.consume(this);
  88. }
  89. } break;
  90. case GLFW_KEY_O: {
  91. if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  92. app()->patch->loadDialog();
  93. e.consume(this);
  94. }
  95. if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
  96. app()->patch->revertDialog();
  97. e.consume(this);
  98. }
  99. } break;
  100. case GLFW_KEY_S: {
  101. if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  102. app()->patch->saveDialog();
  103. e.consume(this);
  104. }
  105. if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
  106. app()->patch->saveAsDialog();
  107. e.consume(this);
  108. }
  109. } break;
  110. case GLFW_KEY_V: {
  111. if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  112. rackWidget->pastePresetClipboard();
  113. e.consume(this);
  114. }
  115. } break;
  116. case GLFW_KEY_Z: {
  117. if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  118. app()->history->undo();
  119. e.consume(this);
  120. }
  121. if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
  122. app()->history->redo();
  123. e.consume(this);
  124. }
  125. } break;
  126. case GLFW_KEY_ENTER:
  127. case GLFW_KEY_KP_ENTER: {
  128. moduleBrowser->visible = true;
  129. e.consume(this);
  130. } break;
  131. case GLFW_KEY_F11: {
  132. app()->window->setFullScreen(!app()->window->isFullScreen());
  133. e.consume(this);
  134. }
  135. }
  136. }
  137. if (!e.getConsumed())
  138. OpaqueWidget::onHoverKey(e);
  139. }
  140. void Scene::onPathDrop(const event::PathDrop &e) {
  141. if (e.paths.size() >= 1) {
  142. const std::string &path = e.paths[0];
  143. if (string::extension(path) == "vcv") {
  144. app()->patch->load(path);
  145. e.consume(this);
  146. }
  147. }
  148. if (!e.getConsumed())
  149. OpaqueWidget::onPathDrop(e);
  150. }
  151. void Scene::runCheckVersion() {
  152. json_t *resJ = network::requestJson(network::METHOD_GET, API_HOST + "/version", NULL);
  153. if (resJ) {
  154. json_t *versionJ = json_object_get(resJ, "version");
  155. if (versionJ) {
  156. std::string version = json_string_value(versionJ);
  157. if (version != APP_VERSION) {
  158. latestVersion = version;
  159. }
  160. }
  161. json_decref(resJ);
  162. }
  163. }
  164. } // namespace rack