Browse Source

- fixed SlidingActor zero delta time
- added new function testIntersection for per pixel intersection testing
- minor

dmuratshin 10 years ago
parent
commit
6594e74b32

+ 3 - 3
.hg_archival.txt

@@ -1,6 +1,6 @@
 repo: b6d71054df5712e643a0685bc3ba54b123db5729
-node: c8c8aaff672dd00da7bfbc646b2e280e70c3df63
+node: 9ac72d76aab8acc05831e02da9266f9ad686d9be
 branch: default
 latesttag: oldrender
-latesttagdistance: 930
-changessincelatesttag: 1084
+latesttagdistance: 938
+changessincelatesttag: 1092

+ 59 - 8
examples/Demo/src/TestDrag.h

@@ -15,21 +15,70 @@ public:
 class DragTest: public Test
 {
 public:
+
+    spSprite sprites[3];
+    spActor contacts;
+    int priority;
+
     DragTest()
     {
+        priority = 0;
+
+        Vector2 pos[3];
+        pos[0] = Vector2(425, 420);
+        pos[1] = Vector2(600, 225);
+        pos[2] = Vector2(305, 170);
+
         for (int i = 0; i < 3; ++i)
         {
             spSprite sprite = new DraggableSprite;
-            Vector2 pos(100.0f * (i + 1), 150.0f);
-            sprite->setPosition(pos);
+            sprite->setPosition(pos[i]);
             sprite->setResAnim(resources.getResAnim("batterfly"));
             sprite->attachTo(content);
 
-            sprite->setRotation(scalar::randFloat(0, (float)MATH_PI * 2));
-            sprite->setScale(scalar::randFloat(1.0f, 2.0f));
+            float angle = scalar::randFloat(0, (float)MATH_PI * 2);
+            sprite->setRotation(angle);
+            sprite->addTween(Actor::TweenRotation(MATH_PI * 2 + angle), 30000, -1);
+            sprite->setScale(scalar::randFloat(1.0f, 1.5f));
+            sprite->setAnchor(0.5f, 0.5f);
 
             sprite->addEventListener(TouchEvent::TOUCH_DOWN, CLOSURE(this, &DragTest::onMouseDown));
             sprite->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &DragTest::onMouseUp));
+
+            sprites[i] = sprite;
+        }
+
+        contacts = new Actor;
+        contacts->attachTo(content);
+        contacts->setPriority(10000);
+        contacts->setInputChildrenEnabled(false);
+    }
+
+    void doUpdate(const UpdateState& us)
+    {
+        //check intersections between sprites and visualize contact points
+        for (int i = 0; i < 3; ++i)
+        {
+            spSprite a = sprites[i];
+
+            for (int n = 0; n < 3; ++n)
+            {
+                spSprite b = sprites[n];
+                if (a == b)
+                    continue;
+
+                Vector2 contact;
+                if (testIntersection(a, b, 0, &contact))
+                {
+                    spSprite c = new Sprite;
+                    c->setAnchor(0.5f, 0.5f);
+                    c->setResAnim(resources.getResAnim("snow"));
+                    c->addTween(Actor::TweenAlpha(0), 300)->setDetachActor(true);
+                    Vector2 pos = convert_local2global(a, content, contact);
+                    c->setPosition(pos);
+                    c->attachTo(contacts);
+                }
+            }
         }
     }
 
@@ -37,16 +86,18 @@ public:
     {
         spActor actor = safeSpCast<Actor>(event->currentTarget);
 
-        int new_priority = actor->getParent()->getLastChild()->getPriority() + 1;
-        actor->setPriority(new_priority);
+        //show clicked sprite on top
+        actor->setPriority(priority++);
 
-        actor->addTween(Sprite::TweenColor(Color(255, 0, 0, 255)), 300, -1, true);
+        spTween t = actor->addTween(Sprite::TweenColor(Color::Red), 300, -1, true);
+        t->setName("color");
     }
 
     void onMouseUp(Event* event)
     {
         spSprite actor = safeSpCast<Sprite>(event->currentTarget);
-        actor->removeTweens();
+
+        actor->removeTween(actor->getTween("color"));
         actor->setColor(Color::White);
     }
 };

