kevinresol / gessie

Gesture Recognition Library for Haxe
MIT License
9 stars 3 forks source link

some more examples or code snippets #2

Open bluelemonade opened 5 years ago

bluelemonade commented 5 years ago

hello I found your gestouch port for haxe. I got the simple gesture to work, but zoom and freetransform won't run. Is it possible to get some more examples for this. haxe/openfl should have an stable multitouch library.

regards

kevinresol commented 5 years ago

The heaps sample contains ZoomGesture code

bluelemonade commented 5 years ago

thanks for your fast answer,

I got this: src/gessie/impl/heaps/HeapsDisplayListAdapter.hx:5: characters 7-17 : Type not found : h2d.Object

I imported the classes:

import gessie.gesture.PanGesture;
import gessie.gesture.SwipeGesture;
import gessie.gesture.TapGesture;
import gessie.gesture.ZoomGesture;
import gessie.gesture.RotateGesture;
import gessie.gesture.TransformGesture;
import gessie.impl.heaps.HeapsDisplayListAdapter;
import gessie.impl.heaps.HeapsInputAdapter;
import gessie.impl.heaps.HeapsTouchHitTester;
import gessie.core.Gessie;

then I put an image insde a sprite1

```

Gessie.init(s2d, new HeapsInputAdapter(s2d)); Gessie.addDisplayListAdapter(h2d.Sprite, new HeapsDisplayListAdapter()); Gessie.addTouchHitTester(new HeapsTouchHitTester(s2d));

var zoom = new ZoomGesture(sprite1);
    zoom.on(GEChanged, function(_) {
                        sprite1.scaleX=zoom.scaleX;
                        sprite1.scaleY=zoom.scaleY;
                    });
    var rotate = new RotateGesture(sprite1);
    rotate.on(GEChanged, function(_) sprite1.rotation=rotate.rotation);

i am using actual openfl and lime libs.

regards

josuigoa commented 5 years ago

if you are using OpenFL you cannot use Heaps specific classes, you should take those classes from the gessie.impl.openfl.*.

So, this:

Gessie.init(s2d, new HeapsInputAdapter(s2d));
Gessie.addDisplayListAdapter(h2d.Sprite, new HeapsDisplayListAdapter());
Gessie.addTouchHitTester(new HeapsTouchHitTester(s2d));

should be this:

Gessie.init(stage, new OpenflInputAdapter(stage, true, true));
Gessie.addDisplayListAdapter(DisplayObject, new OpenflDisplayListAdapter());
Gessie.addTouchHitTester(new OpenflTouchHitTester(stage));
kevinresol commented 5 years ago

Obviously you can't use a heaps adapter in openfl

bluelemonade commented 5 years ago

oh, you're fast, I check it later this evening, thank you, the OpenflDisplayListAdapter is although a package of Gessie?

bluelemonade commented 5 years ago

it works, thanks, now how can I do a free transform?

bluelemonade commented 5 years ago

the rotate and zoom gesture snaps back when releasing the finger from the screen, how can I prevent this?

what I am look for is although an method the prevent zoom when the touchpoint leaves the image area, like in the original gestouch. is this possible to check if the touchpoint are inside the sprite?

bluelemonade commented 5 years ago

Hi, I got the freetransform, but it although rotates at the topleft corner. is it possible to get the middle of the two touchpoints, though I could do a matrixtranformation on this point, should be simple.

regards.

kevinresol commented 5 years ago

I assume you are using TransformGesture, but I fail to see how that relates to the pivot point of your sprite

The gesture object only gives you the transformation data and doesn't manipulate your display object

bluelemonade commented 5 years ago

when using the original gestouch you have a matrix on the flash event target, I can simple rotate at the actual "virtual" middle of these point.

in as3 it looks like this.

    const gesture:TransformGesture = event.target as TransformGesture;
    var matrix:Matrix = event.target.target.transform.matrix;
        const _x:Number = event.target.target.x;
    const _y:Number = event.target.target.y;

            if (gesture.scale != 1) {   //  || gesture.rotation != 0

                // Scale and rotation.
                var transformPoint:Point = matrix.transformPoint(event.target.target.globalToLocal(gesture.location));
                matrix.translate(-transformPoint.x, -transformPoint.y);
                // matrix.rotate(gesture.rotation);

                // lastGestureRotate = gesture.rotation
                // lastGestureScale = gesture.scale;
                matrix.scale(gesture.scale, gesture.scale);

                matrix.translate(transformPoint.x, transformPoint.y);
                event.target.target.transform.matrix = matrix;

                // trace (event.target.target.width);

                // nicht zu klein machen
                if (event.target.target.width < baseWidth) {
                    event.target.target.width = baseWidth;
                    event.target.target.scaleY = event.target.target.scaleX;
                    event.target.target.x = baseX;
                    event.target.target.y = baseY;
                } else if (event.target.target.scaleX > maxImageScale) {
                    event.target.target.scaleX = maxImageScale;
                    event.target.target.scaleY = maxImageScale;
                    event.target.target.x = _x;
                    event.target.target.y = _y;
                }

            }

ok, in openfl, when using the offsetX/Y I can move the sprite around with two fingers, thats fine. but it rotates and scale from the left top corner. Ok I can center the bitmap in the sprite, but that is not the problem the sprite should rotate around every point I touch, when in the bottom right it should not rotate in the middle, it should rotate around thart point.

var transi = new TransformGesture(sprite1); transi.on(GEChanged, function(_) {

var m:Matrix = sprite1.transform.matrix.clone(); var point:Point = new Point(transi.offsetX, transi.offsetY); sprite1.transform.matrix = m;

sprite1.scaleX=transi.scale; sprite1.scaleY=transi.scale; var grad = 90* transi.rotation; sprite1.rotation = grad;

kevinresol commented 5 years ago

~In that case I guess exposing a var center:Point, which is the average of the two touches, could solve your problem?~

Edit: well actually there is location already which is exactly the thing

bluelemonade commented 5 years ago

I thought its the global virtual touchpoint? I have a look into matrix, I think I can get it the two touchpoint, the positon of the sprite...

kevinresol commented 5 years ago

I think gessie/gestouch has no concept of matrix.

Maybe can you specify what API is missing in this port vs the the original AS3 gestouch library?

bluelemonade commented 5 years ago

yes, I hace to do the matrix on sprite area, like in the original gestouch.

kevinresol commented 5 years ago

ok, then I assume this one is done.

bluelemonade commented 5 years ago

Hi,

here's my final code, it works great under html5, when comiling to cpp I it works woth two fingers, when using one finger I get scaling and rotation problem. Have you seen this issue on windows touch? I implemented a touchPointCounter (touchCnt) in the TransformGesture.hx, and got with one finger dragging around almoust 2 points back. ( the scaling and rotation is flickering around. Any ideas where I can filter the touchpoints?

package;

import openfl.display.Sprite;
import openfl.display.DisplayObject;
import openfl.display.Bitmap;
import openfl.utils.Assets;
import openfl.events.IOErrorEvent;
import openfl.events.MouseEvent;
import openfl.events.TouchEvent;
import openfl.geom.Matrix;
import openfl.geom.Point;
import openfl.events.Event;

import gessie.gesture.PanGesture;
import gessie.gesture.SwipeGesture;
import gessie.gesture.TapGesture;
import gessie.gesture.ZoomGesture;
import gessie.gesture.RotateGesture;
import gessie.gesture.TransformGesture;
import gessie.impl.openfl.OpenflDisplayListAdapter;
import gessie.impl.openfl.OpenflInputAdapter;
import gessie.impl.openfl.OpenflTouchHitTester;
import gessie.core.Gessie;

class Main extends Sprite {

    var  lastscale:Float = 1.0;

    public function new () {

        super ();

        if (stage != null)
            start();
        else
            addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    }

    private function onAddedToStage(event:Dynamic):Void {
        removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
        start();
    }

    private function start():Void {

        var bitmapData2 = Assets.getBitmapData("assets/xxx.jpg");
        var bitmap2 = new Bitmap(bitmapData2);
        bitmap2.smoothing = true;
        bitmap2.x = -bitmap2.width/2;
        bitmap2.y = -bitmap2.height/2;
        var  sprite2 = new Sprite();
        sprite2.addChild(bitmap2);
        sprite2.x = 500;
        sprite2.y = 500;
        sprite2.scaleX = 0.3;
        sprite2.scaleY = 0.3;
        addChild(sprite2);
        sprite2.alpha = 1.0;
        sprite2.rotation = 0;

        Gessie.init(stage, new OpenflInputAdapter(stage, true, true));
        Gessie.addDisplayListAdapter(DisplayObject, new OpenflDisplayListAdapter());
        Gessie.addTouchHitTester(new OpenflTouchHitTester(stage));

        var trans2 = new TransformGesture(sprite2);
        trans2.on(GEBegan, function(_) {
            trace ("GEBegan"); 
        } );
        trans2.on(GEEnded, function(_) {
            lastscale = 1.0;
            trace ("GEEnded"); 
        } );
        trans2.on(GECancelled, function(_) {
            trace ("GECancelled"); 
        });
        trans2.on(GEChanged, function(_) {

            //trans2.location.x, trans2.location.y, trans2.offsetY, trans2.offsetY,     
            // trace (trans2.rotation, trans2.scale, trans2.touchCnt); 
            if (trans2.scale < 0.5)
                return;

            var m:Matrix = sprite2.transform.matrix.clone(); // var _x = sprite2.x;
            var _x = trans2.location.x; // var _y = sprite2.y;
            var _y = trans2.location.y;
            var _r = sprite2.rotation * Math.PI / 180;
            var _s = sprite2.scaleX; 

            // if (trans2.touchCnt == 2){

                if (trans2.rotation == 0){
                } else {
                    var grad = trans2.rotation * 180 / Math.PI;
                    var grad =  Math.PI /  trans2.rotation;
                    m.translate(  -1 *(_x) , -1*(_y )  );    

                    // scale 
                    m.scale(1 + trans2.scale - lastscale,1 + trans2.scale -lastscale);
                    lastscale = trans2.scale;

                    // ROTATION
                    m.rotate(trans2.rotation - _r);

                    m.translate(  (_x ) , (_y ) );
                }

            // }

            // PAN
            m.translate(trans2.offsetX, trans2.offsetY);

            sprite2.transform.matrix = m;   

        } );        
    }
}
kevinresol commented 5 years ago

@josuigoa I suspect it should fire GSEnd instead of GSChanged here: https://github.com/kevinresol/gessie/blob/937ea4d/src/gessie/gesture/TransformGesture.hx#L121

@bluelemonade There is touchesCount already, you don't need to reimplement it

kevinresol commented 5 years ago

@josuigoa sorry please ignore my previous comment, I can see that it is for resuming the gesture from one touch. But then I don't have much idea on the problem.

@bluelemonade I don't understand why you mentioned one finger. The TransformGesture is supposed to be using 2 fingers, can you elaborate on the matter?

bluelemonade commented 5 years ago

yes, but when I touch with one finger, user do this, and move it, the transformgesture is fired! that's the error, something isn't filtered correctly. when I have both gesture, transform an pan, only the transform is fired with corrupted scale and rotations, and the sprite gets small.