2
0
Denis Muratshin 12 жил өмнө
parent
commit
7551867f5a
71 өөрчлөгдсөн 1821 нэмэгдсэн , 1485 устгасан
  1. 2 2
      .hg_archival.txt
  2. 1 0
      .hgignore
  3. 1 0
      Android.mk
  4. BIN
      doc.zip
  5. BIN
      examples/Demo/data/images/anim2.png
  6. 1 0
      examples/Demo/data/xmls/res.xml
  7. 0 4
      examples/Demo/ios/OxygineDemo/OxygineDemo.xcodeproj/project.pbxproj
  8. 1 1
      examples/Demo/src/TestClipRect.h
  9. 1 1
      examples/Demo/src/TestDrag.h
  10. 3 3
      examples/Demo/src/TestManageRes.h
  11. 3 3
      examples/Demo/src/TestPerf.h
  12. 14 4
      examples/Demo/src/TestProgressBar.h
  13. 1 5
      examples/Demo/src/TestRender2Texture.h
  14. 9 16
      examples/Demo/src/TestTweens.h
  15. 9 12
      examples/Demo/src/TestUserShader.h
  16. 5 6
      examples/Demo/src/entry_point.cpp
  17. 4 2
      examples/DemoBox2D/src/Box2DDebugDraw.cpp
  18. 1 2
      examples/DemoBox2D/src/entry_point.cpp
  19. 1 1
      examples/GameTemplate/src/GameActor.cpp
  20. 2 2
      examples/GameTemplate/src/MainMenu.cpp
  21. 1 2
      examples/GameTemplate/src/entry_point.cpp
  22. 1 2
      examples/HelloWorld/src/entry_point.cpp
  23. 1 2
      examples/Match3/src/entry_point.cpp
  24. 5 7
      examples/Match3/src/gameframe.cpp
  25. 2 3
      examples/Match3/src/jewels.cpp
  26. 55 0
      mat2vertex.patch
  27. 16 0
      oxygine/SDL/oxygine_xcode/oxygine/oxygine.xcodeproj/project.pbxproj
  28. 47 50
      oxygine/src/Actor.cpp
  29. 8 8
      oxygine/src/Actor.h
  30. 1 1
      oxygine/src/AnimationFrame.cpp
  31. 10 6
      oxygine/src/ClipRectActor.cpp
  32. 1 1
      oxygine/src/DebugActor.cpp
  33. 0 2
      oxygine/src/Event.h
  34. 259 4
      oxygine/src/ProgressBar.cpp
  35. 6 1
      oxygine/src/ProgressBar.h
  36. 2 2
      oxygine/src/RenderState.h
  37. 3 2
      oxygine/src/RootActor.cpp
  38. 7 1
      oxygine/src/SlidingActor.cpp
  39. 1 0
      oxygine/src/SlidingActor.h
  40. 114 116
      oxygine/src/Tweener.cpp
  41. 47 47
      oxygine/src/Tweener.h
  42. 3 28
      oxygine/src/core/NativeTexture.cpp
  43. 280 114
      oxygine/src/core/Renderer.cpp
  44. 57 24
      oxygine/src/core/Renderer.h
  45. 2 3
      oxygine/src/core/ShaderProgram.h
  46. 123 0
      oxygine/src/core/UberShaderProgram.cpp
  47. 60 0
      oxygine/src/core/UberShaderProgram.h
  48. 11 63
      oxygine/src/core/VideoDriver.cpp
  49. 50 88
      oxygine/src/core/VideoDriver.h
  50. 10 1
      oxygine/src/core/gl/NativeTextureGLES.cpp
  51. 104 0
      oxygine/src/core/gl/ShaderProgramGL.cpp
  52. 68 0
      oxygine/src/core/gl/ShaderProgramGL.h
  53. 74 3
      oxygine/src/core/gl/VideoDriverGL.cpp
  54. 6 1
      oxygine/src/core/gl/VideoDriverGL.h
  55. 1 82
      oxygine/src/core/gl/VideoDriverGLES11.cpp
  56. 0 4
      oxygine/src/core/gl/VideoDriverGLES11.h
  57. 59 329
      oxygine/src/core/gl/VideoDriverGLES20.cpp
  58. 7 104
      oxygine/src/core/gl/VideoDriverGLES20.h
  59. 8 2
      oxygine/src/core/gl/oxgl.h
  60. 41 37
      oxygine/src/core/oxygine.cpp
  61. 1 1
      oxygine/src/core/oxygine.h
  62. 32 0
      oxygine/src/core/vertex.h
  63. 2 1
      oxygine/src/dev_tools/TreeInspector.cpp
  64. 8 1
      oxygine/src/dev_tools/TreeInspectorPreview.cpp
  65. 98 33
      oxygine/src/dev_tools/TreeInspectorPreview.h
  66. 13 8
      oxygine/src/math/AffineTransform.h
  67. 3 0
      oxygine/src/math/Rect.h
  68. 1 0
      oxygine/src/oxygine_include.h
  69. 31 236
      tools/main.wpu
  70. 1 1
      tools/others/png_strip.py
  71. 21 0
      tools/others/single_strip.py

+ 2 - 2
.hg_archival.txt

@@ -1,5 +1,5 @@
 repo: b6d71054df5712e643a0685bc3ba54b123db5729
-node: bc13d0178e86dc16a27550b5de8cdcf92f632aa2
+node: 7147c3f28257b9170ee6c230f55f8d8b3e4effa5
 branch: default
 latesttag: null
-latesttagdistance: 258
+latesttagdistance: 287

+ 1 - 0
.hgignore

@@ -84,5 +84,6 @@ examples/Demo/data/ext/res.xml.ox/
 oxygine/system_data/data/
 examples/Demo/win32/My Inspector XE Results *
 examples/DemoBox2D/build_box2d_vc11/
+examples/Demo/build_demo_vc11/
 syntax: regexp
 ^build/

+ 1 - 0
Android.mk

@@ -43,6 +43,7 @@ LOCAL_SRC_FILES += \
 				$(OXYGINE_SRC)/core/gl/NativeTextureGLES.cpp \
 				$(OXYGINE_SRC)/core/gl/oxgl.cpp \
 				$(OXYGINE_SRC)/core/gl/VertexDeclarationGL.cpp \
+				$(OXYGINE_SRC)/core/gl/ShaderProgramGL.cpp \
 				$(OXYGINE_SRC)/core/gl/VideoDriverGL.cpp \
 				$(OXYGINE_SRC)/core/gl/VideoDriverGLES20.cpp \
 

BIN
doc.zip


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


+ 1 - 0
examples/Demo/data/xmls/res.xml

@@ -9,6 +9,7 @@
 		<image file="snow.png"/>
 		
 		<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.jpg" data-custom = "custom user data per xml resource defined in xml"/>

+ 0 - 4
examples/Demo/ios/OxygineDemo/OxygineDemo.xcodeproj/project.pbxproj

@@ -7,7 +7,6 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		048B7AAD17FDEC3D00AE2D0B /* shader.glsl in Resources */ = {isa = PBXBuildFile; fileRef = 048B7AAC17FDEC3D00AE2D0B /* shader.glsl */; };
 		04998CFA17F8A933003441C3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04998CF817F8A933003441C3 /* InfoPlist.strings */; };
 		04998D2B17F8A94F003441C3 /* demo in Resources */ = {isa = PBXBuildFile; fileRef = 04998D2717F8A94F003441C3 /* demo */; };
 		04998D2C17F8A94F003441C3 /* ext in Resources */ = {isa = PBXBuildFile; fileRef = 04998D2817F8A94F003441C3 /* ext */; };
@@ -69,7 +68,6 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
-		048B7AAC17FDEC3D00AE2D0B /* shader.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = shader.glsl; path = "/Users/Mac/dev/oxygine-framework/oxygine/SDL/oxygine_xcode/oxygine/../../../system_data/original/system/shader.glsl"; sourceTree = "<absolute>"; };
 		04998CEC17F8A933003441C3 /* OxygineDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OxygineDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		04998CF717F8A933003441C3 /* OxygineDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OxygineDemo-Info.plist"; sourceTree = "<group>"; };
 		04998CF917F8A933003441C3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -199,7 +197,6 @@
 		04998CF617F8A933003441C3 /* Supporting Files */ = {
 			isa = PBXGroup;
 			children = (
-				048B7AAC17FDEC3D00AE2D0B /* shader.glsl */,
 				04998D2717F8A94F003441C3 /* demo */,
 				04998D2817F8A94F003441C3 /* ext */,
 				04998D2917F8A94F003441C3 /* images */,
@@ -361,7 +358,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				048B7AAD17FDEC3D00AE2D0B /* shader.glsl in Resources */,
 				04998D2E17F8A94F003441C3 /* xmls in Resources */,
 				04998D2C17F8A94F003441C3 /* ext in Resources */,
 				04998D2B17F8A94F003441C3 /* demo in Resources */,

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

@@ -44,7 +44,7 @@ public:
 		int new_priority = actor->getParent()->getLastChild()->getPriority() + 1;
 		actor->setPriority(new_priority);
 
-		actor->addTween(createTween(Sprite::TweenColor(Color(255,0,0,255)), 300, -1, true));
+		actor->addTween(Sprite::TweenColor(Color(255,0,0,255)), 300, -1, true);
 	}
 
 	void onMouseUp(Event *event)

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

@@ -50,7 +50,7 @@ public:
 		int new_priority = actor->getParent()->getLastChild()->getPriority() + 1;
 		actor->setPriority(new_priority);
 
-		actor->addTween(createTween(Sprite::TweenColor(Color(255,0,0,255)), 300, -1, true));
+		actor->addTween(Sprite::TweenColor(Color(255,0,0,255)), 300, -1, true);
 	}
 
 	void onMouseUp(Event *event)

+ 3 - 3
examples/Demo/src/TestManageRes.h

@@ -23,7 +23,7 @@ public:
 				continue;
 			spSprite sprite = new Sprite;
 			sprite->setAnimFrame(ra);
-			sprite->addTween(createTween(TweenAnim(ra), 500, -1));
+			sprite->addTween(TweenAnim(ra), 500, -1);
 			sprite->setPosition(scalar::randFloat(50.0f, getWidth() - 100.0f), scalar::randFloat(50.0f, getHeight() - 100.0f));
 			sprite->attachTo(content);	
 
@@ -58,7 +58,7 @@ public:
 	void _loaded(Event *event)
 	{
 		showPopup("Loaded!");
-		ui->getChild("loading")->addTween(createTween(Sprite::TweenAlpha(0), 400))->setDetachActor(true);
+		ui->getChild("loading")->addTween(Sprite::TweenAlpha(0), 400)->setDetachActor(true);
 	}
 
 	void clicked(string id)
@@ -84,7 +84,7 @@ public:
 			sp->setAnchor(Vector2(0.5f, 0.5f));
 			sp->setPosition(getSize() - sp->getSize()/4);
 			sp->setScale(0.5f);
-			sp->addTween(createTween(Actor::TweenRotation(-(float)MATH_PI * 2), 1500, -1));
+			sp->addTween(Actor::TweenRotation(-(float)MATH_PI * 2), 1500, -1);
 
 			spThreadLoading l = new ThreadLoading;
 			l->addEventListener(ThreadLoading::COMPLETE, CLOSURE(this, &ManageResTest::_loaded));

+ 3 - 3
examples/Demo/src/TestPerf.h

@@ -16,7 +16,7 @@ public:
 		_tweenRot = false;
 		_tweenScale = false;
 		count = 0;
-		addButton("add", "add 250");
+		addButton("add", "add 500");
 		addButton("animate", "animate");
 		addButton("scale0.01", "scale=0.01");
 		addButton("scale0.2", "scale=0.2");
@@ -44,7 +44,7 @@ public:
 
 		if (id == "add")
 		{
-			int a = 250;
+			int a = 500;
 			count += a;
 			for (int i = 0; i < a; ++i)
 			{
@@ -57,7 +57,7 @@ public:
 			}
 
 			char str[255];
-			sprintf(str, "add 250 (%d)", count);			
+			sprintf(str, "add 500 (%d)", count);			
 			updateText(id, str);
 		}
 		if (id == "scale0.01")

+ 14 - 4
examples/Demo/src/TestProgressBar.h

@@ -12,12 +12,14 @@ public:
 		addButton("90", "dir: 90");
 		addButton("180", "dir: 180");
 		addButton("270", "dir: 270");
+		addButton("radial_cw", "dir: radial_cw");
+		//addButton("radial_ccw", "dir: radial_ccw");
 
-		bar = new ProgressBar();
+		bar = new ProgressBar(); 
 		bar->setAnimFrame(resources.getResAnim("logo2"));
-		bar->setAnchor(Vector2(0.5f, 0.5f));
+		//bar->setAnchor(Vector2(0.5f, 0.5f));
 		bar->setPosition(getSize()/2);
-		bar->setScale(2);
+		//bar->setScale(2);
 		content->addChild(bar);
 	}
 
@@ -40,7 +42,15 @@ public:
 		{			
 			bar->setDirection(ProgressBar::dir_270);
 		}
+		if (id == "radial_ccw")
+		{			
+			bar->setDirection(ProgressBar::dir_radial_ccw);
+		}
+		if (id == "radial_cw")
+		{			
+			bar->setDirection(ProgressBar::dir_radial_cw);
+		}
 
-		bar->addTween(createTween(ProgressBar::TweenProgress(1.0f), 1000));
+		bar->addTween(ProgressBar::TweenProgress(1.0f), 1000);
 	}
 };

+ 1 - 5
examples/Demo/src/TestRender2Texture.h

@@ -53,12 +53,8 @@ public:
 
 
 		Point size = content->getSize().cast<Point>();
-		Matrix view = makeViewMatrix(size.x, size.y, true);
-		rs.renderer->setViewTransform(view);
 
-		Matrix proj;
-		Matrix::orthoLH(proj, (float)size.x, (float)size.y, 0.0f, 1.0f);
-		rs.renderer->setProjTransform(proj);
+		r.initCoordinateSystem(size.x, size.y, true);
 
 		Rect vp(Point(0, 0), size);
 

+ 9 - 16
examples/Demo/src/TestTweens.h

@@ -17,7 +17,6 @@ public:
 		addButton("ease", "ease: Linear");
 		addButton("TweenAnim", "Add TweenAnim");
 		addButton("TweenRotation", "Add TweenRotation");
-		addButton("RelTweenRotation", "Add Relative TweenRotation");
 		addButton("TweenScale", "Add TweenScale");
 		addButton("TweenPosition", "Add TweenPosition");
 		addButton("TweenColor", "Add TweenColor");
@@ -32,7 +31,7 @@ public:
 		_sprite->attachTo(content);
 		_sprite->setAnchor(Vector2(0.5f, 0.5f));
 		_sprite->setAnimFrame(resources.getResAnim("anim"));
-		_sprite->setPosition(getWidth()/2.0f, (float)getHeight() - _sprite->getHeight());		
+		_sprite->setPosition(getWidth()/2.0f, getHeight()/2);		
 
 		updateEase();
 	}
@@ -87,14 +86,11 @@ public:
 		showPopup("TweenDone");
 	}
 
-	void _addTween(spTween tween, bool rel = false)
+	void _addTween(spTween tween)
 	{
 		tween->setEase(_ease);
-		if (rel)
-			_sprite->addTweenRelative(tween);
-		else
-			_sprite->addTween(tween);
-		tween->setDoneCallback(CLOSURE(this, &TweensTest::tweenDone));
+		_sprite->addTween(tween);
+		tween->addEventListener(TweenEvent::DONE, CLOSURE(this, &TweensTest::tweenDone));
 	}
 
 	string enum2string(Tween::EASE e)
@@ -149,19 +145,16 @@ public:
 				_ease = Tween::ease_linear;								
 			updateEase();
 		}
+
 		int dur = 2000;
 		if (id == "TweenAnim")
 		{
-			_addTween( createTween(TweenAnim(resources.getResAnim("anim")), dur/2, 1));
+			_addTween( createTween(TweenAnim(resources.getResAnim("anim")), dur/4, 10));
 		}
 		if (id == "TweenRotation")
 		{
 			_addTween( createTween(Actor::TweenRotation(_sprite->getRotation() + (float)MATH_PI * 2), dur, 1));
 		}
-		if (id == "RelTweenRotation")
-		{
-			_addTween( createTween(Actor::TweenRotation((float)MATH_PI / 2), dur/2, 1), true);
-		}
 		if (id == "TweenPosition")
 		{
 			_addTween( createTween(Actor::TweenPosition(_sprite->getPosition() + Vector2(0, -200)), dur, 1, true));
@@ -191,9 +184,9 @@ public:
 		if (id == "TweenQueue")
 		{
 			spTweenQueue queue = new TweenQueue();			
-			queue->add(createTween(TweenAnim(resources.getResAnim("anim")), 500, 1));
-			queue->add(createTween(Actor::TweenRotation(_sprite->getRotation() + (float)MATH_PI * 2.0f), 500, 1, false, 1000));
-			queue->add(createTween(Actor::TweenScale(2), 500, 1, true));
+			queue->add(TweenAnim(resources.getResAnim("anim")), 500, 1);
+			queue->add(Actor::TweenRotation(_sprite->getRotation() + (float)MATH_PI * 2.0f), 500, 1, false, 1000);
+			queue->add(Actor::TweenScale(2), 500, 1, true);
 			_addTween(queue);
 		}
 

+ 9 - 12
examples/Demo/src/TestUserShader.h

@@ -1,5 +1,6 @@
 #pragma once
 #include "test.h"
+#include "core/UberShaderProgram.h"
 #include "core/gl/VideoDriverGLES20.h"
 #include "core/gl/oxgl.h"
 
@@ -13,7 +14,7 @@ public:
 
 	}
 	
-	void setShaderProgram(shaderProgram p)
+	void setShaderProgram(UberShaderProgram* p)
 	{
 		_program = p;
 	}
@@ -32,8 +33,8 @@ public:
 
 private:
 	float _val;
-	shaderProgram _program;
-	void setUniforms(ShaderProgramGL *prog)
+	UberShaderProgram* _program;
+	void setUniforms(ShaderProgram *prog)
 	{
 		prog->setUniform("interp", _val);
 	}
@@ -41,9 +42,9 @@ private:
 	void doRender(const RenderState &rs)
 	{
 		_program->setShaderUniformsCallback(CLOSURE(this, &ShaderSprite::setUniforms));
-		rs.renderer->setShaderProgram(_program);
+		rs.renderer->setUberShaderProgram(_program);
 		Sprite::doRender(rs);
-		rs.renderer->setShaderProgram(0);
+		rs.renderer->setUberShaderProgram(&Renderer::uberShader);
 
 		_program->setShaderUniformsCallback(UberShaderProgram::ShaderUniformsCallback());
 	}