+ 57 - 6
examples/Demo/src/TestTouches.h

@@ -23,25 +23,76 @@ public:
         //orange->setAlpha(200);
         orange->addEventListener(TouchEvent::OVER, CLOSURE(this, &TestTouches::onOver));
         orange->addEventListener(TouchEvent::OUT, CLOSURE(this, &TestTouches::onOver));
+        orange->addEventListener(TouchEvent::TOUCH_DOWN, CLOSURE(this, &TestTouches::onDownUp));
+        orange->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &TestTouches::onDownUp));
+        orange->addEventListener(TouchEvent::MOVE, CLOSURE(this, &TestTouches::onMove));
 
         spTextField tf = new TextField;
-        tf->setText("out");
+        tf->setText("");
         tf->setColor(Color::Black);
-        tf->setName("txt");
-        tf->setX(10);
+        tf->setName("state1");
+        tf->setX(5);
         tf->setY(5);
         tf->attachTo(orange);
 
+        tf = new TextField;
+        tf->setText("");
+        tf->setColor(Color::Black);
+        tf->setName("state2");
+        tf->setX(35);
+        tf->setY(5);
+        tf->attachTo(orange);
+
+        tf = new TextField;
+        tf->setText("");
+        tf->setColor(Color::Black);
+        tf->setName("local");
+        tf->setX(5);
+        tf->setY(25);
+        tf->setMultiline(true);
+        tf->setWidth(orange->getWidth());
+        tf->attachTo(orange);
+
         return orange;
     }
 
     void onOver(Event* ev)
     {
         spSprite s = safeSpCast<Sprite>(ev->currentTarget);
-        spTextField tf = s->getChildT<TextField>("txt");
-        tf->setText(ev->type == TouchEvent::OVER ? "over" : "out");
+        spTextField tf = s->getChildT<TextField>("state1");
+        tf->setText(ev->type == TouchEvent::OVER ? "over" : "");
+        updateLocalPos(ev);
+    }
+
+    void onDownUp(Event* ev)
+    {
+        spSprite s = safeSpCast<Sprite>(ev->currentTarget);
+        spTextField tf = s->getChildT<TextField>("state2");
+        tf->setText(ev->type == TouchEvent::TOUCH_DOWN ? "pressed" : "");
+        updateLocalPos(ev);
     }
 
+    void updateLocalPos(Event* ev)
+    {
+        spSprite s = safeSpCast<Sprite>(ev->currentTarget);
+        spTextField tf = s->getChildT<TextField>("local");
+
+        if (ev->type != TouchEvent::OUT)
+        {
+            TouchEvent* te = safeCast<TouchEvent*>(ev);
+            char str[255];
+            safe_sprintf(str, "loc.pos: %d,%d", (int)te->localPosition.x, (int)te->localPosition.y);
+            tf->setText(str);
+        }
+        else
+            tf->setText("");
+    }
+    void onMove(Event* ev)
+    {
+        updateLocalPos(ev);
+    }
+
+
 
     TestTouches()
     {
@@ -56,7 +107,7 @@ public:
         spSprite Orange = createRect("Orange", Color::Orange, Vector2(200, 200), Vector2(300, 300));
         Orange->attachTo(content);
 
-        spSprite Green = createRect("Green", Color::Green, Vector2(100, 25), Vector2(100, 100));
+        spSprite Green = createRect("Green", Color::Green, Vector2(100, 25), Vector2(100, 150));
         Green->attachTo(Orange);
 
         spSprite Beige = createRect("Beige", Color::Beige, Vector2(150, 150), Vector2(250, 100));

+ 1 - 1
examples/Demo/src/example.cpp

@@ -57,7 +57,7 @@ public:
         addButton("tweens", "Tweens");
         addButton("text", "Text");
         addButton("progress_bar", "Progress Bar");
-        addButton("drag", "Drag and Drop");
+        addButton("drag", "Drag and Drop with Test Intersections");
         addButton("drag2", "Drag and Drop2");
         addButton("hittest", "Alpha Hit Test");
         addButton("perf", "Performance");

+ 1 - 0
oxygine/SDL/android/lib/src/org/oxygine/lib/OxygineActivity.java

@@ -43,6 +43,7 @@ public class OxygineActivity extends SDLActivity {
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
         _observable.onActivityResult(requestCode, resultCode, data);
     }
 

+ 165 - 0
oxygine/src/Actor.cpp

@@ -1339,4 +1339,169 @@ namespace oxygine
         actor->setPosition(pos);
         actor->attachTo(newParent);
     }
