Browse Source

- added no_hit_test option to oxyresbuild
- new atlas generator ready for FreeType fonts
- new events TweenQueue::EVENT_LOOP_BEGIN and EVENT_LOOP_END
- TweenOptions
- added R channel option to MaskedSprite
- improved Demo
- minor fixed

dmuratshin 10 years ago
parent
commit
9ce79fc007
62 changed files with 882 additions and 403 deletions
  1. 2 2
      .hg_archival.txt
  2. BIN
      doc/doc.zip
  3. BIN
      examples/Demo/data/images/anim2.png
  4. BIN
      examples/Demo/data/images/batterfly2.png
  5. BIN
      examples/Demo/data/images/equal_orange.png
  6. BIN
      examples/Demo/data/images/logo2.png
  7. BIN
      examples/Demo/data/images/snow.png
  8. BIN
      examples/Demo/data/images/tiled.png
  9. 5 7
      examples/Demo/data/xmls/res.xml
  10. 5 7
      examples/Demo/src/TestAlphaHitTest.h
  11. 25 21
      examples/Demo/src/TestDrag.h
  12. 38 38
      examples/Demo/src/TestMask.h
  13. 2 2
      examples/Demo/src/TestPolygon.h
  14. 44 43
      examples/Demo/src/TestSliding.h
  15. 3 7
      examples/Demo/src/TestUserShader.h
  16. 4 2
      examples/Demo/src/TestUserShader2.h
  17. 6 7
      examples/Demo/src/example.cpp
  18. BIN
      examples/Game/part1/data/images/sky.jpg
  19. BIN
      examples/Game/part2/data/images/sky.jpg
  20. BIN
      examples/Game/part3/data/images/sky.jpg
  21. BIN
      examples/Game/part3/data/images/ui/bg.jpg
  22. BIN
      examples/Game/part4/data/images/sky.jpg
  23. BIN
      examples/Game/part4/data/images/ui/bg.jpg
  24. BIN
      examples/Game/part5/images/sky.jpg
  25. BIN
      examples/Game/part5/images/ui/bg.jpg
  26. 14 1
      oxygine/SDL/android/lib/src/org/oxygine/lib/HttpRequests.java
  27. 208 177
      oxygine/SDL/qt/oxygine-framework/oxygine-framework.pro
  28. 24 0
      oxygine/src/Actor.h
  29. 25 3
      oxygine/src/Font.cpp
  30. 5 1
      oxygine/src/Font.h
  31. 21 2
      oxygine/src/MaskedSprite.cpp
  32. 8 1
      oxygine/src/MaskedSprite.h
  33. 4 0
      oxygine/src/ProgressBar.cpp
  34. 2 0
      oxygine/src/ProgressBar.h
  35. 3 3
      oxygine/src/SlidingActor.cpp
  36. 1 2
      oxygine/src/Sprite.cpp
  37. 15 1
      oxygine/src/TextField.cpp
  38. 3 1
      oxygine/src/TextField.h
  39. 1 1
      oxygine/src/TextStyle.h
  40. 15 0
      oxygine/src/Tween.cpp
  41. 11 0
      oxygine/src/Tween.h
  42. 7 23
      oxygine/src/TweenAnim.cpp
  43. 2 5
      oxygine/src/TweenAnim.h
  44. 31 15
      oxygine/src/TweenQueue.cpp
  45. 13 0
      oxygine/src/TweenQueue.h
  46. 12 1
      oxygine/src/core/gl/NativeTextureGLES.cpp
  47. 1 1
      oxygine/src/initActor.h
  48. 3 1
      oxygine/src/res/ResAtlas.cpp
  49. 3 0
      oxygine/src/res/ResBuffer.cpp
  50. 1 1
      oxygine/src/res/ResFont.h
  51. 1 1
      oxygine/src/res/ResFontBM.cpp
  52. 1 1
      oxygine/src/res/ResFontBM.h
  53. 7 7
      oxygine/src/text_utils/Aligner.cpp
  54. 4 2
      oxygine/src/text_utils/Aligner.h
  55. 11 8
      oxygine/src/text_utils/Node.cpp
  56. 206 0
      oxygine/src/utils/AtlasTool.cpp
  57. 57 0
      oxygine/src/utils/AtlasTool.h
  58. 1 1
      readme.md
  59. 2 1
      tools/others/build_oxygine_with_sdl.py
  60. 4 0
      tools/oxyresbuild.py
  61. 2 1
      tools/resbuild/process_atlas.py
  62. 19 5
      tools/resbuild/xml_processor.py

+ 2 - 2
.hg_archival.txt

@@ -1,5 +1,5 @@
 repo: b6d71054df5712e643a0685bc3ba54b123db5729
-node: 642e851e1e425ff89c0b1224c0a114ce06971861
+node: 10e3c85aff82f0fd3d9c3357d2245478bdcfbc62
 branch: default
 latesttag: oldrender
-latesttagdistance: 783
+latesttagdistance: 810

BIN
doc/doc.zip


BIN
examples/Demo/data/images/anim2.png


BIN
examples/Demo/data/images/batterfly2.png


BIN
examples/Demo/data/images/equal_orange.png


BIN
examples/Demo/data/images/logo2.png


BIN
examples/Demo/data/images/snow.png


BIN
examples/Demo/data/images/tiled.png


+ 5 - 7
examples/Demo/data/xmls/res.xml

@@ -7,7 +7,6 @@
 
 	<atlas id = "primary" format="8888">
 		<image file="gray.png"/>
-		<image file="logo2.png" /> <!-- border=2 adds 2 pixel border from each side of image in atlas to avoid problem with mask -->
 		<image file="brush.png"/>
 		<image file="palette.png"/>		
 		<image file="snow.png"/>
@@ -17,9 +16,7 @@
 		<set hit_test="false" />
 		
 		<image id="anim" file="anim1.png" cols = "7" /> <!-- 'id' is optional -->
-		<image id="anim2" file="anim2.png" cols = "20" /> <!-- 'id' is optional -->
 		<image file="batterfly.png"/>
-		<image file="batterfly2.png"/>
 		<image file="bg.png" data-custom = "custom user data per xml resource defined in xml"/>
 		<image file="grad.png"/>
 		<image file="t2p.png"/>
@@ -29,26 +26,27 @@
 		<image file="light.png"/>
 		<image file="normal.png"/>
 		<image file="defnormal.png"/>
+		<image file="map.png"/>
+		<image file="mask.png"/>
+		<image file="sky.png"/>
+		<image file="tiled2.png"/>
 	</atlas>
 
 	<atlas>
-		<image file="tiled.png"/>
+		<image file="tiled.png"/>		
 	</atlas>	
 	
 	<set load = "false" /> <!--do not load next atlasses by default-->
 	<atlas format="4444">
 		<image id="bg_4444" file="bg.png"/>
-		<image id="logo2_4444" file="logo2.png"/>
 	</atlas>
 	
 	<atlas format="5551">
 		<image id="bg_5551" file="bg.png"/>
-		<image id="logo2_5551" file="logo2.png"/>
 	</atlas>
 	
 	<atlas format="565">
 		<image id="bg_565" file="bg.png"/>
-		<image id="logo2_565" file="logo2.png"/>
 	</atlas>	
 	
 </resources>

+ 5 - 7
examples/Demo/src/TestAlphaHitTest.h

@@ -1,6 +1,5 @@
 #pragma once
 #include "test.h"
-#include "initActor.h"
 
 #undef OUT
 
@@ -20,12 +19,11 @@ public:
         'hit_test' enables access to alpha channel
         */
 
-        sprite = initActor(new Sprite,
-                           arg_resAnim = resources.getResAnim("flower"),
-                           arg_attachTo = content,
-                           arg_anchor = Vector2(0.5f, 0.5f),
-                           arg_x = content->getWidth() / 2,
-                           arg_y = content->getHeight() / 2);
+        sprite = new Sprite;
+        sprite->setResAnim(resources.getResAnim("flower"));
+        sprite->attachTo(content);
+        sprite->setAnchor(0.5f, 0.5f);
+        sprite->setPosition(content->getSize() / 2);
 
         sprite->addEventListener(TouchEvent::OVER, CLOSURE(this, &TestAlphaHitTest::onEvent));
         sprite->addEventListener(TouchEvent::OUT, CLOSURE(this, &TestAlphaHitTest::onEvent));

+ 25 - 21
examples/Demo/src/TestDrag.h

@@ -27,6 +27,9 @@ public:
 
             sprite->setRotation(scalar::randFloat(0, (float)MATH_PI * 2));
             sprite->setScale(scalar::randFloat(1.0f, 2.0f));
+
+            sprite->addEventListener(TouchEvent::TOUCH_DOWN, CLOSURE(this, &DragTest::onMouseDown));
+            sprite->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &DragTest::onMouseUp));
         }
     }
 
@@ -63,21 +66,21 @@ public:
 
     Drag2Test(): touchedBy(0), timeLeft(0)
     {
-        basket = initActor(new Sprite,
-                           arg_name = "basket",
-                           arg_resAnim = resources.getResAnim("batterfly"),
-                           arg_attachTo = content,
-                           arg_anchor = Vector2(0.5f, 0.5f),
-                           arg_x = content->getWidth() * 3 / 4,
-                           arg_y = content->getHeight() / 2);
-
-        ball = initActor(new Sprite,
-                         arg_name = "ball",
-                         arg_resAnim = resources.getResAnim("batterfly"),
-                         arg_attachTo = content,
-                         arg_anchor = Vector2(0.5f, 0.5f),
-                         arg_x = content->getWidth() * 1 / 4,
-                         arg_y = content->getHeight() / 2);
+        basket = new Sprite;
+        basket->setName("basket");
+        basket->setResAnim(resources.getResAnim("batterfly"));
+        basket->attachTo(content);
+        basket->setAnchor(0.5f, 0.5f);
+        basket->setX(content->getWidth() * 3 / 4);
+        basket->setY(content->getHeight() / 2);
+
+        ball = new Sprite;
+        ball->setName("ball");
+        ball->setResAnim(resources.getResAnim("batterfly"));
+        ball->attachTo(content);
+        ball->setAnchor(0.5f, 0.5f);
+        ball->setX(content->getWidth() * 1 / 4);
+        ball->setY(content->getHeight() / 2);
 
         ball->addEventListener(TouchEvent::TOUCH_DOWN, CLOSURE(this,  &Drag2Test::ballTouchDown));
         ball->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this,  &Drag2Test::ballTouchUp));
@@ -143,12 +146,13 @@ public:
             txt->setText("Now drop it on right object");
 
             timeLeft = 0;
-            dragging = initActor(ball->clone(),
-                                 arg_name = "dragging",
-                                 arg_attachTo = ball->getParent(),
-                                 arg_color = Color(0xff0000ff),
-                                 arg_anchor = Vector2(0, 0),
-                                 arg_input = false);
+            dragging = ball->clone();
+
+            dragging->setName("dragging");
+            dragging->attachTo(ball->getParent());
+            dragging->setColor(Color::Red);
+            dragging->setAnchor(0, 0);
+            dragging->setInputEnabled(false);
             drag.start(touchedBy, dragging.get(), dragging->getSize() / 2);
         }
     }

