SimulationView.qml 31 KB

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