@@ -55,12 +56,10 @@ public:
 	UberShaderProgram *_shader;
 	TestUserShader():_shader(0)
 	{
-		addButton("test", "test");			
-
-		VideoDriverGLES20 *driver = (VideoDriverGLES20*)IVideoDriver::instance;
+		addButton("test", "test");
 
 		_shader = new UberShaderProgram();
-		_shader->init(driver->getShaderBody(), 
+		_shader->init(Renderer::uberShaderBody, 
 			"#define MODIFY_BASE\n"
 			"uniform lowp float interp;"
 			"lowp vec4 modify_base(lowp vec4 base)\n"
@@ -89,11 +88,9 @@ public:
 
 		//Point size = content->getSize().cast<Point>();
 		Matrix view = makeViewMatrix((int)size.x, (int)size.y, true);
-		rs.renderer->setViewTransform(view);
-
 		Matrix proj;
 		Matrix::orthoLH(proj, size.x, size.y, 0.0f, 1.0f);
-		rs.renderer->setProjTransform(proj);
+		r.setViewProjTransform(view, proj);
 
 		Rect vp(Point(0, 0), size.cast<Point>());
 

+ 5 - 6
examples/Demo/src/entry_point.cpp

@@ -90,8 +90,7 @@ void run()
 	getRoot()->addChild(new DebugActor());
 
 
-	//initialization view and projection matrix 	
-	//makeViewMatrix returns View matrix where Left Top corner is (0,0), and right bottom is (w,h)
+	
 	Matrix view = makeViewMatrix(size.x, size.y); 
 
 	viewport = Rect(0, 0, size.x, size.y);
@@ -100,13 +99,13 @@ void run()
 	//initialize projection matrix
 	Matrix::orthoLH(proj, (float)size.x, (float)size.y, 0, 1);
 	
-	//initialize Renderer
 	//Renderer is class helper for rendering primitives and batching them
 	//Renderer is lightweight class you could create it many of times
-	//for example if you need to render something into RenderTarget (FBO)
 	renderer.setDriver(IVideoDriver::instance);
-	renderer.setViewTransform(view);
-	renderer.setProjTransform(proj);
+
+	//initialization view and projection matrix 	
+	//where Left Top corner is (0, 0), and right bottom is (width, height)
+	renderer.initCoordinateSystem(size.x, size.y);
 
 	//initialize this example stuff. see example.cpp
 	example_init();

+ 4 - 2
examples/DemoBox2D/src/Box2DDebugDraw.cpp

@@ -2,6 +2,7 @@
 #include "core/VideoDriver.h"
 #include "RenderState.h"
 #include "core/gl/VideoDriverGLES20.h"
+#include "core/gl/ShaderProgramGL.h"
 
 Box2DDraw::Box2DDraw(): _worldScale(1.0f), _world(0)
 {
@@ -44,8 +45,9 @@ void Box2DDraw::doRender(const RenderState &rs)
 	
 	_world->SetDebugDraw(this);
 
-	_program->bind();
-	Matrix m = Matrix(rs.transform) * rs.renderer->getView() * rs.renderer->getProjection();
+	rs.renderer->getDriver()->setShaderProgram(_program);
+
+	Matrix m = Matrix(rs.transform) * rs.renderer->getViewProjection();
 	_program->setUniform("projection", &m);
 
 	glEnable(GL_BLEND);

+ 1 - 2
examples/DemoBox2D/src/entry_point.cpp

@@ -105,8 +105,7 @@ void run()
 	//Renderer is lightweight class you could create it many of times
 	//for example if you need to render something into RenderTarget (FBO)
 	renderer.setDriver(IVideoDriver::instance);
-	renderer.setViewTransform(view);
-	renderer.setProjTransform(proj);
+	renderer.setViewProjTransform(view, proj);
 
 	//initialize this example stuff. see example.cpp
 	example_init();

+ 1 - 1
examples/GameTemplate/src/GameActor.cpp

@@ -61,7 +61,7 @@ void GameActor::preShowing()
 {	
 	_points = 0;	
 	_score->setAlpha(0);
-	_score->addTween(createTween(Actor::TweenAlpha(255), 300));	
+	_score->addTween(Actor::TweenAlpha(255), 300);	
 }
 
 void GameActor::postShowing()

+ 2 - 2
examples/GameTemplate/src/MainMenu.cpp

@@ -115,7 +115,7 @@ void MainMenu::doLoop()
 			_menu->setInputEnabled(false);
 
 			_menu->setAlpha(255);
-			spTween t = _menu->addTween(createTween(Actor::TweenAlpha(0), 250));
+			spTween t = _menu->addTween(Actor::TweenAlpha(0), 250);
 			blocking::waitTween(t);
 
 			_menu->setInputEnabled(true);				
@@ -129,7 +129,7 @@ void MainMenu::doLoop()
 			_menu->setInputEnabled(false);
 
 			_menu->setAlpha(0);
-			t = _menu->addTween(createTween(Actor::TweenAlpha(255), 250));
+			t = _menu->addTween(Actor::TweenAlpha(255), 250);
 			blocking::waitTween(t);
 
 			_menu->setInputEnabled(true);

+ 1 - 2
examples/GameTemplate/src/entry_point.cpp

@@ -105,8 +105,7 @@ void run()
 	//Renderer is lightweight class you could create it many of times
 	//for example if you need to render something into RenderTarget (FBO)
 	renderer.setDriver(IVideoDriver::instance);
-	renderer.setViewTransform(view);
-	renderer.setProjTransform(proj);
+	renderer.setViewProjTransform(view, proj);
 
 	//initialize this example stuff. see example.cpp
 	example_init();

+ 1 - 2
examples/HelloWorld/src/entry_point.cpp

@@ -105,8 +105,7 @@ void run()
 	//Renderer is lightweight class you could create it many of times
 	//for example if you need to render something into RenderTarget (FBO)
 	renderer.setDriver(IVideoDriver::instance);
-	renderer.setViewTransform(view);
-	renderer.setProjTransform(proj);
+	renderer.setViewProjTransform(view, proj);
 
 	//initialize this example stuff. see example.cpp
 	example_init();

+ 1 - 2
examples/Match3/src/entry_point.cpp

@@ -105,8 +105,7 @@ void run()
 	//Renderer is lightweight class you could create it many of times
 	//for example if you need to render something into RenderTarget (FBO)
 	renderer.setDriver(IVideoDriver::instance);
-	renderer.setViewTransform(view);
-	renderer.setProjTransform(proj);
+	renderer.setViewProjTransform(view, proj);
 
 	//initialize this example stuff. see example.cpp
 	example_init();

+ 5 - 7
examples/Match3/src/gameframe.cpp

@@ -7,7 +7,7 @@ int Field::StartAnimation(Point ind)
 	spTween tween = At(ind)->PlayAnimation();
 	if (tween)
 	{
-		tween->setDoneCallback(CLOSURE(this, &Field::EndAnimationCallback));
+		tween->addEventListener(TweenEvent::DONE, CLOSURE(this, &Field::EndAnimationCallback));
 		animated_count++;
 	}
 	return 0;
@@ -290,10 +290,8 @@ bool Field::Swap(spJewel First, spJewel Second, bool skip_animation)
 		jewel_new_ind  = getCellIndex( First->getPosition());
 		jewel_drag_ind = getCellIndex( Second->getPosition());
 
-		First->addTween( createTween(Sprite::TweenPosition(Second->getPosition()),200));
-		spTween tween = createTween(Sprite::TweenPosition(First->getPosition()),200);
-		tween->setDoneCallback(CLOSURE(this, &Field::EndSwapCallback));
-		Second->addTween(tween);
+		First->addTween(Sprite::TweenPosition(Second->getPosition()),200);
+		Second->addTween(Sprite::TweenPosition(First->getPosition()),200)->addEventListener(TweenEvent::DONE, CLOSURE(this, &Field::EndSwapCallback));
 	}
 
 	return true;
@@ -364,7 +362,7 @@ void  Field::DropJewel(spJewel Target, spJewel Jewel)
 		return;
 
 	spTween tween = Jewel->DropTo(Target->getPosition());
-	tween->setDoneCallback(CLOSURE(this, &Field::DropEndCallback));		
+	tween->addEventListener(TweenEvent::DONE, CLOSURE(this, &Field::DropEndCallback));		
 	Target->setPosition(getCellPosition(Jewel->index.x, Jewel->index.y));
 	ForceSwap(Target,Jewel);
 	droped_count++;
@@ -396,7 +394,7 @@ int Field::GenerateNewJewels(int column)
 			jewels[column][j]->setPosition(Vector2(pos.x,-getPosition().y-count*(JEWEL_SIZE + rand() % 10 + 20)));
 			spTween tween = jewels[column][j]->DropTo(pos);
 			droped_count++;
-			tween->setDoneCallback(CLOSURE(this, &Field::DropEndCallback));		
+			tween->addEventListener(TweenEvent::DONE, CLOSURE(this, &Field::DropEndCallback));		
 			count++;
 
 		}

+ 2 - 3
examples/Match3/src/jewels.cpp

@@ -55,14 +55,13 @@ spTween Jewel::PlayAnimation()
 	state = jsAnimation;
 
 	string anim = jewels_ids[_id];
-	return addTween(createTween(Sprite::TweenAlpha(0), 500, 1));
+	return addTween(Sprite::TweenAlpha(0), 500, 1);
 }
 
 spTween Jewel::DropTo(Vector2 pos)
 {
 	int time = fabs(getPosition().y - pos.y) * 2;
-	spTween tween = createTween(Sprite::TweenPosition(pos),time);
-	addTween( tween );
+	spTween tween = addTween(Sprite::TweenPosition(pos),time);
 	state = jsDropped;
 	return tween;
 }

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 55 - 0
mat2vertex.patch


+ 16 - 0
oxygine/SDL/oxygine_xcode/oxygine/oxygine.xcodeproj/project.pbxproj

@@ -35,6 +35,10 @@
 		04967C4D180B3D7400D66EFA /* Restorable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 04967C4B180B3D7400D66EFA /* Restorable.cpp */; };
 		04967C4E180B3D7400D66EFA /* Restorable.h in Headers */ = {isa = PBXBuildFile; fileRef = 04967C4C180B3D7400D66EFA /* Restorable.h */; };
 		049B64AB1803054300EC333E /* CreateResourceContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 049B64AA1803054300EC333E /* CreateResourceContext.cpp */; };
+		04AEC30F182BD912006413A9 /* ShaderProgramGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 04AEC30D182BD912006413A9 /* ShaderProgramGL.cpp */; };
+		04AEC310182BD912006413A9 /* ShaderProgramGL.h in Headers */ = {isa = PBXBuildFile; fileRef = 04AEC30E182BD912006413A9 /* ShaderProgramGL.h */; };
+		04AEC313182BD98D006413A9 /* UberShaderProgram.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 04AEC311182BD98D006413A9 /* UberShaderProgram.cpp */; };
+		04AEC314182BD98D006413A9 /* UberShaderProgram.h in Headers */ = {isa = PBXBuildFile; fileRef = 04AEC312182BD98D006413A9 /* UberShaderProgram.h */; };
 		C38704A217C0C6AC00015CA8 /* VideoDriverGLES11.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C38704A017C0C6AC00015CA8 /* VideoDriverGLES11.cpp */; };
 		C38704A317C0C6AC00015CA8 /* VideoDriverGLES11.h in Headers */ = {isa = PBXBuildFile; fileRef = C38704A117C0C6AC00015CA8 /* VideoDriverGLES11.h */; };
 		C38704A617C0C71700015CA8 /* VideoDriverGLES20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C38704A417C0C71700015CA8 /* VideoDriverGLES20.cpp */; };
@@ -222,6 +226,10 @@
 		04967C4B180B3D7400D66EFA /* Restorable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Restorable.cpp; sourceTree = "<group>"; };
 		04967C4C180B3D7400D66EFA /* Restorable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Restorable.h; sourceTree = "<group>"; };
 		049B64AA1803054300EC333E /* CreateResourceContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CreateResourceContext.cpp; sourceTree = "<group>"; };
+		04AEC30D182BD912006413A9 /* ShaderProgramGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ShaderProgramGL.cpp; path = gl/ShaderProgramGL.cpp; sourceTree = "<group>"; };
+		04AEC30E182BD912006413A9 /* ShaderProgramGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ShaderProgramGL.h; path = gl/ShaderProgramGL.h; sourceTree = "<group>"; };
+		04AEC311182BD98D006413A9 /* UberShaderProgram.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UberShaderProgram.cpp; sourceTree = "<group>"; };
+		04AEC312182BD98D006413A9 /* UberShaderProgram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UberShaderProgram.h; sourceTree = "<group>"; };
 		C38704A017C0C6AC00015CA8 /* VideoDriverGLES11.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VideoDriverGLES11.cpp; path = gl/VideoDriverGLES11.cpp; sourceTree = "<group>"; };
 		C38704A117C0C6AC00015CA8 /* VideoDriverGLES11.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VideoDriverGLES11.h; path = gl/VideoDriverGLES11.h; sourceTree = "<group>"; };
 		C38704A417C0C71700015CA8 /* VideoDriverGLES20.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VideoDriverGLES20.cpp; path = gl/VideoDriverGLES20.cpp; sourceTree = "<group>"; };
@@ -538,6 +546,8 @@
 		C3E86F6816EBC8EB00052915 /* core */ = {
 			isa = PBXGroup;
 			children = (
+				04AEC311182BD98D006413A9 /* UberShaderProgram.cpp */,
+				04AEC312182BD98D006413A9 /* UberShaderProgram.h */,
 				04967C4B180B3D7400D66EFA /* Restorable.cpp */,
 				04967C4C180B3D7400D66EFA /* Restorable.h */,
 				0472E34817F8A1A80016A832 /* file.cpp */,
@@ -697,6 +707,8 @@
 		C3EE215017BECD6100715678 /* gl */ = {
 			isa = PBXGroup;
 			children = (
+				04AEC30D182BD912006413A9 /* ShaderProgramGL.cpp */,
+				04AEC30E182BD912006413A9 /* ShaderProgramGL.h */,
 				C38704A417C0C71700015CA8 /* VideoDriverGLES20.cpp */,
 				C38704A517C0C71700015CA8 /* VideoDriverGLES20.h */,
 				C38704A017C0C6AC00015CA8 /* VideoDriverGLES11.cpp */,
@@ -751,6 +763,7 @@
 				C3E8702916EBC8EB00052915 /* oxygine.h in Headers */,
 				C3E8702A16EBC8EB00052915 /* pixel.h in Headers */,
 				C3E8702B16EBC8EB00052915 /* ref_counter.h in Headers */,
+				04AEC310182BD912006413A9 /* ShaderProgramGL.h in Headers */,
 				0472E38217F8A2EC0016A832 /* oxygine-framework.h in Headers */,
 				C3E8702D16EBC8EB00052915 /* Renderer.h in Headers */,
 				C3E8702F16EBC8EB00052915 /* Texture.h in Headers */,
@@ -778,6 +791,7 @@
 				C3E8704E16EBC8EB00052915 /* Multithreading.h in Headers */,
 				C3E8705416EBC8EB00052915 /* PointerState.h in Headers */,
 				C3E8705616EBC8EB00052915 /* ProgressBar.h in Headers */,
+				04AEC314182BD98D006413A9 /* UberShaderProgram.h in Headers */,
 				C3E8705716EBC8EB00052915 /* pugiconfig.hpp in Headers */,
 				C3E8705916EBC8EB00052915 /* pugixml.hpp in Headers */,
 				C3E8705A16EBC8EB00052915 /* RenderState.h in Headers */,
@@ -912,6 +926,7 @@
 				C3E8704B16EBC8EB00052915 /* MemoryTexture.cpp in Sources */,
 				C3E8704D16EBC8EB00052915 /* Multithreading.cpp in Sources */,
 				0472E37F17F8A2EC0016A832 /* MaskedSprite.cpp in Sources */,
+				04AEC313182BD98D006413A9 /* UberShaderProgram.cpp in Sources */,
 				C3E8705316EBC8EB00052915 /* PointerState.cpp in Sources */,
 				0472E35717F8A1A80016A832 /* file.cpp in Sources */,
 				C3E8705516EBC8EB00052915 /* ProgressBar.cpp in Sources */,
@@ -933,6 +948,7 @@
 				C3E8707616EBC8EB00052915 /* TextBuilder.cpp in Sources */,
 				C3E8707816EBC8EB00052915 /* TextActor.cpp in Sources */,
 				C3E8708316EBC8EB00052915 /* Tweener.cpp in Sources */,
+				04AEC30F182BD912006413A9 /* ShaderProgramGL.cpp in Sources */,
 				C3E8708616EBC8EB00052915 /* AtlasTool.cpp in Sources */,
 				0472E35E17F8A1A80016A832 /* STDFileSystem.cpp in Sources */,
 				C3E8708816EBC8EB00052915 /* ImageUtils.cpp in Sources */,

+ 47 - 50
oxygine/src/Actor.cpp

@@ -33,7 +33,7 @@ namespace oxygine
 			_anchor(0, 0),
 			_scale(1, 1),
 			_rotation(0),
-			_flags(flag_visible | flag_inputEnabled | flag_inputChildrenEnabled | flag_childrenRelative),
+			_flags(flag_visible | flag_inputEnabled | flag_inputChildrenEnabled | flag_childrenRelative | flag_fastTransform),
 			_parent(0),
 			_alpha(255),
 			_pressed(0),
@@ -479,6 +479,7 @@ namespace oxygine
 			return;
 		_scale = scale;
 		_flags |= flag_transformDirty | flag_transformInvertDirty;
+		_flags &= ~flag_fastTransform;
 	}
 
 	void Actor::setScale(float scaleX, float scaleY)
@@ -492,6 +493,7 @@ namespace oxygine
 			return;
 		_scale.x = sx;
 		_flags |= flag_transformDirty | flag_transformInvertDirty;
+		_flags &= ~flag_fastTransform;
 	}
 
 	void Actor::setScaleY(float sy)
@@ -500,6 +502,7 @@ namespace oxygine
 			return;
 		_scale.y = sy;
 		_flags |= flag_transformDirty | flag_transformInvertDirty;
+		_flags &= ~flag_fastTransform;
 	}
 
 	void Actor::setRotation(float rotation)
@@ -509,6 +512,7 @@ namespace oxygine
 
 		_rotation = rotation;
 		_flags |= flag_transformDirty | flag_transformInvertDirty;
+		_flags &= ~flag_fastTransform;
 	}
 
 	void Actor::sizeChanged(const Vector2 &size)
@@ -518,12 +522,7 @@ namespace oxygine
 
 	void Actor::setSize(const Vector2 &size)
 	{
-		//INT_MAX
-		//OX_ASSERT(size.x < SHORT_MAX);
-		//OX_ASSERT(size.y < SHORT_MAX);
-		//OX_ASSERT(size.x > -SHORT_MAX);
-		//OX_ASSERT(size.y > -SHORT_MAX);
-		_size = size;//.cast<PointS>();
+		_size = size;
 		_flags |= flag_transformDirty | flag_transformInvertDirty;
 		sizeChanged(size);
 	}	
@@ -576,22 +575,27 @@ namespace oxygine
 		if (!(_flags & flag_transformDirty))
 			return;
 
-		bool rot = _rotation != 0.0f;
-		bool sc = _scale.x != 1.0f || _scale.y != 1.0f;
-		
+		AffineTransform tr;
 
-		float c = 1.0f;
-		float s = 0.0f;
-		if (_rotation)			
+		if (_flags & flag_fastTransform)
 		{
-			c = cosf(_rotation);
-			s = sinf(_rotation);
+			tr = AffineTransform(1, 0, 0, 1, _pos.x, _pos.y);
 		}
+		else
+		{
+			float c = 1.0f;
+			float s = 0.0f;
+			if (_rotation)
+			{
+				c = cosf(_rotation);
+				s = sinf(_rotation);
+			}
 
-		AffineTransform tr(
-			c * _scale.x, s * _scale.x,
-			-s * _scale.y, c * _scale.y,
-			_pos.x, _pos.y);
+			tr = AffineTransform (
+				c * _scale.x, s * _scale.x,
+				-s * _scale.y, c * _scale.y,
+				_pos.x, _pos.y);
+		}		
 
 		if (_flags & flag_childrenRelative)
 		{
@@ -827,8 +831,8 @@ namespace oxygine
 
 			bool done = false;
 			if (tween->getParentList())
-				done = tween->update(*this, us);
-			if (done && tween->getParentList())
+				tween->update(*this, us);
+			if (tween->isDone() && tween->getParentList())
 				_tweens.remove(tween);
 			tween = tweenNext;
 		}
@@ -905,26 +909,29 @@ namespace oxygine
 			return false;
 
 		rs = parentRS;		
-		rs.alpha = alpha;		
+		rs.alpha = alpha;
 
-		Renderer::transform tr = getTransform() * parentRS.transform;
-		rs.transform = tr;
 
+		const Renderer::transform &tr = getTransform();
+		if (_flags & flag_fastTransform)
+		{
+			rs.transform = parentRS.transform;
+			rs.transform.translate(Vector2(tr.x, tr.y));
+		}
+		else
+			Renderer::transform::multiply(rs.transform, tr, parentRS.transform);
+
+		
 		if (_flags & flag_cull)
 		{
-			RectF ss_rect = getScreenSpaceDestRect(tr);
+			RectF ss_rect = getScreenSpaceDestRect(rs.transform);
 			RectF intersection = ss_rect;
-			intersection.clip(rs.clip);
+			intersection.clip(*rs.clip);
 			if (intersection.isEmpty())
 				return false;
-
 		}
 
-		
-		//tr.x = int(tr.x);
-		//tr.y = int(tr.y);
-		
-		rs.renderer->setTransform(tr);
+		rs.renderer->setTransform(rs.transform);
 
 		return true;
 	}
@@ -939,8 +946,8 @@ namespace oxygine
 		if (!prepareRender(rs, parentRS))
 			return false;
 
-		if (_cbDoRender)
-			_cbDoRender(rs);
+		//if (_cbDoRender)
+		//	_cbDoRender(rs);
 		doRender(rs);
 		completeRender(rs);
 		return true;
@@ -955,8 +962,9 @@ namespace oxygine
 		Actor *actor = _children._first.get();
 		while (actor)
 		{
-			if (actor->getParent())//todo remove???
-				actor->render(rs);
+			OX_ASSERT(actor->getParent());
+			//if (actor->getParent())//todo remove???
+			actor->render(rs);
 			actor = actor->_next.get();
 		}
 	}
@@ -988,15 +996,9 @@ namespace oxygine
 		OX_ASSERT(tween);
 		if (!tween)
 			return 0;
-
-		tween->setRelative(rel);
-
-		bool done = false;
-		if (tween->getDelay() == 0)
-			done = tween->start(*this);
-
-		if (!done)
-			_tweens.append(tween);
+		
+		tween->start(*this);
+		_tweens.append(tween);
 
 		return tween;
 	}
@@ -1006,11 +1008,6 @@ namespace oxygine
 		return _addTween(tween, false);
 	}	
 