+ 38 - 38
examples/Demo/src/TestMask.h

@@ -1,6 +1,5 @@
 #pragma once
 #include "test.h"
-#include "initActor.h"
 #include "Polygon.h"
 #include "TestPolygon.h"
 
@@ -14,52 +13,51 @@ public:
 
     TestMask(): _lastSnow(0)
     {
-        _mask = initActor(new Sprite,
-                          arg_scale = 2.5f,
-                          arg_priority = 1,
-                          arg_alpha = 100,
-                          arg_x = 100,
-                          arg_y = 50,
-                          arg_anchor = Vector2(0.5f, 0.5f),
-                          arg_resAnim = resources.getResAnim("logo2"),
-                          arg_attachTo = content);
+        spSprite sp = new Sprite;
+        sp->attachTo(content);
+        sp->setResAnim(resources.getResAnim("sky"));
+
+        _mask = new Sprite;
+        _mask->setScale(1.5f);
+        _mask->setPriority(1);
+        _mask->setAlpha(100);
+        _mask->setX(100);
+        _mask->setY(50);
+        _mask->setAnchor(0.5f, 0.5f);
+        _mask->setResAnim(resources.getResAnim("mask"));
+        _mask->setVisible(true);
+        _mask->attachTo(content);
 
         _mask->addTween(Actor::TweenRotation(MATH_PI * 2), 15000, -1, true);
         _mask->addTween(Actor::TweenX(content->getWidth() - 100), 10000, -1, true);
         _mask->addTween(Actor::TweenY(content->getHeight() - 50), 12000, -1, true);
 
-        _masked = initActor(new MaskedSprite,
-                            arg_attachTo = content);
+        _masked = new MaskedSprite;
+        _masked->attachTo(content);
 
-        _masked->setMask(_mask);
+        _masked->setMask(_mask, true);
 
 
         spPolygon poly = new oxygine::Polygon;
 
         vertexPCT2* data = TestPolygon::createVertices(10);
         poly->setVertices(data, sizeof(vertexPCT2) * 10 * 4, vertexPCT2::FORMAT, true);
-        poly->setPosition(getSize() / 2);
-        poly->setScale(1.3f);
+        poly->setPosition(getSize());
         _masked->addChild(poly);
 
-        spSprite sp = new Sprite;
-        sp->attachTo(_masked);
-        sp->setResAnim(resources.getResAnim("bg"));
-
 
         TextStyle style;
         style.font = resourcesUI.getResFont("big")->getFont();
-        style.color = Color::BlanchedAlmond,
-              style.vAlign = TextStyle::VALIGN_MIDDLE;
+        style.color = Color::OrangeRed;
+        style.vAlign = TextStyle::VALIGN_MIDDLE;
         style.hAlign = TextStyle::HALIGN_CENTER;
         style.multiline = true;
 
-        spTextField text = initActor(new TextField(),
-                                     arg_attachTo = _masked,
-                                     arg_pos = content->getSize() / 2,
-                                     arg_scale = 1.5f,
-                                     arg_text = "Oxygine. Masked text",
-                                     arg_style = style);
+        spTextField text = new TextField();
+        text->attachTo(_masked);
+        text->setPosition(content->getSize() / 2);
+        text->setText("Oxygine. Masked sky demo");
+        text->setStyle(style);
 
 
         const Test::toggle sm[] = {Test::toggle("hide mask", 0), Test::toggle("show mask", 1), };
@@ -103,10 +101,12 @@ public:
             switch (t->value)
             {
                 case 1:
-                    _mask->setResAnim(resources.getResAnim("logo2"));
+                    _mask->setResAnim(resources.getResAnim("mask"));
+                    _masked->setMask(_mask, true);
                     break;
                 case 0:
                     _mask->addTween(TweenAnim(resources.getResAnim("anim")), 600, -1, false)->setName("tweenanim");
+                    _masked->setMask(_mask, false);
                     break;
             }
         }
@@ -115,20 +115,20 @@ public:
 
     void doUpdate(const UpdateState& us)
     {
-        if (_lastSnow  + 40 < us.time)
+        if (_lastSnow  + 20 < us.time)
         {
             _lastSnow = us.time;
-            spSprite snow = initActor(new Sprite,
-                                      arg_anchor = Vector2(0.5f, 0.5f),
-                                      arg_resAnim = resources.getResAnim("snow"),
-                                      arg_attachTo = _masked,
-                                      arg_rotation = scalar::randFloat(0, MATH_PI * 2),
-                                      arg_y = -50,
-                                      arg_scale = scalar::randFloat(0.4f, 1.0f),
-                                      arg_x = scalar::randFloat(0, content->getWidth()));
+            spSprite snow = new Sprite;
+            snow->setAnchor(0.5f, 0.5f);
+            snow->setResAnim(resources.getResAnim("snow"));
+            snow->setRotation(scalar::randFloat(0, MATH_PI * 2));
+            snow->setScale(scalar::randFloat(0.4f, 1.0f));
+            snow->setX(scalar::randFloat(0, content->getWidth()));
+            snow->setY(-50);
+            snow->attachTo(_masked);
 
             snow->addTween(Actor::TweenY(content->getHeight() + 50), 6000)->setDetachActor(true);
-            snow->addTween(Actor::TweenRotation(scalar::randFloat(0, MATH_PI * 2)), 10000);
+            snow->addTween(Actor::TweenRotation(scalar::randFloat(0, MATH_PI * 2)), 5000);
         }
     }
 };

+ 2 - 2
examples/Demo/src/TestPolygon.h

@@ -44,8 +44,8 @@ public:
         v.x = pos.x;
         v.y = pos.y;
         v.z = 0;
-        v.u = v.x / 100;
-        v.v = v.y / 100;
+        v.u = v.x / 128;
+        v.v = v.y / 128;
 
         return v;
     }

+ 44 - 43
examples/Demo/src/TestSliding.h

@@ -7,7 +7,10 @@
 class TestSliding: public Test
 {
 public:
-    spSlidingActor _sliding;
+    spSlidingActor  _sliding;
+    spSprite        _map;
+    spButton        _button;
+
     bool _snapEnabled;
     TestSliding()
     {
@@ -22,37 +25,32 @@ public:
         sliding->setSize(getWidth() / 3 * 2, getHeight() / 3 * 2);
 
 
-        spColorRectSprite content = new ColorRectSprite();
-        content->setSize(sliding->getWidth(), 2000);
-        content->setColor(Color(200, 200, 200, 255));
-        for (int i = 0; i < 20; i += 2)
-        {
-            spColorRectSprite c = initActor(new ColorRectSprite,
-                                            arg_size = Vector2(content->getWidth(), 100),
-                                            arg_color = Color(164, 164, 164, 255),
-                                            arg_y = i * 100.0f,
-                                            arg_attachTo = content);
-
-            c->setCull(true);//cull invisible parts
-
-            spButton button = initActor(new Button,
-                                        arg_resAnim = resourcesUI.getResAnim("button"),
-                                        arg_attachTo = c);
-            button->addEventListener(TouchEvent::CLICK, CLOSURE(this, &TestSliding::testClick));
-        }
+        spSprite map = new Sprite();
+        map->setResAnim(resources.getResAnim("map"));
+        map->setPosition(sliding->getSize() / 2 - map->getSize() / 2);
+        _map = map;
+
+        spButton button = new Button;
+        _button = button;
+        button->setPosition(map->getSize() / 2);
+        button->setResAnim(resourcesUI.getResAnim("button"));
+        button->attachTo(map);
+        button->setAnchor(0.5f, 0.5f);
+        button->addEventListener(TouchEvent::CLICK, CLOSURE(this, &TestSliding::testClick));
+
 
-        spTextField title = initActor(new TextField,
-                                      arg_text = "Sliding demo",
-                                      arg_w = content->getWidth(),
-                                      arg_vAlign = TextStyle::VALIGN_TOP,
-                                      arg_hAlign = TextStyle::HALIGN_CENTER,
-                                      arg_font = resourcesUI.getResFont("big")->getFont(),
-                                      arg_color = Color(0xFF0000ff),
-                                      arg_attachTo = content);
+        spTextField title = new TextField;
+        title->setText("Sliding Demo");
+        title->setSize(map->getSize());
+        title->setAlign(TextStyle::VALIGN_MIDDLE, TextStyle::HALIGN_MIDDLE);
+        title->setY(-50);
+        title->setFont(resourcesUI.getResFont("big")->getFont());
+        title->setColor(Color::Black);
+        title->attachTo(map);
 
-        sliding->setContent(content);
+        sliding->setContent(map);
         sliding->setPosition(getSize() / 2 - sliding->getSize() / 2);
-        sliding->attachTo(this->content);
+        sliding->attachTo(content);
 
         _sliding = sliding;
 
@@ -80,6 +78,8 @@ public:
         if (id == "snap")
         {
             _snapEnabled = data->value == 0;
+
+            snap();
         }
     }
 
@@ -89,36 +89,37 @@ public:
         SlidingActor::SlidingEvent* sd = safeCast<SlidingActor::SlidingEvent*>(event);
     }
 
-    void slideEnd(Event* event)
+    void snap()
     {
-        notify("slideEnd");
-
         if (!_snapEnabled)
             return;
 
         //snap to  grid
-        SlidingActor::SlidingEvent* sd = safeCast<SlidingActor::SlidingEvent*>(event);
         spActor content = _sliding->getContent();
         float y = content->getY();
-        y = int(y / 100) * 100.0f;
-        Vector2 dest(content->getX(), y);
+        y = int(y / 169) * 169;
+
+        float x = content->getX();
+        x = int(x / 166) * 166;
+        Vector2 dest(x, y);
         content->addTween(Actor::TweenPosition(dest), 100);
     }
 
+    void slideEnd(Event* event)
+    {
+        notify("slideEnd");
+
+        snap();
+    }
+
     void sliding(Event* event)
     {
-        /*
-        //snap
-        SlidingActor::SlidingEvent* sd = safeCast<SlidingActor::SlidingEvent *>(event);
-        if (sd->speed.sqlength() < 2500)
-        {
-            sd->speed = Vector2(0,0);
-        }
-        */
+
     }
 
     void testClick(Event* event)
     {
         notify("clicked");
+        _button->addTween(Sprite::TweenColor(Color::Red), 300, 1, true);
     }
 };

+ 3 - 7
examples/Demo/src/TestUserShader.h

@@ -92,13 +92,9 @@ public:
                             "}\n");
 
 
