Browse Source

- refactored Touches event handling model
- added new Demo TestTouches

dmuratshin 10 years ago
parent
commit
20458e8c80

+ 3 - 3
.hg_archival.txt

@@ -1,6 +1,6 @@
 repo: b6d71054df5712e643a0685bc3ba54b123db5729
-node: b9dd79f275e2251d86f594fee90711ba0f5e98ce
+node: 7f0868edc42569894d9ed4d66efe234bbbdbdd5d
 branch: default
 latesttag: oldrender
-latesttagdistance: 907
-changessincelatesttag: 1059
+latesttagdistance: 923
+changessincelatesttag: 1075

+ 1 - 0
examples/Demo/proj.win32/Demo.vcxproj

@@ -141,6 +141,7 @@
     <ClInclude Include="../src/TestUserShader2.h" />
     <ClInclude Include="../src/example.h" />
     <ClInclude Include="../src/test.h" />
+    <ClInclude Include="..\src\TestTouches.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 3 - 0
examples/Demo/proj.win32/Demo.vcxproj.filters

@@ -104,5 +104,8 @@
     <ClInclude Include="../src/test.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\TestTouches.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>

+ 9 - 0
examples/Demo/src/TestAlphaHitTest.h

@@ -27,6 +27,7 @@ public:
 
         sprite->addEventListener(TouchEvent::OVER, CLOSURE(this, &TestAlphaHitTest::onEvent));
         sprite->addEventListener(TouchEvent::OUT, CLOSURE(this, &TestAlphaHitTest::onEvent));
+        sprite->setInputChildrenEnabled(false);
 
         txt = new TextField;
         txt->attachTo(content);
@@ -39,6 +40,7 @@ public:
 
     void onEvent(Event* ev)
     {
+        TouchEvent* te = safeCast<TouchEvent*>(ev);
         if (ev->type == TouchEvent::OVER)
         {
             txt->setText("Mouse is OVER");
@@ -49,5 +51,12 @@ public:
             txt->setText("Mouse is OUT");
             sprite->setColor(Color::White);
         }
+
+        spSprite sp = new Sprite;
+        sp->setResAnim(resources.getResAnim("snow"));
+        sp->setAnchor(0.5f, 0.5f);
+        sp->setScale(0.5f);
+        sp->setPosition(te->localPosition);
+        sp->attachTo(sprite);
     }
 };

+ 140 - 0
examples/Demo/src/TestTouches.h

@@ -0,0 +1,140 @@
+#pragma once
+#include "test.h"
+
+class TestTouches: public Test
+{
+public:
+    spTextField txtMove;
+    spTextField txtClick;
+    spTextField txtUp;
+    float y;
+    int n;
+
+    spTextField click;
+
+    spSprite createRect(const char* name, const Color& color, const Vector2& pos, const Vector2& size)
+    {
+        spSprite orange = new ColorRectSprite;
+        orange->setColor(color);
+        orange->setName(name);
+        orange->setSize(size);
+        orange->setPosition(pos);
+        orange->attachTo(content);
+        //orange->setAlpha(200);
+        orange->addEventListener(TouchEvent::OVER, CLOSURE(this, &TestTouches::onOver));
+        orange->addEventListener(TouchEvent::OUT, CLOSURE(this, &TestTouches::onOver));
+
+        spTextField tf = new TextField;
+        tf->setText("out");
+        tf->setColor(Color::Black);
+        tf->setName("txt");
+        tf->setX(10);
+        tf->setY(5);
+        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");
+    }
+
+
+    TestTouches()
+    {
+        y = 0;
+        n = 0;
+
+        txtClick = createTF(Color::White);
+        txtUp = createTF(Color::Green);
+        txtMove = createTF(Color::Yellow);
+
+
+        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));
+        Green->attachTo(Orange);
+
+        spSprite Beige = createRect("Beige", Color::Beige, Vector2(150, 150), Vector2(250, 100));
+        Beige->attachTo(Orange);
+
+        spSprite LightGreen = createRect("LightGreen", Color::LightGreen, Vector2(180, -50), Vector2(50, 200));
+        LightGreen->attachTo(Beige);
+
+
+        spActor target = Orange;
+
+        target->addEventListener(TouchEvent::CLICK, CLOSURE(this, &TestTouches::event));
+        target->addEventListener(TouchEvent::MOVE, CLOSURE(this, &TestTouches::event));
+        target->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &TestTouches::event));
+    }
+
+    spTextField createTF(const Color& c)
+    {
+        spTextField tf = new TextField;
+        tf->attachTo(content);
+        tf->setWidth(300);
+        tf->setColor(c);
+        tf->setX(content->getWidth() - tf->getWidth());
+        tf->setY(y);
+        tf->setMultiline(true);
+        tf->setFont(Test::resourcesUI.getResFont("big")->getFont());
+        y += 200;
+        return tf;
+    }
+
+
+    void event(Event* ev)
+    {
+        TouchEvent* te = safeCast<TouchEvent*>(ev);
+
+
+        spTextField tf;
+        const char* eventName = "";
+        if (te->type == TouchEvent::CLICK)
+        {
+            tf = txtClick;
+            eventName = "CLICK";
+            notify("click");
+        }
+
+        if (te->type == TouchEvent::MOVE)
+        {
+            tf = txtMove;
+            eventName = "MOVE";
+        }
+
+        if (te->type == TouchEvent::TOUCH_UP)
+        {
+            tf = txtUp;
+            eventName = "UP";
+            notify("up");
+        }
+
+        char str[512];
+        safe_sprintf(str,
+                     "%d)touch event: %s\n"
+                     "target: %s\n"
+                     "position: %d %d\n"
+                     "\n"
+                     "current target: %s\n"
+                     "local position: %d %d\n"
+                     ,
+                     n,
+                     eventName,
+                     te->target->getName().c_str(),
+                     (int)te->position.x, (int)te->position.y,
+                     te->currentTarget->getName().c_str(),
+                     (int)te->localPosition.x, (int)te->localPosition.y
+
+                    );
+
+
+        tf->setText(str);
+        ++n;
+    }
+};

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

