SimulationView.qml 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. // Copyright (c) 2017 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.4
  4. import QtQuick.Controls 1.2
  5. import QtQuick.Layouts 1.1
  6. import QtQuick.Controls.Styles 1.1
  7. import UM 1.0 as UM
  8. import Cura 1.0 as Cura
  9. Item
  10. {
  11. id: base
  12. width: {
  13. if (UM.SimulationView.compatibilityMode) {
  14. return UM.Theme.getSize("layerview_menu_size_compatibility").width;
  15. } else {
  16. return UM.Theme.getSize("layerview_menu_size").width;
  17. }
  18. }
  19. height: {
  20. if (viewSettings.collapsed) {
  21. if (UM.SimulationView.compatibilityMode) {
  22. return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height;
  23. }
  24. return UM.Theme.getSize("layerview_menu_size_collapsed").height;
  25. } else if (UM.SimulationView.compatibilityMode) {
  26. return UM.Theme.getSize("layerview_menu_size_compatibility").height;
  27. } else if (UM.Preferences.getValue("layerview/layer_view_type") == 0) {
  28. return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
  29. } else {
  30. return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
  31. }
  32. }
  33. Behavior on height { NumberAnimation { duration: 100 } }
  34. property var buttonTarget: {
  35. if(parent != null)
  36. {
  37. var force_binding = parent.y; // ensure this gets reevaluated when the panel moves
  38. return base.mapFromItem(parent.parent, parent.buttonTarget.x, parent.buttonTarget.y)
  39. }
  40. return Qt.point(0,0)
  41. }
  42. visible: parent != null ? !parent.parent.monitoringPrint: true
  43. Rectangle {
  44. id: layerViewMenu
  45. anchors.right: parent.right
  46. anchors.top: parent.top
  47. width: parent.width
  48. height: parent.height
  49. clip: true
  50. z: layerSlider.z - 1
  51. color: UM.Theme.getColor("tool_panel_background")
  52. border.width: UM.Theme.getSize("default_lining").width
  53. border.color: UM.Theme.getColor("lining")
  54. Button {
  55. id: collapseButton
  56. anchors.top: parent.top
  57. anchors.topMargin: Math.floor(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2)
  58. anchors.right: parent.right
  59. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  60. width: UM.Theme.getSize("standard_arrow").width
  61. height: UM.Theme.getSize("standard_arrow").height
  62. onClicked: viewSettings.collapsed = !viewSettings.collapsed
  63. style: ButtonStyle
  64. {
  65. background: UM.RecolorImage
  66. {
  67. width: control.width
  68. height: control.height
  69. sourceSize.width: width
  70. sourceSize.height: width
  71. color: UM.Theme.getColor("setting_control_text")
  72. source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom")
  73. }
  74. label: Label{ }
  75. }
  76. }
  77. ColumnLayout {
  78. id: viewSettings
  79. property bool collapsed: false
  80. property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
  81. property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
  82. property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
  83. property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
  84. property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
  85. // if we are in compatibility mode, we only show the "line type"
  86. property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
  87. property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
  88. property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
  89. property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
  90. anchors.top: parent.top
  91. anchors.topMargin: UM.Theme.getSize("default_margin").height
  92. anchors.left: parent.left
  93. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  94. anchors.right: parent.right
  95. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  96. spacing: UM.Theme.getSize("layerview_row_spacing").height
  97. Label
  98. {
  99. id: layerViewTypesLabel
  100. anchors.left: parent.left
  101. text: catalog.i18nc("@label","Color scheme")
  102. font: UM.Theme.getFont("default");
  103. visible: !UM.SimulationView.compatibilityMode
  104. Layout.fillWidth: true
  105. color: UM.Theme.getColor("setting_control_text")
  106. }
  107. ListModel // matches SimulationView.py
  108. {
  109. id: layerViewTypes
  110. }
  111. Component.onCompleted:
  112. {
  113. layerViewTypes.append({
  114. text: catalog.i18nc("@label:listbox", "Material Color"),
  115. type_id: 0
  116. })
  117. layerViewTypes.append({
  118. text: catalog.i18nc("@label:listbox", "Line Type"),
  119. type_id: 1
  120. })
  121. layerViewTypes.append({
  122. text: catalog.i18nc("@label:listbox", "Feedrate"),
  123. type_id: 2
  124. })
  125. // TODO DON'T DELETE!!!! This part must be enabled when adaptive layer height feature is available
  126. // layerViewTypes.append({
  127. // text: catalog.i18nc("@label:listbox", "Layer thickness"),
  128. // type_id: 3 // these ids match the switching in the shader
  129. // })
  130. }
  131. ComboBox
  132. {
  133. id: layerTypeCombobox
  134. anchors.left: parent.left
  135. Layout.fillWidth: true
  136. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  137. model: layerViewTypes
  138. visible: !UM.SimulationView.compatibilityMode
  139. style: UM.Theme.styles.combobox
  140. anchors.right: parent.right
  141. onActivated:
  142. {
  143. UM.Preferences.setValue("layerview/layer_view_type", index);
  144. }
  145. Component.onCompleted:
  146. {
  147. currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
  148. updateLegends(currentIndex);
  149. }
  150. function updateLegends(type_id)
  151. {
  152. // update visibility of legends
  153. viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
  154. }
  155. }
  156. Label
  157. {
  158. id: compatibilityModeLabel
  159. anchors.left: parent.left
  160. text: catalog.i18nc("@label","Compatibility Mode")
  161. font: UM.Theme.getFont("default")
  162. color: UM.Theme.getColor("text")
  163. visible: UM.SimulationView.compatibilityMode
  164. Layout.fillWidth: true
  165. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
  166. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  167. }
  168. Item
  169. {
  170. height: Math.floor(UM.Theme.getSize("default_margin").width / 2)
  171. width: width
  172. }
  173. Connections {
  174. target: UM.Preferences
  175. onPreferenceChanged:
  176. {
  177. layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
  178. layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex);
  179. playButton.pauseSimulation();
  180. viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|");
  181. viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves");
  182. viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers");
  183. viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin");
  184. viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill");
  185. viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers");
  186. viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count");
  187. }
  188. }
  189. Repeater {
  190. model: Cura.ExtrudersModel{}
  191. CheckBox {
  192. id: extrudersModelCheckBox
  193. checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
  194. onClicked: {
  195. viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
  196. UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
  197. }
  198. visible: !UM.SimulationView.compatibilityMode
  199. enabled: index + 1 <= 4
  200. Rectangle {
  201. anchors.verticalCenter: parent.verticalCenter
  202. anchors.right: extrudersModelCheckBox.right
  203. width: UM.Theme.getSize("layerview_legend_size").width
  204. height: UM.Theme.getSize("layerview_legend_size").height
  205. color: model.color
  206. radius: width / 2
  207. border.width: UM.Theme.getSize("default_lining").width
  208. border.color: UM.Theme.getColor("lining")
  209. visible: !viewSettings.show_legend & !viewSettings.show_gradient
  210. }
  211. Layout.fillWidth: true
  212. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
  213. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  214. style: UM.Theme.styles.checkbox
  215. Label
  216. {
  217. text: model.name
  218. elide: Text.ElideRight
  219. color: UM.Theme.getColor("setting_control_text")
  220. font: UM.Theme.getFont("default")
  221. anchors.verticalCenter: parent.verticalCenter
  222. anchors.left: extrudersModelCheckBox.left;
  223. anchors.right: extrudersModelCheckBox.right;
  224. anchors.leftMargin: UM.Theme.getSize("checkbox").width + UM.Theme.getSize("default_margin").width /2
  225. anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
  226. }
  227. }
  228. }
  229. Repeater {
  230. model: ListModel {
  231. id: typesLegendModel
  232. Component.onCompleted:
  233. {
  234. typesLegendModel.append({
  235. label: catalog.i18nc("@label", "Show Travels"),
  236. initialValue: viewSettings.show_travel_moves,
  237. preference: "layerview/show_travel_moves",
  238. colorId: "layerview_move_combing"
  239. });
  240. typesLegendModel.append({
  241. label: catalog.i18nc("@label", "Show Helpers"),
  242. initialValue: viewSettings.show_helpers,
  243. preference: "layerview/show_helpers",
  244. colorId: "layerview_support"
  245. });
  246. typesLegendModel.append({
  247. label: catalog.i18nc("@label", "Show Shell"),
  248. initialValue: viewSettings.show_skin,
  249. preference: "layerview/show_skin",
  250. colorId: "layerview_inset_0"
  251. });
  252. typesLegendModel.append({
  253. label: catalog.i18nc("@label", "Show Infill"),
  254. initialValue: viewSettings.show_infill,
  255. preference: "layerview/show_infill",
  256. colorId: "layerview_infill"
  257. });
  258. }
  259. }
  260. CheckBox {
  261. id: legendModelCheckBox
  262. checked: model.initialValue
  263. onClicked: {
  264. UM.Preferences.setValue(model.preference, checked);
  265. }
  266. Rectangle {
  267. anchors.verticalCenter: parent.verticalCenter
  268. anchors.right: legendModelCheckBox.right
  269. width: UM.Theme.getSize("layerview_legend_size").width
  270. height: UM.Theme.getSize("layerview_legend_size").height
  271. color: UM.Theme.getColor(model.colorId)
  272. border.width: UM.Theme.getSize("default_lining").width
  273. border.color: UM.Theme.getColor("lining")
  274. visible: viewSettings.show_legend
  275. }
  276. Layout.fillWidth: true
  277. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
  278. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  279. style: UM.Theme.styles.checkbox
  280. Label
  281. {
  282. text: label
  283. font: UM.Theme.getFont("default")
  284. elide: Text.ElideRight
  285. color: UM.Theme.getColor("setting_control_text")
  286. anchors.verticalCenter: parent.verticalCenter
  287. anchors.left: legendModelCheckBox.left;
  288. anchors.right: legendModelCheckBox.right;
  289. anchors.leftMargin: UM.Theme.getSize("checkbox").width + UM.Theme.getSize("default_margin").width /2
  290. anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
  291. }
  292. }
  293. }
  294. CheckBox {
  295. checked: viewSettings.only_show_top_layers
  296. onClicked: {
  297. UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0);
  298. }
  299. text: catalog.i18nc("@label", "Only Show Top Layers")
  300. visible: UM.SimulationView.compatibilityMode
  301. style: UM.Theme.styles.checkbox
  302. }
  303. CheckBox {
  304. checked: viewSettings.top_layer_count == 5
  305. onClicked: {
  306. UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1);
  307. }
  308. text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
  309. visible: UM.SimulationView.compatibilityMode
  310. style: UM.Theme.styles.checkbox
  311. }
  312. Repeater {
  313. model: ListModel {
  314. id: typesLegendModelNoCheck
  315. Component.onCompleted:
  316. {
  317. typesLegendModelNoCheck.append({
  318. label: catalog.i18nc("@label", "Top / Bottom"),
  319. colorId: "layerview_skin",
  320. });
  321. typesLegendModelNoCheck.append({
  322. label: catalog.i18nc("@label", "Inner Wall"),
  323. colorId: "layerview_inset_x",
  324. });
  325. }
  326. }
  327. Label {
  328. text: label
  329. visible: viewSettings.show_legend
  330. id: typesLegendModelLabel
  331. Rectangle {
  332. anchors.verticalCenter: parent.verticalCenter
  333. anchors.right: typesLegendModelLabel.right
  334. width: UM.Theme.getSize("layerview_legend_size").width
  335. height: UM.Theme.getSize("layerview_legend_size").height
  336. color: UM.Theme.getColor(model.colorId)
  337. border.width: UM.Theme.getSize("default_lining").width
  338. border.color: UM.Theme.getColor("lining")
  339. visible: viewSettings.show_legend
  340. }
  341. Layout.fillWidth: true
  342. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
  343. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  344. color: UM.Theme.getColor("setting_control_text")
  345. font: UM.Theme.getFont("default")
  346. }
  347. }
  348. // Text for the minimum, maximum and units for the feedrates and layer thickness
  349. Item {
  350. id: gradientLegend
  351. visible: viewSettings.show_gradient
  352. width: parent.width
  353. height: UM.Theme.getSize("layerview_row").height
  354. anchors {
  355. topMargin: UM.Theme.getSize("slider_layerview_margin").height
  356. horizontalCenter: parent.horizontalCenter
  357. }
  358. Label {
  359. text: minText()
  360. anchors.left: parent.left
  361. color: UM.Theme.getColor("setting_control_text")
  362. font: UM.Theme.getFont("default")
  363. function minText() {
  364. if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) {
  365. // Feedrate selected
  366. if (UM.Preferences.getValue("layerview/layer_view_type") == 2) {
  367. return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
  368. }
  369. // Layer thickness selected
  370. if (UM.Preferences.getValue("layerview/layer_view_type") == 3) {
  371. return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
  372. }
  373. }
  374. return catalog.i18nc("@label","min")
  375. }
  376. }
  377. Label {
  378. text: unitsText()
  379. anchors.horizontalCenter: parent.horizontalCenter
  380. color: UM.Theme.getColor("setting_control_text")
  381. font: UM.Theme.getFont("default")
  382. function unitsText() {
  383. if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) {
  384. // Feedrate selected
  385. if (UM.Preferences.getValue("layerview/layer_view_type") == 2) {
  386. return "mm/s"
  387. }
  388. // Layer thickness selected
  389. if (UM.Preferences.getValue("layerview/layer_view_type") == 3) {
  390. return "mm"
  391. }
  392. }
  393. return ""
  394. }
  395. }
  396. Label {
  397. text: maxText()
  398. anchors.right: parent.right
  399. color: UM.Theme.getColor("setting_control_text")
  400. font: UM.Theme.getFont("default")
  401. function maxText() {
  402. if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) {
  403. // Feedrate selected
  404. if (UM.Preferences.getValue("layerview/layer_view_type") == 2) {
  405. return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
  406. }
  407. // Layer thickness selected
  408. if (UM.Preferences.getValue("layerview/layer_view_type") == 3) {
  409. return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
  410. }
  411. }
  412. return catalog.i18nc("@label","max")
  413. }
  414. }
  415. }
  416. // Gradient colors for feedrate and thickness
  417. Rectangle { // In QML 5.9 can be changed by LinearGradient
  418. // Invert values because then the bar is rotated 90 degrees
  419. id: gradient
  420. visible: viewSettings.show_gradient
  421. anchors.left: parent.right
  422. height: parent.width
  423. width: UM.Theme.getSize("layerview_row").height * 1.5
  424. border.width: UM.Theme.getSize("default_lining").width
  425. border.color: UM.Theme.getColor("lining")
  426. transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
  427. gradient: Gradient {
  428. GradientStop {
  429. position: 0.000
  430. color: Qt.rgba(1, 0, 0, 1)
  431. }
  432. GradientStop {
  433. position: 0.25
  434. color: Qt.rgba(0.75, 0.5, 0.25, 1)
  435. }
  436. GradientStop {
  437. position: 0.5
  438. color: Qt.rgba(0.5, 1, 0.5, 1)
  439. }
  440. GradientStop {
  441. position: 0.75
  442. color: Qt.rgba(0.25, 0.5, 0.75, 1)
  443. }
  444. GradientStop {
  445. position: 1.0
  446. color: Qt.rgba(0, 0, 1, 1)
  447. }
  448. }
  449. }
  450. }
  451. }
  452. Item {
  453. id: slidersBox
  454. width: parent.width
  455. visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
  456. anchors {
  457. top: parent.bottom
  458. topMargin: UM.Theme.getSize("slider_layerview_margin").height
  459. left: parent.left
  460. }
  461. PathSlider {
  462. id: pathSlider
  463. height: UM.Theme.getSize("slider_handle").width
  464. anchors.right: playButton.left
  465. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  466. anchors.left: parent.left
  467. visible: !UM.SimulationView.compatibilityMode
  468. // custom properties
  469. handleValue: UM.SimulationView.currentPath
  470. maximumValue: UM.SimulationView.numPaths
  471. handleSize: UM.Theme.getSize("slider_handle").width
  472. trackThickness: UM.Theme.getSize("slider_groove").width
  473. trackColor: UM.Theme.getColor("slider_groove")
  474. trackBorderColor: UM.Theme.getColor("slider_groove_border")
  475. handleColor: UM.Theme.getColor("slider_handle")
  476. handleActiveColor: UM.Theme.getColor("slider_handle_active")
  477. rangeColor: UM.Theme.getColor("slider_groove_fill")
  478. // update values when layer data changes
  479. Connections {
  480. target: UM.SimulationView
  481. onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
  482. onCurrentPathChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
  483. }
  484. // make sure the slider handlers show the correct value after switching views
  485. Component.onCompleted: {
  486. pathSlider.setHandleValue(UM.SimulationView.currentPath)
  487. }
  488. }
  489. LayerSlider {
  490. id: layerSlider
  491. width: UM.Theme.getSize("slider_handle").width
  492. height: UM.Theme.getSize("layerview_menu_size").height
  493. anchors {
  494. top: !UM.SimulationView.compatibilityMode ? playButton.bottom : parent.top
  495. topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0
  496. right: parent.right
  497. rightMargin: UM.Theme.getSize("slider_layerview_margin").width
  498. }
  499. // custom properties
  500. upperValue: UM.SimulationView.currentLayer
  501. lowerValue: UM.SimulationView.minimumLayer
  502. maximumValue: UM.SimulationView.numLayers
  503. handleSize: UM.Theme.getSize("slider_handle").width
  504. trackThickness: UM.Theme.getSize("slider_groove").width
  505. trackColor: UM.Theme.getColor("slider_groove")
  506. trackBorderColor: UM.Theme.getColor("slider_groove_border")
  507. upperHandleColor: UM.Theme.getColor("slider_handle")
  508. lowerHandleColor: UM.Theme.getColor("slider_handle")
  509. rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
  510. handleActiveColor: UM.Theme.getColor("slider_handle_active")
  511. handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width
  512. // update values when layer data changes
  513. Connections {
  514. target: UM.SimulationView
  515. onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
  516. onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
  517. onCurrentLayerChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
  518. }
  519. // make sure the slider handlers show the correct value after switching views
  520. Component.onCompleted: {
  521. layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
  522. layerSlider.setUpperValue(UM.SimulationView.currentLayer)
  523. }
  524. }
  525. // Play simulation button
  526. Button {
  527. id: playButton
  528. implicitWidth: Math.floor(UM.Theme.getSize("button").width * 0.75)
  529. implicitHeight: Math.floor(UM.Theme.getSize("button").height * 0.75)
  530. iconSource: "./resources/simulation_resume.svg"
  531. style: UM.Theme.styles.tool_button
  532. visible: !UM.SimulationView.compatibilityMode
  533. anchors {
  534. horizontalCenter: layerSlider.horizontalCenter
  535. verticalCenter: pathSlider.verticalCenter
  536. }
  537. property var status: 0 // indicates if it's stopped (0) or playing (1)
  538. onClicked: {
  539. switch(status) {
  540. case 0: {
  541. resumeSimulation()
  542. break
  543. }
  544. case 1: {
  545. pauseSimulation()
  546. break
  547. }
  548. }
  549. }
  550. function pauseSimulation() {
  551. UM.SimulationView.setSimulationRunning(false)
  552. iconSource = "./resources/simulation_resume.svg"
  553. simulationTimer.stop()
  554. status = 0
  555. }
  556. function resumeSimulation() {
  557. UM.SimulationView.setSimulationRunning(true)
  558. iconSource = "./resources/simulation_pause.svg"
  559. simulationTimer.start()
  560. }
  561. }
  562. Timer
  563. {
  564. id: simulationTimer
  565. interval: 100
  566. running: false
  567. repeat: true
  568. onTriggered: {
  569. var currentPath = UM.SimulationView.currentPath
  570. var numPaths = UM.SimulationView.numPaths
  571. var currentLayer = UM.SimulationView.currentLayer
  572. var numLayers = UM.SimulationView.numLayers
  573. // When the user plays the simulation, if the path slider is at the end of this layer, we start
  574. // the simulation at the beginning of the current layer.
  575. if (playButton.status == 0)
  576. {
  577. if (currentPath >= numPaths)
  578. {
  579. UM.SimulationView.setCurrentPath(0)
  580. }
  581. else
  582. {
  583. UM.SimulationView.setCurrentPath(currentPath+1)
  584. }
  585. }
  586. // If the simulation is already playing and we reach the end of a layer, then it automatically
  587. // starts at the beginning of the next layer.
  588. else
  589. {
  590. if (currentPath >= numPaths)
  591. {
  592. // At the end of the model, the simulation stops
  593. if (currentLayer >= numLayers)
  594. {
  595. playButton.pauseSimulation()
  596. }
  597. else
  598. {
  599. UM.SimulationView.setCurrentLayer(currentLayer+1)
  600. UM.SimulationView.setCurrentPath(0)
  601. }
  602. }
  603. else
  604. {
  605. UM.SimulationView.setCurrentPath(currentPath+1)
  606. }
  607. }
  608. playButton.status = 1
  609. }
  610. }
  611. }
  612. FontMetrics {
  613. id: fontMetrics
  614. font: UM.Theme.getFont("default")
  615. }
  616. }