-        _sprite = initActor(new ShaderSprite,
-                            arg_resAnim = resources.getResAnim("bg"),
-                            arg_attachTo = content
-                                           //arg_pos = content->getSize()/2,
-                                           //arg_anchor = Vector2(0.5f, 0.5f)
-                           );
-
+        _sprite = new ShaderSprite;
+        _sprite->setResAnim(resources.getResAnim("bg"));
+        _sprite->attachTo(content);
         _sprite->addTween(ShaderSprite::TweenVal(Vector4(1, 1, 1, 0)), 5000, -1, true);
         _sprite->setShaderProgram(_shaderInvert);
 

+ 4 - 2
examples/Demo/src/TestUserShader2.h

@@ -158,8 +158,10 @@ public:
 
         AnimationFrame frame = resources.getResAnim("normal")->getFrame(0);
         spSprite spr = new Sprite2(frame);
-        spr->setResAnim(resources.getResAnim("tiled"));
-        spr->setPosition(content->getSize() / 2 - spr->getSize() / 2);
+        spr->setResAnim(resources.getResAnim("tiled2"));
+        spr->setScale(2);
+        spr->setAnchor(0.5f, 0.5f);
+        spr->setPosition(content->getSize() / 2);
         spr->attachTo(lightning);
 
 

+ 6 - 7
examples/Demo/src/example.cpp

@@ -218,13 +218,12 @@ void example_init()
     resourcesUI.loadXML("demo/res_ui.xml");
     resourcesUI.loadXML("demo/fonts.xml");
 
-    spSprite sp = initActor(new Sprite,
-                            arg_resAnim = resourcesUI.getResAnim("logo2"),
-                            arg_input = false,
-                            arg_attachTo = getStage(),
-                            arg_priority = 10,
-                            arg_alpha = 128
-                           );
+    spSprite sp = new Sprite;
+    sp->setResAnim(resourcesUI.getResAnim("logo2"));
+    sp->setInputEnabled(false);
+    sp->attachTo(getStage());
+    sp->setPriority(10);
+    sp->setAlpha(128);
 
     sp->setX(getStage()->getWidth() - sp->getWidth());
     sp->setY(getStage()->getHeight() - sp->getHeight());

BIN
examples/Game/part1/data/images/sky.jpg


BIN
examples/Game/part2/data/images/sky.jpg


BIN
examples/Game/part3/data/images/sky.jpg


BIN
examples/Game/part3/data/images/ui/bg.jpg


BIN
examples/Game/part4/data/images/sky.jpg


BIN
examples/Game/part4/data/images/ui/bg.jpg


BIN
examples/Game/part5/images/sky.jpg


BIN
examples/Game/part5/images/ui/bg.jpg


+ 14 - 1
oxygine/SDL/android/lib/src/org/oxygine/lib/HttpRequests.java

@@ -3,6 +3,8 @@ package org.oxygine.lib;
 import android.content.Context;
 import android.os.AsyncTask;
 import android.os.PowerManager;
+import android.os.Build;
+import android.annotation.TargetApi;
 
 import java.io.*;
 import java.net.HttpURLConnection;
@@ -40,13 +42,24 @@ class HttpRequestHolder {
     {
     }
 
+
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB) // API 11
+    public static <T> void executeAsyncTask(AsyncTask<T, ?, ?> asyncTask, T... params) {
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+            asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
+        else
+            asyncTask.execute(params);
+    }   
+
+
     public  void run(final  RequestDetails details)
     {
         OxygineActivity.instance.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 HttpRequest task = new HttpRequest();
-                task.execute(details);
+                //task.execute(details);
+                executeAsyncTask(task, details);
             }
         });
     }

+ 208 - 177
oxygine/SDL/qt/oxygine-framework/oxygine-framework.pro

@@ -13,245 +13,276 @@ CONFIG += c++11
 
 QMAKE_CXXFLAGS_WARN_OFF -= -Wunused-parameter
 
+DEFINES += \
+    OXYGINE_SDL \
+    OX_NO_HTTP
+
 ROOT = ../../../../
 SRC = ../../../src
 SOURCES += \
-	$$SRC/Actor.cpp \
-	$$SRC/AnimationFrame.cpp \
-	$$SRC/blocking.cpp \
-	$$SRC/Box9Sprite.cpp \
-	$$SRC/Button.cpp \
-	$$SRC/ClipRectActor.cpp \
-	$$SRC/Clock.cpp \
-	$$SRC/ColorRectSprite.cpp \
-	$$SRC/DebugActor.cpp \
-	$$SRC/Draggable.cpp \
-	$$SRC/EventDispatcher.cpp \
-	$$SRC/Font.cpp \
-	$$SRC/Input.cpp \
-	$$SRC/InputText.cpp \
-	$$SRC/MaskedSprite.cpp \
-	$$SRC/MemoryTexture.cpp \
-	$$SRC/Multithreading.cpp \
-	$$SRC/PointerState.cpp \
-	$$SRC/ProgressBar.cpp \
-	$$SRC/SlidingActor.cpp \
-	$$SRC/Sprite.cpp \
-	$$SRC/VisualStyle.cpp \
-	$$SRC/Serialize.cpp
+  $$SRC/Actor.cpp \
+  $$SRC/AnimationFrame.cpp \
+  $$SRC/blocking.cpp \
+  $$SRC/Box9Sprite.cpp \
+  $$SRC/Button.cpp \
+  $$SRC/ClipRectActor.cpp \
+  $$SRC/Clock.cpp \
+  $$SRC/ColorRectSprite.cpp \
+  $$SRC/DebugActor.cpp \
+  $$SRC/Draggable.cpp \
+  $$SRC/EventDispatcher.cpp \
+  $$SRC/Font.cpp \
+  $$SRC/Input.cpp \
+  $$SRC/InputText.cpp \
+  $$SRC/MaskedSprite.cpp \
+  $$SRC/MemoryTexture.cpp \
+  $$SRC/Multithreading.cpp \
+  $$SRC/PointerState.cpp \
+  $$SRC/ProgressBar.cpp \
+  $$SRC/SlidingActor.cpp \
+  $$SRC/Sprite.cpp \
+  $$SRC/VisualStyle.cpp \
+  $$SRC/Serialize.cpp \
+  $$SRC/AsyncTask.cpp \
+  $$SRC/HttpRequestTask.cpp \
+  $$SRC/MaskedRenderer.cpp \
+  $$SRC/Polygon.cpp \
+  $$SRC/Serializable.cpp \
+  $$SRC/Stage.cpp \
+  $$SRC/STDRenderer.cpp \
+  $$SRC/TextField.cpp \
+  $$SRC/Tween.cpp \
+  $$SRC/TweenAnim.cpp \
+  $$SRC/TweenQueue.cpp \
+  $$SRC/WebImage.cpp \
+  $$SRC/utils/cdecode.c
 
 HEADERS +=  \
-	$$SRC/Actor.h \
-	$$SRC/AnimationFrame.h \
-	$$SRC/blocking.h \
-	$$SRC/Box9Sprite.h \
-	$$SRC/Button.h \
-	$$SRC/ClipRectActor.h \
-	$$SRC/Clock.h \
-	$$SRC/ColorRectSprite.h \
-	$$SRC/DebugActor.h \
-	$$SRC/Draggable.h \
-	$$SRC/Event.h \
-	$$SRC/EventDispatcher.h \
-	$$SRC/Font.h \
-	$$SRC/initActor.h \
-	$$SRC/Input.h \
-	$$SRC/InputText.h \
-	$$SRC/MaskedSprite.h \
-	$$SRC/MemoryTexture.h \
-	$$SRC/Multithreading.h \
-	$$SRC/oxygine-framework.h \
-	$$SRC/oxygine_include.h \
-	$$SRC/PointerState.h \
-	$$SRC/ProgressBar.h \
-	$$SRC/RenderState.h \
-	$$SRC/RootActor.h \
-	$$SRC/SlidingActor.h \
-	$$SRC/Sprite.h \
-	$$SRC/TextActor.h \
-	$$SRC/TextStyle.h \
-	$$SRC/Tweener.h \
-	$$SRC/UpdateState.h \
-	$$SRC/VisualStyle.h \
-	$$SRC/Serialize.h
+  $$SRC/Actor.h \
+  $$SRC/AnimationFrame.h \
+  $$SRC/blocking.h \
+  $$SRC/Box9Sprite.h \
+  $$SRC/Button.h \
+  $$SRC/ClipRectActor.h \
+  $$SRC/Clock.h \
+  $$SRC/ColorRectSprite.h \
+  $$SRC/DebugActor.h \
+  $$SRC/Draggable.h \
+  $$SRC/Event.h \
+  $$SRC/EventDispatcher.h \
+  $$SRC/Font.h \
+  $$SRC/initActor.h \
+  $$SRC/Input.h \
+  $$SRC/InputText.h \
+  $$SRC/MaskedSprite.h \
+  $$SRC/MemoryTexture.h \
+  $$SRC/Multithreading.h \
+  $$SRC/oxygine-framework.h \
+  $$SRC/oxygine_include.h \
+  $$SRC/PointerState.h \
+  $$SRC/ProgressBar.h \
+  $$SRC/RenderState.h \
+  $$SRC/RootActor.h \
+  $$SRC/SlidingActor.h \
+  $$SRC/Sprite.h \
+  $$SRC/TextActor.h \
+  $$SRC/TextStyle.h \
+  $$SRC/Tweener.h \
+  $$SRC/UpdateState.h \
+  $$SRC/VisualStyle.h \
+  $$SRC/Serialize.h \
+  $$SRC/AsyncTask.h \
+  $$SRC/HttpRequestTask.h \
+  $$SRC/KeyEvent.h \
+  $$SRC/MaskedRenderer.h \
+  $$SRC/Polygon.h \
+  $$SRC/Property.h \
+  $$SRC/Serializable.h \
+  $$SRC/Stage.h \
+  $$SRC/STDRenderer.h \
+  $$SRC/TextField.h \
+  $$SRC/TouchEvent.h \
+  $$SRC/Tween.h \
+  $$SRC/TweenAnim.h \
+  $$SRC/TweenQueue.h \
+  $$SRC/WebImage.h \
+  $$SRC/utils/cdecode.h
 
 linux:INCLUDEPATH += /usr/include/SDL2
 INCLUDEPATH += $$SRC/../greenlets/src/
 
 SOURCES += \