+
+
+
+
+    class OBB2D
+    {
+    private:
+        /** Corners of the box, where 0 is the lower left. */
+        Vector2         corner[4];
+
+        /** Two edges of the box extended away from corner[0]. */
+        Vector2         axis[2];
+
+        /** origin[a] = corner[0].dot(axis[a]); */
+        double          origin[2];
+
+        /** Returns true if other overlaps one dimension of this. */
+        bool overlaps1Way(const OBB2D& other) const
+        {
+            for (int a = 0; a < 2; ++a)
+            {
+
+                float t = other.corner[0].dot(axis[a]);
+
+                // Find the extent of box 2 on axis a
+                float tMin = t;
+                float tMax = t;
+
+                for (int c = 1; c < 4; ++c)
+                {
+                    t = other.corner[c].dot(axis[a]);
+
+                    if (t < tMin)
+                    {
+                        tMin = t;
+                    }
+                    else if (t > tMax)
+                    {
+                        tMax = t;
+                    }
+                }
+
+                // We have to subtract off the origin
+
+                // See if [tMin, tMax] intersects [0, 1]
+                if ((tMin > 1 + origin[a]) || (tMax < origin[a]))
+                {
+                    // There was no intersection along this dimension;
+                    // the boxes cannot possibly overlap.
+                    return false;
+                }
+            }
+
+            // There was no dimension along which there is no intersection.
+            // Therefore the boxes overlap.
+            return true;
+        }
+
+
+        /** Updates the axes after the corners move.  Assumes the
+        corners actually form a rectangle. */
+        void computeAxes()
+        {
+            axis[0] = corner[1] - corner[0];
+            axis[1] = corner[3] - corner[0];
+
+            // Make the length of each axis 1/edge length so we know any
+            // dot product must be less than 1 to fall within the edge.
+
+            for (int a = 0; a < 2; ++a)
+            {
+                axis[a] /= axis[a].sqlength();
+                origin[a] = corner[0].dot(axis[a]);
+            }
+        }
+
+    public:
+
+        OBB2D(const RectF& rect, const AffineTransform& tr)
+        {
+            corner[0] = tr.transform(rect.getLeftTop());
+            corner[1] = tr.transform(rect.getRightTop());
+            corner[2] = tr.transform(rect.getRightBottom());
+            corner[3] = tr.transform(rect.getLeftBottom());
+
+            computeAxes();
+        }
+
+        /** Returns true if the intersection of the boxes is non-empty. */
+        bool overlaps(const OBB2D& other) const
+        {
+            return overlaps1Way(other) && other.overlaps1Way(*this);
+        }
+    };
+
+
+
+    extern int HIT_TEST_DOWNSCALE;
+
+    bool testIntersection(spActor objA, spActor objB, spActor parent, Vector2* contact)
+    {
+        float s1 = objB->getSize().x * objB->getSize().y;
+        float s2 = objA->getSize().x * objA->getSize().y;
+        bool swapped = false;
+        if (s2 < s1)
+        {
+            swapped = true;
+            std::swap(objA, objB);
+        }
+
+        Renderer::transform transA = getGlobalTransform(objA, parent);
+        Renderer::transform transB = getGlobalTransform(objB, parent);
+        //Renderer::transform transBInv = getGlobalTransform(objB, parent);
+        transB.invert();
+        Renderer::transform n = transA * transB;
+
+        AffineTransform ident;
+        ident.identity();
+
+        OBB2D a(objB->getDestRect(), ident);
+        OBB2D b(objA->getDestRect(), n);
+        if (!a.overlaps(b))
+            return false;
+
+        /*
+        float s1 = objB->getSize().x * objB->getSize().y;
+        float s2 = objA->getSize().x * objA->getSize().y;
+        bool swapped = false;
+        if (s2 < s1)
+        {
+            swapped = true;
+            std::swap(objA, objB);
+            std::swap(transA, transB);
+            n = transA * transB;
+        }
+
+        */
+
+
+        int w = (int)objA->getWidth();
+        int h = (int)objA->getHeight();
+
+
+        for (int y = 0; y < w; y += HIT_TEST_DOWNSCALE)
+        {
+            for (int x = 0; x < h; x += HIT_TEST_DOWNSCALE)
+            {
+                Vector2 posA = Vector2(float(x), float(y));
+
+                if (!objA->isOn(posA))
+                    continue;
+
+                Vector2 posB = n.transform(posA);
+
+                if (!objB->isOn(posB))
+                    continue;
+
+                if (contact)
+                    *contact = swapped ? posB : posA;
+                return true;
+            }
+        }
+
+        return false;
+    }
 }