-	spTween Actor::addTweenRelative(spTween tween)
-	{
-		return _addTween(tween, true);
-	}
-
 	spTween Actor::getTween(const string &name, error_policy ep)
 	{
 		spTween tween = _tweens._first;

+ 8 - 8
oxygine/src/Actor.h

@@ -119,7 +119,7 @@ namespace oxygine
 		bool				getInputEnabled() const {return (_flags & flag_inputEnabled) != 0;}
 		bool				getChildrenRelative() const {return (_flags & flag_childrenRelative) != 0;;}
 		UpdateCallback		getCallbackDoUpdate() const {return _cbDoUpdate;}
-		RenderCallback		getCallbackDoRender() const {return _cbDoRender;}
+		//RenderCallback		getCallbackDoRender() const {return _cbDoRender;}
 
 		const Renderer::transform&		getTransform() const;
 		const Renderer::transform&		getTransformInvert() const;
@@ -170,7 +170,7 @@ namespace oxygine
 		/**Sets callback which would be called each Actor::update cycle before doUpdate. Use it if you don't want inherit from Actor and overload Actor::doUpdate.*/
 		void setCallbackDoUpdate(UpdateCallback cb){_cbDoUpdate = cb;}
 		/**Sets callback which would be called each Actor::render cycle before doRender. Use it if you don't want inherit from Actor and overload Actor::doRender.*/
-		void setCallbackDoRender(RenderCallback cb){_cbDoRender = cb;}
+		//void setCallbackDoRender(RenderCallback cb){_cbDoRender = cb;}
 
 		virtual bool isOn(const Vector2 &localPosition);
 		/**Returns true if actor is child or located deeper in current subtree*/
@@ -202,7 +202,6 @@ namespace oxygine
 		virtual void updateState(){}
 		
 		spTween addTween(spTween);		
-		spTween addTweenRelative(spTween);		
 
 		template<class GS>
 		spTween addTween(const GS &gs, timeMS duration, int loops = 1, bool twoSides = false, timeMS delay = 0, Tween::EASE ease = Tween::ease_linear)
@@ -246,7 +245,7 @@ namespace oxygine
 		
 		virtual void doUpdate(const UpdateState &us);
 		UpdateCallback _cbDoUpdate;
-		RenderCallback _cbDoRender;
+		//RenderCallback _cbDoRender;
 
 		virtual void sizeChanged(const Vector2 &size);
 
@@ -265,14 +264,14 @@ namespace oxygine
 		pointer_index _pressed;
 		pointer_index _overed;
 
-
 	private:
+		short	_zOrder;
+
 		Vector2 _pos;		
 		Vector2 _anchor;		
 		Vector2 _scale;
 		Vector2 _size;
-		float	_rotation;		
-		short	_zOrder;
+		float	_rotation;
 
 		enum flags
 		{
@@ -284,9 +283,10 @@ namespace oxygine
 			flag_transformInvertDirty = 0x20,
 			flag_inputChildrenEnabled = 0x40,
 			flag_cull = 0x80,
+			flag_fastTransform = 0x100,
 		};
 
-		mutable unsigned char _flags;
+		mutable unsigned short _flags;
 		mutable Renderer::transform	_transform;
 		mutable Renderer::transform	_transformInvert;
 

+ 1 - 1
oxygine/src/AnimationFrame.cpp

@@ -20,7 +20,7 @@ namespace oxygine
 
 		RectF srcRect = _srcRect * Vector2(w, h);
 
-		float sc = (float)srcRect.getWidth() / f._destRect.getWidth();
+		float sc = 1.0f;//(float)srcRect.getWidth() / f._destRect.getWidth();
 
 
 		f._srcRect.pos = srcRect.pos - (_destRect.pos - f._destRect.pos) * sc;

+ 10 - 6
oxygine/src/ClipRectActor.cpp

@@ -52,6 +52,10 @@ namespace oxygine
 	{
 		RenderState rs = parentRS;
 
+		const RectF* parentClippedRect = parentRS.clip;
+		RectF clippedRect = *parentClippedRect;
+		rs.clip = &clippedRect;
+
 		Rect scissorRect(0,0,0,0);
 		bool scissorEnabled = rs.renderer->getDriver()->getScissorRect(scissorRect);
 
@@ -63,14 +67,14 @@ namespace oxygine
 			RectF ss_rect = getScreenSpaceDestRect(getTransform() * parentRS.transform);
 			parentRS.renderer->drawBatch();
 			
-			rs.clip.clip(ss_rect);
-			if (!rs.clip.isEmpty())
+			clippedRect.clip(ss_rect);
+			if (!clippedRect.isEmpty())
 			{
 				Rect gl_rect = Rect(
-					int(rs.clip.pos.x + 0.01f), 
-					int(rs.clip.pos.y + 0.01f), 
-					int(rs.clip.size.x + 0.01f), 
-					int(rs.clip.size.y + 0.01f));
+					int(clippedRect.pos.x + 0.01f), 
+					int(clippedRect.pos.y + 0.01f), 
+					int(clippedRect.size.x + 0.01f), 
+					int(clippedRect.size.y + 0.01f));
 
 				Point vp_size = core::getDisplaySize();
 				gl_rect.pos.y = vp_size.y - gl_rect.getBottom();

+ 1 - 1
oxygine/src/DebugActor.cpp

@@ -333,7 +333,7 @@ namespace oxygine
 		//cr->setAlpha(100);
 		cr->setColor(Color(rand()%255, rand()%255, rand()%255, 0));
 		cr->setSize(actor->getSize());
-		cr->addTween(createTween(ColorRectSprite::TweenColor(Color(255,255,255,200)), 700, 1, true, 0, Tween::ease_inCubic))->setDetachActor(true);
+		cr->addTween(ColorRectSprite::TweenColor(Color(255,255,255,200)), 700, 1, true, 0, Tween::ease_inCubic)->setDetachActor(true);
 		actor->addChild(cr);
 		string dmp = actor->dump(0);
 		log::messageln("touched actor:\n%s", dmp.c_str());

+ 0 - 2
oxygine/src/Event.h

@@ -25,8 +25,6 @@ namespace oxygine
 
 		_et_TouchLast,
 
-		_et_TweenDone,
-
 		_et_Complete,
 		//_et_RollOver,
 		//_et_RollOut,

+ 259 - 4
oxygine/src/ProgressBar.cpp

@@ -1,7 +1,41 @@
 #include "ProgressBar.h"
+#include "RenderState.h"
 #include <sstream>
 namespace oxygine
 {
+	void fill_tex_coord(vertexPCT2 &vt, unsigned int rgba, const Vector2 &pnt, float nu, float nv)
+	{
+		vt.color = rgba;
+		vt.z = 0;
+		vt.x = pnt.x;
+		vt.y = pnt.y;
+		vt.u = nu;
+		vt.v = nv;			
+	}
+
+
+	void rotateVector( Vector2 & v, float rad )
+	{
+		Vector2 vh;
+
+		vh.x=v.x*cosf( rad ) - v.y*sinf( rad );
+		vh.y=v.x*sinf( rad ) + v.y*cosf( rad );
+
+		v = vh;
+	}
+
+	float Angle(const Vector2 & current, const Vector2 * pRelative) 
+	{
+		if(pRelative)
+		{
+			Vector2 s=current, t=*pRelative;
+
+			s.normalize(); t.normalize();
+			return acosf(s.dot(t));
+		}
+		else return atan2f(current.y, current.x);
+	}
+
 	ProgressBar::ProgressBar():_progress(1.0f), _direction(dir_0)
 	{
 
@@ -11,7 +45,7 @@ namespace oxygine
 	{
 
 	}
-	
+
 	ProgressBar::ProgressBar(const ProgressBar &src, cloneOptions opt):Sprite(src, opt)
 	{
 		_progress = src._progress;
@@ -55,14 +89,222 @@ namespace oxygine
 		}			
 
 		Vector2 newSize = _originalFrame.getFrameSize() * _progress;
-		_frame.init(0, _frame.getDiffuse(), newSrc, newDest, newSize);
+		_frame.init(_frame.getResAnim(), _frame.getDiffuse(), newSrc, newDest, newSize);
+	}
+
+	void ProgressBar::doRender(const RenderState &rs)
+	{
+		if (_progress == 0)
+			return;
+		if (((_direction != dir_radial_ccw) && (_direction != dir_radial_cw)) || (_progress == 1.0f))
+		{
+			Sprite::doRender(rs);
+			return;
+		}
+
+		_vstyle._apply(rs);
+		const Diffuse &df = _frame.getDiffuse();
+		if (df.base)
+		{
+			rs.renderer->setDiffuse(df);
+
+			unsigned int rgba = rs.renderer->getPrimaryColor().rgba();
+
+			RectF destRect = Sprite::getDestRect();
+
+			RectF srcRect = _frame.getSrcRect();
+			float u = srcRect.pos.x;
+			float v = srcRect.pos.y;
+
+			float du = srcRect.size.x;
+			float dv = srcRect.size.y;	
+
+			u += du / 2.f;
+			v += dv / 2.f;
+
+			Vector2 pos = destRect.pos;
+			const Vector2 &size = destRect.size;
+			pos += size / 2.f;				
+
+			float maxSide = std::max( size.x, size.y );
+
+			Vector2 vecCenter( pos.x, pos.y );
+			Vector2 vdiag = Vector2( pos.x + size.x / 2.f, pos.y - size.y / 2.f ) - vecCenter;
+			Vector2 vdiag2 = Vector2( pos.x + size.x / 2.f, pos.y + size.y / 2.f ) - vecCenter;
+			float lenDiag = vdiag.length();
+			Vector2 vecCircle( pos.x, pos.y - lenDiag );
+
+			Vector2 vecRad = vecCircle - vecCenter;
+
+			float progress = _progress;
+
+			float fP = MATH_PI * 2.f * progress;
+
+			rotateVector( vecRad, fP );
+
+			Vector2 p1(0.f, 0.f);
+			Vector2 p2(0.f, 0.f);
+			Vector2 p3(0.f, 0.f);
+
+			Vector2 vert( 0.f, -1.f );
+			float fA1 = Angle( vdiag, &vert );
+			float fA2 = Angle( vdiag2, &vdiag );
+
+			const int MAX_TRI = 6;
+
+			float u1,v1,u2,v2,u3,v3;
+			float result = 0.f;
+
+			float angles[ 6 ];
+			angles[ 0 ] = fA1;
+			angles[ 1 ] = fA2;
+			angles[ 2 ] = fA1;
+			angles[ 3 ] = fA1;
+			angles[ 4 ] = fA2;
+			angles[ 5 ] = fA1;
+
+			for ( int i = 0; i < MAX_TRI; i++ )
+			{
+				float limitLo = 0.f;
+				float limitHi = 0.f;
+				for (int j = 0; j < i; j++)				
+					limitLo += angles[ j ];
+
+				limitHi = limitLo + angles[ i ];
+
+				bool bOverHi = fP > limitHi;
+				bool bOverLo = fP < limitLo;
+				if ( i && bOverLo )				
+					continue;
+
+				vertexPCT2 vertices[4];
+				vertexPCT2* pv = vertices;
+
+				switch (i)
+				{
+				case 0:
+					{
+						result = bOverHi ? size.x / 2.f : vecRad.x;
+						p1 = Vector2(pos.x, pos.y);
+						p2 = Vector2(pos.x, pos.y - size.y / 2.f);
+						p3 = Vector2(pos.x + result, pos.y - size.y / 2.f);
+						float fPercent = result / size.x;
+						float fDU = du * fPercent;	
+
+						u1 = u;
+						v1 = v;
+						u2 = u;
+						v2 = ( v - dv / 2.f );
+						u3 = ( u + fDU );
+						v3 = ( v - dv / 2.f );
+					}
+					break;
+				case 1:
+					{					
+						result = bOverHi ? size.y / 2.f : ( vecRad.y ) ;
+						p1 = Vector2(pos.x, pos.y);
+						p2 = Vector2(pos.x + size.x / 2.f, pos.y - size.y / 2.f);
+						p3 = Vector2(pos.x + size.x / 2.f, pos.y + result );
+						float fPercent = result /size.y;
+						float fDV = dv * fPercent;	
+
+						u2 = u + du / 2.f;
+						v2 = ( v - dv / 2.f );
+						u3 = u + du / 2.f;
+						v3 = ( v + fDV );
+					}
+					break;
+				case 2:
+					{					
+						result = bOverHi ? 0.f : vecRad.x ;
+						p1 = Vector2(pos.x, pos.y);
+						p2 = Vector2(pos.x + size.x / 2.f, pos.y + size.y / 2.f);
+						p3 = Vector2(pos.x + result, pos.y + size.y / 2.f );
+						float fPercent = result/size.x;
+						float fDU = du * fPercent;	
+						
+						u2 = u + du / 2.f;
+						v2 = ( v + dv / 2.f );
+						u3 = u + fDU;
+						v3 = ( v + dv / 2.f );
+					}
+					break;
+				case 3:
+					{					
+						result = bOverHi ? ( -size.x / 2.f ) : vecRad.x ;
+						p1 = Vector2(pos.x, pos.y);
+						p2 = Vector2(pos.x , pos.y + size.y / 2.f);
+						p3 = Vector2(pos.x + result, pos.y + size.y / 2.f );
+						float fPercent = result / size.x;
+						float fDU = du * fPercent;	
+
+						u2 = u;
+						v2 = ( v + dv / 2.f );
+						u3 = u + fDU;
+						v3 = ( v + dv / 2.f );
+					}
+					break;
+				case 4:
+					{					
+						result = bOverHi ? ( -size.y / 2.f ) : vecRad.y ;
+						p1 = Vector2(pos.x, pos.y);
+						p2 = Vector2(pos.x - ( size.x / 2.f ) , pos.y + size.y / 2.f);
+						p3 = Vector2(pos.x - ( size.x / 2.f ), pos.y + result );
+						float fPercent = result / size.y;
+						float fDV = dv * fPercent;	
+
+						u2 = u - du / 2.f;
+						v2 = ( v + dv / 2.f );
+						u3 = u - du / 2.f;
+						v3 = ( v + fDV );
+					}
+					break;
+				case 5:
+					{					
+						result = bOverHi ? ( 0.f ) : vecRad.x ;
+						p1 = Vector2(pos.x, pos.y);
+						p2 = Vector2(pos.x - ( size.x / 2.f ), pos.y - ( size.y / 2.f ));
+						p3 = Vector2(pos.x + result, pos.y - ( size.y / 2.f ) );
+						float fPercent = result / size.x;
+						float fDU = du * fPercent;	
+
+						u2 = u - du / 2.f;
+						v2 = ( v - dv / 2.f );
+						u3 = u + fDU;
+						v3 = ( v - dv / 2.f );
+					}
+					break;
+				default:
+					continue;
+				}
+
+				u1 = u;
+				v1 = v;
+
+
+				p1 = rs.transform.transform(p1);
+				p2 = rs.transform.transform(p2);
+				p3 = rs.transform.transform(p3);
+
+
+				fill_tex_coord(*pv, rgba, p1, u1, v1);
+				pv++;
+				fill_tex_coord(*pv, rgba, p2, u2, v2);
+				pv++;
+				fill_tex_coord(*pv, rgba, p3, u3, v3);
+				pv++;
+				fill_tex_coord(*pv, rgba, p2, u2, v2);			
+				pv++;
+
+				rs.renderer->draw(vertices, sizeof(vertices), VERTEX_PCT2);			
+			}
+		}
 	}
 
 	string ProgressBar::dump(const dumpOptions &options) const
 	{
 		stringstream stream;
-		stream << "{ProgressBar}\n";
-	
+		stream << "{ProgressBar}\n";	
 
 		const char *dir = "dir_0";
 		switch(_direction)
@@ -76,6 +318,12 @@ namespace oxygine
 		case dir_270:
 			dir = "dir_270";
 			break;
+		case dir_radial_cw:
+			dir = "dir_radial_cw";
+			break;
+		case dir_radial_ccw:
+			dir = "dir_radial_ccw";
+			break;
 		}
 		stream << " direction=" << dir << ""; 
 
@@ -92,12 +340,19 @@ namespace oxygine
 	void ProgressBar::setProgress(float f)
 	{
 		_progress = scalar::clamp(f, 0.0f, 1.0f);
+		if (_direction == dir_radial_ccw || _direction == dir_radial_cw)
+			return;
 		_update();
 	}
 
 	void ProgressBar::setDirection(direction dir)
 	{
 		_direction = dir;
+		if (_direction == dir_radial_ccw || _direction == dir_radial_cw)
+		{
+			_frame = _originalFrame;
+			return;
+		}
 		_update();
 	}
 

+ 6 - 1
oxygine/src/ProgressBar.h

@@ -14,7 +14,9 @@ namespace oxygine
 			dir_0,//moveable right edge
 			dir_90,//moveable top edge
 			dir_180,//moveable left edge
-			dir_270//moveable bottom edge
+			dir_270,//moveable bottom edge
+			dir_radial_cw,
+			dir_radial_ccw//not implemented!!
 		};
 
 		DECLARE_COPYCLONE(ProgressBar);
@@ -34,7 +36,10 @@ namespace oxygine
 		string dump(const dumpOptions &) const;
 		
 		typedef GetSet<float, float, ProgressBar, &ProgressBar::getProgress, &ProgressBar::setProgress> TweenProgress;		
+
 	private:
+		void doRender(const RenderState &rs);
+
 		RectF getDestRect() const;
 		void _update();
 

+ 2 - 2
oxygine/src/RenderState.h

@@ -13,7 +13,7 @@ namespace oxygine
 	class RenderState
 	{
 	public:
-		RenderState():renderer(0), alpha(255), clip(-1, -1, -1, -1)
+		RenderState():renderer(0), alpha(255), clip(0)
 		{
 			transform.identity();
 		}
@@ -21,6 +21,6 @@ namespace oxygine
 		Renderer::transform transform;
 		Renderer *renderer;
 		unsigned char alpha;
-		RectF clip;
+		const RectF* clip;
 	};
 }

+ 3 - 2
oxygine/src/RootActor.cpp

@@ -90,12 +90,13 @@ namespace oxygine
 		rs.renderer = &r;
 		Point ds = core::getDisplaySize();
 
-		rs.clip = RectF(0.0f, 0.0f, (float)ds.x, (float)ds.y);
+		RectF clip(0.0f, 0.0f, (float)ds.x, (float)ds.y);
+		rs.clip = &clip;
 
 		if (_clipOuter)
 		{
 			r.getDriver()->setScissorRect(&_viewport);
-			rs.clip = _viewport.cast<RectF>();
+			clip = _viewport.cast<RectF>();
 		}
 		
 		Actor::render(rs);

+ 7 - 1
oxygine/src/SlidingActor.cpp

@@ -8,7 +8,13 @@
 
 namespace oxygine
 {
-	SlidingActor::SlidingActor():_prevPos(0, 0), _speed(0, 0), _sliding(false), _downPos(0, 0), _rad(10), _downTime(0), _down(false), _maxSpeed(250), _snapSize(0, 0), 
+	float _defaultTouchThreshold = 15;
+	void SlidingActor::setDefaultTouchThreshold(float val)
+	{
+		_defaultTouchThreshold = val;
+	}
+
+	SlidingActor::SlidingActor():_prevPos(0, 0), _speed(0, 0), _sliding(false), _downPos(0, 0), _rad(_defaultTouchThreshold), _downTime(0), _down(false), _maxSpeed(250), _snapSize(0, 0), 
 		_movingX(false), _movingY(false), _snapSpeed(1.0f)
 	{
 		_clip = initActor(new ClipRectActor, 

+ 1 - 0
oxygine/src/SlidingActor.h

@@ -13,6 +13,7 @@ namespace oxygine
 	class SlidingActor: public Actor
 	{
 	public:
+		static void setDefaultTouchThreshold(float val);
 		SlidingActor();
 		~SlidingActor();
 			

+ 114 - 116
oxygine/src/Tweener.cpp

@@ -7,9 +7,8 @@ namespace oxygine
 	Tween::Tween():_duration(0), 
 		_loops(0), 
 		_percent(0), 
-		_value(0), 
-		_done(false), _started(false), _relative(false),
-		_elapsed(0), _twoSides(false), _ease(ease_linear), _remove(false), _delay(0), _client(0)
+		_status(status_not_started),
+		_elapsed(0), _twoSides(false), _ease(ease_linear), _detach(false), _delay(0), _client(0)
 	{
 
 	}
@@ -21,13 +20,11 @@ namespace oxygine
 	void Tween::reset()
 	{
 		_elapsed = 0;
-		_done = false;
-		_started = false;
+		_status = status_not_started;
 	}
 
 	void Tween::init(timeMS duration, int loops, bool twoSides, timeMS delay, EASE ease)
 	{
-		_done = false;
 		_duration = duration;
 		_ease = ease;
 		_loops = loops;
@@ -41,11 +38,16 @@ namespace oxygine
 		}
 	}
 
+	void Tween::setDoneCallback(EventCallback cb)
+	{
+		_cbDone = cb;
+	}
+
 	float Tween::calcEase(EASE ease, float v)
 	{
 		float vi;
 		float r = 0;
-		float s = 1.70158f;// * 1.525f + 1;
+		const float s = 1.70158f;
 
 		switch(ease)
 		{
@@ -71,18 +73,22 @@ namespace oxygine
 			vi = v - 1.0f;
 			r = vi * vi * vi + 1.0f;
 			break;
-		case ease_inOutBack:			
-			v *= 2;
-			if (v < 1)
+		case ease_inOutBack:		
 			{
-				r = v * v * (( (s*=1.525f) + 1) * v - s);
-			}
-			else
-			{				
-				v-=2;
-				r = v * v * (((s *= 1.525f) + 1) * v + s) + 2;
+				const float s15 = s * 1.525f;
+
+				v *= 2;
+				if (v < 1)
+				{
+					r = v * v * ((s15 + 1) * v - s15);
+				}
+				else
+				{				
+					v-=2;
+					r = v * v * ((s15 + 1) * v + s15) + 2;
+				}
+				r /= 2;
 			}
-			r /= 2;
 			break;
 		case ease_inBack:
 			r = v * v * ((s + 1) * v - s);
@@ -118,108 +124,111 @@ namespace oxygine
 		if (_loops == -1)
 			return;
 
-		if (!_started)
-			return;//todo fix, tween with delay wasn't started yet
+		//if already done
+		if (_status >= status_done)
+			return;
 
 		OX_ASSERT(_client);
 
-		UpdateState us;
+		//OX_ASSERT(!"not implemented");
 
-		us.dt = deltaTime;
-		bool done = update(*_client, us);
-		if (!done)
+		//not started yet because if delay
+		if (_status == status_delayed)
 		{
-			callDone(*_client, &us);
+			_start(*_client);
+			_status = status_started;
 		}
-		_client->removeTween(this);
-	}
 
-	void Tween::callDone(Actor &actor, const UpdateState *us)
-	{
-		if (_remove)
-		{
-			actor.detach();
-		}
-		if (_cbDone)
+
+		OX_ASSERT(_status == status_started);
+		//while (_status != status_remove)
 		{
-			TweenEvent ev(this, us);
-			ev.target = ev.currentTarget = &actor;
-			ev.tween = this;
+			UpdateState us;
+			us.dt = deltaTime;
 
-			_cbDone(&ev);					
+			update(*_client, us);
 		}
-	}
 
-	bool Tween::start(Actor &actor)
-	{
-		_client = &actor; 
-		_started = true; 
-
-		return false;
+		OX_ASSERT(_status == status_done);
+		
+		//_client->removeTween(this);		
 	}
 
-	bool Tween::itDone(Actor &t, const UpdateState &us)
+	void Tween::start(Actor &actor)
 	{
-		OX_ASSERT(_client);
-		//if (us.iteration == 0)//wait next cycle update/render
+		_client = &actor; 
+		_status = status_delayed;
+		if (_delay == 0)
 		{
-			callDone(*_client, &us);
-			_client = 0;
-			return true;
-		}			
-
-		return false; 
+			_status = status_started;
+			_start(actor);
+		}
 	}
 
-	bool Tween::update(Actor &actor, const UpdateState &us)
+	void Tween::update(Actor &actor, const UpdateState &us)
 	{
-		if (_done)		
-		{
-			return itDone(actor, us);
-		}
-
 		_elapsed += us.dt;
-
-		if (!_started)
+		switch(_status)
 		{
-			if (_elapsed >= _delay)
+		case status_delayed:
 			{
-				bool done = start(actor);
-				return done;
+				if (_elapsed >= _delay)
+				{
+					_status = status_started;
+					_start(*_client);					
+				}
 			}
-			else
+			break;
+		case status_started:
 			{
-				return false;
-			}
-		}
+				if (_duration)
+				{				
+					timeMS localElapsed = _elapsed - _delay;
 
-		OX_ASSERT(_client);
-
-		timeMS localElapsed = _elapsed - _delay;
+					int loopsDone = localElapsed / _duration;
 
-		int loopsDone = localElapsed / _duration;
-		_percent = ((float)(localElapsed - loopsDone * _duration)) / _duration;
+					_percent = _calcEase(((float)(localElapsed - loopsDone * _duration)) / _duration);
 
-				
-		_percent = _calcEase(_percent);
+					if (_loops > 0 && int(loopsDone) >= _loops)
+					{
+						if (_twoSides)
+							_percent = 0;
+						else
+							_percent = 1;
 
-		bool done = false;
+						_status = status_done;
+					}
+				}
+				_update(*_client, us);
+			}
+			break;
+		case status_done:
+			{
+				done(*_client, us);
+			}
+			break;
+		}
+	}
 
-		if (_loops > 0 && int(loopsDone) >= _loops)
+	void Tween::done(Actor &actor, const UpdateState &us)
+	{		
+		_done(actor, us);
+		
+		if (_detach)
 		{
-			if (_twoSides)
-				_percent = 0;
-			else
-				_percent = 1;
-
-			done = true;
+			actor.detach();
 		}
-		_value = _percent;		
-		_done = done;
 
-		//printf("loopsDone, percent: %d, %.4f\n", loopsDone, _percent);
+		TweenEvent ev(this, &us);
+		ev.target = ev.currentTarget = &actor;
+		ev.tween = this;
+
+		if (_cbDone)		
+			_cbDone(&ev);
 
-		return false;
+		dispatchEvent(&ev);
+
+		_status = status_remove;
 	}
 
 	
@@ -233,49 +242,38 @@ namespace oxygine
 		return t;
 	}
 
-	bool TweenQueue::start(Actor &actor)
+	void TweenQueue::complete(timeMS deltaTime)
+	{
+		OX_ASSERT("Tween::complete is not supported for TweenQueue");
+	}
+
+	void TweenQueue::_start(Actor &actor)
 	{
-		OX_ASSERT(_relative == false);
-		Tween::start(actor);
 		_current = _tweens._first;
-		if(_current->getDelay() == 0)
-			return _current->start(actor);
-		return false;
+		if (!_current)
+			return;
+
+		_current->start(actor);
 	}
 
-	bool TweenQueue::update(Actor &actor, const UpdateState &us)
+	void TweenQueue::_update(Actor &actor, const UpdateState &us)
 	{
 		_elapsed += us.dt;
-		if (_elapsed < _delay)
-			return false;
-		if (!_started)
-		{
-			start(actor);
-		}
 
-		while (_current)
+		if (_current)
 		{
 			spTween next = _current->getNextSibling();
-			bool done = _current->update(actor, us);
-			if (done)
+			_current->update(actor, us);
+			if (_current->isDone())
 			{
-				_current->callDone(actor, &us);
 				_current = next;
-			}
-			else
-			{
-				break;
+				if (_current)				
+					_current->start(actor);				
 			}
 		}
 
-		bool done = _current == 0;
-		_done = done;
-		if (done)
-		{
-			callDone(actor, &us);
-		}
-		
-		return done;
+		if (!_current)
+			_status = status_done;
 	}
 
 	Actor* TweenEvent::getActor() const

+ 47 - 47
oxygine/src/Tweener.h

@@ -81,7 +81,7 @@ namespace oxygine
 	public:
 		enum 
 		{
-			DONE = _et_TweenDone
+			DONE = _et_Complete
 		};
 
 		TweenEvent(Tween *tween_, const UpdateState *us_):Event(DONE, false), tween(tween_), us(us_){}
@@ -96,7 +96,7 @@ namespace oxygine
 
 	DECLARE_SMART(Tween, spTween);
 
-	class Tween: public Object, public intrusive_list_item<spTween>
+	class Tween: public EventDispatcher, public intrusive_list_item<spTween>
 	{
 		typedef intrusive_list_item<spTween> intr_list;
 	public:
@@ -130,57 +130,65 @@ namespace oxygine
 		timeMS		getDelay() const {return _delay;}
 		Actor*		getClient() const {return _client;}
 		float		getPercent() const {return _percent;}
+		spObject	getDataObject() const {return _data;}
 		spTween&	getNextSibling() {return intr_list::getNextSibling();}
 		spTween&	getPrevSibling() {return intr_list::getPrevSibling();}
 
-		bool		isStarted() const {return _started;}
-		bool		isDone() const {return _done;}
+		bool		isStarted() const {return _status != status_not_started;}
+		bool		isDone() const {return _status == status_remove;}
 
-		void setDoneCallback(EventCallback cb){_cbDone = cb;}		
+		void setDataObject(spObject data) {_data = data;}
+		void setDoneCallback(EventCallback cb);//deprecated. use tween->addEventListener(TweenEvent::DONE, ...)
 		void setEase(EASE ease){_ease = ease;}
-		void setRelative(bool rel){_relative = rel;}
 		void setDelay(timeMS delay){_delay = delay;}
 		/** loops = -1 means infinity repeat cycles*/
 		void setLoops(int loops){_loops = loops;}
 		void setClient(Actor *client){_client = client;}
 
 		/**delete actor from parent node when tween done*/
-		void setDetachActor(bool detach){_remove = detach;}
+		void setDetachActor(bool detach){_detach = detach;}
 
 		/**immediately completes tween, calls doneCallback and mark tween as completed and removes self from Actor. If tween has infinity loops (=-1) then do nothing*/
-		void complete(timeMS deltaTime = std::numeric_limits<int>::max());
+		virtual void complete(timeMS deltaTime = std::numeric_limits<int>::max()/2);
 
 		
-		virtual bool start(Actor &actor);
-		virtual bool update(Actor &actor, const UpdateState &us);	
+		void start(Actor &actor);
+		void update(Actor &actor, const UpdateState &us);	
 
 		static float calcEase(EASE ease, float v);
 
 	protected:
-		friend class TweenQueue;
-		timeMS _elapsed;		
-		timeMS _duration;
-		timeMS _delay;
-
-		float _percent;
-		float _value;
-		bool _remove;
-
-
-		bool itDone(Actor &t, const UpdateState &us);
-		void callDone(Actor &t, const UpdateState *us);
+		void done(Actor &, const UpdateState &us);
 
+		virtual void _start(Actor &actor){}
+		virtual void _update(Actor &actor, const UpdateState &us){}
+		virtual void _done(Actor &actor, const UpdateState &us){}
 		virtual float _calcEase(float v);
 
+		enum status
+		{
+			status_not_started,
+			status_delayed,
+			status_started,
+			status_done,
+			status_remove,
+		};
+		status _status;		
+		timeMS _elapsed;
+
+		timeMS _duration;
+		timeMS _delay;
 		int _loops;
-		EventCallback _cbDone;
-		Actor *_client;
 		EASE _ease;		
 		bool _twoSides;
-		bool _done;
-		bool _started;
-		bool _relative;
-		
+
+		float _percent;
+		bool _detach;		
+				
+		EventCallback _cbDone;
+		Actor *_client;	
+
+		spObject _data;		
 	};	
 
 	template<class GS>
@@ -191,28 +199,19 @@ namespace oxygine
 
 		TweenT(const GS &gs):_gs(gs){}
 
-		bool update(Actor &actor, const UpdateState &us)
+		void _update(Actor &actor, const UpdateState &us)
 		{
-			bool done = Tween::update(actor, us);			
-			if (!done && _elapsed >= _delay)//done was delayed for 1 frame
-			{
-				type &t = *safeCast<type*>(&actor);
-				_gs.update(t, _value, us);//todo fix cast
-			}
-			
-			return done;
+			type &t = *safeCast<type*>(&actor); 
+			_gs.update(t, _percent, us);//todo fix cast
 		}
 
-		bool start(Actor &actor)
+		void _start(Actor &actor)
 		{
 			type &t = *safeCast<type*>(&actor);
-			_gs.init(t, _relative);
-			Tween::start(actor);
-
+			_gs.init(t, false);
 			UpdateState us;
 			us.iteration = -1;
-			bool done = update(actor, us);
-			return done;
+			_gs.update(t, _calcEase(0.0f), us);
 		}
 
 		GS &getGS(){return _gs;}
@@ -230,11 +229,12 @@ namespace oxygine
 		template<class GS>
 		spTween add(const GS &gs, timeMS duration, int loops = 1, bool twoSides = false, timeMS delay = 0, Tween::EASE ease = Tween::ease_linear)
 		{return add(createTween(gs, duration, loops, twoSides, delay, ease));}
-
-		bool start(Actor &actor);
-		bool update(Actor &actor, const UpdateState &us);
-
+		
 	private:
+		void complete(timeMS deltaTime);
+		void _start(Actor &actor);
+		void _update(Actor &actor, const UpdateState &us);
+
 		typedef intrusive_list<spTween> tweens;
 		tweens _tweens;
 		spTween _current;

+ 3 - 28
oxygine/src/core/NativeTexture.cpp

@@ -150,35 +150,10 @@ namespace oxygine
 
 		offset = 0;
 
-		if (flipU)
-		{
-			//printf("s2\n");
-			Matrix::translation(tr, Vector3(-(float)w / 2.0f - offset, -(float)h / 2.0f + offset, 0.0f));
-			Matrix::scaling(scale, Vector3(1.0f, 1.0f, 1.0f));
-
-			view = scale * tr;
-		}
-		else
-		{
-			/*
-			Matrix::translation(tr, Vector3((float)w / 2.0f - offset, (float)h / 2.0f + offset, 0.0f));			
-			Matrix::scaling(scale, Vector3(-1.0f, 1.0f, 1.0f));
-			Matrix rot;
-			Matrix::rotationZ(rot, M_PI/2);
-			view = scale * rot * tr;
-			*/
-
+		Matrix::translation(tr, Vector3(-(float)w / 2.0f - offset, (flipU ? -1.0f : 1.0f) * (float)h / 2.0f + offset, 0.0f));
+		Matrix::scaling(scale, Vector3(1.0f, flipU ? 1.0f : -1.0f, 1.0f));
 
-			Matrix::translation(tr, Vector3(-(float)w / 2.0f - offset, (float)h / 2.0f + offset, 0.0f));
-			Matrix::scaling(scale, Vector3(1.0f, -1.0f, 1.0f));
-
-
-			//Matrix::translation(tr, Vector3(-(float)w / 2.0f - offset, -(float)h / 2.0f + offset, 0.0f));
-			//Matrix::scaling(scale, Vector3(1.0f, -1.0f, 1.0f));
-
-
-			view = scale * tr;
-		}
+		view = scale * tr;
 
 		return view;
 	}