@@ -23,6 +23,7 @@
 #include "TestCounter.h"
 #include "TestTweenText.h"
 #include "TestTweenShine.h"
+#include "TestTouches.h"
 
 #ifdef __S3E__
 #include "s3eKeyboard.h"
@@ -32,7 +33,8 @@ using namespace oxygine;
 
 
 //it is our resources
-//in real project you would have more than one Resources declarations. It is important on mobile devices with limited memory and you would load/unload them
+//in real project you would have more than one Resources declarations.
+//It is important on mobile devices with limited memory and you would load/unload them
 Resources resources;
 
 //#define MULTIWINDOW 1
@@ -63,6 +65,7 @@ public:
         addButton("texture_format", "Textures Format");
         addButton("r2t", "Render to Texture");
         addButton("t2p", "Texel to Pixel");
+        addButton("touches", "Touches");
         addButton("sliding", "Sliding Actor");
         addButton("box9sprite", "Box9 Sprite");
         addButton("cliprect", "ClipRect Actor");
@@ -150,6 +153,11 @@ public:
             showTest(new TestTexel2Pixel);
         }
 
+        if (id == "touches")
+        {
+            showTest(new TestTouches);
+        }
+
         if (id == "box9sprite")
         {
             showTest(new TestBox9Sprite);

+ 1 - 1
examples/Demo/src/test.h

@@ -14,7 +14,7 @@ spButton createButtonHelper(spButton, const std::string& txt, EventCallback cb);
 class Content: public Actor
 {
 public:
-    Content(): driver(0) {}
+    Content() : driver(0) { setName("content"); }
     IVideoDriver* driver;
 
     void render(const RenderState& parentRS)

+ 78 - 123
oxygine/src/Actor.cpp

@@ -248,140 +248,103 @@ namespace oxygine
         return _overred;
     }
 
-    void Actor::setPressed(pointer_index v)
+    void Actor::setNotPressed()
     {
-        if (_pressed == v)
-            return;
-        pointer_index old = _pressed;
-        _pressed = v;
+        _pressed = 0;
+        _getStage()->removeEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &Actor::_onGlobalTouchUpEvent));
 
-        //spMouseEvent
-        //dispatchEvent()
+        updateState();
+    }
 
-        if (v)
-        {
-            _getStage()->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &Actor::_onMouseEvent));
-            //printf("added\n");
-        }
-        else
-            _getStage()->removeEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &Actor::_onMouseEvent));
+    void Actor::_onGlobalTouchUpEvent(Event* ev)
+    {
+        TouchEvent* te = safeCast<TouchEvent*>(ev);
+        if (te->index != _pressed)
+            return;
 
-        if (!old)
-            updateState();
+        setNotPressed();
+
+        TouchEvent up = *te;
+        up.bubbles = false;
+        up.localPosition = convert_global2local(this, _getStage(), te->localPosition);
+        dispatchEvent(&up);
     }
 