+ 2 - 0
oxygine/src/Actor.h

@@ -374,6 +374,8 @@ namespace oxygine
     /**Deprecated*/
     inline Vector2 convert_root2local(spActor child, const Vector2& pos, spActor root = 0) { return convert_stage2local(child, pos, root); }
 
+    /*Tests 2 actors intersection and returns contact point in space of object1.*/
+    bool testIntersection(spActor obj1, spActor obj2, spActor commonParent = 0, Vector2* contact = 0);
 
 
     Renderer::transform getGlobalTransform(spActor child, spActor parent = 0);

+ 6 - 0
oxygine/src/Draggable.cpp

@@ -56,6 +56,7 @@ namespace oxygine
         _actor(0),
         _clientPos(0, 0),
         _dragPos(0, 0),
+        _startTm(0),
         _clientIsParent(false),
         _dragEnabled(true),
         _pressed(false),
@@ -111,6 +112,7 @@ namespace oxygine
 
     void Draggable::startDrag(const Vector2& localCenter)
     {
+        _startTm = getTimeMS();
         _pressed = true;
         _dragPos = localCenter;
         _clientPos = _dragClient->getPosition();
@@ -166,6 +168,10 @@ namespace oxygine
             {
                 _pressed = false;
                 _actor->_getStage()->removeEventListeners(this);
+                if (getTimeMS() - _startTm < 2)
+                {
+                    _actor->setPosition(_clientPos);
+                }
             }
             break;
 

+ 1 - 1
oxygine/src/Draggable.h

@@ -43,7 +43,7 @@ namespace oxygine
 
         Actor* _dragClient;
         Actor* _actor;
-
+        timeMS _startTm;
         bool _singleDrag;
 
         RectF _bounds;

+ 3 - 0
oxygine/src/Polygon.cpp

@@ -3,6 +3,8 @@
 #include "RenderState.h"
 #include "core/VertexDeclaration.h"
 #include <sstream>
+#include "core/UberShaderProgram.h"
+#include "STDRenderer.h"
 
 namespace oxygine
 {
@@ -101,4 +103,5 @@ namespace oxygine
             rs.renderer->addVertices(&buff.front(), buff.size());
         }
     }
+
 }

+ 3 - 0
oxygine/src/Polygon.h

@@ -15,6 +15,9 @@ namespace oxygine
         Polygon();
         ~Polygon();
 
+        /**
+        if *own* is true Polygon will delete[] data array;
+        */
         void setVertices(const void* data, int size, int bformat, bool own);
 
         void serialize(serializedata* data);

