Conveyor.qml 5.8 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. // Forgive me
  6. import "../.."
  7. Item {
  8. id: root
  9. anchors.fill: parent
  10. property var pictureArray: []
  11. property var nextImage
  12. QtObject {
  13. id: d
  14. property int footStartingX: -50 - foot.width
  15. property int mountingDesperation: 1
  16. readonly property int piMaxTextureSize: 2048
  17. readonly property int nvidiaMaxTextureSize: 8192
  18. readonly property int nvidiaMaxTextureSizeTheoretical: 16384
  19. property int feedGapFudgeFactor: 100
  20. }
  21. ImageBoxBody {
  22. id: foot
  23. categories: Box.Category1
  24. collidesWith: Box.Category2
  25. world: theWorld
  26. density: 200000
  27. bodyType: Body.Dynamic
  28. x: d.footStartingX
  29. anchors.verticalCenter: viewport.verticalCenter
  30. fixedRotation: true
  31. z: 10
  32. source: "Monty_python_foot.png"
  33. height: viewport.height
  34. width: viewport.height/foot.implicitHeight*foot.implicitWidth
  35. sourceSize.height: height
  36. sourceSize.width: width
  37. Behavior on x { SmoothedAnimation{ duration: conveyorSettings.footAnimationTime } }
  38. Component.onCompleted: {
  39. foot.body.gravityScale = 0
  40. }
  41. onBeginContact: {
  42. var body = pictureArray[pictureArray.length-1].body
  43. var impulseStrength = body.getMass()*Math.sqrt(conveyorSettings.rowCount)*3*d.mountingDesperation*Math.sqrt((pictureArray.length+1)/conveyorSettings.rowCount)
  44. body.applyLinearImpulse(Qt.point(impulseStrength,0), Qt.point(0,0));
  45. withdrawlBoot()
  46. }
  47. }
  48. function bootImage() {
  49. d.mountingDesperation += 1
  50. foot.active = true;
  51. foot.x = pictureArray[pictureArray.length-1].x*2
  52. }
  53. function withdrawlBoot() {
  54. foot.active = false;
  55. foot.x = d.footStartingX
  56. }
  57. function spawnImage() {
  58. if (foot.x != d.footStartingX)
  59. return
  60. if (!nextImage) {
  61. nextImage = imageDelegate.createObject(viewport, { y: -10000 });
  62. }
  63. if (pictureArray.length > 0 && pictureArray[pictureArray.length-1].x < nextImage.width) {
  64. var body = pictureArray[pictureArray.length-1].body
  65. if ((body.linearVelocity.y < 0.001) && (body.linearVelocity.x < 1)) {
  66. bootImage()
  67. }
  68. } else {
  69. nextImage.murder.connect(removeImage)
  70. nextImage.y = -nextImage.height
  71. nextImage.world = theWorld
  72. pictureArray.push(nextImage)
  73. nextImage = null
  74. d.mountingDesperation = 1
  75. }
  76. }
  77. function removeImage(image)
  78. {
  79. pictureArray.splice(pictureArray.indexOf(image),1)
  80. image.destroy()
  81. }
  82. Settings {
  83. id: conveyorSettings
  84. category: "Conveyor"
  85. property int rowCount: 4
  86. property int footAnimationTime: 500
  87. property bool constrainToPi: false
  88. property real friction: 0.01
  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.SizeRole).height*imageModel.data(modelIndex, PictureModel.SizeRole).width
  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. sourceItem: viewport
  153. width: viewport.width
  154. height: viewport.height
  155. hideSource: true
  156. live: true
  157. textureSize: conveyorSettings.constrainToPi ? Qt.size(d.piMaxTextureSize,d.piMaxTextureSize/root.width*root.height) : undefined
  158. }
  159. ShaderEffect {
  160. anchors.fill: parent
  161. property real rowCount: conveyorSettings.rowCount
  162. property variant source: viewportTexture
  163. blending: false
  164. cullMode: ShaderEffect.BackFaceCulling
  165. fragmentShader: "
  166. varying highp vec2 qt_TexCoord0;
  167. uniform sampler2D source;
  168. uniform lowp float qt_Opacity;
  169. uniform lowp float rowCount;
  170. void main() {
  171. highp vec2 tc;
  172. lowp float row = floor(qt_TexCoord0.t * rowCount);
  173. tc.s = qt_TexCoord0.s / rowCount + row / rowCount;
  174. tc.t = mod(qt_TexCoord0.t, 1.0 / rowCount) * rowCount;
  175. lowp vec4 tex = texture2D(source, tc);
  176. gl_FragColor = vec4(tex.rgb, 1.0);
  177. }
  178. "
  179. }
  180. }