+ 280 - 114
oxygine/src/core/Renderer.cpp

@@ -5,17 +5,25 @@
 #include "ImageDataOperations.h"
 #include "AnimationFrame.h"
 #include "VertexDeclaration.h"
+#include "gl/VideoDriverGLES20.h"
+
+#include "ZipFileSystem.h"
+#include "system_data.h"
+#include "UberShaderProgram.h"
 
 namespace oxygine
 {
 	Renderer::Stats Renderer::statsPrev;
 	Renderer::Stats Renderer::statsCurrent;
-
+	bool _restored = false;
 	spNativeTexture Renderer::white;
-
+	std::vector<unsigned char> Renderer::indices8;
+	std::vector<unsigned short> Renderer::indices16;
+	int _maxVertices = 0;
+	UberShaderProgram Renderer::uberShader;
+	std::vector<unsigned char> Renderer::uberShaderBody;
 	
 
-
 	template<class V, class XY>
 	void fillQuad(V *v, const RectF &uv, XY *positions, const Color &color)
 	{
@@ -58,6 +66,72 @@ namespace oxygine
 	}
 	
 	void Renderer::initialize()
+	{
+		indices8.reserve(60 * 4);
+		for (int t = 0; t < 60; t += 1)
+		{
+			int i = t * 4;
+			indices8.push_back(i + 0);
+			indices8.push_back(i + 1);
+			indices8.push_back(i + 2);
+
+			indices8.push_back(i + 2);
+			indices8.push_back(i + 1);
+			indices8.push_back(i + 3);
+		}
+
+		indices16.reserve(12000 * 6);
+		for (int t = 0; t < 12000; t += 1)
+		{
+			int i = t * 4;
+			indices16.push_back(i + 0);
+			indices16.push_back(i + 1);
+			indices16.push_back(i + 2);
+
+			indices16.push_back(i + 2);
+			indices16.push_back(i + 1);
+			indices16.push_back(i + 3);
+		}
+
+		_maxVertices = indices16.size()/3 * 2;
+
+		file::buffer shaderBody;
+		file::read("shader.glsl", shaderBody, ep_ignore_error);
+        uberShaderBody = shaderBody.data;
+		if (!shaderBody.getSize())
+		{
+			file::Zips zp;
+			zp.add(system_data, system_size);
+			zp.read("system/shader.glsl", shaderBody);
+			uberShaderBody = shaderBody.data;
+		}
+
+		uberShader.init(uberShaderBody);
+
+		restore();
+	}
+
+	void Renderer::release()
+	{
+		indices8.clear();
+		indices16.clear();
+		uberShader.release();
+		uberShaderBody.clear();
+		if (white)
+			white->release();
+		white = 0;
+	}	
+
+	void Renderer::reset()
+	{
+		_restored = false;
+		if (white)
+			white->release();
+		white = 0;
+		uberShader.release();
+	}
+
+	void Renderer::restore()
 	{
 		MemoryTexture memwhite;
 		memwhite.init(4, 4, TF_R8G8B8A8);
@@ -70,26 +144,31 @@ namespace oxygine
 		white->setName("!renderer. white");
 		white->init(im, false);
 		white->setLinearFiltration(false);
-	}
 
-	void Renderer::release()
-	{
-		if (white)
-			white->release();
-		white = 0;
-	}	
+		setDefaultSettings();
+		_restored = true;
+	}
 
 
-	Renderer::Renderer(IVideoDriver *driver):_rt(0), _maxVertices(0), _driver(driver), _viewport(0,0,0,0)
+	Renderer::Renderer(IVideoDriver *driver):_rt(0), _driver(driver), 
+		_viewport(0,0,0,0), _program(0), _uberShader(0), _blend(blend_disabled), 
+		_shaderFlags(0), _clipMask(0,0,0,0), _vdecl(0)
 	{
 		if (!driver)
-			setDriver(IVideoDriver::instance);
+			driver = IVideoDriver::instance;
 
-		_batch.vertices.reserve(200);
-		setPrimaryColor(Color(255,255,255,255));
+		if (driver)
+			setDriver(driver);
 
-		_view.identity();
+		_vertices.reserve(32 * 1000);
+		setPrimaryColor(Color(0xffffffff));
+
+		//_view.identity();
+		//_proj.identity();
 		_transform.identity();
+		_vp.identity();
+
+		_uberShader = &uberShader;
 	}
 	
 	Renderer::~Renderer()
@@ -99,19 +178,46 @@ namespace oxygine
 
 	void Renderer::cleanup()
 	{
-		_batch.base = 0;
-		_batch.vertices.resize(0);
+		_base = 0;
+		_mask = 0;
+		_alpha =0;
+		_vertices.resize(0);
 	}
 
 	void Renderer::setBlendMode(blend_mode blend)
 	{
-		batch &b = _batch;
-		if (b.blend != blend)
+		if (_blend != blend)
 		{
 			drawBatch();
-		}
 
-		b.blend = blend;
+			switch (blend)
+			{
+			case blend_disabled:
+				_driver->setState(IVideoDriver::STATE_BLEND, 0);
+				break;
+			case blend_premultiplied_alpha:
+				_driver->setBlendFunc(IVideoDriver::BT_ONE, IVideoDriver::BT_ONE_MINUS_SRC_ALPHA);
+				break;
+			case blend_alpha:
+				_driver->setBlendFunc(IVideoDriver::BT_SRC_ALPHA, IVideoDriver::BT_ONE_MINUS_SRC_ALPHA);
+				break;
+			case blend_add:
+				_driver->setBlendFunc(IVideoDriver::BT_ONE, IVideoDriver::BT_ONE);
+				break;
+			//case blend_sub:
+				//_driver->setBlendFunc(IVideoDriver::BT_ONE, IVideoDriver::BT_ONE);
+				//glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+			//	break;
+			default:
+				OX_ASSERT(!"unknown blend");
+			}
+
+			if (_blend == blend_disabled)
+			{
+				_driver->setState(IVideoDriver::STATE_BLEND, 1);
+			}
+			_blend = blend;
+		}
 	}
 
 	void Renderer::setDiffuse(const Diffuse &df)
@@ -124,14 +230,34 @@ namespace oxygine
 		if (base == 0 || base->getHandle() == 0)
 			base = white;
 
-		batch &b = _batch;
-		if (b.base != base || b.alpha != alpha || b.basePremultiplied != basePremultiplied)
-		{
+		int shaderFlags = _shaderFlags;
+
+		if (basePremultiplied)			
+			shaderFlags &= ~UberShaderProgram::ALPHA_PREMULTIPLY;
+		else
+			shaderFlags |= UberShaderProgram::ALPHA_PREMULTIPLY;
+		
+		if (alpha)
+			shaderFlags |= UberShaderProgram::SEPARATE_ALPHA;
+		else
+			shaderFlags &= ~UberShaderProgram::SEPARATE_ALPHA;
+				
+//##ifdef OX_DEBUG
+#if 0
+		if (_base != base){OX_ASSERT(_alpha != alpha);}
+		else{OX_ASSERT(_alpha == alpha);}
+#endif //OX_DEBUG
+
+		//no reason to check changed alpha because it is in pair with base
+		if (_base != base || /*_alpha != alpha || */_shaderFlags != shaderFlags)
+		{			
 			drawBatch();
 		}
-		b.basePremultiplied = basePremultiplied;
-		b.base = base;
-		b.alpha = alpha;
+
+		_shaderFlags = shaderFlags;
+		
+		_base = base;
+		_alpha = alpha;
 	}
 
 	void Renderer::setTransform(const transform &m)
@@ -139,15 +265,24 @@ namespace oxygine
 		_transform = m;
 	}
 
-	void Renderer::setShaderProgram(shaderProgram pr)
+	void Renderer::setShader(ShaderProgram *prog)
 	{
-		batch &b = _batch;
-		if (b.program != pr)
+		if (prog != _program)
+		{
+			_driver->setShaderProgram(prog);
+			prog->setUniform("mat", &_vp);
+		}
+		_program = prog;
+	}
+
+	void Renderer::setUberShaderProgram(UberShaderProgram* pr)
+	{
+		if (_uberShader != pr)
 		{
 			drawBatch();
 		}
 
-		b.program = pr;
+		_uberShader = pr;
 	}
 
 	const Color &Renderer::getPrimaryColor() const
@@ -162,32 +297,50 @@ namespace oxygine
 	}
 
 	void Renderer::drawBatch()
-	{		
-		batch &b = _batch;
-
-		if (!b.vertices.empty())
+	{
+		if (!_vertices.empty())
 		{
-			getDriver()->drawBatch(b);
+			ShaderProgram *prog = _uberShader->getShaderProgram(_shaderFlags)->program;
+			setShader(prog);
+
+			_driver->setTexture(UberShaderProgram::SAMPLER_BASE, _base);
+
+			if (_alpha)
+			{
+				_driver->setTexture(UberShaderProgram::SAMPLER_ALPHA, _alpha);
+			}
+
+			if (_mask) 
+			{
+				_driver->setTexture(UberShaderProgram::SAMPLER_MASK, _mask);
+
+				Vector4 v(_clipMask.getLeft(), _clipMask.getTop(), _clipMask.getRight(), _clipMask.getBottom());
+				prog->setUniform("clip_mask", &v, 1);
+			}
+
 			
-			++statsCurrent.batches;
-			statsCurrent.triangles += b.vertices.size()/(b.vdecl->size * 2);
+			UberShaderProgram::ShaderUniformsCallback cb = _uberShader->getShaderUniformsCallback();
+			if (cb)
+			{
+				cb(prog);
+			}			
 
-			b.vertices.resize(0);			
-		}
-	}
+			int count = _vertices.size() / _vdecl->size;
+			int indices = (count * 3)/2;
 
-	RectF calcUV(const Rect &srcRect, float iw, float ih)
-	{
-		float u = srcRect.pos.x * iw;
-		float v = srcRect.pos.y * ih;
+			if (indices <= (int)indices8.size())
+				getDriver()->draw(IVideoDriver::PT_TRIANGLES, _vdecl, &_vertices.front(), count, &indices8.front(), indices, false);
+			else
+				getDriver()->draw(IVideoDriver::PT_TRIANGLES, _vdecl, &_vertices.front(), count, &indices16.front(), indices, true);
+			
+			++statsCurrent.batches;
+			statsCurrent.triangles += _vertices.size()/(_vdecl->size * 2);
 
-		float du = srcRect.size.x * iw;
-		float dv = srcRect.size.y * ih;	
-		
-		return RectF (u, v, du, dv);
+			_vertices.resize(0);			
+			//b.shaderFlags = 0;
+		}
 	}
 