+ 2 - 5
oxygine/src/STDRenderer.cpp

@@ -123,10 +123,7 @@ namespace oxygine
         ShaderProgram* prog = _uberShader->getShaderProgram(_shaderFlags)->program;
         setShader(prog);
 
-        _driver->setTexture(UberShaderProgram::SAMPLER_BASE, _base);
-
-        if (_alpha)
-            _driver->setTexture(UberShaderProgram::SAMPLER_ALPHA, _alpha);
+        _uberShader->apply(_base, _alpha);
 
         UberShaderProgramBase::ShaderUniformsCallback cb = _uberShader->getShaderUniformsCallback();
         if (cb)
@@ -211,7 +208,7 @@ namespace oxygine
         addVertices(v, sizeof(v));
     }
 
-    void STDRenderer::setUberShaderProgram(UberShaderProgramBase* pr)
+    void STDRenderer::setUberShaderProgram(UberShaderProgram* pr)
     {
         if (_uberShader != pr)
         {

+ 2 - 2
oxygine/src/STDRenderer.h

@@ -11,7 +11,7 @@ namespace oxygine
         /**Sets blend mode. Default value is blend_premultiplied_alpha*/
         void draw(const RState* rs, const Color&, const RectF& srcRect, const RectF& destRect) OVERRIDE;
 
-        void setUberShaderProgram(UberShaderProgramBase* pr);
+        void setUberShaderProgram(UberShaderProgram* pr);
 
         void setBlendMode(blend_mode blend);
         /**Sets texture. If texture is null White texture would be used.*/
@@ -35,7 +35,7 @@ namespace oxygine
 
         blend_mode _blend;
 
-        UberShaderProgramBase* _uberShader;
+        UberShaderProgram* _uberShader;
         unsigned int _shaderFlags;
     };
 

+ 28 - 19
oxygine/src/SlidingActor.cpp

@@ -2,7 +2,7 @@
 #include "ClipRectActor.h"
 #include "PointerState.h"
 #include "UpdateState.h"
-#include "Draggable.h"
+//#include "Draggable.h"
 #include "initActor.h"
 #include "Serialize.h"
 
@@ -77,6 +77,23 @@ namespace oxygine
             _content->detach();
         }
 
+        _downTime = 0;
+
+        _current = 0;
+        _lastIterTime = 0;
+        _sliding = false;
+
+        //_prev[0].pos = _content->getPosition();
+        //_prev[0].tm = tm;
+
+        for (int i = 0; i < NUM; ++i)
+            _prev[i].tm = 0;
+
+        _holded = 0; //event->target;
+        //_downPos = te->localPosition;
+        //_downTime = tm;
+
+
         _speed = Vector2(0, 0);
 
         _content = content;
@@ -246,35 +263,27 @@ namespace oxygine
                     if (!mid)
                         mid = last;
 
+
+
                     Vector2 midpos = mid->pos;
                     Vector2 dir = pos - midpos;
                     if (dir.sqlength() < 10 * 10)
                         _speed = Vector2(0, 0);
                     else
                     {
-                        Vector2 dr = pos - old->pos;
                         timeMS v = tm - old->tm;
-                        OX_ASSERT(v);
-                        if (v)
-                        {
-                            Vector2 ns = (dr * 1000.0f) / v;
+                        if (!v)
+                            return;
 
-                            /*
-                            int d = tm - _downTime;
-                            Vector2 dr2 = pos - _downPos;
-                            Vector2 ts = dr2 / float(d) * 1000.0f;
-                            ts.x = 0;
+                        Vector2 dr = pos - old->pos;
 
-                            log::messageln("fs: %.2f %d ns: %.2f %d", ns.y, int(tm), ts.y, d);
-                            */
-                            //ns = ts;
+                        Vector2 ns = (dr * 1000.0f) / v;
 
+                        if (_speed.dot(ns) < 0)
+                            _speed = ns;
+                        else
+                            _speed += ns;
 
-                            if (_speed.dot(ns) < 0)
-                                _speed = ns;
-                            else
-                                _speed += ns;
-                        }
                     }
 
 

