Browse Source

Introduce Conveyor art view

Change-Id: I9c68ccf873f552a286d5f19fe6e107f6fd83f0dd
Donald Carr 8 years ago
parent
commit
1036b7ef8c

+ 0 - 7
qml/basic/Basic.qml

@@ -51,10 +51,6 @@ View {
                 function addImage() {
                     var image = pictureDelegate.createObject(artworkStack)
 
-                    if (globalSettings.effect !== "" && Effects.validate(globalSettings.effect)) {
-                        image.effect = effectDelegate.createObject(artworkStack, { target: image, effect: globalSettings.effect })
-                    }
-
                     artworkHeight += image.height
                     compoundArtworkHeight += image.height
                     image.y = root.height - compoundArtworkHeight
@@ -64,9 +60,6 @@ View {
                 }
 
                 function removeImage(image) {
-                    if (image.effect) {
-                        image.effect.destroy()
-                    }
                     image.destroy()
                     globalUtil.itemCount--
                 }

+ 9 - 0
qml/common/ArtImage.qml

@@ -1,7 +1,10 @@
 import QtQuick 2.5
 import PictureModel 1.0
 
+import ".."
+
 Rectangle {
+    id: root
     property var effect
     property int modelIndex
 
@@ -11,6 +14,7 @@ Rectangle {
     width: parent.width
 
     Image {
+        id: image
         opacity: 0
         anchors.fill: parent
         asynchronous: true
@@ -37,5 +41,10 @@ Rectangle {
 
     Component.onCompleted: {
         modelIndex = Math.floor(Math.random()*imageModel.count)
+        if (globalSettings.effect !== "" && Effects.validate(globalSettings.effect)) {
+            var component = Qt.createComponent("VisualEffect.qml");
+            component.status !== Component.Ready && console.log('Component failed with:' + effectDelegate.errorString())
+            root.effect = component.createObject(root, { target: image, effect: globalSettings.effect })
+        }
     }
 }

+ 0 - 3
qml/common/View.qml

@@ -7,9 +7,6 @@ Item {
     property var pictureDelegate: Component {
         ArtImage {}
     }
-    property var effectDelegate: Component {
-        VisualEffect {}
-    }
 
     function reset() {
         columnArray = []

+ 177 - 0
qml/conveyor/Conveyor.qml

@@ -0,0 +1,177 @@
+import QtQuick 2.7
+import Box2D 2.0
+import Qt.labs.settings 1.0
+import PictureModel 1.0
+
+import ".."
+
+Item {
+    id: root
+
+    anchors.fill: parent
+    property var pictureArray: []
+    property var nextImage
+
+    ImageBoxBody {
+        id: foot
+        world: theWorld
+        density: 20000
+        bodyType: Body.Dynamic
+        x: -width
+        anchors.verticalCenter: viewport.verticalCenter
+        rotation: -90
+        mirror: true
+        fixedRotation: true
+        z: 10
+        source: "qrc:/Monty_python_foot.png"
+        sourceSize.height: viewport.height
+        sourceSize.width: viewport.height/foot.implicitHeight*foot.implicitWidth
+        Behavior on x { SmoothedAnimation{ duration: conveyorSettings.footAnimationTime } }
+        Component.onCompleted: {
+            foot.body.gravityScale = 0
+        }
+    }
+
+    SequentialAnimation {
+        id: stomp
+        running: false
+        ScriptAction { script: foot.x = pictureArray[pictureArray.length-1].x*1.1 }
+        NumberAnimation { duration: conveyorSettings.footAnimationTime }
+        // linger
+        NumberAnimation { duration: 2*conveyorSettings.footAnimationTime }
+        ScriptAction { script: foot.x = -foot.width - 10 }
+        NumberAnimation { duration: conveyorSettings.footAnimationTime }
+    }
+
+    function spawnImage() {
+        if (stomp.running)
+            return
+
+        if (!nextImage) {
+            nextImage = imageDelegate.createObject(viewport, { y: -10000 });
+        }
+
+        if (pictureArray.length > 0 && pictureArray[pictureArray.length-1].x < nextImage.width) {
+            var body = pictureArray[pictureArray.length-1].body
+            if (body.linearVelocity.y < 0.001) {
+                stomp.start()
+            }
+        } else {
+            nextImage.murder.connect(removeImage)
+            nextImage.y = -nextImage.height
+            nextImage.world = theWorld
+
+            pictureArray.push(nextImage)
+            nextImage = null
+        }
+    }
+
+    function removeImage(image)
+    {
+        pictureArray.splice(pictureArray.indexOf(image),1)
+        image.destroy()
+    }
+
+    Settings {
+        id: conveyorSettings
+        category: "Conveyor"
+
+        property int rowCount: 6
+        property int footAnimationTime: 500
+    }
+
+    Component {
+        id: imageDelegate
+        ArtBoxBody {
+            signal murder(var item)
+
+            density: 1
+            height: root.height/conveyorSettings.rowCount
+            width: height*imageModel.data(modelIndex, PictureModel.RatioRole)
+            bodyType: Body.Dynamic
+            fixedRotation: true
+
+            onXChanged: {
+                if (x < 0) {
+                    murder(this)
+                } else if (x + width > floor.width) {
+                    fixedRotation = false
+                }
+            }
+
+            onYChanged: {
+                if (y > viewport.height) {
+                    murder(this)
+                }
+            }
+        }
+    }
+
+    Item {
+        id: viewport
+
+        width: root.width*conveyorSettings.rowCount
+        height: root.height/conveyorSettings.rowCount
+
+        World {
+            id: theWorld
+            running: true
+            timeStep: 1/20
+        }
+
+        DebugDraw {
+            world: theWorld
+            anchors.fill: parent
+            visible: false
+            enabled: visible
+        }
+
+        RectangleBoxBody {
+            id: floor
+            world: theWorld
+            height: 0
+            width: parent.width - 400
+            anchors {
+                top: parent.bottom
+            }
+            friction: 0
+        }
+    }
+
+    Timer {
+        id: feedTimer
+        repeat: true
+        running: true
+        interval: 100
+        onTriggered: {
+            spawnImage()
+        }
+    }
+
+    ShaderEffectSource {
+        id: viewportTexture
+        sourceItem: viewport
+        width: viewport.width
+        height: viewport.height
+    }
+
+    ShaderEffect {
+        anchors.fill: parent
+        property real rowCount: conveyorSettings.rowCount
+        property variant source: viewportTexture
+        fragmentShader: "
+            varying lowp vec2 qt_TexCoord0;
+            uniform sampler2D source;
+            uniform lowp float qt_Opacity;
+            uniform lowp float rowCount;
+            void main() {
+                lowp vec2 tc;
+                lowp float row = floor(qt_TexCoord0.t * rowCount);
+                tc.s = qt_TexCoord0.s / rowCount + row / rowCount;
+                tc.t = mod(qt_TexCoord0.t, 1.0 / rowCount) * rowCount;
+                lowp vec4 tex = texture2D(source, tc);
+                gl_FragColor = vec4(tex.rgb, 1.0);
+            }
+        "
+    }
+}

+ 1 - 9
qml/main.qml

@@ -57,7 +57,7 @@ Window {
         property int interval: 5
         property bool viewItemCount: false
         property string effect: ""
-        property string view: "Physics"
+        property string view: "Conveyor"
         property bool smoothArt: false
         property bool randomlyMirrorArt: true
         property bool fullscreen: true
@@ -124,12 +124,4 @@ Window {
     Component.onCompleted: {
         globalSettings.fullscreen ? showFullScreen() : show()
     }
-
-    /*Connections {
-        target: imageModel
-        onCountChanged: {
-            //console.log('Count adjusted to:' + imageModel.count)
-            console.log('Image model data:' + imageModel.get(0))
-        }
-    }*/
 }

+ 54 - 0
qml/physics/ArtBoxBody.qml

@@ -0,0 +1,54 @@
+import QtQuick 2.0
+import Box2D 2.0
+
+import ".."
+
+ArtImage {
+    id: image
+
+    property alias body: boxBody
+    property alias fixture: box
+
+    // Body properties
+    property alias world: boxBody.world
+    property alias linearDamping: boxBody.linearDamping
+    property alias angularDamping: boxBody.angularDamping
+    property alias bodyType: boxBody.bodyType
+    property alias bullet: boxBody.bullet
+    property alias sleepingAllowed: boxBody.sleepingAllowed
+    property alias fixedRotation: boxBody.fixedRotation
+    property alias active: boxBody.active
+    property alias awake: boxBody.awake
+    property alias linearVelocity: boxBody.linearVelocity
+    property alias angularVelocity: boxBody.angularVelocity
+    property alias fixtures: boxBody.fixtures
+    property alias gravityScale: boxBody.gravityScale
+
+    // Box properties
+    property alias density: box.density
+    property alias friction: box.friction
+    property alias restitution: box.restitution
+    property alias sensor: box.sensor
+    property alias categories: box.categories
+    property alias collidesWith: box.collidesWith
+    property alias groupIndex: box.groupIndex
+
+    signal beginContact(Fixture other)
+    signal endContact(Fixture other)
+
+    Body {
+        id: boxBody
+
+        target: image
+
+        Box {
+            id: box
+
+            width: image.width
+            height: image.height
+
+            onBeginContact: image.beginContact(other)
+            onEndContact: image.endContact(other)
+        }
+    }
+}

+ 30 - 0
qml/physics/BoxBody.qml

@@ -0,0 +1,30 @@
+import Box2D 2.0
+
+Body {
+    id: body
+
+    property alias fixture: box
+
+    property alias density: box.density
+    property alias friction: box.friction
+    property alias restitution: box.restitution
+    property alias sensor: box.sensor
+    property alias categories: box.categories
+    property alias collidesWith: box.collidesWith
+    property alias groupIndex: box.groupIndex
+
+    property alias x: box.x
+    property alias y: box.y
+    property alias width: box.width
+    property alias height: box.height
+
+    signal beginContact(Fixture other)
+    signal endContact(Fixture other)
+
+    Box {
+        id: box
+
+        onBeginContact: body.beginContact(other)
+        onEndContact: body.endContact(other)
+    }
+}

+ 3 - 5
qml/physics/ImageBoxBody.qml

@@ -1,9 +1,7 @@
 import QtQuick 2.0
 import Box2D 2.0
 
-import ".."
-
-ArtImage {
+Image {
     id: image
 
     property alias body: boxBody
@@ -44,8 +42,8 @@ ArtImage {
         Box {
             id: box
 
-            width: image.width
-            height: image.height
+            width:  image.width/1.05
+            height: image.height/1.05
 
             onBeginContact: image.beginContact(other)
             onEndContact: image.endContact(other)

+ 6 - 0
qml/physics/RectangleBoxBody.qml

@@ -31,6 +31,9 @@ Rectangle {
     property alias collidesWith: box.collidesWith
     property alias groupIndex: box.groupIndex
 
+    signal beginContact(Fixture other)
+    signal endContact(Fixture other)
+
     Body {
         id: boxBody
 
@@ -41,6 +44,9 @@ Rectangle {
 
             width: rectangle.width
             height: rectangle.height
+
+            onBeginContact: rectangle.beginContact(other)
+            onEndContact: rectangle.endContact(other)
         }
     }
 }

+ 5 - 2
qml/qml.qrc

@@ -3,10 +3,13 @@
         <file>main.qml</file>
         <file>qmldir</file>
         <file>common/VisualEffect.qml</file>
-        <file>physics/ArtDelegate.qml</file>
+        <file>physics/BoxBody.qml</file>
         <file>physics/ImageBoxBody.qml</file>
+        <file>physics/ArtBoxBody.qml</file>
         <file>physics/RectangleBoxBody.qml</file>
-        <file>physics/Physics.qml</file>
+        <file>well/WellDelegate.qml</file>
+        <file>well/Well.qml</file>
+        <file>conveyor/Conveyor.qml</file>
         <file>basic/Basic.qml</file>
         <file>effects/Effect.qml</file>
         <file>effects/Billboard.qml</file>

+ 4 - 0
qml/qmldir

@@ -2,3 +2,7 @@ singleton Effects 1.0 effects/Effects.qml
 ArtImage 1.0 common/ArtImage.qml
 VisualEffect 1.0 common/VisualEffect.qml
 View 1.0 common/View.qml
+ImageBoxBody 1.0 physics/ImageBoxBody.qml
+ArtBoxBody 1.0 physics/ArtBoxBody.qml
+RectangleBoxBody 1.0 physics/RectangleBoxBody.qml
+BoxBody 1.0 physics/BoxBody.qml

+ 1 - 9
qml/physics/Physics.qml → qml/well/Well.qml

@@ -12,7 +12,7 @@ View {
     signal next
 
     property var pictureDelegate: Component {
-        ArtDelegate {}
+        WellDelegate {}
     }
 
     Settings {
@@ -67,10 +67,6 @@ View {
             function addImage() {
                 var image = pictureDelegate.createObject(column, { x: -1000, y: -1000 })
 
-                if (globalSettings.effect !== "" && Effects.validate(globalSettings.effect)) {
-                    image.effect = effectDelegate.createObject(column, { target: image, effect: globalSettings.effect })
-                }
-
                 image.beyondThePale.connect(removeImage)
                 image.world = physicsSettings.globalWorld ? world : isolatedWorld
                 image.x = xOffset
@@ -82,9 +78,6 @@ View {
             }
 
             function removeImage(image) {
-                if (image.effect) {
-                    image.effect.destroy()
-                }
                 stackHeight -= image.height
                 image.destroy()
                 globalUtil.itemCount--
@@ -187,6 +180,5 @@ View {
 
     Component.onCompleted: {
         pictureDelegate.status !== Component.Ready && console.log('Component failed with:' + pictureDelegate.errorString())
-        effectDelegate.status !== Component.Ready && console.log('Component failed with:' + effectDelegate.errorString())
     }
 }

+ 3 - 2
qml/physics/ArtDelegate.qml → qml/well/WellDelegate.qml

@@ -2,11 +2,12 @@ import QtQuick 2.5
 import Box2D 2.0
 import Qt.labs.settings 1.0
 
-ImageBoxBody {
+import ".."
+
+ArtBoxBody {
     id: picture
 
     signal beyondThePale(var item)
-    property var effect
 
     onYChanged: {
         if (y > globalFloor.y) {

BIN
resources/Monty_python_foot.png


+ 1 - 0
resources/resources.qrc

@@ -1,6 +1,7 @@
 <RCC>
     <qresource prefix="/">
         <file>qt_logo_green_rgb.png</file>
+        <file>Monty_python_foot.png</file>
         <file>shaders/billboard.fsh</file>
         <file>shaders/emboss.fsh</file>
         <file>shaders/gaussianblur_h.fsh</file>