-
 	bool checkT2P(const Rect &viewport, const Matrix &vp, const vertexPCT2 *v1, const vertexPCT2 *v2, int w, int h)
 	{
 		Vector3 p1(v1->x, v1->y, 0);
@@ -241,8 +394,7 @@ namespace oxygine
 
 	void Renderer::setMask(spNativeTexture mask, const RectF &srcRect, const RectF &destRect, const transform &t, bool channelR)
 	{
-		batch &b = _batch;
-		if (b.mask != mask)
+		if (_mask != mask)
 		{
 			drawBatch();
 		}
@@ -255,47 +407,43 @@ namespace oxygine
 			srcRect.getRightTop(),
 			srcRect.getLeftBottom());
 
-		b.mask = mask;
-		b.maskChannelR = channelR;
-		if (b.vdecl->bformat != VERTEX_PCT2T2)
-			b.vdecl = _driver->getVertexDeclaration(VERTEX_PCT2T2);		
-		b.clipMask = srcRect;
+		_mask = mask;
+		if (_vdecl->bformat != VERTEX_PCT2T2)
+			_vdecl = _driver->getVertexDeclaration(VERTEX_PCT2T2);		
+		_clipMask = srcRect;
 		Vector2 v(1.0f / mask->getWidth(), 1.0f / mask->getHeight());
-		b.clipMask.expand(v, v);
+		_clipMask.expand(v, v);
+
+		_shaderFlags |= UberShaderProgram::MASK;
+		if (channelR)
+			_shaderFlags |= UberShaderProgram::MASK_R_CHANNEL;
 	}
 
 	void Renderer::removeMask()
 	{
 		drawBatch();
-		batch &b = _batch;
-		b.mask = 0;
-		b.vdecl = _driver->getVertexDeclaration(VERTEX_PCT2);
+
+		_mask = 0;
+		_shaderFlags &= ~(UberShaderProgram::MASK | UberShaderProgram::MASK_R_CHANNEL);
+		_vdecl = _driver->getVertexDeclaration(VERTEX_PCT2);
 	}
 
-	void Renderer::updateDriver()
+	Vector2	Renderer::getMaskedUV(const Vector2 &pos)
 	{
-		if (_batch.vdecl)
-			return;
-		_batch.vdecl = _driver->getVertexDeclaration(VERTEX_PCT2);
-		_maxVertices = _driver->getMaxVertices();
+		Vector2 uv = _clipUV.calc(pos);
+		return uv;
 	}
 
 	void Renderer::draw(const RectF &srcRect, const RectF &destRect)
 	{
-		updateDriver();
-
-		batch &b = _batch; 
+		const Color* color = &_primaryColor;
+		if (_blend == blend_premultiplied_alpha)
+			color = &_primaryColorPremultiplied;
 
-		NativeTexture *nt = b.base.get();
-
-		Color color = _primaryColor;
-		if (b.blend == blend_premultiplied_alpha)
-			color = _primaryColorPremultiplied;
-
-		if (b.mask)
+		if (_mask)
 		{
 			vertexPCT2T2 v[4];
-			fillQuadT(v, srcRect, destRect, _transform, color);		
+			fillQuadT(v, srcRect, destRect, _transform, *color);
 			
 			for (int i = 0; i < 4; ++i)
 			{
@@ -304,80 +452,81 @@ namespace oxygine
 				v[i].v2 = uv.y;
 			}
 
-			b.vertices.insert(b.vertices.end(), (unsigned char*)v, (unsigned char*)v + sizeof(v));
-
+			_vertices.insert(_vertices.end(), (unsigned char*)v, (unsigned char*)v + sizeof(v));
 		}
 		else
 		{
 			vertexPCT2 v[4];
-			fillQuadT(v, srcRect, destRect, _transform, color);		
+			fillQuadT(v, srcRect, destRect, _transform, *color);		
 
 #ifdef OXYGINE_DEBUG_T2P
-			if (b.base != white && _showTexel2PixelErrors)
+			if (_base != white && _showTexel2PixelErrors)
 			{
-				Matrix vp = _view * _proj;
-
-				bool t = checkT2P(_viewport, vp, &v[0], &v[3], nt->getWidth(), nt->getHeight());
+				bool t = checkT2P(_viewport, _vp, &v[0], &v[3], _base->getWidth(), _base->getHeight());
 				if (!t)
 				{
 					float c = (sinf((float)getTimeMS()/200 + v[0].x * v[0].y) + 1)/2.0f;
-					color = interpolate(Color(rand() % 255, rand() % 255,rand() % 255, 255), color, c);
-					fillQuadT(v, srcRect, destRect, _transform, color);		
+					Color b = interpolate(Color(rand() % 255, rand() % 255,rand() % 255, 255), *color, c);
+					fillQuadT(v, srcRect, destRect, _transform, b);		
 				}
 			}	
 #endif
 
-			b.vertices.insert(b.vertices.end(), (unsigned char*)v, (unsigned char*)v + sizeof(v));
+			_vertices.insert(_vertices.end(), (unsigned char*)v, (unsigned char*)v + sizeof(v));
 		}
 		
-		if (b.vertices.size()/sizeof(b.vdecl->size) >= _maxVertices)
+		if (_vertices.size()/sizeof(_vdecl->size) >= _maxVertices)
 			drawBatch();
 	}
 
 	void Renderer::draw(const void *data, int size, bvertex_format format)
 	{
-		updateDriver();
-
-		batch &b = _batch; 
-		if (b.vdecl->bformat != format)
+		if (_vdecl->bformat != format)
 		{
 			drawBatch();
+			_vdecl = _driver->getVertexDeclaration(format);
 		}
-		
-		if (b.vdecl->bformat != format)
-			b.vdecl = _driver->getVertexDeclaration(format);
 
-		int num = size / b.vdecl->size;
-		size_t currentNum = b.vertices.size() / b.vdecl->size;
+		int num = size / _vdecl->size;
+		size_t currentNum = _vertices.size() / _vdecl->size;
 		if (currentNum + num >= _maxVertices)
 		{
 			drawBatch();
-		}	
-		
-
+		}		
 
-		b.vertices.insert(b.vertices.end(), (unsigned char*)data, (unsigned char*)data + size);
-
-		
-		//if (b.vertices.size()/sizeof(vSize) >= _maxVertices)
-		//	drawBatch();
+		_vertices.insert(_vertices.end(), (unsigned char*)data, (unsigned char*)data + size);
 	}
 
+	
+
 
 	void Renderer::setDefaultSettings()
 	{
-		OX_ASSERT(!"NO");
-		//_driver->setDefaultSettings();		
+		/*
+		_blend = blend_disabled;
+		IVideoDriver* instance = IVideoDriver::instance;
+		instance->setState(IVideoDriver::STATE_BLEND, 0);
+		*/
+		/*
+		
+		instance->setState(IVideoDriver::STATE_BLEND, 1);
+		instance->setBlendFunc(IVideoDriver::BT_ONE, IVideoDriver::BT_ONE);
+		*/
 	}
 
-	void Renderer::setViewTransform(const Matrix &m)
+	void Renderer::initCoordinateSystem(int width, int height, bool flipU)
 	{
-		_view = m;
+		Matrix view = makeViewMatrix(width, height, flipU); 
+		Matrix proj;
+		//initialize projection matrix
+		Matrix::orthoLH(proj, (float)width, (float)height, 0, 1);
+
+		setViewProjTransform(view, proj);
 	}
 
-	void Renderer::setProjTransform(const Matrix &m)
+	void Renderer::setViewProjTransform(const Matrix &view, const Matrix &proj)
 	{
-		_proj = m;
+		_vp = view * proj;
 	}
 
 	IVideoDriver *Renderer::getDriver()
@@ -390,10 +539,19 @@ namespace oxygine
 		_driver = driver;
 	}
 
+	void Renderer::resetSettings()
+	{
+		_blend = blend_disabled;
+		_driver->setState(IVideoDriver::STATE_BLEND, 0);
+	}
+
 	bool Renderer::begin(spNativeTexture rt, const Rect &viewport, const Color *clearColor)
 	{
-		if (!getDriver()->isReady())
+		if (!_restored)
 			return false;
+
+		//if (!getDriver()->isReady())
+		//	return false;
 		_rt = rt;
 
 		if (_rt)
@@ -402,8 +560,16 @@ namespace oxygine
 		}
 
 		_viewport = viewport;
-
-		getDriver()->begin(_proj, _view, viewport, clearColor);
+		_program = 0;
+
+		getDriver()->begin(viewport, clearColor);
+		_vdecl = _driver->getVertexDeclaration(VERTEX_PCT2);
+		_base = 0;
+		_mask = 0;
+		_alpha = 0;
+		_program = 0;
+		_vertices.resize(0);
+		resetSettings();		
 
 		return true;
 	}

+ 57 - 24
oxygine/src/core/Renderer.h

@@ -14,6 +14,19 @@ namespace oxygine
 {
 	using namespace std;
 
+	enum blend_mode
+	{
+		blend_default,
+		blend_disabled,
+		blend_premultiplied_alpha,
+		blend_alpha,
+		blend_add,
+		//blend_xor,
+
+		//gles2
+		blend_sub
+	};
+
 	class ClipUV
 	{
 	public:
@@ -112,7 +125,7 @@ namespace oxygine
 	} 
 
 	class IVideoDriver;
-
+	class UberShaderProgram;
 	class Diffuse;
 
 	class Renderer
@@ -134,8 +147,17 @@ namespace oxygine
 		static void initialize();
 		/**Cleans internal static classes*/
 		static void release();
+		/**for lost context*/
+		static void reset();
+		/**restore after lost context*/
+		static void restore();
 		/**White 4x4 Texture*/
 		static spNativeTexture white;
+		static UberShaderProgram uberShader;
+		static std::vector<unsigned char> uberShaderBody;
+
+		static std::vector<unsigned char> indices8;
+		static std::vector<unsigned short> indices16;
 				
 		static Stats statsPrev;
 		static Stats statsCurrent;
@@ -144,14 +166,23 @@ namespace oxygine
 		Renderer(IVideoDriver *driver = 0);
 		virtual ~Renderer();
 
+
+		/**Returns triangles vertex Color.*/
+		const Color&	getPrimaryColor() const;
+		const Matrix&	getViewProjection() const {return _vp;}
+		//const Matrix&	getProjection() const {return _proj;}
+		Vector2			getMaskedUV(const Vector2 &pos);
+		IVideoDriver*	getDriver();
+
+
 		/**Begins rendering into RenderTexture or into primary framebuffer if rt is null*/
 		bool begin(spNativeTexture rt, const Rect &viewport, const Color *clearColor);
 		/**Completes started rendering and restores previous Framebuffer.*/
-		void end();
-		/**Sets View matrix*/
-		void setViewTransform(const Matrix &m);
-		/**Sets Projection matrix*/
-		void setProjTransform(const Matrix &m);
+		void end();		
+
+		/**initializes View + Projection matrices where TopLeft is (0,0) and RightBottom is (width, height). use flipU = true for render to texture*/
+		void initCoordinateSystem(int width, int height, bool flipU = false);
+		void setViewProjTransform(const Matrix &view, const Matrix &proj);
 		/**Sets blend mode. Default value is blend_premultiplied_alpha*/
 		void setBlendMode(blend_mode blend);
 		/**Sets texture. If texture is null White texture would be used.*/
@@ -160,12 +191,11 @@ namespace oxygine
 		void setMask(spNativeTexture mask, const RectF &srcRect, const RectF &destRect, const transform &t, bool channelR);
 		void removeMask();
 		/**Sets World transformation matrix.*/
-		void setTransform(const transform &m);		
-
-		void setShaderProgram(shaderProgram pr);
+		void setTransform(const transform &m);				
+		void setUberShaderProgram(UberShaderProgram* pr);
+		void resetSettings();
+		void setDriver(IVideoDriver *);
 
-		/**Returns triangles vertex Color.*/
-		const Color &getPrimaryColor() const;
 		/**Sets triangles vertex Color.*/
 		void setPrimaryColor(const Color &);
 		/**Accumulates rectangles into batch or render it.*/
@@ -176,25 +206,29 @@ namespace oxygine
 		/**Cleans existing accumulated batch.*/
 		void cleanup();
 
-		int				getMaxVertices() const {return _maxVertices;}		
-		const Matrix&	getView() const {return _view;}
-		const Matrix&	getProjection() const {return _proj;}
-
-		IVideoDriver *getDriver();
-		void setDriver(IVideoDriver *);
-
-
 		//debug utils
 #ifdef OXYGINE_DEBUG_T2P
 		static void showTexel2PixelErrors(bool show);
 #endif
 
 	protected:			
-		void updateDriver();
+		void setShader(ShaderProgram *prog);
+
+		UberShaderProgram *_uberShader;
+		unsigned int _shaderFlags;
+
+		std::vector<unsigned char> _vertices;
+		spNativeTexture _base;
+		spNativeTexture _mask;
+		spNativeTexture _alpha;
+		RectF _clipMask;
+		const VertexDeclaration *_vdecl;
 
 		IVideoDriver *_driver;
-		Matrix _view;
-		Matrix _proj;
+		ShaderProgram *_program;
+		//Matrix _view;
+		//Matrix _proj;
+		Matrix _vp;
 		Rect _viewport;
 		transform _transform;
 
@@ -204,7 +238,6 @@ namespace oxygine
 
 		spNativeTexture _rt;
 
-		batch _batch;
-		unsigned int _maxVertices;		
+		blend_mode _blend;
 	};
 }

+ 2 - 3
oxygine/src/core/ShaderProgram.h

@@ -4,17 +4,16 @@
 
 namespace oxygine
 {
-	DECLARE_SMART(ShaderProgram, spShaderProgram);
-
 	class ShaderProgram: public Object
 	{
 	public:
-		virtual void bind() = 0;
+		//virtual void bind() = 0;
 
 		virtual unsigned int getID() const = 0;
 
 		virtual void setUniform(const char *id, const Vector4 *v, int num) = 0;
 		virtual void setUniform(const char *id, const Matrix *) = 0;
 		virtual void setUniform(const char *id, float v) = 0;
+		virtual void setUniformInt(const char *id, int v) = 0;
 	};
 }

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

@@ -0,0 +1,123 @@
+#include "UberShaderProgram.h"
+#include "vertex.h"
+#include "gl/VideoDriverGLES20.h"
+#include "gl/ShaderProgramGL.h"
+
+namespace oxygine
+{
+	UberShaderProgram::UberShaderProgram()
+	{
+
+	}
+
+	void UberShaderProgram::init(const std::vector<unsigned char> &baseShader, const char *prepend, const char *append)		
+	{
+		_data = baseShader;
+
+		_data.insert(_data.begin(), prepend, prepend + strlen(prepend));
+		_data.insert(_data.end(), append, append + strlen(append));
+		_data.push_back(0);
+
+		reg(CLOSURE(this, &UberShaderProgram::_restore), 0);
+	}
+
+	void UberShaderProgram::releaseShaders()
+	{
+		for (int i = 0; i < SIZE; ++i)
+		{
+			shader &s = _shaders[i];
+			delete s.program;
+			s.program = 0;
+		}
+	}
+
+	UberShaderProgram::~UberShaderProgram()
+	{
+		releaseShaders();
+	}
+
+	void UberShaderProgram::_restore(Restorable *, void*)
+	{
+
+	}
+
+	void UberShaderProgram::release()
+	{
+		for (int i = 0; i < SIZE; ++i)
+		{
+			shader &s = _shaders[i];
+			if (s.program)
+			{
+				delete s.program;
+				s.program = 0;
+			}			
+		}
+	}
+
+	UberShaderProgram::shader *UberShaderProgram::getShaderProgram(int flags)
+	{
+		shader &s = _shaders[flags];
+
+		if (!s.program)
+		{
+			bvertex_format bformat = VERTEX_PCT2;
+			s.flags = flags;
+			const char* data = (const char*)&_data.front();
+
+			char prepend[255];
+			char append[255];
+
+			append[0] = 0;
+			prepend[0] = 0;
+
+			if (flags & ALPHA_PREMULTIPLY)
+				strcat(prepend, "#define ALPHA_PREMULTIPLY\n");
+
+			if (flags & SEPARATE_ALPHA)
+				strcat(prepend, "#define SEPARATE_ALPHA\n");
+
+			if (flags & MASK_R_CHANNEL)
+				strcat(prepend, "#define MASK_R_CHANNEL\n");
+
+			if (flags & MASK)
+			{
+				strcat(prepend, "#define MASK\n");
+				bformat = VERTEX_PCT2T2;
+			}
+
+			char *end = prepend + strlen(prepend);
+			strcat(prepend, "#define program_main_ps main\n");
+			strcat(prepend, "#define PS\n");
+
+			int fs = ShaderProgramGL::createShader(GL_FRAGMENT_SHADER, data, prepend, append);
+
+			*end = 0;
+			strcat(prepend, "#define program_main_vs main\n");
+			strcat(prepend, "#define VS\n");
+
+			int vs = ShaderProgramGL::createShader(GL_VERTEX_SHADER, data, prepend, append);					
+
+			ShaderProgramGL *pgl = new ShaderProgramGL;
+			const VertexDeclarationGL *decl = ((VideoDriverGLES20*)IVideoDriver::instance)->getVertexDeclaration(bformat);
+			pgl->init(ShaderProgramGL::createProgram(vs, fs, decl));
+
+            
+            CHECKGL();
+
+			glUseProgram(pgl->getID());
+            
+            CHECKGL();
+
+			pgl->setUniformInt("base_texture", UberShaderProgram::SAMPLER_BASE);
+			pgl->setUniformInt("alpha_texture", UberShaderProgram::SAMPLER_ALPHA);
+			pgl->setUniformInt("mask_texture", UberShaderProgram::SAMPLER_MASK);
+
+			s.program = pgl;
+            
+            
+            CHECKGL();
+		}
+
+		return &s;
+	}
+}

+ 60 - 0
oxygine/src/core/UberShaderProgram.h

@@ -0,0 +1,60 @@
+#pragma once
+#include <vector>
+#include "Restorable.h"
+
+namespace oxygine
+{
+	class ShaderProgram;
+
+	class UberShaderProgram: public Restorable
+	{
+	public:
+		struct shader
+		{
+			shader():program(0), flags(0){}
+			ShaderProgram *program;
+			int flags;
+		};
+
+		enum
+		{
+			ALPHA_PREMULTIPLY = 1,
+			SEPARATE_ALPHA = 1 << 1,
+			MASK_R_CHANNEL = 1 << 2,
+			MASK = 1 << 3,
+			SIZE = 1 << 4
+		};		
+
+		enum 
+		{
+			SAMPLER_BASE,
+			SAMPLER_ALPHA,
+			SAMPLER_MASK,
+			SAMPLER_NUM,
+		};
+
+		UberShaderProgram();
+		~UberShaderProgram();
+
+		void init(const std::vector<unsigned char> &baseShader, const char *prepend="", const char *append = "");
+
+		void release();
+
+		typedef Closure<void (ShaderProgram *)> ShaderUniformsCallback;
+		void setShaderUniformsCallback(ShaderUniformsCallback cb){_cb = cb;}
+
+		ShaderUniformsCallback	getShaderUniformsCallback() const {return _cb;}
+		shader*					getShaderProgram(int flags);
+
+
+	protected:
+		void *_getRestorableObject() {return this;}
+		void _restore(Restorable *, void*);
+
+		shader _shaders[SIZE];
+		std::vector<unsigned char> _data;
+		ShaderUniformsCallback _cb;		
+
+		void releaseShaders();
+	};
+}

+ 11 - 63
oxygine/src/core/VideoDriver.cpp

@@ -1,70 +1,20 @@
 #include "VideoDriver.h"
 #include "NativeTexture.h"
 #include "math/Color.h"