-	$$SRC/../greenlets/src/greenlet.c \
-	$$SRC/core/coroutines.cpp \
-	$$SRC/core/file.cpp \
-	$$SRC/core/FileSystem.cpp \
-	$$SRC/core/ImageData.cpp \
-	$$SRC/core/ImageDataOperations.cpp \
-	$$SRC/core/log.cpp \
-	$$SRC/core/Mem2Native.cpp \
-	$$SRC/core/Mutex.cpp \
-	$$SRC/core/NativeTexture.cpp \
-	$$SRC/core/Object.cpp \
-	$$SRC/core/oxygine.cpp \
-	$$SRC/core/Renderer.cpp \
-	$$SRC/core/Restorable.cpp \
-	$$SRC/core/STDFileSystem.cpp \
-	$$SRC/core/system_data.cpp \
-	$$SRC/core/Texture.cpp \
-	$$SRC/core/ThreadMessages.cpp \
-	$$SRC/core/UberShaderProgram.cpp \
-	$$SRC/core/VideoDriver.cpp \
-	$$SRC/core/ZipFileSystem.cpp \
+  $$SRC/core/coroutines.cpp \
+  $$SRC/core/file.cpp \
+  $$SRC/core/FileSystem.cpp \
+  $$SRC/core/ImageData.cpp \
+  $$SRC/core/ImageDataOperations.cpp \
+  $$SRC/core/log.cpp \
+  $$SRC/core/Mem2Native.cpp \
+  $$SRC/core/Mutex.cpp \
+  $$SRC/core/NativeTexture.cpp \
+  $$SRC/core/Object.cpp \
+  $$SRC/core/oxygine.cpp \
+  $$SRC/core/Renderer.cpp \
+  $$SRC/core/Restorable.cpp \
+  $$SRC/core/STDFileSystem.cpp \
+  $$SRC/core/system_data.cpp \
+  $$SRC/core/Texture.cpp \
+  $$SRC/core/ThreadMessages.cpp \
+  $$SRC/core/UberShaderProgram.cpp \
+  $$SRC/core/VideoDriver.cpp \
+  $$SRC/core/ZipFileSystem.cpp \
 
 HEADERS += \
 $$SRC/core/coroutines.h \
-	$$SRC/core/file.h \
-	$$SRC/core/FileSystem.h \
-	$$SRC/core/files_io.h \
-	$$SRC/core/ImageData.h \
-	$$SRC/core/ImageDataOperations.h \
-	$$SRC/core/intrusive_ptr.h \
-	$$SRC/core/log.h \
-	$$SRC/core/logging.h \
-	$$SRC/core/Mem2Native.h \
-	$$SRC/core/memory_pool.h \
-	$$SRC/core/Mutex.h \
-	$$SRC/core/NativeTexture.h \
-	$$SRC/core/Object.h \
-	$$SRC/core/oxygine.h \
-	$$SRC/core/ox_debug.h \
-	$$SRC/core/pixel.h \
-	$$SRC/core/ref_counter.h \
-	$$SRC/core/Renderer.h \
-	$$SRC/core/Restorable.h \
-	$$SRC/core/ShaderProgram.h \
-	$$SRC/core/STDFileSystem.h \
-	$$SRC/core/system_data.h \
-	$$SRC/core/Texture.h \
-	$$SRC/core/ThreadMessages.h \
-	$$SRC/core/UberShaderProgram.h \
-	$$SRC/core/vertex.h \
-	$$SRC/core/VertexDeclaration.h \
-	$$SRC/core/VideoDriver.h \
-	$$SRC/core/ZipFileSystem.h \
+  $$SRC/core/file.h \
+  $$SRC/core/FileSystem.h \
+  $$SRC/core/files_io.h \
+  $$SRC/core/ImageData.h \
+  $$SRC/core/ImageDataOperations.h \
+  $$SRC/core/intrusive_ptr.h \
+  $$SRC/core/log.h \
+  $$SRC/core/logging.h \
+  $$SRC/core/Mem2Native.h \
+  $$SRC/core/memory_pool.h \
+  $$SRC/core/Mutex.h \
+  $$SRC/core/NativeTexture.h \
+  $$SRC/core/Object.h \
+  $$SRC/core/oxygine.h \
+  $$SRC/core/ox_debug.h \
+  $$SRC/core/pixel.h \
+  $$SRC/core/ref_counter.h \
+  $$SRC/core/Renderer.h \
+  $$SRC/core/Restorable.h \
+  $$SRC/core/ShaderProgram.h \
+  $$SRC/core/STDFileSystem.h \
+  $$SRC/core/system_data.h \
+  $$SRC/core/Texture.h \
+  $$SRC/core/ThreadMessages.h \
+  $$SRC/core/UberShaderProgram.h \
+  $$SRC/core/vertex.h \
+  $$SRC/core/VertexDeclaration.h \
+  $$SRC/core/VideoDriver.h \
+  $$SRC/core/ZipFileSystem.h \
 
 
 SOURCES += \
-	$$SRC/dev_tools/DeveloperMenu.cpp \
-	$$SRC/dev_tools/TexturesInspector.cpp \
-	$$SRC/dev_tools/TreeInspector.cpp \
-	$$SRC/dev_tools/TreeInspectorLine.cpp \
-	$$SRC/dev_tools/TreeInspectorPage.cpp \
-	$$SRC/dev_tools/TreeInspectorPreview.cpp \
+  $$SRC/dev_tools/DeveloperMenu.cpp \
+  $$SRC/dev_tools/TexturesInspector.cpp \
+  $$SRC/dev_tools/TreeInspector.cpp \
+  $$SRC/dev_tools/TreeInspectorLine.cpp \
+  $$SRC/dev_tools/TreeInspectorPage.cpp \
+  $$SRC/dev_tools/TreeInspectorPreview.cpp \
 
 
 HEADERS +=  \
-	$$SRC/dev_tools/DeveloperMenu.h \
-	$$SRC/dev_tools/TexturesInspector.h \
-	$$SRC/dev_tools/TreeInspector.h \
-	$$SRC/dev_tools/TreeInspectorLine.h \
-	$$SRC/dev_tools/TreeInspectorPage.h \
-	$$SRC/dev_tools/TreeInspectorPreview.h \
+  $$SRC/dev_tools/DeveloperMenu.h \
+  $$SRC/dev_tools/TexturesInspector.h \
+  $$SRC/dev_tools/TreeInspector.h \
+  $$SRC/dev_tools/TreeInspectorLine.h \
+  $$SRC/dev_tools/TreeInspectorPage.h \
+  $$SRC/dev_tools/TreeInspectorPreview.h \
 
 
 SOURCES += \
-	$$SRC/minizip/ioapi.c \
-	$$SRC/minizip/ioapi_mem.c \
-	$$SRC/minizip/unzip.c \
+  $$SRC/minizip/ioapi.c \
+  $$SRC/minizip/ioapi_mem.c \
+  $$SRC/minizip/unzip.c \
 
 HEADERS +=  \
-	$$SRC/minizip/ioapi.h \
-	$$SRC/minizip/ioapi_mem.h \
-	$$SRC/minizip/unzip.h \
+  $$SRC/minizip/ioapi.h \
+  $$SRC/minizip/ioapi_mem.h \
+  $$SRC/minizip/unzip.h \
 
 SOURCES += \
-	$$SRC/pugixml/pugixml.cpp \
+  $$SRC/pugixml/pugixml.cpp \
 
 HEADERS +=  \
-	$$SRC/pugixml/pugiconfig.hpp \
-	$$SRC/pugixml/pugixml.hpp \
+  $$SRC/pugixml/pugiconfig.hpp \
+  $$SRC/pugixml/pugixml.hpp \
 
 SOURCES += \
-	$$SRC/res/CreateResourceContext.cpp \
-	$$SRC/res/ResAnim.cpp \
-	$$SRC/res/ResAtlas.cpp \
-	$$SRC/res/ResBuffer.cpp \
-	$$SRC/res/ResFont.cpp \
-	$$SRC/res/ResFontBM.cpp \
-	$$SRC/res/Resource.cpp \
-	$$SRC/res/Resources.cpp \
-	$$SRC/res/ResStarlingAtlas.cpp \
+  $$SRC/res/CreateResourceContext.cpp \
+  $$SRC/res/ResAnim.cpp \
+  $$SRC/res/ResAtlas.cpp \
+  $$SRC/res/ResBuffer.cpp \
+  $$SRC/res/ResFont.cpp \
+  $$SRC/res/ResFontBM.cpp \
+  $$SRC/res/Resource.cpp \
+  $$SRC/res/Resources.cpp \
+  $$SRC/res/ResStarlingAtlas.cpp \
 
 HEADERS += \
-	$$SRC/res/CreateResourceContext.h \
-	$$SRC/res/ResAnim.h \
-	$$SRC/res/ResAtlas.h \
-	$$SRC/res/ResBuffer.h \
-	$$SRC/res/ResFont.h \
-	$$SRC/res/ResFontBM.h \
-	$$SRC/res/Resource.h \
-	$$SRC/res/Resources.h \
-	$$SRC/res/ResStarlingAtlas.h \
+  $$SRC/res/CreateResourceContext.h \
+  $$SRC/res/ResAnim.h \
+  $$SRC/res/ResAtlas.h \
+  $$SRC/res/ResBuffer.h \
+  $$SRC/res/ResFont.h \
+  $$SRC/res/ResFontBM.h \
+  $$SRC/res/Resource.h \
+  $$SRC/res/Resources.h \
+  $$SRC/res/ResStarlingAtlas.h \
 
 SOURCES += \
-	$$SRC/text_utils/Aligner.cpp \
-	$$SRC/text_utils/Node.cpp \
-	$$SRC/text_utils/TextBuilder.cpp \
+  $$SRC/text_utils/Aligner.cpp \
+  $$SRC/text_utils/Node.cpp \
+  $$SRC/text_utils/TextBuilder.cpp \
 
 HEADERS += \
-	$$SRC/text_utils/Aligner.h \
-	$$SRC/text_utils/Node.h \
-	$$SRC/text_utils/TextBuilder.h \
+  $$SRC/text_utils/Aligner.h \
+  $$SRC/text_utils/Node.h \
+  $$SRC/text_utils/TextBuilder.h \
 
 SOURCES += \
-	$$SRC/utils/AtlasTool.cpp \
-	$$SRC/utils/ImageUtils.cpp \
-	$$SRC/utils/stringUtils.cpp \
+  $$SRC/utils/AtlasTool.cpp \
+  $$SRC/utils/ImageUtils.cpp \
+  $$SRC/utils/stringUtils.cpp \
 
 HEADERS += \
-	$$SRC/utils/AtlasTool.h \
-	$$SRC/utils/ImageUtils.h \
-	$$SRC/utils/intrusive_list.h \
-	$$SRC/utils/stringUtils.h \
+  $$SRC/utils/AtlasTool.h \
+  $$SRC/utils/ImageUtils.h \
+  $$SRC/utils/intrusive_list.h \
+  $$SRC/utils/stringUtils.h \
 
 SOURCES += \
-	$$SRC/winnie_alloc/system_alloc.cpp \
-	$$SRC/winnie_alloc/winnie_alloc.cpp \
+  $$SRC/winnie_alloc/system_alloc.cpp \
+  $$SRC/winnie_alloc/winnie_alloc.cpp \
 
 HEADERS += \
-	$$SRC/winnie_alloc/system_alloc.h \
-	$$SRC/winnie_alloc/winnie_alloc.h \
-	$$SRC/winnie_alloc/winnie_alloc_config.h \
+  $$SRC/winnie_alloc/system_alloc.h \
+  $$SRC/winnie_alloc/winnie_alloc.h \
+  $$SRC/winnie_alloc/winnie_alloc_config.h \
 
 SOURCES += \
