Conveyor.qml 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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()*conveyorSettings.forceFudgeFactor*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. property real friction: 0.02
  87. property int forceFudgeFactor: 1
  88. }
  89. Component {
  90. id: imageDelegate
  91. ArtBoxBody {
  92. signal murder(var item)
  93. categories: Box.Category2
  94. collidesWith: Box.Category1 | Box.Category2 | Box.Category3
  95. density: 1
  96. height: root.height/conveyorSettings.rowCount
  97. width: height*imageModel.data(modelIndex, PictureModel.RatioRole)
  98. bodyType: Body.Dynamic
  99. fixedRotation: true
  100. onXChanged: {
  101. if (x + width > floor.width) {
  102. fixedRotation = false
  103. }
  104. }
  105. onYChanged: {
  106. if (y > viewport.height) {
  107. murder(this)
  108. }
  109. }
  110. }
  111. }
  112. Item {
  113. id: viewport
  114. width: root.width*conveyorSettings.rowCount
  115. height: root.height/conveyorSettings.rowCount
  116. World {
  117. id: theWorld
  118. running: true
  119. timeStep: 1/20
  120. }
  121. DebugDraw {
  122. world: theWorld
  123. anchors.fill: parent
  124. visible: false
  125. enabled: visible
  126. }
  127. RectangleBoxBody {
  128. id: floor
  129. categories: Box.Category3
  130. collidesWith: Box.Category2
  131. world: theWorld
  132. height: 0
  133. width: parent.width - root.width/4
  134. anchors {
  135. top: parent.bottom
  136. }
  137. friction: conveyorSettings.friction
  138. }
  139. }
  140. Timer {
  141. id: feedTimer
  142. repeat: true
  143. running: true
  144. interval: 200
  145. onTriggered: {
  146. spawnImage()
  147. }
  148. }
  149. ShaderEffectSource {
  150. id: viewportTexture
  151. property int textureDimension: conveyorSettings.constrainToPi ? d.piMaxTextureSize : d.nvidiaMaxTextureSize
  152. sourceItem: viewport
  153. width: viewport.width
  154. height: viewport.height
  155. hideSource: true
  156. live: true
  157. textureSize: Qt.size(textureDimension,textureDimension/root.width*root.height)
  158. }
  159. ShaderEffect {
  160. anchors.fill: parent
  161. property real rowCount: conveyorSettings.rowCount
  162. property variant source: viewportTexture
  163. fragmentShader: "
  164. varying highp vec2 qt_TexCoord0;
  165. uniform sampler2D source;
  166. uniform lowp float qt_Opacity;
  167. uniform lowp float rowCount;
  168. void main() {
  169. highp vec2 tc;
  170. lowp float row = floor(qt_TexCoord0.t * rowCount);
  171. tc.s = qt_TexCoord0.s / rowCount + row / rowCount;
  172. tc.t = mod(qt_TexCoord0.t, 1.0 / rowCount) * rowCount;
  173. lowp vec4 tex = texture2D(source, tc);
  174. gl_FragColor = vec4(tex.rgb, 1.0);
  175. }
  176. "
  177. }
  178. }