+#include "ShaderProgram.h"
 
 
 namespace oxygine
 {
 	IVideoDriver* IVideoDriver::instance = 0;
 
-	batch::batch():blend(blend_premultiplied_alpha), program(0), basePremultiplied(false), vdecl(0), maskChannelR(false){}
-	batch::~batch()
-	{
-	}
-
-
-	typedef std::vector<unsigned char> indices8;
-	typedef std::vector<unsigned short> indices16;
-
-	indices8 initIndices8()
-	{
-		indices8 ind;
-		for (int t = 0; t < 60; t += 1)
-		{
-			int i = t * 4;
-			ind.push_back(i + 0);
-			ind.push_back(i + 1);
-			ind.push_back(i + 2);
-
-			ind.push_back(i + 2);
-			ind.push_back(i + 1);
-			ind.push_back(i + 3);
-		}
-
-		return ind;
-	}
-
-	indices16 initIndices16()
-	{
-		indices16 ind;
-		ind.reserve(12000 * 6);
-		for (int t = 0; t < 12000; t += 1)
-		{
-			int i = t * 4;
-			ind.push_back(i + 0);
-			ind.push_back(i + 1);
-			ind.push_back(i + 2);
-
-			ind.push_back(i + 2);
-			ind.push_back(i + 1);
-			ind.push_back(i + 3);
-		}
-
-		return ind;
-	}
-
-	indices8 _indices8 = initIndices8();
-	indices16 _indices16 = initIndices16();
-
-
-
 	spNativeTexture VideoDriverNull::createTexture()
 	{
 		//return new NativeTextureNull;
 		return 0;
 	}
 
-	void VideoDriverNull::begin(const Matrix &proj, const Matrix &view, const Rect &viewport, const Color *clearColor)
+	void VideoDriverNull::begin(const Rect &viewport, const Color *clearColor)
 	{
 
 	}
@@ -73,12 +23,7 @@ namespace oxygine
 	{
 		
 	}
-
-	int VideoDriverNull::getMaxVertices() const
-	{
-		return 255;
-	}
-
+	
 	bool VideoDriverNull::getScissorRect(Rect &) const
 	{
 		return false;
@@ -89,11 +34,6 @@ namespace oxygine
 		OX_ASSERT(0);
 		return 0;
 	}
-	
-	void VideoDriverNull::drawBatch(const batch &b)
-	{
-
-	}
 
 	void VideoDriverNull::setScissorRect(const Rect *)
 	{
@@ -107,5 +47,13 @@ namespace oxygine
 	void VideoDriverNull::setRenderTarget(spNativeTexture)
 	{
 
+	}
+	void VideoDriverNull::setShaderProgram(ShaderProgram*)
+	{
+
+	}
+	void VideoDriverNull::setTexture(int sampler, spNativeTexture)
+	{
+
 	}
 }

+ 50 - 88
oxygine/src/core/VideoDriver.h

@@ -1,89 +1,50 @@
 #pragma once
 #include "oxygine_include.h"
 #include "ref_counter.h"
-#include <vector>
-#include "math/matrix.h"
-#include "math/Rect.h"
 #include "vertex.h"
+#include "math/Rect.h"
+#include <vector>
 
 namespace oxygine
 {	
 	class Color;
 	DECLARE_SMART(NativeTexture, spNativeTexture);
 
-	struct vertexP2T2
-	{
-		float x, y;		
-		float u, v;
-
-		Vector2 &getPos() {return *((Vector2*)&x);}
-		Vector2 &getUV() {return *((Vector2*)&u);}
-	};
-
-	struct vertexP2C
-	{
-		float x, y;		
-		unsigned int color;
-
-		Vector2 &getPos() {return *((Vector2*)&x);}
-	};
-
-	struct vertexPCT2
-	{
-		float x, y, z;
-		unsigned int color;
-		float u, v;				
-	};
-
-	struct vertexPCT2T2: public vertexPCT2
-	{	
-		float u2, v2;				
-	};
-
-	typedef std::vector<unsigned char> Vertices;
-
-	enum blend_mode
-	{
-		blend_default,
-		blend_disabled,
-		blend_premultiplied_alpha,
-		blend_alpha,
-		blend_add,
-		//blend_xor,
-
-		//gles2
-		blend_sub
-	};
-
-	class UberShaderProgram;
-	typedef UberShaderProgram* shaderProgram;
+	class ShaderProgram;
 	class VertexDeclaration;
-	
-
-	struct batch
-	{
-		batch();
-		~batch();
-
-		//bvertex_format bformat;
-		Vertices vertices;
-		const VertexDeclaration *vdecl;
-
-		spNativeTexture base;
-		spNativeTexture alpha;
-		spNativeTexture mask;
-		bool maskChannelR;
-
-		RectF clipMask;
-		bool basePremultiplied;
-
-		blend_mode blend;
-		shaderProgram program;
-	};
 
 	class IVideoDriver
 	{
 	public:
+		enum PRIMITIVE_TYPE
+		{
+			PT_POINTS,
+			PT_LINES,
+			PT_LINE_LOOP,
+			PT_LINE_STRIP,
+			PT_TRIANGLES,
+			PT_TRIANGLE_STRIP,
+			PT_TRIANGLE_FAN,
+		};
+
+		enum BLEND_TYPE
+		{
+			BT_ZERO,
+			BT_ONE,
+			BT_SRC_COLOR,
+			BT_ONE_MINUS_SRC_COLOR,
+			BT_SRC_ALPHA,
+			BT_ONE_MINUS_SRC_ALPHA,
+			BT_DST_ALPHA,
+			BT_ONE_MINUS_DST_ALPHA,
+		};
+
+		enum STATE
+		{
+			STATE_BLEND,
+			STATE_NUM
+		};
+
 		static IVideoDriver *instance;
 		virtual ~IVideoDriver(){}
 
@@ -93,44 +54,45 @@ namespace oxygine
 
 		virtual spNativeTexture createTexture() = 0;
 
-		virtual void begin(const Matrix &proj, const Matrix &view, const Rect &viewport, const Color *color) = 0;				
-		virtual void drawBatch(const batch &b) = 0;
+		virtual void begin(const Rect &viewport, const Color *color) = 0;				
+		virtual void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData, unsigned int numVertices) = 0;
+		virtual void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData, unsigned int numVertices, const void *indicesData, unsigned int numIndices, bool indicesShortType) = 0;
 
 		virtual void	getViewport(Rect &r) const = 0;
-		virtual int		getMaxVertices() const = 0;
 		virtual bool	getScissorRect(Rect &) const = 0;
 		virtual const VertexDeclaration *getVertexDeclaration(bvertex_format) const = 0;
 		
 		virtual void setScissorRect(const Rect *) = 0;
 		virtual void setDefaultSettings() = 0;
 		virtual void setRenderTarget(spNativeTexture) = 0;
-	};
-
-
-	typedef std::vector<unsigned char> indices8;
-	typedef std::vector<unsigned short> indices16;
-	
-	extern indices8 _indices8;
-	extern indices16 _indices16;
-		
+		virtual void setShaderProgram(ShaderProgram*) = 0;
+		virtual void setTexture(int sampler, spNativeTexture) = 0;
+		virtual void setState(STATE, unsigned int value) = 0;
+		virtual void setBlendFunc(BLEND_TYPE src, BLEND_TYPE dest) = 0;
+	};		
 
 	class VideoDriverNull: public IVideoDriver
 	{
 	public:
 		spNativeTexture createTexture();
 
-		void begin(const Matrix &proj, const Matrix &view, const Rect &viewport, const Color *clearColor);
+		void begin(const Rect &viewport, const Color *clearColor);
 		bool isReady() const {return true;}
-		void	getViewport(Rect &r) const;
-		int		getMaxVertices() const;
-		bool	getScissorRect(Rect &) const;
+		void getViewport(Rect &r) const;
+		bool getScissorRect(Rect &) const;
 		const VertexDeclaration*	getVertexDeclaration(bvertex_format) const;
 		
-		void drawBatch(const batch &b);
+		void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData, unsigned int verticesDataSize){}
+		void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData, unsigned int verticesDataSize, const void *indicesData, unsigned int indicesDataSize, bool indicesShortType){}
+
 
 		void setScissorRect(const Rect *);
 		void setDefaultSettings();
 		void setRenderTarget(spNativeTexture);
+		void setShaderProgram(ShaderProgram*);
+		void setTexture(int sampler, spNativeTexture);
+		void setState(STATE, unsigned int value){}
+		void setBlendFunc(BLEND_TYPE src, BLEND_TYPE dest){}
 
 		void reset(){}
 		void restore(){}

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

@@ -90,6 +90,8 @@ namespace oxygine
 		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
 
 		NativeTextureGLES::created++;
+        
+        CHECKGL();
 
 		return id;
 	}
@@ -153,6 +155,7 @@ namespace oxygine
 		_width = w;
 		_height = h;
 		_format = tf;
+        CHECKGL();
 	}
 
 	void NativeTextureGLES::init(nativeTextureHandle id, int w, int h, TextureFormat tf)
@@ -181,6 +184,7 @@ namespace oxygine
 		OX_ASSERT(sysMemCopy == false);
 
 		init((nativeTextureHandle)id, src.w, src.h, src.format);
+        CHECKGL();
 	}
 
 	void NativeTextureGLES::setLinearFiltration(bool enable)
@@ -190,6 +194,7 @@ namespace oxygine
 		unsigned int f = enable ? GL_LINEAR : GL_NEAREST;
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f);
+        CHECKGL();
 	}
 
 	void NativeTextureGLES::release()
@@ -209,6 +214,7 @@ namespace oxygine
 		}
 
 		unreg();
+        CHECKGL();
 	}
 
 
@@ -306,7 +312,9 @@ namespace oxygine
 			er = glGetError();
 
 			_lockFlags = 0;	
-		}		
+		}
+        
+        CHECKGL();
 	}
 
 
@@ -322,6 +330,7 @@ namespace oxygine
 		glTexSubImage2D(GL_TEXTURE_2D, 0, 
 			x, y, data.w, data.h, 
 			glp.format, glp.type, data.data);
+        CHECKGL();
 	}
 
 	void NativeTextureGLES::apply(const Rect *)

+ 104 - 0
oxygine/src/core/gl/ShaderProgramGL.cpp

@@ -0,0 +1,104 @@
+#include "ShaderProgramGL.h"
+#include "VertexDeclarationGL.h"
+#include "oxgl.h"
+
+namespace oxygine
+{
+	ShaderProgramGL::ShaderProgramGL():_program(0)
+	{
+
+	}
+
+	ShaderProgramGL::~ShaderProgramGL()
+	{
+		if (_program)
+			glDeleteProgram(_program);
+        CHECKGL();
+	}
+
+
+
+	void printShaderInfoLog(GLuint shader)
+	{
+		GLint length = 0;
+		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
+		if (length)
+		{
+			char* buffer = (char*)malloc( sizeof(char) * length ) ;
+			glGetShaderInfoLog(shader, length, NULL, buffer);
+			if (buffer[0])
+				log::error("%s", buffer);
+			free(buffer);
+
+			GLint success;
+			glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+			if (success != GL_TRUE) 
+			{
+				OX_ASSERT(!"shader build error");
+				exit(1);
+			}
+		}
+        
+        CHECKGL();
+	}
+
+
+	unsigned int ShaderProgramGL::createShader(unsigned int type, const char* data, const char *prepend, const char *append)
+	{
+		GLuint shader = glCreateShader(type);
+
+		const char *sources[16];
+		const char **ptr = &sources[0];
+
+		char nonGLES[] = 
+			"#define lowp\n"
+			"#define mediump\n"
+			"#define highp\n";
+
+#if SDL_VIDEO_OPENGL
+		*ptr = nonGLES;
+		ptr++;
+#endif
+
+		if (prepend)
+		{
+			*ptr = prepend;
+			ptr++;
+		}
+
+		*ptr = data;
+		ptr++;
+
+		if (append)
+		{
+			*ptr = append;
+			ptr++;
+		}
+
+		int num = ptr - sources;
+		glShaderSource(shader, num, sources, 0);
+		glCompileShader(shader);
+		printShaderInfoLog(shader);
+        
+        CHECKGL();
+
+		return shader;
+	}
+
+
+	unsigned int ShaderProgramGL::createProgram(int vs, int fs, const VertexDeclarationGL *decl)
+	{
+		int p = glCreateProgram();
+		glAttachShader(p, vs);
+		glAttachShader(p, fs);
+
+		for (int i = 0; i < decl->numElements; ++i)		
+			glBindAttribLocation(p, decl->elements[i].index, decl->elements[i].name);
+
+		glLinkProgram(p);
+        
+        CHECKGL();
+
+		return p;
+	}
+}

+ 68 - 0
oxygine/src/core/gl/ShaderProgramGL.h

@@ -0,0 +1,68 @@
+#pragma once
+#include "../ShaderProgram.h"
+#include "oxgl.h"
+namespace oxygine
+{
+	class VertexDeclarationGL;
+	class ShaderProgramGL: public ShaderProgram
+	{
+	public:
+		ShaderProgramGL();
+		~ShaderProgramGL();
+
+		void init(GLuint p)
+		{
+			_program = p;
+		}
+
+		unsigned int getID() const 
+		{
+			return _program;
+		}
+
+		void setUniformInt(const char *id, int v)
+		{
+			int location = glGetUniformLocation(_program, id);
+			if (location == -1)
+				return;
+			glUniform1i(location, v);
+            CHECKGL();
+		}
+
+		int getUniformLocation(const char *id) const
+		{
+			int i = glGetUniformLocation(_program, id);
+            CHECKGL();
+            return i;
+		}
+
+		void setUniform(const char *id, const Vector4 *v, int num)
+		{
+			int p = glGetUniformLocation(_program, id);
+			glUniform4fv(p, num, v->m);
+            CHECKGL();
+		}
+
+		void setUniform(const char *id, const Matrix *mat)
+		{
+			int p = glGetUniformLocation(_program, id);
+			glUniformMatrix4fv(p, 1, GL_FALSE, mat->ml);
+            CHECKGL();
+		}
+
+		void setUniform(const char *id, float val)
+		{
+			int p = glGetUniformLocation(_program, id);
+			glUniform1f(p, val);
+            CHECKGL();
+		}
+
+		static unsigned int createShader(unsigned int type, const char* data, const char *prepend, const char *append);
+		static unsigned int createProgram(int vs, int fs, const VertexDeclarationGL *decl);
+
+	private:
+		GLuint _program;
+	};
+
+
+}

+ 74 - 3
oxygine/src/core/gl/VideoDriverGL.cpp

@@ -11,12 +11,54 @@ namespace oxygine
 
 	}
 
-	int VideoDriverGL::getMaxVertices() const
+	unsigned int VideoDriverGL::getPT(IVideoDriver::PRIMITIVE_TYPE pt)
 	{
-		int m = _indices16.size()/3 * 2;
-		return m;
+		switch (pt)
+		{
+		case PT_POINTS:
+			return GL_POINTS;
+		case PT_LINES:
+			return GL_LINES;
+		case PT_LINE_LOOP:
+			return GL_LINE_LOOP;
+		case PT_LINE_STRIP:
+			return PT_LINE_STRIP;
+		case PT_TRIANGLES:
+			return GL_TRIANGLES;
+		case PT_TRIANGLE_STRIP:
+			return GL_TRIANGLE_STRIP;
+		case PT_TRIANGLE_FAN:
+			return GL_TRIANGLE_FAN;
+		}
+		OX_ASSERT(!"unknown primityve type");
+		return PT_POINTS;
 	}
 
+	unsigned int VideoDriverGL::getBT(IVideoDriver::BLEND_TYPE pt)
+	{
+		switch(pt)
+		{
+		case BT_ZERO:
+			return GL_ZERO;
+		case BT_ONE:
+			return GL_ONE;
+		case BT_SRC_COLOR:
+			return GL_SRC_COLOR;
+		case BT_ONE_MINUS_SRC_COLOR:
+			return GL_ONE_MINUS_SRC_COLOR;
+		case BT_SRC_ALPHA:
+			return GL_SRC_ALPHA;
+		case BT_ONE_MINUS_SRC_ALPHA:
+			return GL_ONE_MINUS_SRC_ALPHA;
+		case BT_DST_ALPHA:
+			return GL_DST_ALPHA;
+		case BT_ONE_MINUS_DST_ALPHA:
+			return GL_ONE_MINUS_DST_ALPHA;
+		}
+		OX_ASSERT(!"unknown blend");
+		return GL_ONE;
+	}
+	
 	bool VideoDriverGL::getScissorRect(Rect &r) const
 	{
 		GLboolean scrTest = glIsEnabled(GL_SCISSOR_TEST);
@@ -24,6 +66,8 @@ namespace oxygine
 		GLint box[4];
 		glGetIntegerv(GL_SCISSOR_BOX, box);
 		r = Rect(box[0], box[1], box[2], box[3]);
+        
+        CHECKGL();
 
 		return scrTest ? true : false;	
 	}
@@ -39,6 +83,7 @@ namespace oxygine
 		glGetIntegerv(GL_VIEWPORT, vp);
 
 		r = Rect(vp[0], vp[1], vp[2], vp[3]);;
+        CHECKGL();
 	}
 
 	void VideoDriverGL::setScissorRect(const Rect *rect)
@@ -50,6 +95,7 @@ namespace oxygine
 		}
 		else
 			glDisable(GL_SCISSOR_TEST);
+        CHECKGL();
 	}
 
 	void VideoDriverGL::setRenderTarget(spNativeTexture rt)
@@ -57,6 +103,7 @@ namespace oxygine
 		if (!rt)
 		{
 			glBindFramebuffer(GL_FRAMEBUFFER, _prevFBO);
+            CHECKGL();
 			return;
 		}
 
@@ -64,6 +111,7 @@ namespace oxygine
 
 		NativeTextureGLES *gl = safeCast<NativeTextureGLES*>(rt.get());		
 		glBindFramebuffer(GL_FRAMEBUFFER, gl->getFboID());
+        CHECKGL();
 	}
 
 	void VideoDriverGL::_begin(const Rect &viewport, const Color *clearColor)
@@ -80,6 +128,29 @@ namespace oxygine
 		{
 			glClear(GL_DEPTH_BUFFER_BIT);
 		}
+        CHECKGL();
+	}
+
+	void VideoDriverGL::setBlendFunc(BLEND_TYPE src, BLEND_TYPE dest)
+	{
+		glBlendFunc(getBT(src), getBT(dest));
+        CHECKGL();
+	}
+
+	void VideoDriverGL::setState(STATE state, unsigned int value)
+	{
+		switch(state)
+		{
+		case STATE_BLEND:
+			if (value)
+				glEnable(GL_BLEND);
+			else
+				glDisable(GL_BLEND);
+			break;
+		default:
+			OX_ASSERT(!"unknown state");
+		}
+        CHECKGL();
 	}
 
 	/*

+ 6 - 1
oxygine/src/core/gl/VideoDriverGL.h

@@ -15,14 +15,19 @@ namespace oxygine
 		VideoDriverGL();
 
 		void	getViewport(Rect &r) const;
-		int		getMaxVertices() const;
 		bool	getScissorRect(Rect &) const;
 		const VertexDeclarationGL*	getVertexDeclaration(bvertex_format) const;
 
 		void setScissorRect(const Rect *);
 		void setRenderTarget(spNativeTexture rt);
 
+		void setBlendFunc(BLEND_TYPE src, BLEND_TYPE dest);
+		void setState(STATE, unsigned int value);
+
 	protected:
+		unsigned int getPT(IVideoDriver::PRIMITIVE_TYPE pt);
+		unsigned int getBT(IVideoDriver::BLEND_TYPE pt);
+
 		void _begin(const Rect &viewport, const Color *clearColor);
 		GLint _prevFBO;
 

+ 1 - 82
oxygine/src/core/gl/VideoDriverGLES11.cpp

@@ -11,89 +11,8 @@ namespace oxygine
 		return new NativeTextureGLES();
 	}
 
-
-	void VideoDriverGLES11::drawBatch(const batch &b)
-	{
-		const VertexDeclarationGL *decl = static_cast<const VertexDeclarationGL*>(b.vdecl);
-
-		int count = b.vertices.size() / decl->size;
-		int indices = (count * 3)/2;
-		const unsigned char *p = &b.vertices[0];
-
-
-		unsigned int id = (unsigned int)b.base->getHandle();
-
-		if (_blend != b.blend)
-		{
-			_blend = b.blend;
-
-			switch(b.blend)
-			{
-			case blend_disabled:
-				glDisable(GL_BLEND);
-				break;
-
-			case blend_premultiplied_alpha:
-				glEnable     (GL_BLEND);
-				glBlendFunc  (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-				break;
-
-			case blend_alpha:
-				glEnable     (GL_BLEND);
-				glBlendFunc  (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-				break;
-
-			case blend_add:
-				glEnable     (GL_BLEND);
-				glBlendFunc  (GL_ONE, GL_ONE);
-				break;
-				/*
-			case blend_xor:
-				glEnable     (GL_BLEND);
-				glBlendFunc  (GL_ZERO, GL_ONE_MINUS_DST_COLOR);
-				break;
-				*/
-			default:
-				//OX_ASSERT(0);
-				break;
-			}				
-		}			
-
-		glBindTexture(GL_TEXTURE_2D, id);
-
-		/*
-		const VertexDeclarationGL::Element *el = decl->elements;
-		for (int i = 0; i < decl->numElements; ++i)		
-		{
-			glEnableVertexAttribArray(el->index);
-			glVertexAttribPointer(el->index, el->size, el->elemType, el->normalized, decl->size, p + el->offset);
-			el++;
-		}
-		*/
-
-
-		OX_ASSERT(decl->bformat == VERTEX_PCT2);
-		glVertexPointer(3, GL_FLOAT, decl->size, p + decl->elements[0].offset);
-		glEnableClientState(GL_VERTEX_ARRAY);
-
-		glColorPointer(4, GL_UNSIGNED_BYTE, decl->size, p + decl->elements[1].offset);
-		glEnableClientState(GL_COLOR_ARRAY); 
-
-		glTexCoordPointer(2, GL_FLOAT, decl->size, p + decl->elements[2].offset);
-		glEnableClientState(GL_TEXTURE_COORD_ARRAY);			
-
-		//glDrawArrays(GL_TRIANGLES, 0, count);
-
-		if (indices <= (int)_indices8.size())
-			glDrawElements(GL_TRIANGLES, indices, GL_UNSIGNED_BYTE, &_indices8[0]);
-		else
-			glDrawElements(GL_TRIANGLES, indices, GL_UNSIGNED_SHORT, &_indices16[0]);
-	}
-
 	void VideoDriverGLES11::setDefaultSettings()
 	{
-		_blend = blend_disabled;
-
 		glDisable(GL_ALPHA_TEST);
 
 		glDisable(GL_DEPTH_TEST);
@@ -115,7 +34,7 @@ namespace oxygine
 		glEnable(GL_TEXTURE_2D);
 	}
 
-	VideoDriverGLES11::VideoDriverGLES11():_blend(blend_default)
+	VideoDriverGLES11::VideoDriverGLES11()
 	{
 
 	}

+ 0 - 4
oxygine/src/core/gl/VideoDriverGLES11.h

@@ -18,10 +18,6 @@ namespace oxygine
 
 		void begin(const Matrix &proj, const Matrix &view, const Rect &viewport, const Color *clearColor);
 		
-		void drawBatch(const batch &b);
 		void setDefaultSettings();
-
-	private:
-		blend_mode _blend;
 	};
 }

+ 59 - 329
oxygine/src/core/gl/VideoDriverGLES20.cpp

@@ -1,5 +1,6 @@
 #include "VideoDriverGLES20.h"
 #include "NativeTextureGLES.h"
+#include "ShaderProgramGL.h"
 #include "oxgl.h"
 #include "math/Color.h"
 #include "utils/stringUtils.h"
@@ -19,230 +20,26 @@
 #endif
 
 namespace oxygine