-    void Actor::setOverred(pointer_index v)
+    void Actor::_onGlobalTouchMoveEvent(Event* ev)
     {
-        if (_overred == v)
+        TouchEvent* te = safeCast<TouchEvent*>(ev);
+        if (te->index != _overred)
             return;
 
-        pointer_index old = _overred;
-        _overred = v;
+        if (isDescendant(safeCast<Actor*>(ev->target.get())))
+            return;
 
-        if (v)
-        {
-            TouchEvent e(TouchEvent::OVER);
-            e.index = v;
-            dispatchEvent(&e);
+        _overred = 0;
+        _getStage()->removeEventListener(TouchEvent::MOVE, CLOSURE(this, &Actor::_onGlobalTouchMoveEvent));
 
-            _getStage()->addEventListener(TouchEvent::MOVE, CLOSURE(this, &Actor::_onMouseEvent));
-        }
-        else
-        {
-            _getStage()->removeEventListener(TouchEvent::MOVE, CLOSURE(this, &Actor::_onMouseEvent));
-            //if (!_overed)
-            {
-                TouchEvent e(TouchEvent::OUT);
-                e.index = old;
-                dispatchEvent(&e);
-            }
-        }
+        TouchEvent up = *te;
+        up.type = TouchEvent::OUT;
+        up.bubbles = false;
+        up.localPosition = convert_global2local(this, _getStage(), te->localPosition);
+        dispatchEvent(&up);
+        //log::messageln("out %s", getName().c_str());
 
-        if (!old)
-            updateState();
+        updateState();
     }
 
-    void Actor::_onMouseEvent(Event* event)
+    void Actor::dispatchEvent(Event* event)
     {
-        TouchEvent* me = safeCast<TouchEvent*>(event);
-        Actor* act = safeCast<Actor*>(event->target.get());
+        EventDispatcher::dispatchEvent(event);
 
-        switch (event->type)
+
+        if (event->type == TouchEvent::MOVE)
         {
-            case  TouchEvent::TOUCH_DOWN:
-                if (isDescendant(act))
-                {
-                    setPressed(me->index);
-                    //_pressed = me->id;
-                    //setPressed(true);
-                }
-                break;
-            case  TouchEvent::TOUCH_UP:
+            TouchEvent* te = safeCast<TouchEvent*>(event);
+            if (!_overred)
             {
-                //if (_pressed))
-                {
-                    if (_pressed == me->index)
-                    {
-                        setPressed(0);
-                        //it is event from ROOT, convert to local space
-                        Vector2 lp = convert_global2local(this, _getStage(), me->localPosition);
-                        if (isDescendant(act))
-                        {
-                            TouchEvent e(TouchEvent::CLICK, true, lp);
-                            e.index = me->index;
-                            dispatchEvent(&e);
-                        }
-                        else
-                        {
-                            dispatchEvent(event);
-                        }
-                    }
-                }
-            }
-            break;
-            case  TouchEvent::MOVE:
-            {
-                if (isDescendant(act))
-                {
-                    if (!_overred)
-                    {
-                        setOverred(me->index);
-
-                        /*
-                        if (event->phase == Event::phase_target)
-                        {
-                            _getStage()->removeEventListener(TouchEvent::MOVE, CLOSURE(this, &Actor::_onMouseEvent));
-                            _getStage()->addEventListener(TouchEvent::MOVE, CLOSURE(this, &Actor::_onMouseEvent));
-                        }
-                        */
-                    }
-                }
-                else
-                {
-                    if (_overred == me->index)
-                        setOverred(0);
-                }
+                _overred = te->index;
+                updateState();
+
+                TouchEvent over = *te;
+                over.type = TouchEvent::OVER;
+                over.bubbles = false;
+                dispatchEvent(&over);
+
+                _getStage()->addEventListener(TouchEvent::MOVE, CLOSURE(this, &Actor::_onGlobalTouchMoveEvent));
             }
-            break;
         }
 
-    }
+        if (event->type == TouchEvent::TOUCH_DOWN)
+        {
+            TouchEvent* te = safeCast<TouchEvent*>(event);
+            if (!_pressed)
+            {
+                _pressed = te->index;
+                _getStage()->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &Actor::_onGlobalTouchUpEvent));
 
