Conveyor.qml 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import QtQuick 2.7
  2. import Box2D 2.0
  3. import Qt.labs.settings 1.0
  4. import PictureModel 1.0
  5. import ".."
  6. Item {
  7. id: root
  8. anchors.fill: parent
  9. property var pictureArray: []
  10. property var nextImage
  11. QtObject {
  12. id: d
  13. property int footStartingX: -50 - foot.width
  14. property int mountingDesperation: 1
  15. readonly property int piMaxTextureSize: 2048
  16. readonly property int nvidiaMaxTextureSize: 8192
  17. readonly property int nvidiaMaxTextureSizeTheoretical: 16384
  18. }
  19. ImageBoxBody {
  20. id: foot
  21. categories: Box.Category1
  22. collidesWith: Box.Category2
  23. world: theWorld
  24. density: 200000
  25. bodyType: Body.Dynamic
  26. x: d.footStartingX
  27. anchors.verticalCenter: viewport.verticalCenter
  28. fixedRotation: true
  29. z: 10
  30. source: "qrc:/Monty_python_foot.png"
  31. height: viewport.height
  32. width: viewport.height/foot.implicitHeight*foot.implicitWidth
  33. sourceSize.height: height
  34. sourceSize.width: width
  35. Behavior on x { SmoothedAnimation{ duration: conveyorSettings.footAnimationTime } }
  36. Component.onCompleted: {
  37. foot.body.gravityScale = 0
  38. }
  39. onBeginContact: {
  40. var body = pictureArray[pictureArray.length-1].body
  41. var impulseStrength = body.getMass()*d.mountingDesperation*Math.sqrt((pictureArray.length+1)/conveyorSettings.rowCount)
  42. body.applyLinearImpulse(Qt.point(impulseStrength,0), Qt.point(0,0));
  43. withdrawlBoot()
  44. }
  45. }
  46. function bootImage() {
  47. d.mountingDesperation += 1
  48. foot.active = true;
  49. foot.x = pictureArray[pictureArray.length-1].x*2
  50. }
  51. function withdrawlBoot() {
  52. foot.active = false;
  53. foot.x = d.footStartingX
  54. }
  55. function spawnImage() {
  56. if (foot.x != d.footStartingX)
  57. return
  58. if (!nextImage) {
  59. nextImage = imageDelegate.createObject(viewport, { y: -10000 });
  60. }
  61. if (pictureArray.length > 0 && pictureArray[pictureArray.length-1].x < nextImage.width) {
  62. var body = pictureArray[pictureArray.length-1].body
  63. if ((body.linearVelocity.y < 0.001) && (body.linearVelocity.x < 1)) {
  64. bootImage()
  65. }
  66. } else {
  67. nextImage.murder.connect(removeImage)
  68. nextImage.y = -nextImage.height
  69. nextImage.world = theWorld
  70. pictureArray.push(nextImage)
  71. nextImage = null
  72. d.mountingDesperation = 1
  73. }
  74. }
  75. function removeImage(image)
  76. {
  77. pictureArray.splice(pictureArray.indexOf(image),1)
  78. image.destroy()
  79. }
  80. Settings {
  81. id: conveyorSettings
  82. category: "Conveyor"
  83. property int rowCount: 6
  84. property int footAnimationTime: 500
  85. property bool constrainToPi: false
  86. }
  87. Component {
  88. id: imageDelegate
  89. ArtBoxBody {
  90. signal murder(var item)
  91. categories: Box.Category2
  92. collidesWith: Box.Category1 | Box.Category2 | Box.Category3
  93. density: 1
  94. height: root.height/conveyorSettings.rowCount
  95. width: height*imageModel.data(modelIndex, PictureModel.RatioRole)
  96. bodyType: Body.Dynamic
  97. fixedRotation: true
  98. onXChanged: {
  99. if (x + width > floor.width) {
  100. fixedRotation = false
  101. }
  102. }
  103. onYChanged: {
  104. if (y > viewport.height) {
  105. murder(this)
  106. }
  107. }
  108. }
  109. }
  110. Item {
  111. id: viewport
  112. width: root.width*conveyorSettings.rowCount
  113. height: root.height/conveyorSettings.rowCount
  114. World {
  115. id: theWorld
  116. running: true
  117. timeStep: 1/20
  118. }
  119. DebugDraw {
  120. world: theWorld
  121. anchors.fill: parent
  122. visible: false
  123. enabled: visible
  124. }
  125. RectangleBoxBody {
  126. id: floor
  127. categories: Box.Category3
  128. collidesWith: Box.Category2
  129. world: theWorld
  130. height: 0
  131. width: parent.width - root.width/4
  132. anchors {
  133. top: parent.bottom
  134. }
  135. friction: 0.02
  136. }
  137. }
  138. Timer {
  139. id: feedTimer
  140. repeat: true
  141. running: true
  142. interval: 200
  143. onTriggered: {
  144. spawnImage()
  145. }
  146. }
  147. ShaderEffectSource {
  148. id: viewportTexture
  149. property int textureDimension: conveyorSettings.constrainToPi ? d.piMaxTextureSize : d.nvidiaMaxTextureSize
  150. sourceItem: viewport
  151. width: viewport.width
  152. height: viewport.height
  153. hideSource: true
  154. live: true
  155. textureSize: Qt.size(textureDimension,textureDimension/root.width*root.height)
  156. }
  157. ShaderEffect {
  158. anchors.fill: parent
  159. property real rowCount: conveyorSettings.rowCount
  160. property variant source: viewportTexture
  161. fragmentShader: "
  162. varying highp vec2 qt_TexCoord0;
  163. uniform sampler2D source;
  164. uniform lowp float qt_Opacity;
  165. uniform lowp float rowCount;
  166. void main() {
  167. highp vec2 tc;
  168. lowp float row = floor(qt_TexCoord0.t * rowCount);
  169. tc.s = qt_TexCoord0.s / rowCount + row / rowCount;
  170. tc.t = mod(qt_TexCoord0.t, 1.0 / rowCount) * rowCount;
  171. lowp vec4 tex = texture2D(source, tc);
  172. gl_FragColor = vec4(tex.rgb, 1.0);
  173. }
  174. "
  175. }
  176. }