-{	
-	ShaderProgramGL::ShaderProgramGL():_program(0)
+{    
+	VideoDriverGLES20::VideoDriverGLES20()
 	{
- 
-	}
-
-	ShaderProgramGL::~ShaderProgramGL()
-	{
-		if (_program)
-			glDeleteProgram(_program);
-	}
-
-
-
-	void printShaderInfoLog(GLuint shader)
-	{
-		GLint length = 0;
-		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
-		if (length)
-		{
-			char* buffer = (char*)malloc( sizeof(char) * length ) ;
-			glGetShaderInfoLog(shader, length, NULL, buffer);
-			if (buffer[0])
-				log::error("%s", buffer);
-			free(buffer);
-
-			GLint success;
-			glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
-			if (success != GL_TRUE) 
-			{
-				OX_ASSERT(!"shader build error");
-				exit(1);
-			}
-		}
-	}
-
-
-	unsigned int ShaderProgramGL::createShader(unsigned int type, const char* data, const char *prepend, const char *append)
-	{
-		GLuint shader = glCreateShader(type);
-
-		const char *sources[16];
-		const char **ptr = &sources[0];
-
-		char nonGLES[] = 
-			"#define lowp\n"
-			"#define mediump\n"
-			"#define highp\n";
-
-#if SDL_VIDEO_OPENGL
-		*ptr = nonGLES;
-		ptr++;
-#endif
-
-		if (prepend)
-		{
-			*ptr = prepend;
-			ptr++;
-		}
-
-		*ptr = data;
-		ptr++;
-
-		if (append)
-		{
-			*ptr = append;
-			ptr++;
-		}
-
-		int num = ptr - sources;
-		glShaderSource(shader, num, sources, 0);
-		glCompileShader(shader);
-		printShaderInfoLog(shader);
-
-		return shader;
-	}
-
-
-	unsigned int ShaderProgramGL::createProgram(int vs, int fs, const VertexDeclarationGL *decl)
-	{
-		int p = glCreateProgram();
-		glAttachShader(p, vs);
-		glAttachShader(p, fs);
-
-		for (int i = 0; i < decl->numElements; ++i)		
-			glBindAttribLocation(p, decl->elements[i].index, decl->elements[i].name);
-
-		glLinkProgram(p);
-
-		return p;
-	}
-
-	UberShaderProgram::UberShaderProgram()
-	{
-
-	}
-
-	void UberShaderProgram::init(const file::buffer &baseShader, const char *prepend, const char *append)		
-	{
-		_data.data = baseShader.data;
-
-		_data.data.insert(_data.data.begin(), prepend, prepend + strlen(prepend));
-		_data.data.insert(_data.data.end(), append, append + strlen(append));
-		_data.data.push_back(0);
-
-		reg(CLOSURE(this, &UberShaderProgram::_restore), 0);
-	}
-
-	void UberShaderProgram::releaseShaders()
-	{
-		for (int i = 0; i < SIZE; ++i)
-		{
-			shader &s = _shaders[i];
-			delete s.program;
-			s.program = 0;
-		}
-	}
-
-	UberShaderProgram::~UberShaderProgram()
-	{
-		releaseShaders();
-	}
-
-	void UberShaderProgram::_restore(Restorable *, void*)
-	{
-
-	}
-
-	void UberShaderProgram::release()
-	{
-		for (int i = 0; i < SIZE; ++i)
-		{
-			shader &s = _shaders[i];
-			if (s.program)
-			{
-				delete s.program;
-				s.program = 0;
-			}			
-		}
-	}
-
-	UberShaderProgram::shader *UberShaderProgram::getShaderProgram(int flags)
-	{
-		shader &s = _shaders[flags];
-				
-		if (!s.program)
-		{
-			bvertex_format bformat = VERTEX_PCT2;
-			s.flags = flags;
-			const char* data = (const char*)_data.getData();
-			
-			char prepend[255];
-			char append[255];
-
-			append[0] = 0;
-			prepend[0] = 0;
-
-			if (flags & ALPHA_PREMULTIPLY)
-				strcat(prepend, "#define ALPHA_PREMULTIPLY\n");
-
-			if (flags & SEPARATE_ALPHA)
-				strcat(prepend, "#define SEPARATE_ALPHA\n");
-
-			if (flags & MASK_R_CHANNEL)
-				strcat(prepend, "#define MASK_R_CHANNEL\n");
-
-			if (flags & MASK)
-			{
-				strcat(prepend, "#define MASK\n");
-				bformat = VERTEX_PCT2T2;
-			}
-
-			char *end = prepend + strlen(prepend);
-			strcat(prepend, "#define program_main_ps main\n");
-			strcat(prepend, "#define PS\n");
-
-			int fs = ShaderProgramGL::createShader(GL_FRAGMENT_SHADER, data, prepend, append);
-
-			*end = 0;
-			strcat(prepend, "#define program_main_vs main\n");
-			strcat(prepend, "#define VS\n");
-
-			int vs = ShaderProgramGL::createShader(GL_VERTEX_SHADER, data, prepend, append);
-					
-			const VertexDeclarationGL *decl = ((VideoDriverGLES20*)IVideoDriver::instance)->getVertexDeclaration(bformat);
-			ShaderProgramGL *pgl = new ShaderProgramGL;
-			pgl->init(ShaderProgramGL::createProgram(vs, fs, decl));
-			s.program = pgl;
-		}
-
-		return &s;
-	}
-
-	
-
-	VideoDriverGLES20::VideoDriverGLES20():_blend(blend_default), 
-		_currentProgram(0)
-	{
-		_matrixVP.identity();
-        file::read("shader.glsl", _shaderBody, ep_ignore_error);
-        if (!_shaderBody.getSize())
-        {
-            file::Zips zp;
-            zp.add(system_data, system_size);
-            zp.read("system/shader.glsl", _shaderBody);
-        }
-
-		_us.init(_shaderBody);
 	}
 
 	VideoDriverGLES20::~VideoDriverGLES20()
 	{
 		glUseProgram(0);
+        CHECKGL();
 	}
 
 	void VideoDriverGLES20::restore()
 	{
-		_us.restore();
-		setDefaultSettings();		
+		//_us.restore();
+		setDefaultSettings();
 	}
 
 	bool VideoDriverGLES20::isReady() const
 	{
-		return _currentProgram != 0;
+		return true;
 	}
 
 	spNativeTexture VideoDriverGLES20::createTexture()
@@ -250,141 +47,75 @@ namespace oxygine
 		return new NativeTextureGLES;
 	}
 
-	void VideoDriverGLES20::setProgram(ShaderProgramGL *p)
-	{
-		if (_currentProgram == p)
-			return;
-
-		_currentProgram = p;
-		_currentProgram->bind();
-
-		updateConstants();
-	}
-
 	void VideoDriverGLES20::reset()
 	{
-		_currentProgram = 0;
+		//_currentProgram = 0;
 	}
 
 	void VideoDriverGLES20::updateConstants()
 	{
-		_currentProgram->setUniform("mat", &_matrixVP);
+		//_currentProgram->setUniform("mat", &_matrixVP);
 	}
 
 
-	void VideoDriverGLES20::begin(const Matrix &proj, const Matrix &view, const Rect &viewport, const Color *clearColor)
+	void VideoDriverGLES20::begin(const Rect &viewport, const Color *clearColor)
 	{
 		_begin(viewport, clearColor);
-
-		_matrixVP = view * proj;
-
-		updateConstants();
 	}
-	
-	void VideoDriverGLES20::bindTexture(int SAMPLER, const char *id, void* handle)
-	{
-		glActiveTexture(SAMPLER);
-		glBindTexture(GL_TEXTURE_2D, (unsigned int)handle);	
 
-		int alpha_location = glGetUniformLocation(_currentProgram->getID(), id);
-		OX_ASSERT(alpha_location != -1);
-		if (alpha_location != -1)
-			glUniform1i(alpha_location, SAMPLER - GL_TEXTURE0);
+	void VideoDriverGLES20::setShaderProgram(ShaderProgram* prog_)
+	{
+        CHECKGL();
+		ShaderProgramGL* prog = safeCast<ShaderProgramGL*>(prog_);
+		unsigned int id = prog->getID();
+		glUseProgram(id);
+        CHECKGL();
 	}
 
-	void VideoDriverGLES20::drawBatch(const batch &b)
-	{		
-		const VertexDeclarationGL *decl = static_cast<const VertexDeclarationGL*>(b.vdecl);
-
-		int count = b.vertices.size() / decl->size;
-		int indices = (count * 3)/2;
-		const unsigned char *verticesData = &b.vertices[0];
-
-
-		if (_blend != b.blend)
-		{
-			_blend = b.blend;
+	void VideoDriverGLES20::setTexture(int sampler, spNativeTexture t)
+	{
+		glActiveTexture(GL_TEXTURE0 + sampler);
+		if (t)
+			glBindTexture(GL_TEXTURE_2D, (unsigned int)t->getHandle());	
+		else
+			glBindTexture(GL_TEXTURE_2D, 0);
+        CHECKGL();
+	}
 
-			glBlendEquation(GL_FUNC_ADD);
-			bool blend = true;
-			switch(b.blend)
-			{
-			case blend_disabled:
-				blend = false;
-				break;
+	
 
-			case blend_premultiplied_alpha:
-				glBlendFunc  (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-				break;
-			case blend_alpha:
-				glBlendFunc  (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-				break;
-			case blend_add:
-				glBlendFunc  (GL_ONE, GL_ONE);
-				break;
-			case blend_sub:
-				glBlendFunc  (GL_ONE, GL_ONE);
-				glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
-				break;
-			default:
-				OX_ASSERT(!"unknown blend");
-			}				
+	void VideoDriverGLES20::draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl_, const void *vdata, unsigned int size)
+	{
+		const VertexDeclarationGL *decl = static_cast<const VertexDeclarationGL*>(decl_);
 
-			if (blend)
-				glEnable(GL_BLEND);
-			else
-				glDisable(GL_BLEND);
-		}
+		const unsigned char *verticesData = (const unsigned char *)vdata;
 
-		UberShaderProgram *program = b.program;
-		if (program)		
-		{
-			int q=0;
-		}
-		else
-		{
-			program = &_us;
+		const VertexDeclarationGL::Element *el = decl->elements;
+		for (int i = 0; i < decl->numElements; ++i)		
+		{	
+			glEnableVertexAttribArray(el->index);
+			glVertexAttribPointer(el->index, el->size, el->elemType, el->normalized, decl->size, verticesData + el->offset);			
+			el++;
 		}
 
+		glDrawArrays(getPT(pt), 0, size / decl->size);
 
-		
-		int flags = 0;
-		if (!b.basePremultiplied)
-			flags |= UberShaderProgram::ALPHA_PREMULTIPLY;
-		if (b.alpha)
-			flags |= UberShaderProgram::SEPARATE_ALPHA;
-		if (b.mask)
-		{
-			flags |= UberShaderProgram::MASK;
-			if (b.maskChannelR)
-				flags |= UberShaderProgram::MASK_R_CHANNEL;
+		el = decl->elements;
+		for (int i = 0; i < decl->numElements; ++i)		
+		{			
+			glDisableVertexAttribArray(el->index);
+			el++;
 		}
+        
+        CHECKGL();
+	}
 
-		ShaderProgramGL *glProg = program->getShaderProgram(flags)->program;
-
-
-		setProgram(glProg);		
-
-		bindTexture(GL_TEXTURE0, "base_texture", b.base->getHandle());
+	void VideoDriverGLES20::draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl_, const void *vdata, unsigned int numVertices, const void *indicesData, unsigned int numIndices, bool indicesShortType)
+	{
+		const VertexDeclarationGL *decl = static_cast<const VertexDeclarationGL*>(decl_);
 
-		if (b.alpha)
-		{
-			bindTexture(GL_TEXTURE1, "alpha_texture", b.alpha->getHandle());
-		}
-		if (b.mask) 
-		{
-			bindTexture(GL_TEXTURE2, "mask_texture", b.mask->getHandle());
-			glUniform4f(
-				glGetUniformLocation(_currentProgram->getID(), "clip_mask"), 
-				b.clipMask.getLeft(), b.clipMask.getTop(), b.clipMask.getRight(), b.clipMask.getBottom());
-		}
+		const unsigned char *verticesData = (const unsigned char *)vdata;
 
-		UberShaderProgram::ShaderUniformsCallback cb = program->getShaderUniformsCallback();
-		if (cb)
-		{
-			cb(glProg);
-		}
-		
 		const VertexDeclarationGL::Element *el = decl->elements;
 		for (int i = 0; i < decl->numElements; ++i)		
 		{	
@@ -393,13 +124,7 @@ namespace oxygine
 			el++;
 		}
 
-		//log::messageln("indices %d", indices);
-
-		
-		if (indices <= (int)_indices8.size())
-			glDrawElements(GL_TRIANGLES, indices, GL_UNSIGNED_BYTE, &_indices8[0]);
-		else
-			glDrawElements(GL_TRIANGLES, indices, GL_UNSIGNED_SHORT, &_indices16[0]);
+		glDrawElements(getPT(pt), numIndices, indicesShortType ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE, indicesData);
 
 		el = decl->elements;
 		for (int i = 0; i < decl->numElements; ++i)		
@@ -407,15 +132,20 @@ namespace oxygine
 			glDisableVertexAttribArray(el->index);
 			el++;
 		}
+        CHECKGL();
 	}
 
 	void VideoDriverGLES20::setDefaultSettings()
 	{
-		_currentProgram = 0;
-		_blend = blend_default;
+		//glEnable(GL_TEXTURE_2D);
+
+		glDisable(GL_SCISSOR_TEST);
 		glDisable(GL_DEPTH_TEST);
+		glDisable(GL_BLEND);
 		glDepthMask(GL_FALSE);
 		glCullFace(GL_FRONT_AND_BACK);
-		setProgram(_us.getShaderProgram(0)->program);
+        
+        CHECKGL();
+		//setProgram(_us.getShaderProgram(0)->program);
 	}
 }

+ 7 - 104
oxygine/src/core/gl/VideoDriverGLES20.h

@@ -7,97 +7,6 @@
 
 namespace oxygine
 {
-	class ShaderProgramGL: public ShaderProgram
-	{
-	public:
-		ShaderProgramGL();
-		~ShaderProgramGL();
-
-		void init(GLuint p)
-		{
-			_program = p;
-		}
-
-		unsigned int getID() const 
-		{
-			return _program;
-		}
-
-		void bind()
-		{
-			glUseProgram(_program);
-		}
-
-
-		void setUniform(const char *id, const Vector4 *v, int num)
-		{
-			int p = glGetUniformLocation(_program, id);
-			glUniform4fv(p, num, v->m);
-		}
-
-		void setUniform(const char *id, const Matrix *mat)
-		{
-			int p = glGetUniformLocation(_program, id);
-			glUniformMatrix4fv(p, 1, GL_FALSE, mat->ml);
-		}
-
-		void setUniform(const char *id, float val)
-		{
-			int p = glGetUniformLocation(_program, id);
-			glUniform1f(p, val);
-		}
-
-		static unsigned int createShader(unsigned int type, const char* data, const char *prepend, const char *append);
-		static unsigned int createProgram(int vs, int fs, const VertexDeclarationGL *decl);
-
-	private:
-		GLuint _program;
-	};
-
-	class UberShaderProgram: public Restorable
-	{
-	public:
-		struct shader
-		{
-			shader():program(0), flags(0){}
-			ShaderProgramGL *program;
-			int flags;
-		};
-
-		enum
-		{
-			ALPHA_PREMULTIPLY = 1,
-			SEPARATE_ALPHA = 1 << 1,
-			MASK_R_CHANNEL = 1 << 2,
-			MASK = 1 << 3,
-			SIZE = 1 << 4
-		};		
-
-		UberShaderProgram();
-		~UberShaderProgram();
-		void init(const file::buffer &baseShader, const char *prepend="", const char *append = "");
-
-		void release();
-
-		typedef Closure<void (ShaderProgramGL *)> ShaderUniformsCallback;
-		void setShaderUniformsCallback(ShaderUniformsCallback cb){_cb = cb;}
-
-		ShaderUniformsCallback	getShaderUniformsCallback() const {return _cb;}
-		shader*					getShaderProgram(int flags);
-
-
-	protected:
-		void *_getRestorableObject() {return this;}
-		void _restore(Restorable *, void*);
-
-		shader _shaders[SIZE];
-		file::buffer _data;
-		ShaderUniformsCallback _cb;		
-
-		void releaseShaders();
-	};
-
-
 	class VideoDriverGLES20: public VideoDriverGL
 	{
 	public:
@@ -108,25 +17,19 @@ namespace oxygine
 		void restore();
 
 		spNativeTexture createTexture();
-		const file::buffer& getShaderBody() const {return _shaderBody;}
+		//const file::buffer& getShaderBody() const {return _shaderBody;}
 		bool isReady() const;
 
-		void begin(const Matrix &proj, const Matrix &view, const Rect &viewport, const Color *clearColor);
+		void begin(const Rect &viewport, const Color *clearColor);
 
-		void drawBatch(const batch &b);
+		void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData, unsigned int verticesDataSize);
+		void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData, unsigned int verticesDataSize, const void *indicesData, unsigned int indicesDataSize, bool indicesShortType);
 		void setDefaultSettings();		
 
+		void setShaderProgram(ShaderProgram*);
+		void setTexture(int sampler, spNativeTexture);
+
 	protected:		
 		void updateConstants();
-		void setProgram(ShaderProgramGL *p);
-		void bindTexture(int sampler, const char *id, void* handle);
-		file::buffer _shaderBody;
-		UberShaderProgram _us;
-
-		ShaderProgramGL *_currentProgram;
-
-		Matrix _matrixVP;
-
-		blend_mode _blend;
 	};
 }

+ 8 - 2
oxygine/src/core/gl/oxgl.h

@@ -9,7 +9,10 @@
 	#define GL_GLEXT_PROTOTYPES 
 	#include "GLES/glext.h"
 	#include <gles/egl.h>
-#elif WIN32
+#else
+	#include "SDL_config.h"
+
+#if WIN32
 	#include "glew.h"
 
 	#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
@@ -53,7 +56,10 @@
 
 	#define GL_ETC1_RGB8_OES                                        0x8D64
 
-
 #endif
+#endif
+    namespace oxygine {void checkGLError();}
+	//#define CHECKGL() checkGLError()
+	#define CHECKGL() {}
 
 	void initGLExtensions();

+ 41 - 37
oxygine/src/core/oxygine.cpp

@@ -67,6 +67,19 @@ extern "C"
 
 namespace oxygine
 {
+    void checkGLError()
+    {
+        int gl_error = glGetError();
+        if (gl_error != GL_NO_ERROR)
+        {
+            log::error("OpenGL error: %#x\n", gl_error);
+            if (gl_error == GL_OUT_OF_MEMORY)
+            {
+                exit(0);
+            }
+        }
+    }
+    
 	Mutex mutexAlloc;
 
 	void *fastAlloc(size_t size)
@@ -198,39 +211,27 @@ namespace oxygine
 	namespace core
 	{
 		void focusLost()
-		{
-			/*
+		{			
+			return;
 #if OXYGINE_SDL
 			log::messageln("focus lost");
-			Restorable::releaseAll();
-
 			SDL_GL_DeleteContext(_context);
 			_context = 0;
 #endif
-			*/
+			
 		}
 
 		void lostContext()
 		{
-			/*
+			return;
 #if OXYGINE_SDL			
-			log::messageln("lost context");
-			
+			log::messageln("lost context");			
 			if(!_context)
 			{
 				_context = SDL_GL_CreateContext(_window);
 				initGLExtensions();
 			}
-
-			IVideoDriver::instance->restore();
-			Renderer::initialize();			
-
-			Event ev(RootActor::LOST_CONTEXT);
-			getRoot()->dispatchEvent(&ev);
-
-			Restorable::restoreAll(); 
 #endif			
-			*/
 		}
 
 		void init(init_desc *desc_ptr)
@@ -389,7 +390,10 @@ namespace oxygine
 			if (major_gl == 2)
 				IVideoDriver::instance = new VideoDriverGLES20();
 			else
-				IVideoDriver::instance = new VideoDriverGLES11();			
+			{
+				OX_ASSERT(!"gl version should be 2");
+				//IVideoDriver::instance = new VideoDriverGLES11();			
+			}
 
 	#elif __FLASHPLAYER__
 			{
@@ -404,10 +408,12 @@ namespace oxygine
 	#endif
 
 		
-
+            checkGLError();
 
 			IVideoDriver::instance->setDefaultSettings();
 
+            checkGLError();
+            
 			Renderer::initialize();
 
 			Resources::registerResourceType(ResAtlas::create, "atlas");
@@ -417,6 +423,7 @@ namespace oxygine
 			Resources::registerResourceType(ResFontBM::createSD, "sdfont");
 			Resources::registerResourceType(ResStarlingAtlas::create, "starling_atlas");
 
+            checkGLError();
 			log::messageln("oxygine initialized");
 		}
 
@@ -449,33 +456,25 @@ namespace oxygine
 
 		void reset()
 		{
+			log::messageln("core::reset()");
 			Restorable::releaseAll();
-			Renderer::release();
+			Renderer::reset();
 			IVideoDriver::instance->reset();
 		}
 
 		void restore()
 		{
+			log::messageln("core::restore()");
 			IVideoDriver::instance->restore();
-			Renderer::initialize();
+			Renderer::restore();
 			Restorable::restoreAll();
 		}
 
-		void checkGLError()
-		{
-			int gl_error = glGetError();
-			if (gl_error != GL_NO_ERROR)
-			{
-				log::error("OpenGL error: %#x\n", gl_error);
-				if (gl_error == GL_OUT_OF_MEMORY)
-				{
-					exit(0);
-				}
-			}
-		}
+		
 
 		void swapDisplayBuffers()
 		{
+            checkGLError();
 #if __S3E__
 			IwGLSwapBuffers();
 #elif USE_EGL
@@ -556,10 +555,8 @@ namespace oxygine
 						if (focus != newFocus)
 						{
 							focus = newFocus;
-							log::messageln("focus: %d", (int)focus);
-							Event ev(focus ? RootActor::ACTIVATE : RootActor::DEACTIVATE);
-							if (getRoot())
-								getRoot()->dispatchEvent(&ev);
+#if !SDL_VIDEO_OPENGL
+							
 							if (focus)
 							{
 								lostContext();
@@ -568,6 +565,13 @@ namespace oxygine
 							{
 								focusLost();
 							}
+
+							log::messageln("focus: %d", (int)focus);
+							Event ev(focus ? RootActor::ACTIVATE : RootActor::DEACTIVATE);
+							if (getRoot())
+								getRoot()->dispatchEvent(&ev);
+#endif
+							
 						}
 						//log::messageln("SDL_SYSWMEVENT %d", (int)event.window.event);
 						break;

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

@@ -21,7 +21,7 @@
 #endif
 
 
-#define makefourcc(a,b,c,d) ( ((unsigned int)a) | (((unsigned int)b)<< 8) | (((unsigned int)c)<<16) | (((unsigned int)d)<<24))
+#define makefourcc(a,data,c,d) ( ((unsigned int)a) | (((unsigned int)data)<< 8) | (((unsigned int)c)<<16) | (((unsigned int)d)<<24))
 
 /**main oxygine namespace*/
 namespace oxygine

+ 32 - 0
oxygine/src/core/vertex.h

@@ -1,5 +1,6 @@
 #pragma once
 #include "oxygine_include.h"
+#include "math/vector2.h"
 
 namespace oxygine
 {
@@ -77,4 +78,35 @@ namespace oxygine
 		}
 		return offset;
 	}
+
+
+
+	struct vertexP2T2
+	{
+		float x, y;		
+		float u, v;
+
+		Vector2 &getPos() {return *((Vector2*)&x);}
+		Vector2 &getUV() {return *((Vector2*)&u);}
+	};
+
+	struct vertexP2C
+	{
+		float x, y;		
+		unsigned int color;
+
+		Vector2 &getPos() {return *((Vector2*)&x);}
+	};
+
+	struct vertexPCT2
+	{
+		float x, y, z;
+		unsigned int color;
+		float u, v;				
+	};
+
+	struct vertexPCT2T2: public vertexPCT2
+	{	
+		float u2, v2;				
+	};
 }

+ 2 - 1
oxygine/src/dev_tools/TreeInspector.cpp

@@ -104,7 +104,8 @@ namespace oxygine
 		
 		Rect vp;
 		rs.renderer->getDriver()->getViewport(vp);		
-		rs.clip = vp.cast<RectF>();		
+		RectF clip = vp.cast<RectF>();
+		rs.clip = &clip;
 
 		ClipRectActor::render(rs);
 	}

+ 8 - 1
oxygine/src/dev_tools/TreeInspectorPreview.cpp

@@ -50,7 +50,13 @@ namespace oxygine
 
 		setSize(30, 30);
 
-		const RectF &itemRect = _videoCache._bounds;
+		RectF itemRect = _videoCache._bounds;
+		if (itemRect.isEmpty())
+		{
+			itemRect = item->getDestRect();
+			if (itemRect.isEmpty())
+				itemRect.setSize(Vector2(10,4));
+		}
 
 		Vector2 ns = fitSize(Vector2(50.0f, 50.0f), itemRect.size); 
 		float scale = ns.x / itemRect.size.x;
@@ -96,6 +102,7 @@ namespace oxygine
 		parentRenderState.renderer->drawBatch();
 		_videoCache.render(_cacheTransform * parentRenderState.transform);
 		parentRenderState.renderer->drawBatch();
+		parentRenderState.renderer->resetSettings();
 
 		/*
 		bool rel = _item->getChildrenRelative();

+ 98 - 33
oxygine/src/dev_tools/TreeInspectorPreview.h

@@ -20,29 +20,54 @@ namespace oxygine
 	class VideoDriverCache: public VideoDriverNull
 	{
 	public:
-		typedef vector<batch> batches;
+		struct cached_batch
+		{
+			cached_batch():program(0), vdecl(0), indicesShortType(false), numVertices(0), numIndices(0), blendSrc(IVideoDriver::BT_ONE), blendDest(IVideoDriver::BT_ONE)
+			{
+				memset(states, 0, sizeof(states));
+			}
+			ShaderProgram *program;
+
+			enum {MAX_TEXTURES = 16};
+			spNativeTexture textures[MAX_TEXTURES];
+
+			const VertexDeclaration *vdecl;
+			PRIMITIVE_TYPE pt;
+			vector<char> vertices;
+			vector<char> indices;			
+			int numVertices;
+			int numIndices;
+			unsigned int states[STATE_NUM];
+			BLEND_TYPE blendSrc, blendDest;
+			bool indicesShortType;
+		};
+
+		typedef vector<cached_batch> batches;
 		batches _batches;
 		RectF _bounds;
+		
 		AffineTransform _transform;
 		mutable VertexDeclarations<VertexDeclarationNull> _declarations;
 
-		VideoDriverCache():_bounds(0,0,0,0){}
-
-		spNativeTexture createTexture(){return 0;}
+		VideoDriverCache():_bounds(0,0,0,0)
+		{		
+			_batches.push_back(cached_batch());
+		}
 
-		void begin(const Matrix &proj, const Matrix &view, const Rect &viewport, const Color *color)
+		cached_batch &current() 
 		{
-
+			return _batches.back();
 		}
 
-		int getMaxVertices() const
+		spNativeTexture createTexture(){return 0;}
+
+		void begin(const Rect &viewport, const Color *color)
 		{
-			return IVideoDriver::instance->getMaxVertices();
 		}
 
 		const VertexDeclaration *getVertexDeclaration(bvertex_format fmt) const
 		{
-			return _declarations.get(fmt);
+			return instance->getVertexDeclaration(fmt);
 		}
 
 		void setDefaultSettings()
@@ -55,57 +80,97 @@ namespace oxygine
 
 		}
 
-		
+		void setShaderProgram(ShaderProgram* program)
+		{
+			current().program = program;
+		}
 
-		void drawBatch(const batch &b)
+		void setTexture(int sampler, spNativeTexture texture)
 		{
-			const vertexPCT2 *v = (const vertexPCT2*)(&b.vertices.front());
-			if (_batches.empty())
+			current().textures[sampler] = texture;
+		}
+
+		void setState(STATE state, unsigned int value)
+		{
+			current().states[state] = value;
+		}
+
+		void setBlendFunc(BLEND_TYPE src, BLEND_TYPE dest)
+		{
+			current().blendSrc = src;
+			current().blendDest = dest;
+		}
+
+		void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData,  unsigned int numVertices)
+		{
+			current().vdecl = decl;
+			current().pt = pt;
+			current().numVertices = numVertices;
+			current().vertices.assign((const char*)verticesData, (const char*)verticesData + current().vdecl->size * numVertices);
+			_batches.push_back(cached_batch());
+			
+		}
+
+		void draw(PRIMITIVE_TYPE pt, const VertexDeclaration *decl, const void *verticesData,  unsigned int numVertices, const void *indicesData, unsigned int numIndices, bool indicesShortType)
+		{
+			current().vdecl = decl;
+			current().pt = pt;
+			current().numVertices = numVertices;
+			current().numIndices = numIndices;
+			current().vertices.assign((const char*)verticesData, (const char*)verticesData + decl->size * numVertices);
+			current().indices.assign((const char*)indicesData, (const char*)indicesData + numIndices * (indicesShortType ? 2 : 1));			
+
+			const vertexPCT2 *v = (const vertexPCT2*)(&current().vertices.front());
+			if (_batches.size() == 1)
 			{
-				OX_ASSERT(b.vertices.size());				
+				OX_ASSERT(current().vertices.size());				
 				_bounds = RectF(v->x, v->y, 0, 0);				
 			}
 
-			_batches.push_back(b);
-			size_t num = b.vertices.size() / b.vdecl->size;
-			
+			size_t num = current().vertices.size() / current().vdecl->size;
+
 			for (size_t i = 0; i != num; ++i)
 			{				
-				v = (const vertexPCT2*)(&b.vertices.front() + b.vdecl->size * i);
+				v = (const vertexPCT2*)(&current().vertices.front() + current().vdecl->size * i);
 				RectF f(v->x, v->y, 0, 0);
 				_bounds.unite(f);				
 			}
+
+
+			_batches.push_back(cached_batch());
 		}
 
 		void render(const AffineTransform &transform)
 		{
-			static batch modified;
-			
-
 			for (batches::iterator i = _batches.begin(); i != _batches.end(); ++i)
 			{
-				const batch &b = *i;
-
-				modified = b;
-				
+				const cached_batch &b = *i;
+				if (!b.program)
+					break;
+								
 				size_t num = b.vertices.size() / b.vdecl->size;
 
+				vector<char> modified = b.vertices;
 				for (size_t i = 0; i != num; ++i)
 				{				
-					vertexPCT2* v = (vertexPCT2*)(&modified.vertices.front() + b.vdecl->size * i);
+					vertexPCT2* v = (vertexPCT2*)(&modified.front() + b.vdecl->size * i);
 					Vector2 np = transform.transform(Vector2(v->x, v->y));
 					v->x = np.x;
 					v->y = np.y;
 				}
 
-				modified.vdecl = IVideoDriver::instance->getVertexDeclaration(modified.vdecl->bformat);
-
-				IVideoDriver::instance->drawBatch(modified);
+				for (int i = 0; i < cached_batch::MAX_TEXTURES; ++i)				
+					instance->setTexture(i, b.textures[i]);
+
+				instance->setShaderProgram(b.program);
+				instance->setBlendFunc(b.blendSrc, b.blendDest);
+				for (int i = 0; i < STATE_NUM; ++i)
+					instance->setState((STATE)i, b.states[i]);
+				if (b.numIndices)
+					instance->draw(b.pt, b.vdecl, &modified.front(), b.numVertices, &b.indices.front(), b.numIndices, b.indicesShortType);
+				else
+					instance->draw(b.pt, b.vdecl, &modified.front(), b.numVertices);
 			}
-
-			modified.base = 0;
-			modified.alpha = 0;
-			modified.mask = 0;
 		}
 	};
 

+ 13 - 8
oxygine/src/math/AffineTransform.h

@@ -87,18 +87,23 @@ namespace oxygine
 		}
 
 
+		static affineTransform& multiply(affineTransform &out, const affineTransform &t1, const affineTransform &t2)
+		{
+			out.a = t1.a * t2.a + t1.b * t2.c;
+			out.b = t1.a * t2.b + t1.b * t2.d;
+			out.c = t1.c * t2.a + t1.d * t2.c;
+			out.d = t1.c * t2.b + t1.d * t2.d;
+			out.x = t1.x * t2.a + t1.y * t2.c + t2.x;
+			out.y = t1.x * t2.b + t1.y * t2.d + t2.y;
+
+			return out;
+		}
+
 
 		affineTransform operator * (const affineTransform &t2) const
 		{
 			affineTransform r;
-			const affineTransform &t1 = *this;
-			r.a = t1.a * t2.a + t1.b * t2.c;
-			r.b = t1.a * t2.b + t1.b * t2.d;
-			r.c = t1.c * t2.a + t1.d * t2.c;
-			r.d = t1.c * t2.b + t1.d * t2.d;
-			r.x = t1.x * t2.a + t1.y * t2.c + t2.x;
-			r.y = t1.x * t2.b + t1.y * t2.d + t2.y;
-			
+			multiply(r, *this, t2);			
 			return r;
 		}
 

+ 3 - 0
oxygine/src/math/Rect.h

@@ -95,9 +95,12 @@ namespace oxygine
 		T getRight() const{return pos.x + size.x;}
 		T getBottom() const{return pos.y + size.y;}
 
+		void setPosition(const point2 &pos_){pos = pos_;}
+		void setSize(const point2 &size_){size = size_;}
 		void setX(T v) {pos.x = v;}
 		void setY(T v) {pos.y = v;}
 
+
 		void setWidth(T v) {size.x = v;}
 		void setHeight(T v) {size.y = v;}
 		void expand(const point2 &v1, const point2 &v2){pos -= v1; size += v1 + v2;}

+ 1 - 0
oxygine/src/oxygine_include.h

@@ -45,5 +45,6 @@ namespace oxygine{namespace log{void error(const char *format, ...);}}
 #endif
 
 #define OXYGINE_HAS_RESTORE
+#define OXYGINE_RENDER_2 1
 
 #endif

+ 31 - 236
tools/main.wpu

@@ -16,14 +16,14 @@ debug.breakpoints = {loc('../../elements_battle_2/assets/build.py'): {8: (0,
         None,
         1,
         0)}}
-debug.err-values = {loc('../../elements_battle/assets/build_res.py'): {},
+debug.err-values = {loc('../../Dropbox/maxrects/atlas.py'): {},
+                    loc('../../elements_battle/assets/build_res.py'): {},
                     loc('../../funmath/assets/build_res.py'): {},
                     loc('../../m3q/build/build_app.py'): {},
                     loc('convert_font2sd.py'): {},
                     loc('process_xml.py'): {},
                     loc('process_xml2.py'): {},
-                    loc('../../oxygine-pipeline/example/game/assets/build_res.py'): {},
-                    loc('../../Dropbox/maxrects/atlas.py'): {}}
+                    loc('../../oxygine-pipeline/example/game/assets/build_res.py'): {}}
 debug.recent-run-args = {loc('convert_font2sd.py'): ['font.xml'],
                          loc('generate_xml_lines.py'): ['-d data -i images/m'\
         'onsters -o xmls/monsters.xml -a 1 -s 0.375',
@@ -359,238 +359,23 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window',
                                       'expanded-nodes': [],
                                       'selected-nodes': [(0,)],
                                       'top-node': (0,)}})],
-        'primary_view_state': {'editor_states': {'bookmarks': ([(loc('src2/process_atlas.py'),
-        {'attrib-starts': [('atlas_Processor',
-                            180),
-                           ('atlas_Processor.process',
-                            186)],
-         'first-line': 359,
+        'primary_view_state': {'editor_states': {'bookmarks': ([(loc('src2/xml_processor.py'),
+        {'attrib-starts': [('XmlProcessor',
+                            8),
+                           ('XmlProcessor.process',
+                            114)],
+         'first-line': 119,
          'folded-linenos': [],
-         'sel-line': 383,
-         'sel-line-start': 11756,
-         'selection_end': 11790,
-         'selection_start': 11778},
-        1382286352.5109999),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186),
-                            ('atlas_Processor.process.get_frame_size',
-                             364)],
-          'first-line': 359,
-          'folded-linenos': [],
-          'sel-line': 364,
-          'sel-line-start': 11095,
-          'selection_end': 11119,
-          'selection_start': 11107},
-         1382286353.4619999),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 359,
-          'folded-linenos': [],
-          'sel-line': 383,
-          'sel-line-start': 11756,
-          'selection_end': 11775,
-          'selection_start': 11767},
-         1382286353.927),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('settings',
-                             107),
-                            ('settings.__init__',
-                             108)],
-          'first-line': 104,
-          'folded-linenos': [],
-          'sel-line': 109,
-          'sel-line-start': 2383,
-          'selection_end': 2404,
-          'selection_start': 2396},
-         1382286355.9920001),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('get_pow2list',
-                             135)],
-          'first-line': 129,
-          'folded-linenos': [],
-          'sel-line': 143,
-          'sel-line-start': 3176,
-          'selection_end': 3193,
-          'selection_start': 3193},
-         1382286356.793),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 466,
-          'folded-linenos': [],
-          'sel-line': 497,
-          'sel-line-start': 16399,
-          'selection_end': 16422,
-          'selection_start': 16422},
-         1382286367.154),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [],
-          'first-line': 0,
-          'folded-linenos': [],
-          'sel-line': 3,
-          'sel-line-start': 63,
-          'selection_end': 75,
-          'selection_start': 70},
-         1382290536.0309999),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180)],
-          'first-line': 145,
-          'folded-linenos': [],
-          'sel-line': 180,
-          'sel-line-start': 4273,
-          'selection_end': 4285,
-          'selection_start': 4279},
-         1382290536.8099999),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 356,
-          'folded-linenos': [],
-          'sel-line': 391,
-          'sel-line-start': 11950,
-          'selection_end': 11969,
-          'selection_start': 11962},
-         1382290537.3080001),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 356,
-          'folded-linenos': [],
-          'sel-line': 391,
-          'sel-line-start': 11950,
-          'selection_end': 11970,
-          'selection_start': 11962},
-         1382290538.0120001),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 366,
-          'folded-linenos': [],
-          'sel-line': 401,
-          'sel-line-start': 12374,
-          'selection_end': 12412,
-          'selection_start': 12412},
-         1382290538.266),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 372,
-          'folded-linenos': [],
-          'sel-line': 407,
-          'sel-line-start': 12570,
-          'selection_end': 12634,
-          'selection_start': 12626},
-         1382290542.3610001),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 454,
-          'folded-linenos': [],
-          'sel-line': 489,
-          'sel-line-start': 15920,
-          'selection_end': 15981,
-          'selection_start': 15973},
-         1382290545.5109999),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 176,
-          'folded-linenos': [],
-          'sel-line': 187,
-          'sel-line-start': 4436,
-          'selection_end': 4450,
-          'selection_start': 4450},
-         1382290549.977),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 176,
-          'folded-linenos': [],
-          'sel-line': 187,
-          'sel-line-start': 4436,
-          'selection_end': 4436,
-          'selection_start': 4436},
-         1382290584.1630001),
-        (loc('src2/xml_processor.py'),
-         {'attrib-starts': [('XmlProcessor',
-                             8),
-                            ('XmlProcessor.process',
-                             114)],
-          'first-line': 119,
-          'folded-linenos': [],
-          'sel-line': 154,
-          'sel-line-start': 5028,
-          'selection_end': 5028,
-          'selection_start': 5028},
-         1382290585.448),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 475,
-          'folded-linenos': [],
-          'sel-line': 495,
-          'sel-line-start': 16344,
-          'selection_end': 16389,
-          'selection_start': 16389},
-         1382290586.724),
-        (loc('process_xml2.py'),
-         {'attrib-starts': [('get_parser',
-                             0)],
-          'first-line': 0,
-          'folded-linenos': [],
-          'sel-line': 6,
-          'sel-line-start': 418,
-          'selection_end': 444,
-          'selection_start': 444},
-         1382290666.1730001),
-        (loc('src2/process_atlas.py'),
-         {'attrib-starts': [('atlas_Processor',
-                             180),
-                            ('atlas_Processor.process',
-                             186)],
-          'first-line': 365,
-          'folded-linenos': [],
-          'sel-line': 393,
-          'sel-line-start': 12038,
-          'selection_end': 12091,
-          'selection_start': 12091},
-         1382290838.405),
-        [loc('others/convert_font2sd.py'),
-         {'attrib-starts': [],
-          'first-line': 0,
-          'folded-linenos': [],
-          'sel-line': 0,
-          'sel-line-start': 0,
-          'selection_end': 0,
-          'selection_start': 0},
-         1382291027.983]],
-        19),
-        'current-loc': loc('others/convert_font2sd.py'),
+         'sel-line': 154,
+         'sel-line-start': 5028,
+         'selection_end': 5028,
+         'selection_start': 5028},
+        1383400651.109),
+        [loc('../examples/Demo/data/images/New folder/images/png_strip.py'),
+         {},
+         1383400651.2290001]],
+        1),
+        'current-loc': loc('../examples/Demo/data/images/New folder/images/png_strip.py'),
         'editor-states': {loc('file:C:/Program Files (x86)/Wing IDE 4.1/resources/doc/en/TOC.idx'): {''\
         'displayed-index': 88,
         'viewer-state': {'history': [-1,
@@ -599,6 +384,14 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window',
                          'index': 88,
                          'top': (0,
                                  0)}},
+                          loc('../examples/Demo/data/images/New folder/images/png_strip.py'): {''\
+        'attrib-starts': [],
+        'first-line': 0,
+        'folded-linenos': [],
+        'sel-line': 0,
+        'sel-line-start': 0,
+        'selection_end': 0,
+        'selection_start': 0},
                           loc('others/convert_font2sd.py'): {'attrib-starts': [],
         'first-line': 183,
         'folded-linenos': [],
@@ -666,7 +459,8 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window',
         u'src2/oxygine_helper.py',
         u'src2/process_atlas.py',
         u'src2/xml_processor.py',
-        u'others/convert_font2sd.py']},
+        u'others/convert_font2sd.py',
+        u'../examples/Demo/data/images/New folder/images/png_strip.py']},
         'saved_notebook_display': None,
         'split_percents': {0: 0.45911949685534592},
         'splits': 2,
@@ -681,7 +475,8 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window',
                          46,
                          1242,
                          722)}]}
-guimgr.recent-documents = [loc('others/convert_font2sd.py'),
+guimgr.recent-documents = [loc('../examples/Demo/data/images/New folder/images/png_strip.py'),
+                           loc('others/convert_font2sd.py'),
                            loc('src2/xml_processor.py'),
                            loc('src2/process_atlas.py'),
                            loc('process_xml2.py'),

+ 1 - 1
tools/others/png_strip.py

@@ -8,7 +8,7 @@ for g in glob.glob("*.png"):
     im = Image.open(g)
     images.append(im)
     h = max(h, im.size[1])
-    w += im.size[1]
+    w += im.size[0]
     
 anim = Image.new("RGBA", (w, h))
 w = 0

+ 21 - 0
tools/others/single_strip.py

@@ -0,0 +1,21 @@
+from PIL import Image
+import sys
+image = sys.argv[1]
+cols = int(sys.argv[2])
+rows = int(sys.argv[3])
+
+src = Image.open(image)
+fw = src.size[0] / cols
+fh = src.size[1] / rows
+
+dest = Image.new("RGBA", (fw * cols * rows, fh))
+w = 0
+for row in xrange(rows):
+    for col in xrange(cols):  
+        frame = src.crop((fw * col, fh * row, fw * (col + 1), fh * (row + 1)))
+        dest.paste(frame, (w, 0))
+        w += fw
+    
+dest.save("anim.png")
+print "cols = %d" % (rows * cols, )
+    

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно