Cascade.qml 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import QtQuick 2.5
  2. import Box2D 2.0
  3. import Qt.labs.settings 1.0
  4. // Forgive me
  5. import "../.."
  6. Item {
  7. id: root
  8. signal togglePause
  9. signal next
  10. property var columnArray: []
  11. property var pictureDelegate: Component {
  12. CascadeDelegate {}
  13. }
  14. function drain() {
  15. // TODO: implement draining of all visible artwork
  16. }
  17. anchors.fill: parent
  18. Settings {
  19. id: cascadeSettings
  20. category: "Cascade"
  21. property int initialFeedRate: 500
  22. }
  23. QtObject {
  24. id: d
  25. property int feedrate: populated ? globalUtil.adjustedInterval : cascadeSettings.initialFeedRate
  26. property bool populated: false
  27. property bool paused: false
  28. property real columnRatio: globalSettings.useGoldenRatio ? globalVars.goldenRatio : globalSettings.lessGoldenRatio
  29. property real pace: 1.0/30.0
  30. property real columnWidth: root.width*globalUtil.columnWidthRatio(d.columnRatio, globalSettings.columnCount)
  31. }
  32. Repeater {
  33. model: globalSettings.columnCount
  34. delegate: columnComponent
  35. }
  36. Component {
  37. id: columnComponent
  38. Item {
  39. id: column
  40. property int stackHeight: 0
  41. property int xOffset: d.columnWidth/globalUtil.columnWidthRatio(d.columnRatio, index)
  42. property var pictureArray: []
  43. property var pictureQueue: []
  44. property bool full: {
  45. var fullStack = stackHeight > (1.3 + 1/globalSettings.columnCount)*root.height
  46. !d.populated && fullStack && (index === (globalSettings.columnCount - 1)) && (d.populated = true)
  47. return fullStack
  48. }
  49. function addExistingImage(image) {
  50. image.width = width
  51. image.x = image.y = index*-1000
  52. image.linearVelocity.x = image.linearVelocity.y = 0.0
  53. image.beyondThePale.connect(removeImage)
  54. stackHeight += image.height
  55. image.x = xOffset
  56. image.y = index == 0 ? root.height - stackHeight : -stackHeight - pictureArray.length*10
  57. image.world = isolatedWorld
  58. pictureArray.push(image)
  59. }
  60. function addImage() {
  61. var image = pictureDelegate.createObject(column)
  62. addExistingImage(image)
  63. globalUtil.itemCount++
  64. }
  65. function removeImage(image) {
  66. image.beyondThePale.disconnect(removeImage)
  67. if (index === (globalSettings.columnCount - 1)) {
  68. image.destroy()
  69. globalUtil.itemCount--
  70. } else {
  71. columnArray[index+1].pictureQueue.push(image)
  72. }
  73. }
  74. function shift() {
  75. var image = pictureArray.shift()
  76. image.world = image.world.limbo
  77. stackHeight -= image.height
  78. }
  79. width: {
  80. var colWidth = d.columnWidth*Math.pow(d.columnRatio, index);
  81. (index === (globalSettings.columnCount - 1)) && (globalVars.imageWidthOverride = colWidth)
  82. return colWidth
  83. }
  84. anchors { top: parent.top; bottom: parent.bottom }
  85. World {
  86. id: isolatedWorld
  87. timeStep: d.pace
  88. running: true
  89. property var limbo: World {
  90. timeStep: isolatedWorld.timeStep
  91. running: isolatedWorld.running
  92. }
  93. }
  94. RectangleBoxBody {
  95. id: floor
  96. world: isolatedWorld
  97. height: 0
  98. width: parent.width
  99. x: xOffset
  100. anchors {
  101. top: parent.bottom
  102. }
  103. friction: 1
  104. }
  105. Timer {
  106. id: pumpTimer
  107. interval: d.feedrate
  108. repeat: true && !d.paused
  109. running: true
  110. onTriggered: {
  111. if (index === 0) {
  112. addImage()
  113. } else {
  114. pictureQueue.length && addExistingImage(pictureQueue.shift())
  115. }
  116. }
  117. }
  118. Timer {
  119. id: deathTimer
  120. running: full
  121. repeat: true
  122. interval: d.feedrate
  123. onTriggered: shift()
  124. }
  125. Connections {
  126. target: root
  127. onTogglePause: d.paused = !d.paused
  128. onNext: deathTimer.triggered()
  129. }
  130. Component.onCompleted: {
  131. columnArray.push(this)
  132. }
  133. }
  134. }
  135. Keys.onUpPressed: d.paused = !d.paused
  136. Keys.onDownPressed: root.drain()
  137. Component.onCompleted: {
  138. pictureDelegate.status !== Component.Ready && console.log('Component failed with:' + pictureDelegate.errorString())
  139. }
  140. }