-    void Actor::dispatchEvent(Event* event)
-    {
-        spEventDispatcher prevTarget = event->target;
-        if (prevTarget == 0 || event->currentTarget != 0)
-            event->target = this;
+                updateState();
+            }
+        }
 
+        TouchEvent click(0);
 
-        //event->currentTarget = this;
+        if (event->type == TouchEvent::TOUCH_UP)
+        {
+            TouchEvent* te = safeCast<TouchEvent*>(event);
+            if (_pressed == te->index)
+            {
+                click = *te;
+                click.type = TouchEvent::CLICK;
+                click.bubbles = false;
+                //will be dispatched later after UP
 
-        EventDispatcher::dispatchEvent(event);
+                setNotPressed();
+            }
+        }
 
 
         if (!event->stopsImmediatePropagation && event->bubbles && !event->stopsPropagation)
         {
-
             if (_parent)
             {
                 if (TouchEvent::isTouchEvent(event->type))
@@ -389,14 +352,18 @@ namespace oxygine
                     TouchEvent* me = safeCast<TouchEvent*>(event);
                     me->localPosition = local2global(me->localPosition);
                 }
-                event->phase = Event::phase_bubbling;
 
+                event->phase = Event::phase_bubbling;
                 event->currentTarget = 0;
                 _parent->dispatchEvent(event);
             }
         }
-        if (prevTarget)
-            event->target = prevTarget;
+
+        if (click.type)
+        {
+            //send click event at the end after TOUCH_UP event
+            dispatchEvent(&click);
+        }
     }
 
     void Actor::handleEvent(Event* event)
@@ -408,7 +375,7 @@ namespace oxygine
                 return;
         }
 
-        Vector2 originalLocalPos(0, 0);
+        Vector2 originalLocalPos;
 
         if (touchEvent)
         {
@@ -429,10 +396,6 @@ namespace oxygine
             actor = prev;
         }
 
-        /*
-        if (getID() == 46 && event->type == TouchEvent::TOUCH_DOWN)
-            int q=0;
-            */
         if (touchEvent)
         {
             TouchEvent* me = safeCast<TouchEvent*>(event);
@@ -443,24 +406,16 @@ namespace oxygine
                     event->phase = Event::phase_target;
                     event->target = this;
 
-
-                    if (event->type == TouchEvent::TOUCH_DOWN || event->type == TouchEvent::MOVE)
-                        _onMouseEvent(event);
-
-
+                    me->position = me->localPosition;
                     dispatchEvent(event);
                 }
             }
-            else
-            {
-                if (event->type == TouchEvent::TOUCH_UP && getParent() == 0)
-                    dispatchEvent(event);
-            }
 
             me->localPosition = originalLocalPos;
         }
     }
 
+
     void Actor::setAnchor(const Vector2& anchor)
     {
         _anchor = anchor;

+ 5 - 4
oxygine/src/Actor.h

@@ -285,6 +285,8 @@ namespace oxygine
         /**Returns Stage where Actor attached to. Use if for multi stage (window) mode*/
         Stage*              _getStage();
 
+        void setNotPressed();
+
     protected:
         Stage* _stage;
         void added2stage(Stage*);
@@ -295,12 +297,11 @@ namespace oxygine
 
         typedef intrusive_list<spActor> children;
         static void setParent(Actor* actor, Actor* parent);
-        static void setPressed(Actor* actor, pointer_index v) { actor->setPressed(v); }
         static children& getChildren(spActor& actor) { return actor->_children; }
 
-        void setOverred(pointer_index v);
-        void setPressed(pointer_index v);
-        void _onMouseEvent(Event* ev);
+        void _onGlobalTouchUpEvent(Event*);
+        void _onGlobalTouchMoveEvent(Event*);
+
         RectF calcDestRectF(const RectF& destRect, const Vector2& size) const;
         void _setSize(const Vector2&);
         virtual void sizeChanged(const Vector2& size);

+ 4 - 53
oxygine/src/Button.cpp

@@ -23,27 +23,11 @@ namespace oxygine
 
     Button::~Button()
     {
-        /*
-        removeEventHandlers();
-        if (_ph)
-        {
-            _ph->reset();
-        }
-        */
-    }
-
-    void Button::_mouseUpOutside(Event* event)
-    {
-        //Actor *act = safeCast<Actor*>(event->target.get());
-        //if (isDescendant(act))
-        _pressed = false;
-        setState(stateNormal);
     }
 
     void Button::_mouseEvent(Event* event)
     {
         TouchEvent* me = safeCast<TouchEvent*>(event);
-        //Actor *act = safeCast<Actor*>(event->target.get());
 
         switch (event->type)
         {
@@ -51,13 +35,6 @@ namespace oxygine
             {
                 event->phase = Event::phase_target;
                 event->target = this;
-                /*
-                if (event->target.get() != this)
-                {
-                    spMouseEvent e = new MouseEvent(et_Click);
-                    dispatchEvent(e.get());
-                }
-                */
             }
             break;
             case TouchEvent::OVER:
@@ -82,17 +59,12 @@ namespace oxygine
             break;
             case TouchEvent::TOUCH_DOWN:
             {
-                //if (isDescendant(act))
-                //if (me->target.get() == this)
+                if (!_btnPressed)
                 {
-                    //event->stopImmediatePropagation();
-                    if (!_btnPressed)
-                    {
-                        _btnPressed = me->index;
-                        setState(statePressed);
+                    _btnPressed = me->index;
+                    setState(statePressed);
 
-                        _getStage()->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &Button::_mouseEvent));
-                    }
+                    _getStage()->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &Button::_mouseEvent));
                 }
             }
             break;