-	$$SRC/core/gl/NativeTextureGLES.cpp \
-	$$SRC/core/gl/oxgl.cpp \
-	$$SRC/core/gl/VertexDeclarationGL.cpp \
-	$$SRC/core/gl/ShaderProgramGL.cpp \
-	$$SRC/core/gl/VideoDriverGL.cpp \
-	$$SRC/core/gl/VideoDriverGLES20.cpp \
+  $$SRC/core/gl/NativeTextureGLES.cpp \
+  $$SRC/core/gl/oxgl.cpp \
+  $$SRC/core/gl/VertexDeclarationGL.cpp \
+  $$SRC/core/gl/ShaderProgramGL.cpp \
+  $$SRC/core/gl/VideoDriverGL.cpp \
+  $$SRC/core/gl/VideoDriverGLES20.cpp \
 
 INCLUDEPATH += \
-	$$SRC \
-	$$SRC/../../../SDL/include/
+  $$SRC \
+  $$SRC/../../../SDL/include/
 
 debug
 {
-	DEFINES +=_DEBUG
-	DEFINES += OXYGINE_QT
+  DEFINES +=_DEBUG
+  DEFINES += OBJECT_POOL_ALLOCATOR
 }
 release
 {
-	DEFINES += OXYGINE_QT
 }
 
 THIRD_PARTY = $$ROOT/oxygine/third_party/win32_mingw
 
 INCLUDEPATH += $$THIRD_PARTY/libpng
 INCLUDEPATH += $$THIRD_PARTY/zlib
-#INCLUDEPATH += $$THIRD_PARTY/pthreads
+INCLUDEPATH += $$THIRD_PARTY/pthreads/include
 
 DEFINES += "OX_HAVE_LIBPNG=1"
 
 unix {
-	target.path = /usr/lib
-	INSTALLS += target
+  target.path = /usr/lib
+  INSTALLS += target
 }

+ 24 - 0
oxygine/src/Actor.h

@@ -53,6 +53,24 @@ namespace oxygine
     type* type::clone(cloneOptions opt) const {type *tp = new type(); tp->copyFrom(*this, opt); return tp;}
 
 
+    class TweenOptions
+    {
+    public:
+        explicit TweenOptions(timeMS duration): _duration(duration), _delay(0), _ease(Tween::ease_linear), _loops(1), _twoSides(false) {}
+        TweenOptions& duration(timeMS duration) { _duration = duration; return *this; }
+        TweenOptions& delay(timeMS delay) { _delay = delay; return *this; }
+        TweenOptions& loops(int loops) { _loops = loops; return *this; }
+        TweenOptions& twoSides(bool enabled = true) { _twoSides = enabled; return *this; }
+        TweenOptions& ease(Tween::EASE ease) { _ease = ease; return *this; }
+
+        timeMS  _duration;
+        timeMS  _delay;
+        Tween::EASE _ease;
+        int     _loops;
+        bool    _twoSides;
+    };
+
+
     class Actor : public EventDispatcher, public intrusive_list_item<spActor>, public Serializable
     {
         typedef intrusive_list_item<spActor> intr_list;
@@ -108,6 +126,8 @@ namespace oxygine
         Actor*              getParent() {return _parent;}
         const Actor*        getParent() const {return _parent;}
         Vector2             getSize() const {return _size;}
+        /**Returns Size*Scale*/
+        Vector2             getScaledSize() const { return _size.mult(_scale); }
         float               getWidth() const {return getSize().x;}
         float               getHeight() const {return getSize().y;}
         unsigned char       getAlpha() const {return _alpha;}
@@ -217,6 +237,10 @@ namespace oxygine
         spTween addTween(const Prop& prop, timeMS duration, int loops = 1, bool twoSides = false, timeMS delay = 0, Tween::EASE ease = Tween::ease_linear)
         {return addTween(createTween(prop, duration, loops, twoSides, delay, ease));}
 
+        template<class Prop>
+        spTween addTween2(const Prop& prop, const TweenOptions& opt)
+        {return addTween(createTween2(prop, opt));}
+
         void removeTween(spTween);
         void removeTweensByName(const std::string& name);
         /**remove all tweens and call completes them if callComplete == true*/

+ 25 - 3
oxygine/src/Font.cpp

@@ -55,19 +55,41 @@ namespace oxygine
         std::sort(_glyphs.begin(), _glyphs.end(), glyphsComparePred);
     }
 
-    const glyph* Font::getGlyph(int ch) const
+    const glyph* Font::findGlyph(int code) const
     {
-        glyphs::const_iterator it = std::lower_bound(_glyphs.begin(), _glyphs.end(), ch, glyphFindPred);
+        glyphs::const_iterator it = std::lower_bound(_glyphs.begin(), _glyphs.end(), code, glyphFindPred);
         if (it != _glyphs.end())
         {
             const glyph& g = *it;
-            if (g.ch == ch)
+            if (g.ch == code)
                 return &g;
         }
 
         return 0;
     }
 
+    const glyph* Font::getGlyph(int code) const
+    {
+        const glyph* g = findGlyph(code);
+        if (g)
+            return g;
+
+        glyph gl;
+        Font* fn = const_cast<Font*>(this);
+        if (fn->loadGlyph(code, gl))
+        {
+            glyphs::iterator it = std::lower_bound(fn->_glyphs.begin(), fn->_glyphs.end(), code, glyphFindPred);
+            fn->_glyphs.insert(it, gl);
+
+            //fn->addGlyph(gl);
+            //fn->sortGlyphs();
+            g = findGlyph(code);
+            OX_ASSERT(g);
+        }
+
+        return g;
+    }
+
     int Font::getBaselineDistance() const
     {
         return _baselineDistance;

+ 5 - 1
oxygine/src/Font.h

@@ -44,7 +44,11 @@ namespace oxygine
         float           getScale() const;
         int             getLineHeight() const;
 
-    private:
+    protected:
+        const glyph* findGlyph(int code) const;
+
+        virtual bool loadGlyph(int code, glyph&) { return false; }
+
         typedef std::vector<glyph> glyphs;
         glyphs _glyphs;
 

+ 21 - 2
oxygine/src/MaskedSprite.cpp

@@ -5,14 +5,30 @@
 
 namespace oxygine
 {
+    MaskedSprite::MaskedSprite() : _useRChannel(false)
+    {
+    }
+
+    MaskedSprite::~MaskedSprite()
+    {
+    }
+
+    void MaskedSprite::copyFrom(const MaskedSprite& src, cloneOptions opt)
+    {
+        _Sprite::copyFrom(src, opt);
+        _useRChannel = src._useRChannel;
+        //_mask = src._mask;
+    }
+
     spSprite MaskedSprite::getMask() const
     {
         return _mask;
     }
 
-    void MaskedSprite::setMask(spSprite mask)
+    void MaskedSprite::setMask(spSprite mask, bool useRChannel)
     {
         _mask = mask;
+        _useRChannel = useRChannel;
     }
 
     void MaskedSprite::render(const RenderState& parentRS)
@@ -27,7 +43,10 @@ namespace oxygine
             const Diffuse& df = _mask->getAnimFrame().getDiffuse();
 
 
-            MaskedRenderer mr(df.alpha ? df.alpha : df.base, maskSrc, maskDest, t, df.alpha ? true : false);
+            bool rchannel       = _useRChannel ? true    : (df.alpha ? true     : false);
+            spNativeTexture msk = _useRChannel ? df.base : (df.alpha ? df.alpha : df.base);
+
+            MaskedRenderer mr(msk, maskSrc, maskDest, t, rchannel);
             RenderState rs = parentRS;
             rs.renderer = &mr;
             mr.begin(parentRS.renderer);

+ 8 - 1
oxygine/src/MaskedSprite.h

@@ -8,8 +8,14 @@ namespace oxygine
     class MaskedSprite: public _Sprite
     {
     public:
+        DECLARE_COPYCLONE_NEW(MaskedSprite);
+
+        MaskedSprite();
+        ~MaskedSprite();
+
         spSprite getMask() const;
-        void setMask(spSprite);
+
+        void setMask(spSprite, bool useRChannel = false);
 
         void serialize(serializedata* data);
         void deserialize(const deserializedata* data);
@@ -20,6 +26,7 @@ namespace oxygine
 
     private:
         spSprite _mask;
+        bool _useRChannel;
     };
 }
 

+ 4 - 0
oxygine/src/ProgressBar.cpp

@@ -344,6 +344,10 @@ namespace oxygine
     void ProgressBar::setProgress(float f)
     {
         _progress = scalar::clamp(f, 0.0f, 1.0f);
+
+        Event ev(PROGRESS_CHANGED);
+        dispatchEvent(&ev);
+
         if (_direction == __dir_radial_ccw || _direction == dir_radial_cw)
             return;
         _update();

+ 2 - 0
oxygine/src/ProgressBar.h

@@ -9,6 +9,8 @@ namespace oxygine
     class ProgressBar: public _Sprite
     {
     public:
+        enum { PROGRESS_CHANGED = sysEventID('P', 'C', 'h') };
+
         enum direction
         {
             dir_0,//moveable right edge

+ 3 - 3
oxygine/src/SlidingActor.cpp

@@ -23,12 +23,12 @@ namespace oxygine
         _speed(0, 0),
         _lastTime(0), _current(0), _lastIterTime(0)
     {
-        _clip = initActor(new ClipRectActor,
-                          arg_attachTo = this);
-
+        _clip = new ClipRectActor;
         _clip->addEventListener(TouchEvent::TOUCH_DOWN, CLOSURE(this, &SlidingActor::_newEvent));
         _clip->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &SlidingActor::_newEvent));
         _clip->addEventListener(TouchEvent::MOVE, CLOSURE(this, &SlidingActor::_newEvent));
+
+        addChild(_clip);
     }
 
     void SlidingActor::destroy()

+ 1 - 2
oxygine/src/Sprite.cpp

@@ -257,8 +257,7 @@ namespace oxygine
         if (res)
         {
             ResAnim* rs = safeCast<ResAnim*>(data->factory->getResAnim(res));
-
-            setResAnim(rs);
+            setResAnim(rs, node.attribute("col").as_int(0), node.attribute("row").as_int(0));
         }
     }
 }

+ 15 - 1
oxygine/src/TextField.cpp

@@ -93,7 +93,7 @@ namespace oxygine
         needRebuild();
     }
 
-    void TextField::setFont(Font* font)
+    void TextField::setFont(const Font* font)
     {
         _style.font = font;
     }
@@ -104,6 +104,13 @@ namespace oxygine
         needRebuild();
     }
 