+ 3 - 3
oxygine/src/core/Object.h

@@ -26,7 +26,7 @@ namespace oxygine
         virtual ~ObjectBase();
 
         const std::string&  getName() const;
-        void*               getUserData() const {return __userData;}
+        const void*         getUserData() const {return __userData;}
         int                 getObjectID()const {return __id;}
         bool                isName(const std::string& name) const;
         bool                isName(const char* name) const;
@@ -34,7 +34,7 @@ namespace oxygine
 
 
         void setName(const std::string& name);
-        void setUserData(void* data) {__userData = data;}
+        void setUserData(const void* data) {__userData = data;}
 
         void dumpObject() const;
 
@@ -69,7 +69,7 @@ namespace oxygine
         void __freeName() const;
 
         int __id;
-        void* __userData;
+        const void* __userData;
 
 
 #ifdef OXYGINE_DEBUG_TRACE_LEAKS

+ 12 - 0
oxygine/src/core/UberShaderProgram.cpp

@@ -2,6 +2,7 @@
 #include "vertex.h"
 #include "gl/VideoDriverGLES20.h"
 #include "gl/ShaderProgramGL.h"
+#include "NativeTexture.h"
 
 namespace oxygine
 {
@@ -123,4 +124,15 @@ namespace oxygine
             s.program = 0;
         }
     }
+
+    void UberShaderProgram::apply(spNativeTexture base, spNativeTexture alpha)
+    {
+        //STDRenderer
+        IVideoDriver* driver = IVideoDriver::instance;
+
+        driver->setTexture(UberShaderProgram::SAMPLER_BASE, base);
+
+        if (alpha)
+            driver->setTexture(UberShaderProgram::SAMPLER_ALPHA, alpha);
+    }
 }

+ 8 - 1
oxygine/src/core/UberShaderProgram.h

@@ -1,12 +1,15 @@
 #pragma once
 #include <vector>
 #include "Restorable.h"
+#include "Object.h"
 //#include <unordered_map>
 
 namespace oxygine
 {
     class ShaderProgram;
     class IVideoDriver;
+    DECLARE_SMART(NativeTexture, spNativeTexture);
+
 
     class UberShaderProgramBase: public Restorable
     {
@@ -26,9 +29,11 @@ namespace oxygine
         void release();
 
         typedef Closure<void (IVideoDriver*, ShaderProgram*)> ShaderUniformsCallback;
+
+        ShaderUniformsCallback  getShaderUniformsCallback() const { return _cb; }
         void setShaderUniformsCallback(ShaderUniformsCallback cb) {_cb = cb;}
 
-        ShaderUniformsCallback  getShaderUniformsCallback() const {return _cb;}
+
         virtual shader*         getShaderProgram(int flags) = 0;
 
 
@@ -67,6 +72,8 @@ namespace oxygine
 
         shader*                 getShaderProgram(int flags);
 
+        void apply(spNativeTexture base, spNativeTexture alpha);
+
     protected:
         void releaseShaders() OVERRIDE;
         shader _shaders[SIZE];

+ 1 - 1
oxygine/src/initActor.h

@@ -60,7 +60,7 @@ namespace oxygine
         typedef argT<Color, const Color&, VStyleActor, &VStyleActor::setColor> color;
         typedef argT<blend_mode, blend_mode, VStyleActor, &VStyleActor::setBlendMode> blend;
         typedef argT<short, short, Actor, &Actor::setPriority> priority;
-        typedef argT<void*, void*, ObjectBase, &ObjectBase::setUserData> userData;
+        typedef argT<const void*, const void*, ObjectBase, &ObjectBase::setUserData> userData;
         typedef argT<char, char, Actor, &Actor::setExtendedClickArea> extendedClickArea;
 
         typedef argT<TextStyle, const TextStyle&, TextField, &TextField::setStyle> style;