@@ -105,14 +77,6 @@ namespace oxygine
                         _getStage()->removeEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &Button::_mouseEvent));
                     _btnPressed = 0;
                 }
-
-                //if (isOn(me->localPosition))
-                //if (isDescendant(act))
-                if (_overred)
-                {
-                    //spMouseEvent e = new MouseEvent(et_Click);
-                    //dispatchEvent(e.get());
-                }
             }
             break;
         }
@@ -124,24 +88,11 @@ namespace oxygine
         updateButtonState(_state);
     }
 
-    /*
-    void Button::setAnimFrame(const ResAnim *resanim, int col, int row)
-    {
-        setResAnim(resanim);
-    }
-    */
-
     void Button::setRow(int row)
     {
         _row = row;
         updateButtonState(_state);
     }
-    /*
-    void Button::setCallbackClick(EventCallback cb)
-    {
-        _cbClick = cb;
-    }
-    */
 
     void Button::setState(state s)
     {

+ 0 - 1
oxygine/src/Button.h

@@ -40,7 +40,6 @@ namespace oxygine
         pointer_index _btnOvered;
 
         void _mouseEvent(Event* event);
-        void _mouseUpOutside(Event* event);
 
         void setState(state s);
     };

+ 2 - 2
oxygine/src/Event.h

@@ -33,8 +33,8 @@ namespace oxygine
         void* userData;
         spObject userDataObject;
 
-        spEventDispatcher target;
-        spEventDispatcher currentTarget;// = object with our listener
+        spEventDispatcher target; //The event target
+        spEventDispatcher currentTarget;// The object that is actively processing the Event object with an event listener.
 
         Event(eventType Type, bool Bubbles = false) : userData(0), type(Type), phase(phase_target), bubbles(Bubbles), stopsImmediatePropagation(false), stopsPropagation(false) {}
         virtual ~Event() {}

+ 3 - 0
oxygine/src/EventDispatcher.cpp

@@ -145,6 +145,9 @@ namespace oxygine
 
     void EventDispatcher::dispatchEvent(Event* event)
     {
+        if (!event->target)
+            event->target = this;
+
         __doCheck();
         if (!_listeners)
             return;

+ 1 - 5
oxygine/src/SlidingActor.cpp

@@ -299,17 +299,13 @@ namespace oxygine
                 float d = offset.dot(offset);
                 if (_holded && (d >= _rad * _rad))
                 {
-                    TouchEvent ev(TouchEvent::TOUCH_UP, false, Vector2(-10000, -10000));
                     spActor act = safeSpCast<Actor>(_holded);
                     while (act && act.get() != _content.get())
                     {
-                        _Actor::setPressed(act.get(), 0);
-                        //act->setPressed(0);
-                        //act->setOvered(0);
+                        act->setNotPressed();
                         act = act->getParent();
                     }
 
-                    _Actor::setPressed(_content.get(), te->index);
                     _holded = 0;
                 }
             }

+ 3 - 2
oxygine/src/TouchEvent.h