+    void TextField::setAlign(TextStyle::VerticalAlign vAlign, TextStyle::HorizontalAlign hAlign)
+    {
+        _style.vAlign = vAlign;
+        _style.hAlign = hAlign;
+        needRebuild();
+    }
+
     void TextField::setStyle(const TextStyle& st)
     {
         TextStyle::HorizontalAlign halign = _style.hAlign;
@@ -159,6 +166,11 @@ namespace oxygine
         return _style.fontSize2Scale;
     }
 
+    int TextField::getLinesOffset() const
+    {
+        return _style.linesOffset;
+    }
+
     TextStyle::VerticalAlign    TextField::getVAlign() const
     {
         return _style.vAlign;
@@ -351,6 +363,7 @@ namespace oxygine
         if (!_text.empty())
             node.append_attribute("text").set_value(_text.c_str());
         setAttr(node, "fontsize2scale", _style.fontSize2Scale, def.fontSize2Scale);
+        setAttr(node, "linesOffset", _style.linesOffset, def.linesOffset);
         setAttr(node, "valign", _style.vAlign, def.vAlign);
         setAttr(node, "halign", _style.hAlign, def.hAlign);
         setAttr(node, "multiline", _style.multiline, def.multiline);
@@ -370,6 +383,7 @@ namespace oxygine
         _style.multiline = node.attribute("multiline").as_bool(def.multiline);
         _style.breakLongWords = node.attribute("breakLongWords").as_bool(def.breakLongWords);
         _style.fontSize2Scale = node.attribute("fontsize2scale").as_int(def.fontSize2Scale);
+        _style.linesOffset = node.attribute("linesOffset").as_int(def.linesOffset);
         needRebuild();
         setText(node.attribute("text").as_string());
     }

+ 3 - 1
oxygine/src/TextField.h

@@ -31,6 +31,7 @@ namespace oxygine
         /**Returns current text*/
         const std::string&          getText() const { return _text; }
         int                         getFontSize2Scale() const;
+        int                         getLinesOffset() const;
         TextStyle::VerticalAlign    getVAlign() const;
         TextStyle::HorizontalAlign  getHAlign() const;
         bool                        getMultiline() const;
@@ -40,6 +41,7 @@ namespace oxygine
         void setVAlign(TextStyle::VerticalAlign align);
         /**Overwrites TextStyle Horizontal align*/
         void setHAlign(TextStyle::HorizontalAlign align);
+        void setAlign(TextStyle::VerticalAlign, TextStyle::HorizontalAlign);
         /**Overwrites TextStyle multiline*/
         void setMultiline(bool multiline);
         /**Overwrites TextStyle breakLongWords*/
@@ -49,7 +51,7 @@ namespace oxygine
         /**Overwrites TextStyle scale2Size.*/
         void setFontSize2Scale(int scale2size);
         /**Overwrites TextStyle font.*/
-        void setFont(Font* rs);
+        void setFont(const Font* rs);
 
         void setStyle(const TextStyle& st);
         /**Changes text utf-8 string*/

+ 1 - 1
oxygine/src/TextStyle.h

@@ -37,7 +37,7 @@ namespace oxygine
             fontSize2Scale(0),
             breakLongWords(false) {}
 
-        Font* font;
+        const Font* font;
 
         HorizontalAlign hAlign;
         VerticalAlign vAlign;

+ 15 - 0
oxygine/src/Tween.cpp

@@ -39,6 +39,21 @@ namespace oxygine
         }
     }
 
+	void Tween::init2(const TweenOptions& opt)
+	{
+		_duration = opt._duration;
+		_ease = opt._ease;
+		_loops = opt._loops;
+		_twoSides = opt._twoSides;
+		_delay = opt._delay;
+
+		if (_duration <= 0)
+		{
+			OX_ASSERT(!"Tweener duration should be more than ZERO");
+			_duration = 1;
+		}
+	}
+
     void Tween::setDoneCallback(EventCallback cb)
     {
         _cbDone = cb;

+ 11 - 0
oxygine/src/Tween.h

@@ -33,6 +33,7 @@ namespace oxygine
     };
 
     class UpdateState;
+    class TweenOptions;
 
 
     DECLARE_SMART(Tween, spTween);
@@ -98,11 +99,13 @@ namespace oxygine
         ~Tween();
 
         void init(timeMS duration, int loops = 1, bool twoSides = false, timeMS delay = 0, EASE ease = Tween::ease_linear);//todo twoSide find better name
+        void init2(const TweenOptions& opt);
         /**if you reset internal Tween state it could be reused and added to actor again */
         void reset();
 
         int         getLoops() const { return _loops; }
         timeMS      getDuration() const { return _duration; }
+        timeMS      getElapsed() const { return _elapsed; }
         EASE        getEase() const { return _ease; }
         timeMS      getDelay() const { return _delay; }
         Actor*      getClient() const { return _client; }
@@ -217,5 +220,13 @@ namespace oxygine
         return p;
     }
 
+    template <typename GS>
+    TweenT<GS>* createTween2(const GS& gs, const TweenOptions& opt)
+    {
+        TweenT<GS>* p = new TweenT<GS>(gs);
+        p->init2(opt);
+        return p;
+    }
+
     std::string ease2String(Tween::EASE ease);
 }

+ 7 - 23
oxygine/src/TweenAnim.cpp

@@ -11,7 +11,7 @@ namespace oxygine
         _end(0)
     {
         if (_resAnim)
-            _end = _resAnim->getColumns();
+            _end = _resAnim->getColumns() - 1;
     }
 
     TweenAnim::TweenAnim(const ResAnim* resAnim, int startFrame, int endFrame):
@@ -20,7 +20,7 @@ namespace oxygine
         _start(0),
         _end(0)
     {
-
+        setInterval(startFrame, endFrame);
     }
 
     void TweenAnim::init(Sprite& actor)
@@ -33,20 +33,17 @@ namespace oxygine
     {
         _resAnim = resAnim;
         if (_resAnim && _row != -1)
-            _end = _resAnim->getColumns();
-    }
-
-
-    void TweenAnim::setColumns(int start, int end)
-    {
-        _start = start;
-        _end = end;
+            _end = _resAnim->getColumns() - 1;
     }
 
     void TweenAnim::setInterval(int start, int end)
     {
         _start = start;
         _end = end;
+
+        int num = _row == -1 ? _resAnim->getTotalFrames() : _resAnim->getColumns();
+        OX_ASSERT(_start >= 0 && _start < num);
+        OX_ASSERT(_end >= 0 && _end < num);
     }
 
 
@@ -55,19 +52,6 @@ namespace oxygine
         OX_ASSERT(_resAnim);
         int frame = interpolate<int>(_start, _end, p);
 
-        if (_start > _end)
-        {
-            if (frame <= _end)
-                frame = _end + 1;
-            OX_ASSERT(frame <= _start && frame > _end);
-        }
-        else
-        {
-            if (frame >= _end)
-                frame = _end - 1;
-            OX_ASSERT(frame >= _start && frame < _end);
-        }
-
         if (_row == -1)
             actor.setAnimFrame(_resAnim->getFrame(frame));
         else

+ 2 - 5
oxygine/src/TweenAnim.h

@@ -22,7 +22,7 @@ namespace oxygine
         /**Row/Column mode. Plays single row*/
         TweenAnim(const ResAnim* resAnim, int row = 0);
 
-        /**Frames mode. Plays frames from start to end*/
+        /**Frames mode. Play animation in interval [start, end]*/
         TweenAnim(const ResAnim* resAnim, int startFrame, int endFrame);
 
         void init(Sprite& actor);
@@ -35,10 +35,7 @@ namespace oxygine
         /**Changes ResAnim*/
         void setResAnim(const ResAnim* resAnim);
 
-        /**Play animation in interval [start, end). Deprecated, use setInterval*/
-        void setColumns(int start, int end);
-
-        /**Play animation in interval [start, end)*/
+        /**Play animation in interval [start, end]*/
         void setInterval(int start, int end);
 
         void update(Sprite& actor, float p, const UpdateState& us);

+ 31 - 15
oxygine/src/TweenQueue.cpp

@@ -2,44 +2,55 @@
 
 namespace oxygine
 {
-    spTweenQueue TweenQueue::create(spTween t1, spTween t2)
+    spTweenQueue TweenQueue::create(spTween t1)
     {
         spTweenQueue t = new TweenQueue;
         t->add(t1);
+        return t;
+    }
+
+    spTweenQueue TweenQueue::create(spTween t1, spTween t2)
+    {
+        spTweenQueue t = create(t1);
         t->add(t2);
         return t;
     }
 
     spTweenQueue TweenQueue::create(spTween t1, spTween t2, spTween t3)
     {
-        spTweenQueue t = new TweenQueue;
-        t->add(t1);
-        t->add(t2);
+        spTweenQueue t = create(t1, t2);
         t->add(t3);
         return t;
     }
 
     spTweenQueue TweenQueue::create(spTween t1, spTween t2, spTween t3, spTween t4)
     {
-        spTweenQueue t = new TweenQueue;
-        t->add(t1);
-        t->add(t2);
-        t->add(t3);
+        spTweenQueue t = create(t1, t2, t3);
         t->add(t4);
         return t;
     }
 
     spTweenQueue TweenQueue::create(spTween t1, spTween t2, spTween t3, spTween t4, spTween t5)
     {
-        spTweenQueue t = new TweenQueue;
-        t->add(t1);
-        t->add(t2);
-        t->add(t3);
-        t->add(t4);
+        spTweenQueue t = create(t1, t2, t3, t4);
         t->add(t5);
         return t;
     }
 
+    spTweenQueue TweenQueue::create(spTween t1, spTween t2, spTween t3, spTween t4, spTween t5, spTween t6)
+    {
+        spTweenQueue t = create(t1, t2, t3, t4, t5);
+        t->add(t6);
+        return t;
+    }
+
+    spTweenQueue TweenQueue::create(spTween t1, spTween t2, spTween t3, spTween t4, spTween t5, spTween t6, spTween t7)
+    {
+        spTweenQueue t = create(t1, t2, t3, t4, t5, t6);
+        t->add(t7);
+        return t;
+    }
+
     TweenQueue::TweenQueue(): _loopsDone(0) {}
 
     spTween TweenQueue::add(spTween t)
@@ -64,6 +75,9 @@ namespace oxygine
         if (!_current)
             return;
 
+        Event ev(EVENT_LOOP_BEGIN);
+        dispatchEvent(&ev);
+
         _current->start(actor);
     }
 
@@ -85,6 +99,9 @@ namespace oxygine
 
         if (!_current)
         {
+            Event ev(EVENT_LOOP_END);
+            dispatchEvent(&ev);
+
             _loopsDone++;
 
             if (_loopsDone >= _loops && _loops > 0)
@@ -100,8 +117,7 @@ namespace oxygine
                     next = next->getNextSibling();
                 }
 
-                _current = _tweens._first;
-                _current->start(actor);
+                _start(actor);
             }
         }
     }

+ 13 - 0
oxygine/src/TweenQueue.h

