Conveyor.qml 5.7 KB

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