@@ -27,8 +27,9 @@ namespace oxygine
 
         TouchEvent(eventType type, bool Bubbles = true, const Vector2& locPosition = Vector2(0, 0)) : Event(type, Bubbles), localPosition(locPosition), position(locPosition), mouseButton(MouseButton_Touch), pressure(1.0f), index(1) {}
 
-        Vector2 localPosition;
-        Vector2 position;
+        Vector2 localPosition;//local position for Event::currentTarget actor
+        Vector2 position;//local position for Event::target actor
+
         float pressure;
 
         MouseButton mouseButton;//valid only for TouchUP/Down events

+ 6 - 2
oxygine/src/closure/closure_impl.h

@@ -134,9 +134,13 @@ struct Closure<R(PARAM_TYPE_LIST)>: public detail::CLOSURE_NUM::ClosureBase<R PA
         return !safe_bool(*this);
     }
 
-	bool operator == (const Closure &c)
+	bool operator == (const Closure &c) const
 	{
-		return this->p_proxy == c.p_proxy && this->p_this == c.p_this;
+		return this->p_proxy == c.p_proxy && this->p_this == c.p_this
+#if CLOSURE_FUNCTION
+			&& this->p_function == c.p_function
+#endif
+		;
 	}
 
 };

+ 10 - 1
oxygine/src/core/UberShaderProgram.cpp

@@ -104,10 +104,19 @@ namespace oxygine
         return &s;
     }
 
+    UberShaderProgram::UberShaderProgram()
+    {
+
+    }
+
+    UberShaderProgram::~UberShaderProgram()
+    {
+        releaseShaders();
+    }
+
     void UberShaderProgram::releaseShaders()
     {
         for (int i = 0; i < SIZE; ++i)
-            //for (shaders::iterator i = _shaders.begin(); i != _shaders.end(); ++i)
         {
             shader& s = _shaders[i];
             delete s.program;

+ 3 - 6
oxygine/src/core/UberShaderProgram.h

@@ -36,11 +36,6 @@ namespace oxygine
         void* _getRestorableObject() {return this;}
         void _restore(Restorable*, void*);
 
-        //typedef std::unordered_map<int, shader*> shaders;
-        //shaders _shaders;
-
-        //shader* _shaders[SIZE];
-
         std::vector<unsigned char> _data;
         ShaderUniformsCallback _cb;
 
@@ -50,6 +45,8 @@ namespace oxygine
     class UberShaderProgram : public UberShaderProgramBase
     {
     public:
+        UberShaderProgram();
+        ~UberShaderProgram();
 
         enum
         {
@@ -71,7 +68,7 @@ namespace oxygine
         shader*                 getShaderProgram(int flags);
 
     protected:
-        void releaseShaders();
+        void releaseShaders() OVERRIDE;
         shader _shaders[SIZE];
     };
 }

+ 10 - 6
oxygine/src/utils/AtlasTool.cpp

@@ -131,7 +131,7 @@ namespace oxygine
 
     void Atlas2::clean()
     {
-
+        _free.clear();
     }
 
     void Atlas2::init(int w, int h, int skipSize)
@@ -155,10 +155,13 @@ namespace oxygine
     bool Atlas2::add(Texture* dest, const ImageData& src, Rect& srcRect)
     {
         Point offset(2, 2);
-        if (src.w == dest->getWidth())
-            offset.x = 0;
-        if (src.h == dest->getHeight())
-            offset.y = 0;
+        if (dest)
+        {
+            if (src.w == dest->getWidth())
+                offset.x = 0;
+            if (src.h == dest->getHeight())
+                offset.y = 0;
+        }
 
         int w = src.w + offset.x;
         int h = src.h + offset.y;
@@ -177,7 +180,8 @@ namespace oxygine
 
                 _bounds.unite(srcRect);
 
-                dest->updateRegion(rect.pos.x, rect.pos.y, src);
+                if (dest)
+                    dest->updateRegion(rect.pos.x, rect.pos.y, src);
 
                 _free.erase(_free.begin() + i);
 

+ 1 - 1
tools/oxygine.py

@@ -17,7 +17,7 @@ def helper(root = ""):
                         break
                     cur = parent
                     
-                    ox = cur + "oxygine-framework"
+                    ox = cur + "/oxygine-framework"
                     if os.path.isdir(ox):
                         print("oxygine-framework folder found at " + ox)
                         root = ox