@@ -7,8 +7,15 @@ namespace oxygine
     class TweenQueue : public Tween
     {
     public:
+
+        enum { EVENT_LOOP_BEGIN = sysEventID('T', 'L', 'B'), };
+        enum { EVENT_LOOP_END = sysEventID('T', 'L', 'E'), };
+
         TweenQueue();
 
+        /**short syntax for easy tween queue creation*/
+        static spTweenQueue create(spTween t1);
+
         /**short syntax for easy tween queue creation*/
         static spTweenQueue create(spTween t1, spTween t2);
 
@@ -21,6 +28,12 @@ namespace oxygine
         /**short syntax for easy tween queue creation*/
         static spTweenQueue create(spTween t1, spTween t2, spTween t3, spTween t4, spTween t5);
 
+        /**short syntax for easy tween queue creation*/
+        static spTweenQueue create(spTween t1, spTween t2, spTween t3, spTween t4, spTween t5, spTween t6);
+
+        /**short syntax for easy tween queue creation*/
+        static spTweenQueue create(spTween t1, spTween t2, spTween t3, spTween t4, spTween t5, spTween t6, spTween t7);
+
         /*Add new new tween to Queue, returns added tween*/
         spTween add(spTween t);
 

+ 12 - 1
oxygine/src/core/gl/NativeTextureGLES.cpp

@@ -329,8 +329,9 @@ namespace oxygine
     }
 
 
-    void NativeTextureGLES::updateRegion(int x, int y, const ImageData& data)
+    void NativeTextureGLES::updateRegion(int x, int y, const ImageData& data_)
     {
+        ImageData data = data_;
         assert(_width >= data.w - x);
         assert(_height >= data.h - y);
         glBindTexture(GL_TEXTURE_2D, _id);
@@ -338,6 +339,16 @@ namespace oxygine
         glPixel glp = SurfaceFormat2GL(_format);
         //saveImage(data, "test1.png");
 
+
+        MemoryTexture mt;
+        if (_format != data.format)
+        {
+            mt.init(data.w, data.h, _format);
+            mt.fill_zero();
+            mt.updateRegion(0, 0, data);
+            data = mt.lock();
+        }
+
         glTexSubImage2D(GL_TEXTURE_2D, 0,
                         x, y, data.w, data.h,
                         glp.format, glp.type, data.data);

+ 1 - 1
oxygine/src/initActor.h

@@ -69,7 +69,7 @@ namespace oxygine
         typedef argT<TextStyle::HorizontalAlign, TextStyle::HorizontalAlign, TextField, &TextField::setHAlign> hAlign;
         typedef argT<TextStyle::VerticalAlign, TextStyle::VerticalAlign, TextField, &TextField::setVAlign> vAlign;
         typedef argT<int, int, TextField, &TextField::setFontSize2Scale> fontSize2Scale;
-        typedef argT<Font*, Font*, TextField, &TextField::setFont> font;
+        typedef argT<const Font*, const Font*, TextField, &TextField::setFont> font;
         typedef argT<bool, bool, TextField, &TextField::setMultiline> multiline;
 
 

+ 3 - 1
oxygine/src/res/ResAtlas.cpp

@@ -34,7 +34,7 @@ namespace oxygine
     {
         spNativeTexture texture;
         MemoryTexture mt;
-        Atlas atlas;
+        Atlas2 atlas;
     };
 
 
@@ -156,6 +156,8 @@ namespace oxygine
             ra = rs;
         }
 
+        context.resources->add(ra);
+
         ra->setName(_Resource::extractID(context.walker.getNode(), "", std::string("!atlas:") + *context.xml_name));
         setNode(ra, context.walker.getNode());
 

+ 3 - 0
oxygine/src/res/ResBuffer.cpp

@@ -1,4 +1,5 @@
 #include "ResBuffer.h"
+#include "Resources.h"
 #include "CreateResourceContext.h"
 
 namespace oxygine
@@ -13,6 +14,8 @@ namespace oxygine
         rs->init(context.walker.getPath("file").c_str());
         setNode(rs, node);
 
+        context.resources->add(rs);
+
         return rs;
     }
 

+ 1 - 1
oxygine/src/res/ResFont.h

@@ -9,6 +9,6 @@ namespace oxygine
     class ResFont: public _Resource
     {
     public:
-        virtual Font* getFont(const char* name = 0, int size = 0) const = 0;
+        virtual const Font* getFont(const char* name = 0, int size = 0) const = 0;
     };
 }

+ 1 - 1
oxygine/src/res/ResFontBM.cpp

@@ -330,7 +330,7 @@ namespace oxygine
         }
     }
 
-    Font* ResFontBM::getFont(const char* name, int size) const
+    const Font* ResFontBM::getFont(const char* name, int size) const
     {
         return _font;
     }

+ 1 - 1
oxygine/src/res/ResFontBM.h

@@ -27,7 +27,7 @@ namespace oxygine
 
         void cleanup();
 
-        Font* getFont(const char* name = 0, int size = 0) const;
+        const Font* getFont(const char* name = 0, int size = 0) const OVERRIDE;
 
     private:
         struct page

+ 7 - 7
oxygine/src/text_utils/Aligner.cpp

@@ -113,7 +113,7 @@ namespace oxygine
                 for (size_t i = 0; i < ln.size(); ++i)
                 {
                     Symbol& s = *ln[i];
-                    rx = std::max(s.x + s.gl->sw, rx);
+                    rx = std::max(s.x + s.gl.sw, rx);
                 }
 
                 int tx = _alignX(rx);
@@ -163,14 +163,14 @@ namespace oxygine
             _line.push_back(&s);
 
             //optional.. remove?
-            if (_line.size() == 1 && s.gl->offset_x < 0)
-                _x -= s.gl->offset_x;
+            if (_line.size() == 1 && s.gl.offset_x < 0)
+                _x -= s.gl.offset_x;
 
-            s.x = _x + s.gl->offset_x;
-            s.y = _y + s.gl->offset_y;
-            _x += s.gl->advance_x + getStyle().kerning;
+            s.x = _x + s.gl.offset_x;
+            s.y = _y + s.gl.offset_y;
+            _x += s.gl.advance_x + getStyle().kerning;
 
-            int rx = s.x + s.gl->sw;
+            int rx = s.x + s.gl.sw;
 
 
             _lineWidth = std::max(rx, _lineWidth);

+ 4 - 2
oxygine/src/text_utils/Aligner.h

@@ -4,6 +4,8 @@
 #include "math/Rect.h"
 #include "math/Color.h"
 #include "TextStyle.h"
+#include "Font.h"
+#include "core/NativeTexture.h"
 
 namespace oxygine
 {
@@ -14,11 +16,11 @@ namespace oxygine
     {
         struct Symbol
         {
-            Symbol(): gl(0), x(0), y(0), code(0) {}
+            Symbol(): x(0), y(0), code(0) {}
 
             short x, y;
             int code;
-            const glyph* gl;
+            glyph gl;
             RectF destRect;
         };
 

+ 11 - 8
oxygine/src/text_utils/Node.cpp

@@ -127,9 +127,9 @@ namespace oxygine
             for (size_t i = 0; i < _data.size(); ++i)
             {
                 const Symbol& s = _data[i];
-                if (!s.gl)
+                if (!s.gl.texture)
                     continue;
-                dc.renderer->draw(dc.rs->transform, s.gl->texture, dc.color.rgba(), s.gl->src, s.destRect);
+                dc.renderer->draw(dc.rs->transform, s.gl.texture, dc.color.rgba(), s.gl.src, s.destRect);
             }
 
             drawChildren(dc);
@@ -146,22 +146,25 @@ namespace oxygine
             if (!_data.empty())
             {
                 int i = 0;
-                Font* font = rd.getStyle().font;
+                const Font* font = rd.getStyle().font;
 
                 while (i != (int)_data.size())
                 {
                     Symbol& s = _data[i];
                     //wchar_t c = s.c;
-                    s.gl = font->getGlyph(s.code);
-                    if (s.gl)
+                    const glyph* gl = font->getGlyph(s.code);
+                    if (gl)
+                    {
+                        s.gl = *gl;
                         i += rd.putSymbol(s);
+                    }
                     else
                     {
                         if (s.code == '\n')
                             rd.nextLine();
                         else
                         {
-                            s.gl = font->getGlyph(_defMissing);
+                            s.gl = *font->getGlyph(_defMissing);
                             i += rd.putSymbol(s);
                         }
                     }
@@ -189,8 +192,8 @@ namespace oxygine
                 Symbol& s = _data[i];
                 s.y += offsetY;
 
-                if (s.gl)
-                    s.destRect = RectF(mlt(s.x, scaleFactor), mlt(s.y, scaleFactor), mlt(s.gl->sw, scaleFactor), mlt(s.gl->sh, scaleFactor));
+                if (s.gl.texture)
+                    s.destRect = RectF(mlt(s.x, scaleFactor), mlt(s.y, scaleFactor), mlt(s.gl.sw, scaleFactor), mlt(s.gl.sh, scaleFactor));
                 else
                     s.destRect = RectF(0, 0, 0, 0);
 

+ 206 - 0
oxygine/src/utils/AtlasTool.cpp

@@ -122,4 +122,210 @@ namespace oxygine
 
         return false;
     }
+
+
+    Atlas2::Atlas2() : _bounds(0, 0, 0, 0), _skipSize(3)
+    {
+
+    }
+
+    void Atlas2::clean()
+    {
+
+    }
+
+    void Atlas2::init(int w, int h, int skipSize)
+    {
+        _skipSize = skipSize;
+        _bounds = Rect(0, 0, 0, 0);
+        _free.clear();
+        //_free.reserve(15);
+        _free.push_back(Rect(0, 0, w, h));
+    }
+
+    bool sortRects(const Rect& a, const Rect& b)
+    {
+        return std::min(a.size.x, a.size.y) < std::min(b.size.x, b.size.y);
+        //return a.pos.y < b.pos.y;
+        //return a.size.x * a.size.y < b.size.x * b.size.y;
+        //return a.size.x < b.size.x;
+        //return a.size.y < b.size.y;
+    }
+
+    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;
+
+        int w = src.w + offset.x;
+        int h = src.h + offset.y;
+
+        Point size(w, h);
+
+        for (size_t i = 0; i != _free.size(); ++i)
+        {
+            const Rect& rect_ = _free[i];
+            if (rect_.getWidth() >= w && rect_.getHeight() >= h)
+            {
+                Rect rect = rect_;
+
+                srcRect.pos = rect.pos;
+                srcRect.size = Point(src.w, src.h);
+
+                _bounds.unite(srcRect);
+
+                dest->updateRegion(rect.pos.x, rect.pos.y, src);
+
+                _free.erase(_free.begin() + i);
+
+                Point ds = rect.size - size;
+
+
+                Rect a = rect;
+                Rect b = rect;
+
+                if (ds.x > ds.y)
+                    a.setWidth(w);
+                else
+                    b.setHeight(h);
+
+                b.setWidth(ds.x);
+                a.setHeight(ds.y);
+
+                if (!a.isEmpty() && std::min(a.getWidth(), a.getHeight()) > _skipSize)
+                {
+                    a.pos.y = rect.pos.y + h;
+                    rects::iterator i = std::lower_bound(_free.begin(), _free.end(), a, sortRects);
+                    _free.insert(i, a);
+                }
+
+
+                if (!b.isEmpty() && std::min(b.getWidth(), b.getHeight()) > _skipSize)
+                {
+                    b.pos.x = rect.pos.x + w;
+                    rects::iterator i = std::lower_bound(_free.begin(), _free.end(), b, sortRects);
+                    _free.insert(i, b);
+                }
+
+                return true;
+            }
+        }
+        return false;
+        ///Rect a = re
+    }
+
+    MultiAtlas::MultiAtlas(createTextureCallback cb) : _bounds(0, 0, 0, 0), _skipSize(3), _cb(cb)
+    {
+
+    }
+
+    void MultiAtlas::clean()
+    {
+        _free.clear();
+    }
+
+    void MultiAtlas::init(int skipSize)
+    {
+        _skipSize = skipSize;
+
+        /*
+        _bounds = Rect(0, 0, 0, 0);
+        _free.clear();
+        //_free.reserve(15);
+        _free.push_back(Rect(0, 0, w, h));
+        */
+    }
+
+    bool MultiAtlas::sortRects(const rect& a, const rect& b)
+    {
+        return std::min(a.rct.size.x, a.rct.size.y) < std::min(b.rct.size.x, b.rct.size.y);
+        //return a.pos.y < b.pos.y;
+        //return a.size.x * a.size.y < b.size.x * b.size.y;
+        //return a.size.x < b.size.x;
+        //return a.size.y < b.size.y;
+    }
+
+    void MultiAtlas::place(const rect& rct, int w, int h, const ImageData& src, spTexture& t, Rect& srcRect)
+    {
+        const Rect& rc = rct.rct;
+        srcRect.pos = rc.pos;
+        srcRect.size = Point(src.w, src.h);
+        t = rct.texture;
+
+
+        Point size(w, h);
+
+        Point ds = rc.size - size;
+        rct.texture->updateRegion(rc.pos.x, rc.pos.y, src);
+
+
+        rect a = rct;
+        rect b = rct;
+
+        if (ds.x > ds.y)
+            a.rct.setWidth(w);
+        else
+            b.rct.setHeight(h);
+
+        b.rct.setWidth(ds.x);
+        a.rct.setHeight(ds.y);
+
+        if (!a.rct.isEmpty() && std::min(a.rct.getWidth(), a.rct.getHeight()) > _skipSize)
+        {
+            a.rct.pos.y = rct.rct.pos.y + h;
+            rects::iterator i = std::lower_bound(_free.begin(), _free.end(), a, sortRects);
+            _free.insert(i, a);
+        }
+
+
+        if (!b.rct.isEmpty() && std::min(b.rct.getWidth(), b.rct.getHeight()) > _skipSize)
+        {
+            b.rct.pos.x = rct.rct.pos.x + w;
+            rects::iterator i = std::lower_bound(_free.begin(), _free.end(), b, sortRects);
+            _free.insert(i, b);
+        }
+    }
+
+    bool MultiAtlas::add(const ImageData& src, Rect& srcRect, spTexture& t)
+    {
+        Point offset(2, 2);
+
+        int w = src.w + offset.x;
+        int h = src.h + offset.y;
+
+        Point size(w, h);
+
+        for (size_t i = 0; i != _free.size(); ++i)
+        {
+            const rect& rect_ = _free[i];
+            if (rect_.rct.getWidth() >= w && rect_.rct.getHeight() >= h)
+            {
+                rect rct = rect_;
+
+                _bounds.unite(srcRect);
+
+                _free.erase(_free.begin() + i);
+                place(rct, w, h, src, t, srcRect);
+
+                return true;
+            }
+        }
+
+        rect rc;
+        rc.texture = _cb(w, h);
+        if (!rc.texture)
+            return false;
+
+        rc.rct = Rect(0, 0, rc.texture->getWidth(), rc.texture->getHeight());
+
+
+        place(rc, w, h, src, t, srcRect);
+
+
+        return true;
+        ///Rect a = re
+    }
 }

+ 57 - 0
oxygine/src/utils/AtlasTool.h

@@ -2,6 +2,8 @@
 #include "oxygine_include.h"
 #include "math/Rect.h"
 #include "AnimationFrame.h"
+#include <deque>
+#include <list>
 
 namespace oxygine
 {
@@ -47,4 +49,59 @@ namespace oxygine
         Rect _bounds;
         AtlasNode* _tree;
     };
+
+
+
+    class Atlas2
+    {
+    public:
+        Atlas2();
+
+        void init(int w, int h, int skipSize = 3);
+        void clean();
+
+        bool add(Texture* dest, const ImageData& src, Rect& srcRect);
+
+        const Rect& getBounds() const { return _bounds; }
+
+    protected:
+        typedef std::deque<Rect> rects;
+        Rect _bounds;
+        rects _free;
+        int _skipSize;
+    };
+
+
+
+    class MultiAtlas
+    {
+    public:
+        typedef Closure<spTexture(int w, int h)> createTextureCallback;
+
+        MultiAtlas(createTextureCallback);
+
+        void init(int skipSize = 3);
+        void clean();
+
+        bool add(const ImageData& src, Rect& srcRect, spTexture& t);
+
+        const Rect& getBounds() const { return _bounds; }
+
+    protected:
+        struct rect
+        {
+            spTexture texture;
+            Rect rct;
+        };
+
+        createTextureCallback _cb;
+
+        void place(const rect& dest, int w, int h, const ImageData& src, spTexture& t, Rect& srcRect);
+
+        typedef std::deque<rect> rects;
+        Rect _bounds;
+        rects _free;
+        int _skipSize;
+        static bool sortRects(const rect& a, const rect& b);
+    };
 }

+ 1 - 1
readme.md

@@ -1,4 +1,4 @@
-# BUILD AND RUN 
+# BUILD AND RUN  
 See **oxygine-framework/readme/** folder. It has insructions how to build and run oxygine on different platforms.
 
 # Online documentation available at

+ 2 - 1
tools/others/build_oxygine_with_sdl.py

@@ -20,7 +20,8 @@ def recursive_zip(zipf, directory, folder = ""):
             bts = open(src, "rb").read()
             if ext == ".sh" or item in ("PVRTexToolCLI", "oxyresbuild.py", "gen_template.py", "png_strip.py"):
                 info.external_attr = 0755 << 16L #a+x
-            zipf.writestr(info, bts, zipfile.ZIP_DEFLATED)
+            #zipf.writestr(info, bts, zipfile.ZIP_DEFLATED)
+            zipf.write(os.path.join(directory, item), folder + os.sep + item)
             
             
         elif os.path.isdir(os.path.join(directory, item)):

+ 4 - 0
tools/oxyresbuild.py

@@ -1,5 +1,8 @@
 #!/usr/bin/python
 
+def str2bool(v):
+    return v.lower() in ("yes", "true", "t", "1")
+
 def get_parser():
     import argparse	
     parser = argparse.ArgumentParser(description="oxyresbuild is being used to processing and optimizing xml resources file. It generated <xml-name>.ox folder with meta.xml file inside. Meta file has optimized information about resources, atlasses.")
@@ -21,6 +24,7 @@ def get_parser():
     parser.add_argument("-v", "--verbosity", help = "verbosity level. 1 - only errors, 2 - normal. Default value is 2", type=int, default = 2)
     parser.add_argument("--hash", help = "enables creating md5 hash lists for some special files", action="store_true", default = False)
     parser.add_argument("--debug", help = "debug mode", action="store_true", default = False)
+    parser.add_argument("--no_hit_test", help = "disables generation hit_test data by default", action="store_true", default = False)
     parser.add_argument("--nopng", help = "stores images without packing to png. TGA will be used if compressiong disabled.", 
                         action="store_true", default = False)            
     return parser

+ 2 - 1
tools/resbuild/process_atlas.py

@@ -422,7 +422,8 @@ def processRS(context, walker):
                 r,g,b,a = frame_image.split()
                 a = a.point(lambda p: p - 2)
 
-                adata = makeAlpha(a)
+                if walker.hit_test:
+                    adata = makeAlpha(a)
 
                 frame_bbox = a.getbbox()
             else:

+ 19 - 5
tools/resbuild/xml_processor.py

@@ -6,8 +6,14 @@ from . import process_font
 from . import process_starling_atlas
 from . import oxygine_helper
 
+def as_bool(attr):
+    if not attr:
+        return False
+    lw = attr.lower()
+    return lw == "true" or lw == "1"
+
 class XmlWalker:
-    def __init__(self, src, xml_folder, path, scale_factor, node, meta_node, scale_quality):
+    def __init__(self, src, xml_folder, path, scale_factor, node, meta_node, scale_quality, hit_test):
         self.xml_folder = xml_folder
         self.path = path
         self.scale_factor = scale_factor
@@ -17,6 +23,7 @@ class XmlWalker:
         self.last_meta = None        
         self.src = src
         self.scale_quality = scale_quality
+        self.hit_test = hit_test
         self.checkSetAttributes()
     
     def getType(self):
@@ -48,6 +55,7 @@ class XmlWalker:
             if path.startswith("./") or path.startswith(".\\"):
                 path = self.xml_folder + path[2:len(path)]
             self.path = path + "/"
+
         scale_factor = node.getAttribute("scale_factor")
         if scale_factor:
             self.scale_factor = float(scale_factor)
@@ -55,6 +63,10 @@ class XmlWalker:
         scale_quality = node.getAttribute("scale_quality")
         if scale_quality:
             self.scale_quality = float(scale_quality)        
+
+        attr = node.getAttribute("hit_test")
+        if attr:
+            self.hit_test = as_bool(attr)
     
     def next(self):
         while True:
@@ -82,12 +94,10 @@ class XmlWalker:
             if self.last.nodeName == "set":
                 self._checkSetAttributes(self.last)
                 continue
-            
-            
                 
             break
             
-        return XmlWalker(self.src, self.xml_folder, self.path, self.scale_factor, self.last, self.last_meta, self.scale_quality)
+        return XmlWalker(self.src, self.xml_folder, self.path, self.scale_factor, self.last, self.last_meta, self.scale_quality, self.hit_test)
                 
             
         
@@ -243,7 +253,11 @@ class XmlProcessor:
         
         xml_folder = os.path.split(self.path_xml)[0] + "/"
         
-        walker = XmlWalker(self.src_data, xml_folder, "", 1.0, doc.documentElement, meta_element, 1.0)
+        hit_test = True
+        if self.args.no_hit_test:
+            hit_test = False
+            
+        walker = XmlWalker(self.src_data, xml_folder, "", 1.0, doc.documentElement, meta_element, 1.0, hit_test)
         
         while True:
             next = walker.next();