Parcourir la source

UI improvements, Major IDE updates (2D entity editor, bezier curve editor, asset browser), ids and tags for entities, ScreenEntityInstances, binary Object serialization, various bugfixes and improvements across the board, Particle systems no longer require a parent Scene/Screen, Label code rewrite (now aligned to baseline by default),

Ivan Safrin il y a 13 ans
Parent
commit
193e0e2251
100 fichiers modifiés avec 3314 ajouts et 822 suppressions
  1. BIN
      Assets/Default asset pack/default.pak
  2. BIN
      Assets/Default asset pack/default/default.entity2d
  3. 7 0
      Assets/Default asset pack/default/default.sprite
  4. BIN
      Assets/Default asset pack/default/default.wav
  5. 2 0
      Bindings/Scripts/create_lua_library/create_lua_library.py
  6. 2 0
      Core/Contents/CMakeLists.txt
  7. 12 2
      Core/Contents/Include/PolyBezierCurve.h
  8. 1 0
      Core/Contents/Include/PolyCore.h
  9. 37 8
      Core/Contents/Include/PolyEntity.h
  10. 10 0
      Core/Contents/Include/PolyFont.h
  11. 7 0
      Core/Contents/Include/PolyFontManager.h
  12. 2 1
      Core/Contents/Include/PolyGLRenderer.h
  13. 40 6
      Core/Contents/Include/PolyLabel.h
  14. 26 0
      Core/Contents/Include/PolyMatrix4.h
  15. 7 0
      Core/Contents/Include/PolyMesh.h
  16. 55 0
      Core/Contents/Include/PolyObject.h
  17. 35 11
      Core/Contents/Include/PolyParticleEmitter.h
  18. 14 4
      Core/Contents/Include/PolyRenderer.h
  19. 15 52
      Core/Contents/Include/PolyScreen.h
  20. 29 10
      Core/Contents/Include/PolyScreenEntity.h
  21. 58 0
      Core/Contents/Include/PolyScreenEntityInstance.h
  22. 7 1
      Core/Contents/Include/PolyScreenLabel.h
  23. 4 1
      Core/Contents/Include/PolyScreenLine.h
  24. 19 4
      Core/Contents/Include/PolyScreenShape.h
  25. 2 1
      Core/Contents/Include/PolyScreenSound.h
  26. 34 1
      Core/Contents/Include/PolyScreenSprite.h
  27. 24 0
      Core/Contents/Include/PolySound.h
  28. 1 0
      Core/Contents/Include/Polycode.h
  29. 45 5
      Core/Contents/Source/PolyBezierCurve.cpp
  30. 3 0
      Core/Contents/Source/PolyCocoaCore.mm
  31. 6 3
      Core/Contents/Source/PolyCoreServices.cpp
  32. 137 24
      Core/Contents/Source/PolyEntity.cpp
  33. 15 0
      Core/Contents/Source/PolyFont.cpp
  34. 36 0
      Core/Contents/Source/PolyFontManager.cpp
  35. 20 5
      Core/Contents/Source/PolyGLRenderer.cpp
  36. 273 134
      Core/Contents/Source/PolyLabel.cpp
  37. 255 0
      Core/Contents/Source/PolyObject.cpp
  38. 1 1
      Core/Contents/Source/PolyParticle.cpp
  39. 106 21
      Core/Contents/Source/PolyParticleEmitter.cpp
  40. 19 0
      Core/Contents/Source/PolyRenderer.cpp
  41. 0 4
      Core/Contents/Source/PolySceneLabel.cpp
  42. 28 157
      Core/Contents/Source/PolyScreen.cpp
  43. 147 98
      Core/Contents/Source/PolyScreenEntity.cpp
  44. 300 0
      Core/Contents/Source/PolyScreenEntityInstance.cpp
  45. 19 6
      Core/Contents/Source/PolyScreenLabel.cpp
  46. 24 7
      Core/Contents/Source/PolyScreenLine.cpp
  47. 2 2
      Core/Contents/Source/PolyScreenManager.cpp
  48. 72 28
      Core/Contents/Source/PolyScreenShape.cpp
  49. 136 14
      Core/Contents/Source/PolyScreenSprite.cpp
  50. 80 12
      Core/Contents/Source/PolySound.cpp
  51. 26 0
      Documentation/Misc/binary_object.txt
  52. 2 173
      IDE/Build/Mac OS X/English.lproj/MainMenu.xib
  53. 18 0
      IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj
  54. 3 2
      IDE/Contents/Include/PolycodeConsole.h
  55. 2 0
      IDE/Contents/Include/PolycodeEditor.h
  56. 116 1
      IDE/Contents/Include/PolycodeFrame.h
  57. 2 1
      IDE/Contents/Include/PolycodeIDEApp.h
  58. 2 3
      IDE/Contents/Include/PolycodeMaterialEditor.h
  59. 14 1
      IDE/Contents/Include/PolycodeProject.h
  60. 6 1
      IDE/Contents/Include/PolycodeProjectBrowser.h
  61. 28 4
      IDE/Contents/Include/PolycodeProjectEditor.h
  62. 453 0
      IDE/Contents/Include/PolycodeProps.h
  63. 266 13
      IDE/Contents/Include/PolycodeScreenEditor.h
  64. 87 0
      IDE/Contents/Include/PolycodeSpriteEditor.h
  65. 109 0
      IDE/Contents/Include/TextureBrowser.h
  66. BIN
      IDE/Contents/Resources/FileTemplates/2D/2D Entity.entity2d
  67. 6 0
      IDE/Contents/Resources/FileTemplates/2D/Sprite.sprite
  68. BIN
      IDE/Contents/Resources/Images/ScreenEditor/arrow.png
  69. BIN
      IDE/Contents/Resources/Images/ScreenEditor/entity_marker.png
  70. BIN
      IDE/Contents/Resources/Images/ScreenEditor/image.png
  71. BIN
      IDE/Contents/Resources/Images/ScreenEditor/link.png
  72. BIN
      IDE/Contents/Resources/Images/ScreenEditor/pan.png
  73. BIN
      IDE/Contents/Resources/Images/ScreenEditor/screenCenter.png
  74. BIN
      IDE/Contents/Resources/Images/ScreenEditor/screen_entity.png
  75. BIN
      IDE/Contents/Resources/Images/ScreenEditor/screen_sound.png
  76. BIN
      IDE/Contents/Resources/Images/ScreenEditor/screen_sound_icon.png
  77. BIN
      IDE/Contents/Resources/Images/ScreenEditor/selector.png
  78. BIN
      IDE/Contents/Resources/Images/ScreenEditor/shape.png
  79. BIN
      IDE/Contents/Resources/Images/ScreenEditor/sound.png
  80. BIN
      IDE/Contents/Resources/Images/ScreenEditor/sprite_icon.png
  81. BIN
      IDE/Contents/Resources/Images/ScreenEditor/text.png
  82. BIN
      IDE/Contents/Resources/Images/ScreenEditor/transform_base.png
  83. BIN
      IDE/Contents/Resources/Images/ScreenEditor/transform_rotator.png
  84. BIN
      IDE/Contents/Resources/Images/ScreenEditor/transform_scaler.png
  85. BIN
      IDE/Contents/Resources/Images/ScreenEditor/zoom.png
  86. BIN
      IDE/Contents/Resources/Images/arrow_add.png
  87. BIN
      IDE/Contents/Resources/Images/arrow_remove.png
  88. BIN
      IDE/Contents/Resources/Images/bezier_handle.png
  89. BIN
      IDE/Contents/Resources/Images/bezier_point.png
  90. BIN
      IDE/Contents/Resources/Images/collapse.png
  91. BIN
      IDE/Contents/Resources/Images/curve_editor_bg.png
  92. BIN
      IDE/Contents/Resources/Images/curve_icon.png
  93. BIN
      IDE/Contents/Resources/Images/entity_icon.png
  94. BIN
      IDE/Contents/Resources/Images/expand.png
  95. BIN
      IDE/Contents/Resources/Images/font_icon.png
  96. BIN
      IDE/Contents/Resources/Images/invisible.png
  97. BIN
      IDE/Contents/Resources/Images/link_entity.png
  98. BIN
      IDE/Contents/Resources/Images/new_layer.png
  99. BIN
      IDE/Contents/Resources/Images/particle_system_icon.png
  100. BIN
      IDE/Contents/Resources/Images/particle_system_icon_editor.png

BIN
Assets/Default asset pack/default.pak


BIN
Assets/Default asset pack/default/default.entity2d


+ 7 - 0
Assets/Default asset pack/default/default.sprite

@@ -0,0 +1,7 @@
+<?xml version="1.0" ?>
+<sprite>
+    <image frameWidth="32" frameHeight="32" fileName="default/default.png" />
+    <animations>
+        <animation name="default" frames="0" speed="1.0" />
+    </animations>
+</sprite>

BIN
Assets/Default asset pack/default/default.wav


+ 2 - 0
Bindings/Scripts/create_lua_library/create_lua_library.py

@@ -480,6 +480,8 @@ def createLUABindings(inputPath, prefix, mainInclude, libSmallName, libName, api
 										className = "Polycode::Polygon"
 									if className == "Rectangle":
 										className = "Polycode::Rectangle"
+									if className == "Polycode : : Rectangle":
+										className = "Polycode::Rectangle"
 									wrappersHeaderOut += "\t%s *retInst = new %s();\n" % (className, className)
 									wrappersHeaderOut += "\t*retInst = %s;\n" % (call)
 									wrappersHeaderOut += "\t%s(L, retInst);\n" % (outfunc)

+ 2 - 0
Core/Contents/CMakeLists.txt

@@ -69,6 +69,7 @@ SET(polycore_SRCS
     Source/PolyScreenShape.cpp
     Source/PolyScreenSound.cpp
     Source/PolyScreenSprite.cpp
+    Source/PolyScreenEntityInstance.cpp
     Source/PolyShader.cpp
     Source/PolySkeleton.cpp
     Source/PolySound.cpp
@@ -165,6 +166,7 @@ SET(polycore_HDRS
     Include/PolyScreenShape.h
     Include/PolyScreenSound.h
     Include/PolyScreenSprite.h
+    Include/PolyScreenEntityInstance.h
     Include/PolyShader.h
     Include/PolySkeleton.h
     Include/PolySound.h

+ 12 - 2
Core/Contents/Include/PolyBezierCurve.h

@@ -162,23 +162,33 @@ namespace Polycode {
 		* @return 3d point at specified position.
 		*/																				
 		Vector3 getPointBetween(Number a, BezierPoint *bp1, BezierPoint *bp2);
-			
+		
+		void clearControlPoints();
+		
 		/** 
 		* Rebuilds the height cache buffers for 2d height curves.
 		*/	
 		void rebuildBuffers();
+		
+		/**
+		* Removes (and deletes!) a gives point by pointer
+		*/
+		void removePoint(BezierPoint *point);
 
 		Number heightBuffer[BUFFER_CACHE_PRECISION];
 
+		BezierPoint *insertPoint;
+
 		std::vector<BezierPoint*> controlPoints;
 		std::vector<Number> distances;
 		
+		void recalculateDistances();		
 		
 		protected:
 		
 			bool buffersDirty;
 		
-			void recalculateDistances();
+
 	
 			
 	};

+ 1 - 0
Core/Contents/Include/PolyCore.h

@@ -36,6 +36,7 @@ THE SOFTWARE.
 #define CURSOR_CROSSHAIR 3
 #define CURSOR_RESIZE_LEFT_RIGHT 4
 #define CURSOR_RESIZE_UP_DOWN 5
+#define CURSOR_OPEN_HAND 6
 
 long getThreadID();
 

+ 37 - 8
Core/Contents/Include/PolyEntity.h

@@ -113,19 +113,15 @@ namespace Polycode {
 			*/
 			Matrix4 getConcatenatedMatrix();
 			
+			Matrix4 getConcatenatedMatrixRelativeTo(Entity *relativeEntity);
+			
 			/** 
 			* Returns Same as getConcatenatedMatrix(), but contains only roll information for rotation. Used internally for billboards.
 			@return Entity's concatenated roll matrix.
 			@see getConcatenatedMatrix()
 			*/			
 			Matrix4 getConcatenatedRollMatrix() const;
-			
-			/**
-			* Sets all of the individual transform properties from the matrix and rebuilds the transform matrix.
-			@param matrix 4x4 transform matrix to apply.
-			*/			
-			void setTransformByMatrix(const Matrix4& matrix);
-			
+						
 			/**
 			* Sets the transform matrix directly, without setting all of the individual transfrom properties of the entity.
 			@param matrix 4x4 transform matrix to apply.
@@ -507,6 +503,12 @@ namespace Polycode {
 			*/									
 			bool billboardRoll;
 			
+			/**
+			* If set to true, the entity will not be scaled by the modelview
+			* matrix when billboardMode is enabled
+			*/
+			bool billboardIgnoreScale;
+			
 			/**
 			* Normally, translucent textures do not affect the depth buffer, but if this flag is set to true, this entity's alpha channel is written to the depth buffer at a preset threshold. This flag is set to false by default.
 			*/			
@@ -593,11 +595,15 @@ namespace Polycode {
 			* @see Renderer			
 			*/
 			void setBlendingMode(int newBlendingMode);
-				
+			
+			Entity *getEntityById(String id, bool recursive);
+			std::vector<Entity*> getEntitiesByTag(String tag, bool recursive);
+						
 			Vector3 getChildCenter() const;
 			
 			std::vector <EntityProp> entityProps;
 			String getEntityProp(const String& propName);
+			void setEntityProp(const String& propName, const String& propValue);
 			
 			void doUpdates();				
 			virtual Matrix4 buildPositionMatrix();
@@ -614,9 +620,32 @@ namespace Polycode {
 			Vector3 position;
 			Vector3 scale;		
 			Rotation rotation;
+			
+			
+			bool editorOnly;
 	
+			/** @name Class and ID strings
+			*  These properties can be used to set and retrieve string-based ids and
+			* tags
+			*/
+			//@{			
+
+			String id;
+
+			unsigned int getNumTags() const;
+			String getTagAtIndex(unsigned int index) const;
+			bool hasTag(String tag) const;
+			
+			void clearTags();
+			void addTag(String tag); 
+
+
+
+			//@}		
 		protected:
 		
+			std::vector<String> tags;
+		
 			void checkTransformSetters();
 		
 			void *userData;

+ 10 - 0
Core/Contents/Include/PolyFont.h

@@ -23,6 +23,8 @@ THE SOFTWARE.
 #pragma once
 #include "PolyGlobals.h"
 #include "ft2build.h"
+#include "PolyString.h"
+
 #include FT_FREETYPE_H
 
 namespace Polycode {
@@ -37,8 +39,16 @@ namespace Polycode {
 			FT_Face getFace();
 			bool isValid() const;
 			
+			void setFontName(String fontName);
+			String getFontName();			
+			String getFontPath();
+			
 			bool loaded;
 		protected:
+		
+			String fileName;
+			String fontName;
+		
 			unsigned char *buffer;
 			bool valid;
 			FT_Face ftFace;

+ 7 - 0
Core/Contents/Include/PolyFontManager.h

@@ -58,6 +58,13 @@ namespace Polycode {
 		*/		
 		Font *getFontByName(const String& fontName);
 		
+		unsigned int getNumFonts() const;
+		FontEntry *getFontEntryByIndex(const unsigned int index);
+
+		FontEntry *getFontEntryByFontPath(const String &fontPath);
+		
+		void removeFontEntry(FontEntry *entry, bool deleteFont);
+		
 	private:
 		
 		std::vector <FontEntry> fonts;

+ 2 - 1
Core/Contents/Include/PolyGLRenderer.h

@@ -1,3 +1,4 @@
+
 /*
 Copyright (C) 2011 by Ivan Safrin
 
@@ -125,7 +126,7 @@ namespace Polycode {
 		void setRenderArrayData(RenderDataArray *array, Number *arrayData);
 		void drawArrays(int drawType);		
 				
-		void setOrthoMode(Number xSize=0.0f, Number ySize=0.0f);
+		void setOrthoMode(Number xSize=0.0f, Number ySize=0.0f, bool centered = false);
 		void _setOrthoMode(Number orthoSizeX, Number orthoSizeY);
 		void setPerspectiveMode();
 		

+ 40 - 6
Core/Contents/Include/PolyLabel.h

@@ -25,11 +25,25 @@ THE SOFTWARE.
 #include "PolyGlobals.h"
 #include "PolyImage.h"
 
-#define TAB_REPLACE "    "
+#include "PolyFont.h"
+
+#include FT_GLYPH_H
+#include FT_IMAGE_H
 
 namespace Polycode {
 
-	class Font;
+	class Font;	
+	
+	class GlyphData {
+		public:
+			GlyphData();
+			~GlyphData();
+			FT_Glyph *glyphs;
+			FT_Vector *positions;	
+			FT_UInt num_glyphs;
+			
+			int trailingAdvance;
+	};
 
 	class ColorRange {
 		public:
@@ -47,8 +61,15 @@ namespace Polycode {
 			void setText(const String& text);
 			const String& getText() const;
 			
-			static int getTextWidth(Font *font, const String& text, int size);
-			static int getTextHeight(Font *font, const String& text, int size);
+			int getTextWidthForString(const String& text);
+			int getTextHeightForString(const String& text);
+
+			void computeStringBbox(GlyphData *glyphData, FT_BBox *abbox);			
+			void precacheGlyphs(String text, GlyphData *glyphData);
+			
+			void renderGlyphs(GlyphData *glyphData);
+			
+			void drawGlyphBitmap(FT_Bitmap *bitmap, unsigned int x, unsigned int y, Color glyphColor);
 					
 			Number getTextWidth() const;
 			Number getTextHeight() const;
@@ -58,19 +79,32 @@ namespace Polycode {
 		
 			Color getColorForIndex(unsigned int index);
 		
+			void setFont(Font *newFont);
 			Font *getFont() const;
+			
+			void setSize(int newSize);
+			unsigned int getSize() const;
+			
+			int getAntialiasMode() const;			
+			void setAntialiasMode(int newMode);
 					
 			static const int ANTIALIAS_FULL = 0;
 			static const int ANTIALIAS_NONE = 1;
 			
+			int getBaselineAdjust();
+			
 		protected:
+		
+			
+			GlyphData labelData;
 	
 			std::vector<ColorRange> colorRanges;
 		
+			int baseLineOffset;
+			int xAdjustOffset;
+			int baseLineAdjust;			
 			bool premultiplyAlpha;
 
-			Number currentTextWidth;
-			Number currentTextHeight;
 			int antiAliasMode;
 			int size;
 			String text;

+ 26 - 0
Core/Contents/Include/PolyMatrix4.h

@@ -151,6 +151,32 @@ namespace Polycode {
 				return r;
 			}
 			
+			inline Matrix4 operator - ( const Matrix4 &m2 ) const {
+				Matrix4 r;
+				
+				r.m[0][0] = m[0][0] - m2.m[0][0];
+				r.m[0][1] = m[0][1] - m2.m[0][1];
+				r.m[0][2] = m[0][2] - m2.m[0][2];
+				r.m[0][3] = m[0][3] - m2.m[0][3];
+				
+				r.m[1][0] = m[1][0] - m2.m[1][0];
+				r.m[1][1] = m[1][1] - m2.m[1][1];
+				r.m[1][2] = m[1][2] - m2.m[1][2];
+				r.m[1][3] = m[1][3] - m2.m[1][3];
+
+				r.m[2][0] = m[2][0] - m2.m[2][0];
+				r.m[2][1] = m[2][1] - m2.m[2][1];
+				r.m[2][2] = m[2][2] - m2.m[2][2];
+				r.m[2][3] = m[2][3] - m2.m[2][3];
+				
+				r.m[3][0] = m[3][0] - m2.m[3][0];
+				r.m[3][1] = m[3][1] - m2.m[3][1];
+				r.m[3][2] = m[3][2] - m2.m[3][2];
+				r.m[3][3] = m[3][3] - m2.m[3][3];
+				
+				return r;
+			}	
+			
 			inline Matrix4 operator * (const Matrix4 &m2) const {
            Matrix4 r;
             r.m[0][0] = m[0][0] * m2.m[0][0] + m[0][1] * m2.m[1][0] + m[0][2] * m2.m[2][0] + m[0][3] * m2.m[3][0];

+ 7 - 0
Core/Contents/Include/PolyMesh.h

@@ -329,6 +329,13 @@ namespace Polycode {
 			*/									
 			static const int POINT_MESH = 5;
 		
+			/**
+			* Line strip based mesh.
+			*/									
+			static const int LINE_STRIP_MESH = 6;
+			
+		
+		
 			/**
 			* Render array dirty map. If any of these are flagged as dirty, the renderer will rebuild them from the mesh data. See RenderDataArray for types of render arrays.
 			* @see RenderDataArray

+ 55 - 0
Core/Contents/Include/PolyObject.h

@@ -23,6 +23,7 @@
 #pragma once
 #include "PolyGlobals.h"
 #include "PolyString.h"
+#include "OSBasics.h"
 
 class TiXmlElement;
 
@@ -237,6 +238,20 @@ namespace Polycode {
 		* @param fileName Path to the XML file to save to.
 		*/				
 		void saveToXML(const String& fileName);
+
+		/**
+		* Saves the object to an optimized binary file
+		* @param fileName Path to the file to save to.
+		*/				
+		void saveToBinary(const String& fileName);
+
+		/**
+		* Loads data from a binary file into the object. 
+		* @param fileName Path to the binary file to load.
+		* @return Returns true is succesful, false if otherwise.
+		*/		
+		bool loadFromBinary(const String& fileName);
+
 		
 		void createFromXMLElement(TiXmlElement *element, ObjectEntry *entry);
 		TiXmlElement *createElementFromObjectEntry(ObjectEntry *entry);
@@ -247,5 +262,45 @@ namespace Polycode {
 		ObjectEntry root;
 		
 	};
+
+	class _PolyExport BinaryObjectReader {
+		public:
+			BinaryObjectReader(const String& fileName, Object *object);
+			~BinaryObjectReader();			
+			
+			bool success;				
+		protected:
+		
+			bool parseEntryFromFile(ObjectEntry *entry);
+			String getKeyByIndex(unsigned int index);
+			
+			bool readFile();
+					
+			OSFILE *inFile;		
+			std::vector<String> keys;
+			Object *object;		
+
+	};
+		
+	class _PolyExport BinaryObjectWriter {
+		public:
+			BinaryObjectWriter(Object *object);
+			~BinaryObjectWriter();
+			
+			void parseKeysFromObjectEntry(ObjectEntry *entry);
+			void writeEntryToFile(ObjectEntry *entry);
+			
+			unsigned int addKey(const String &key);			
+			unsigned int getKeyIndex(const String &key);
+			
+			bool writeToFile(const String& fileName);			
+			
+		protected:
+			OSFILE *outFile;
+			int numEntriesWritten;
+			std::vector<String> keys;			
+			Object *object;
+	};
+
 	
 }

+ 35 - 11
Core/Contents/Include/PolyParticleEmitter.h

@@ -67,6 +67,8 @@ namespace Polycode {
 			*/ 			
 			void setParticleBlendingMode(int mode);
 			
+			int getParticleBlendingMode() const;
+			
 			/**
 			* Turns depth write on and off for particles.
 			*/ 						
@@ -122,9 +124,17 @@ namespace Polycode {
 			*/ 																													
 			void setAllAtOnce(bool val);
 			
+
+			unsigned int getNumParticles() const;
+
+			Particle *getParticleAtIndex(unsigned int index) const;
+
 			/**
 			* If emitter mode is TRIGGERED_EMITTER, calling this method will trigger particle emission.
-			*/ 																													
+			*/ 
+			
+			void resetAll();
+	
 			void Trigger();
 			
 			void resetParticle(Particle *particle);
@@ -134,6 +144,7 @@ namespace Polycode {
 			*/ 																													
 			void setParticleCount(int count);
 		
+			virtual Vector3 getParticleCompoundScale();
 			virtual void addParticleBody(Entity *particleBody);
 			virtual Matrix4 getBaseMatrix();
 		
@@ -214,14 +225,30 @@ namespace Polycode {
 			* If set to true, will use the scale curve to control particle scale. False by default.
 			*/			
 			bool useScaleCurves;
+			
+			Number particleSize;
+			
+			Texture *getParticleTexture();
+			
+			void setParticleTexture(Texture *texture);
 		
+			Vector3 emitterRadius;
+					
+			Number perlinModSize;
+
+			bool perlinEnabled;
+				
+			Number rotationSpeed;
+							
+			int emitterType;											
 		protected:
 		
+			int blendingMode;
+		
 			bool isScreenEmitter;
 			Mesh *pMesh;
 		
 			bool allAtOnce;
-			int emitterType;
 			int particleType;
 			Material *particleMaterial;
 			Texture *particleTexture;
@@ -230,12 +257,9 @@ namespace Polycode {
 		
 			bool isEmitterEnabled;
 		
-			Vector3 emitterRadius;
-			Number perlinModSize;
+						
 			Perlin *motionPerlin;
-			bool perlinEnabled;
 			
-			Number rotationSpeed;
 			Number numParticles;
 			std::vector<Particle*> particles;
 			
@@ -262,7 +286,7 @@ namespace Polycode {
 		* @param particleMesh If particle type is Particle::MESH_PARTICLE, this must be set to the mesh to use for each particle
 		* @param emitter If this is specified, particles will be emitted from this meshe's vertices.
 		*/
-		SceneParticleEmitter(const String& materialName, Scene *particleParentScene, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh = NULL, SceneMesh *emitter = NULL);
+		SceneParticleEmitter(const String& materialName, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh = NULL, SceneMesh *emitter = NULL);
 		virtual ~SceneParticleEmitter();		
 		
 		/**
@@ -290,7 +314,6 @@ namespace Polycode {
 		
 	protected:
 		SceneMesh *emitterMesh;		
-		Scene *particleParentScene;
 	};	
 		
 	/**
@@ -298,7 +321,7 @@ namespace Polycode {
 	*/
 	class _PolyExport ScreenParticleEmitter : public ScreenEntity, public ParticleEmitter {
 	public:
-		ScreenParticleEmitter(const String& imageFile, Screen *particleParentScreen, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh = NULL, ScreenMesh *emitter = NULL);
+		ScreenParticleEmitter(const String& imageFile, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh = NULL, ScreenMesh *emitter = NULL);
 		virtual ~ScreenParticleEmitter();		
 		
 		/**
@@ -312,6 +335,8 @@ namespace Polycode {
 		Matrix4 getBaseMatrix();
 		void Update();
 		
+		Vector3 getParticleCompoundScale();
+		
 			/**
 			* Continuous emitter setting.
 			*/ 																													
@@ -324,7 +349,6 @@ namespace Polycode {
 		
 		
 	protected:
-		ScreenMesh *emitterMesh;		
-		Screen *particleParentScreen;
+		ScreenMesh *emitterMesh;
 	};		
 }

+ 14 - 4
Core/Contents/Include/PolyRenderer.h

@@ -104,7 +104,7 @@ namespace Polycode {
 		virtual void resetViewport() = 0;
 				
 		virtual void loadIdentity() = 0;		
-		virtual void setOrthoMode(Number xSize=0.0f, Number ySize=0.0f) = 0;
+		virtual void setOrthoMode(Number xSize=0.0f, Number ySize=0.0f, bool centered = false) = 0;
 		virtual void _setOrthoMode(Number orthoSizeX, Number orthoSizeY) = 0;
 		virtual void setPerspectiveMode() = 0;
 		
@@ -191,8 +191,12 @@ namespace Polycode {
 		int getXRes();
 		int getYRes();
 		
-		virtual void enableScissor(bool val) = 0;
-		virtual void setScissorBox(Polycode::Rectangle box) = 0;
+		bool isScissorEnabled();
+		
+		virtual void enableScissor(bool val);
+		virtual void setScissorBox(Polycode::Rectangle box);
+		
+		Polycode::Rectangle getScissorBox();
 		
 		void setAnisotropyAmount(Number amount);
 		Number getAnisotropyAmount();
@@ -263,7 +267,13 @@ namespace Polycode {
 		std::vector<LightInfo> getAreaLights() { return areaLights; }
 		std::vector<LightInfo> getSpotLights() { return spotLights;	}
 		
-	protected:
+		bool doClearBuffer;
+				
+	protected:	
+	
+		bool scissorEnabled;
+		
+		Polycode::Rectangle scissorBox;
 	
 		Number anisotropy;
 		Matrix4 currentModelMatrix;

+ 15 - 52
Core/Contents/Include/PolyScreen.h

@@ -25,6 +25,7 @@ THE SOFTWARE.
 #include "PolyGlobals.h"
 #include "PolyVector2.h"
 #include "PolyEventDispatcher.h"
+#include "PolyScreenEntity.h"
 #include <vector>
 
 namespace Polycode {
@@ -33,7 +34,6 @@ namespace Polycode {
 	class Renderer;
 	class Material;
 	class Texture;
-	class ScreenEntity;
 	class ShaderBinding;
 
 	/**
@@ -51,45 +51,31 @@ namespace Polycode {
 		/**
 		* Adds a ScreenEntity to the 2d rendering pipeline.
 		* @param newEntity Entity to add.
-		* @return Returns the same entity for convenience.
 		*/		
-		ScreenEntity* addChild(ScreenEntity *newEntity);
+		void addChild(ScreenEntity *newEntity);
 
 		/**
 		* Adds a ScreenEntity to the 2d rendering pipeline.
 		* @param newEntity Entity to add.
-		* @return Returns the same entity for convenience.
 		*/		
-		ScreenEntity* addEntity(ScreenEntity *newEntity);
+		void addEntity(ScreenEntity *newEntity);
 		
 		/**
-		* Removes a ScreenEntity from the screen's render list.
+		* Removes a ScreenEntity from the screen's root entity
 		* @param entityToRemove Entity to remove.
-		* @return Returns the same entity for convenience.
 		*/				
-		virtual ScreenEntity* removeChild(ScreenEntity *entityToRemove);
-		
+		virtual void removeChild(ScreenEntity *entityToRemove);
+				
 		/**
 		* Sets the screen's offset. You can also translate the root entity to do the same thing.
 		* @param x New x offset.
 		* @param y New y offset.		
 		*/						
 		void setScreenOffset(Number x, Number y);
-		
-		/** 
-		* Returns the screen's offset.
-		* @return The screen's offset as 2d vector.
-		*/		
-		Vector2 getScreenOffset() const;
 				
 		virtual void Shutdown();
 		virtual void Update();
-		
-		/**
-		* Returns the entity at specified point. This is a deprecated method which does not take rotation or scale into account. Please use the 2d physics and collision module for proper collision detection.
-		*/
-		ScreenEntity *getEntityAt(Number x, Number y);
-
+				
 		void Render();
 		void setRenderer(Renderer *renderer);
 
@@ -109,18 +95,8 @@ namespace Polycode {
 		/**
 		* Removes the current screen shader for this screen.
 		*/
-		void clearScreenShader();
-		
-		void handleEvent(Event *event);
-		int getHighestZIndex() const;
-		
-		/**
-		* Sorts the screen's children based on their z index.
-		*/ 
-		void sortChildren();
-		
-		static bool cmpZindex(const ScreenEntity *left, const ScreenEntity *right);
-		
+		void clearScreenShader();		
+
 		void handleInputEvent(InputEvent *inputEvent);
 		
 		/**
@@ -131,16 +107,7 @@ namespace Polycode {
 		
 		bool usesNormalizedCoordinates() const { return useNormalizedCoordinates; }
 		Number getYCoordinateSize() const { return yCoordinateSize; }
-		
-		/**
-		* Returns the root entity. The root entity can be used to transform the entire screen and change its color.
-		* @return The root entity.
-		*/		
-		ScreenEntity *getRootEntity() { return rootEntity; }
-		
-		int getNumChildren() { return children.size(); }
-		ScreenEntity *getChild(int index) { return children[index]; }
-		
+				
 		/**
 		* If set to false, the screen will not be rendered or updated.
 		*/
@@ -166,22 +133,18 @@ namespace Polycode {
 		*/
 		bool ownsChildren;		
 		
-		/**
-		* If true, children snap to pixels by default. You can still change it per entity. Defaults to false.
-		*/		
-		bool snapToPixelsByDefault;
-		
+
+		ScreenEntity rootEntity;
+				
 	protected:
+	
+		Vector2 offset;
 		
 		bool useNormalizedCoordinates;
 		Number yCoordinateSize;		
 		
-		ScreenEntity *rootEntity;
-		
-		Vector2 offset;
 		Renderer *renderer;
 		ScreenEntity *focusChild;
-		std::vector <ScreenEntity*> children;
 		
 		Material *filterShaderMaterial;			
 		Texture *originalSceneTexture;				

+ 29 - 10
Core/Contents/Include/PolyScreenEntity.h

@@ -28,10 +28,17 @@ THE SOFTWARE.
 #include "PolyRectangle.h"
 #include "PolyInputKeys.h"
 #include "PolyEntity.h"
+#include "PolyObject.h"
 #include "PolyEventDispatcher.h"
 
 namespace Polycode {
 
+	class _PolyExport MouseEventResult {
+		public:
+			bool hit;
+			bool blocked;
+	};
+
 /**
 * 2D Entity base. The ScreenEntity is the base class for all 2D elements in Polycode. They can be added to a screen or to other ScreenEntities and are rendered automatically. If you want to create custom screen objects, subclass this. ScreenEntity subclasses Entity, which use 3d positioning and tranformation, but provides some 2d-only versions of the transformation functions for convenience.
 */
@@ -87,11 +94,11 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		*/						
 		Number getRotation() const;
 			
-		bool _onMouseDown(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust = Vector2(0,0));
-		bool _onMouseUp(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust = Vector2(0,0));
-		void _onMouseMove(Number x, Number y, int timestamp, Vector2 parentAdjust = Vector2(0,0));
-		void _onMouseWheelUp(Number x, Number y, int timestamp, Vector2 parentAdjust = Vector2(0,0));
-		void _onMouseWheelDown(Number x, Number y, int timestamp, Vector2 parentAdjust = Vector2(0,0));
+		MouseEventResult _onMouseDown(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust = Vector2(0,0));
+		MouseEventResult _onMouseUp(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust = Vector2(0,0));
+		MouseEventResult _onMouseMove(Number x, Number y, int timestamp, Vector2 parentAdjust = Vector2(0,0));
+		MouseEventResult _onMouseWheelUp(Number x, Number y, int timestamp, Vector2 parentAdjust = Vector2(0,0));
+		MouseEventResult _onMouseWheelDown(Number x, Number y, int timestamp, Vector2 parentAdjust = Vector2(0,0));
 	
 		virtual void onMouseDown(Number x, Number y){}
 		virtual void onMouseUp(Number x, Number y){}
@@ -139,7 +146,7 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		virtual void onLoseFocus(){}		
 		
 		void startDrag(Number xOffset, Number yOffset);
-		void stopDrag();
+		void stopDrag();		
 				
 		void setBlendingMode(int newBlendingMode);
 		
@@ -162,9 +169,16 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		
 		void focusChild(ScreenEntity *child);
 		void focusNextChild();
-	
+		
+		void moveChildUp(ScreenEntity *child);
+		void moveChildDown(ScreenEntity *child);
+		void moveChildTop(ScreenEntity *child);
+		void moveChildBottom(ScreenEntity *child);
+							
 		Vector2 getPosition2D() const;
 		Vector2 getScreenPosition() const;
+
+		Vector2 getScale2D() const;
 		
 		static const int POSITION_TOPLEFT = 0;
 		static const int POSITION_CENTER = 1;
@@ -172,8 +186,13 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		bool isFocusable() const;
 		
 		bool hasFocus;
-		bool blockMouseInput;
-		int zindex;	
+		
+		
+		/**
+		* If set to true, will block mouse events for underlaying entities.
+		* (NOTE: processInputEvents must be set to true)
+		*/
+		bool blockMouseInput;	
 	
 		/**
 		* If this option is true, the screen entity's positions will be roudnded to whole pixels. This only works if the screen is using pixel coordinates.
@@ -211,4 +230,4 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 
 };
 
-}
+}

+ 58 - 0
Core/Contents/Include/PolyScreenEntityInstance.h

@@ -0,0 +1,58 @@
+/*
+Copyright (C) 2011 by Ivan Safrin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#pragma once
+#include "PolyGlobals.h"
+#include "PolyScreenEntity.h"
+#include "PolyObject.h"
+#include "PolyScreenShape.h"
+#include "PolyScreenImage.h"
+#include "PolyScreenLabel.h"
+#include "PolyScreenSound.h"
+#include "PolyScreenSprite.h"
+#include "PolyParticleEmitter.h"
+#include "PolyParticle.h"
+#include "PolySound.h"
+
+namespace Polycode {
+
+class ScreenEntityInstance : public ScreenEntity {
+	public:
+		ScreenEntityInstance(const String& fileName);
+		~ScreenEntityInstance();
+		
+		void parseObjectIntoCurve(ObjectEntry *entry, BezierCurve *curve);
+		void applyScreenShape(ObjectEntry *entry, ScreenShape *shape);
+		ScreenEntity *loadObjectEntryIntoEntity(ObjectEntry *entry);
+		bool loadFromFile(const String& fileName);
+		
+		ScreenEntity *getRootEntity();
+		
+		String getFileName() const;
+		
+	protected:
+		ScreenEntity *rootEntity;		
+		String fileName;
+};
+
+}

+ 7 - 1
Core/Contents/Include/PolyScreenLabel.h

@@ -54,11 +54,12 @@ namespace Polycode {
 			*/
 			void addDropShadow(Color color, Number size, Number offsetX, Number offsetY);
 			
+			
 			/**
 			* Sets a new text to the screen label.
 			* @param newText Text to set.
 			*/
-			void setText(const String& newText);
+			void setText(const String& newText);			
 			
 			/**
 			* Returns the label's text as a string.
@@ -68,8 +69,13 @@ namespace Polycode {
 		
 			Label *getLabel() const;
 			
+			void Render();
+			bool positionAtBaseline;
+			
 		protected:
 			
+			void updateTexture();
+			
 			Label *label;
 			ScreenImage *dropShadowImage;
 	};

+ 4 - 1
Core/Contents/Include/PolyScreenLine.h

@@ -38,7 +38,7 @@ namespace Polycode {
 			* @start Starting point.
 			* @end Enfing point.	
 			*/
-			ScreenLine(Vector2* start, Vector2* end);
+			ScreenLine(Vector2 start, Vector2 end);
 			
 			/**
 			* Create a line between two entities. It's automatically updated every frame to follow the entities.
@@ -48,6 +48,9 @@ namespace Polycode {
 			ScreenLine(ScreenEntity* target1, ScreenEntity* target2);
 			virtual ~ScreenLine();
 			
+			void setStart(Vector2 point);
+			void setEnd(Vector2 point);
+						
 			static ScreenLine *ScreenLineBetweenEntities(ScreenEntity* target1, ScreenEntity* target2);			
 
 			void Update();

+ 19 - 4
Core/Contents/Include/PolyScreenShape.h

@@ -43,6 +43,7 @@ namespace Polycode {
 			* @param option4 Reserved.
 			*/
 			ScreenShape(int shapeType, Number option1=0, Number option2=0, Number option3=0, Number option4=0);
+						
 			virtual ~ScreenShape();
 			void Render();
 
@@ -82,9 +83,14 @@ namespace Polycode {
 			* Removes the gradient from the shape.
 			*/
 			void clearGradient();
-				
+			
+			int getShapeType() const;
+			
+			void setShapeType(unsigned int type);
 
-			void setShapeSize(Number newWidth, Number newHeight);
+			void setShapeSize(Number newWidth, Number newHeight);		
+		
+			void buildShapeMesh();
 		
 			/** 
 			* Adds a point to the mesh.
@@ -93,6 +99,11 @@ namespace Polycode {
 			*/ 
 			void addShapePoint(Number x, Number y);
 			
+			/**
+			* Assignment operator
+			*/
+			void operator=(const ScreenShape& copy);
+			
 			static const int SHAPE_RECT = 1;
 			static const int SHAPE_CIRCLE = 2;
 			static const int SHAPE_CUSTOM = 4;
@@ -106,7 +117,12 @@ namespace Polycode {
 			* Color of the shape stroke.
 			*/
 			Color strokeColor;
-			
+
+			/**
+			* Width of the shape stroke.
+			*/			
+			Number strokeWidth;
+						
 		protected:
 		
 			Number option1;
@@ -115,7 +131,6 @@ namespace Polycode {
 			Number option4;
 									
 			Polygon *customShapePoly;
-			Number strokeWidth;
 			int shapeType;
 			
 	};

+ 2 - 1
Core/Contents/Include/PolyScreenSound.h

@@ -46,7 +46,7 @@ namespace Polycode {
 		public:
 			ScreenSound(const String& fileName, Number referenceDistance, Number maxDistance);
 			virtual ~ScreenSound();			
-			void Update();
+			void Update();			
 			
 			/**
 			* Returns the sound object associated with this positional sound.
@@ -54,6 +54,7 @@ namespace Polycode {
 			Sound *getSound() const;
 			
 		protected:
+					
 			Sound *sound;
 	};
 	

+ 34 - 1
Core/Contents/Include/PolyScreenSprite.h

@@ -31,7 +31,15 @@ class _PolyExport SpriteAnimation {
 	public:
 		Number speed;
 		String name;
+		String frames;
 		int numFrames;
+		
+		int numFramesX;
+		int numFramesY;
+		Number spriteUVWidth;
+		Number spriteUVHeight;
+						
+		void setOffsetsFromFrameString(const String& frames);
 	
 		std::vector<Vector2> framesOffsets;
 };
@@ -42,6 +50,13 @@ class _PolyExport SpriteAnimation {
 class _PolyExport ScreenSprite : public ScreenShape 
 {
 	public:
+	
+		/**
+		* Create a sprite from a sprite file format
+		* @param fileName Sprite file to load
+		*/
+		ScreenSprite(const String& fileName);
+	
 		/**
 		* Create a sprite from a spritesheet image of specified size.
 		* @param fileName Image file to load spritesheet from.
@@ -56,8 +71,9 @@ class _PolyExport ScreenSprite : public ScreenShape
 		* @param name Name of the new animation.
 		* @param frames A comma separated list of frames indexes to include in the animation.
 		* @speed Speed at which to play back the animation.
+		* @return Returns newly added animation
 		*/
-		void addAnimation(const String& name, const String& frames, Number speed);
+		SpriteAnimation *addAnimation(const String& name, const String& frames, Number speed);
 		
 		/**
 		* Shows a specific frame of the current animation.
@@ -73,6 +89,16 @@ class _PolyExport ScreenSprite : public ScreenShape
 		*/
 		void playAnimation(const String& name, int startFrame, bool once);
 		void Update();
+		
+		void setSpriteSize(const Number spriteWidth, const Number spriteHeight);
+	
+		Vector2 getSpriteSize();
+	
+		String getFileName() const;
+	
+		void recalculateSpriteDimensions();
+	
+		bool loadFromFile(const String& fileName);
 	
 		/**
 		* Pauses or unpauses the current sprite animation.
@@ -80,10 +106,17 @@ class _PolyExport ScreenSprite : public ScreenShape
 		*/ 
 		void Pause(bool val);
 		
+		unsigned int getNumAnimations();		
+		SpriteAnimation *getAnimationAtIndex(unsigned int index);
+		
+		SpriteAnimation *getCurrentAnimation();
+		
 		void updateSprite();
 		
 	protected:
 	
+		String fileName;
+		
 		bool paused;
 	
 		Number spriteWidth;

+ 24 - 0
Core/Contents/Include/PolySound.h

@@ -23,6 +23,7 @@
 #pragma once
 #include "PolyGlobals.h"
 #include "PolyVector3.h"
+#include "PolyString.h"
 
 #include "al.h"
 #include "alc.h"
@@ -55,6 +56,8 @@ namespace Polycode {
 		Sound(const char *data, int size, int channels = 1, ALsizei freq = 44100, int bps = 16);
 		virtual ~Sound();
 		
+		void loadFile(String fileName);
+		
 		/**
 		* Play the sound once or in a loop.
 		* @param once If this is true, play it once, otherwise, loop.
@@ -72,12 +75,16 @@ namespace Polycode {
 		*/
 		void setVolume(Number newVolume);
 
+		Number getVolume();
+
 		/**
 		* Sets the pitch of this sound.
 		* @param newPitch A Number 0-1.
 		*/		
 		void setPitch(Number newPitch);
 		
+		Number getPitch();
+		
 		/**
 		* Returns true if the sound is playing.
 		* @return True if sound is playing, false if otherwise.
@@ -96,6 +103,7 @@ namespace Polycode {
 		*/
 		void setOffset(int off);
 		
+		String getFileName();
 		
 		Number getPlaybackDuration();
 		
@@ -116,6 +124,12 @@ namespace Polycode {
 		
 		void setPositionalProperties(Number referenceDistance, Number maxDistance);
 		
+		void setReferenceDistance(Number referenceDistance);
+		void setMaxDistance(Number maxDistance);
+		
+		Number getReferenceDistance();
+		Number getMaxDistance();
+		
 		ALuint loadBytes(const char *data, int size, int channels = 1, ALsizei freq = 44100, int bps = 16);
 		ALuint loadWAV(const String& fileName);
 		ALuint loadOGG(const String& fileName);
@@ -131,6 +145,16 @@ namespace Polycode {
 
 	protected:
 	
+		Number referenceDistance;
+		Number maxDistance;
+			
+		Number pitch;
+		Number volume;
+	
+		String fileName;
+		
+		bool soundLoaded;
+	
 		bool isPositional;
 		ALuint soundSource;
 		int sampleLength;

+ 1 - 0
Core/Contents/Include/Polycode.h

@@ -61,6 +61,7 @@
 #include "PolyScreenSprite.h"
 #include "PolyScreenLabel.h"
 #include "PolyScreenCurve.h"
+#include "PolyScreenEntityInstance.h"
 #include "PolyTexture.h"
 #include "PolyMaterial.h"
 #include "PolyMesh.h"

+ 45 - 5
Core/Contents/Source/PolyBezierCurve.cpp

@@ -38,6 +38,7 @@ BezierPoint::BezierPoint(Number p1x, Number p1y, Number p1z, Number p2x, Number
 }
 
 BezierCurve::BezierCurve(){
+	insertPoint = NULL;
 	for(int i=0; i < BUFFER_CACHE_PRECISION; i++) {
 		heightBuffer[i] = 0;
 	}
@@ -45,13 +46,39 @@ BezierCurve::BezierCurve(){
 	buffersDirty = false;	
 }
 
+void BezierCurve::clearControlPoints() {
+	insertPoint = NULL;
+	for(int i=0; i < BUFFER_CACHE_PRECISION; i++) {
+		heightBuffer[i] = 0;
+	}
+	
+	buffersDirty = true;
+	for(int i=0; i < controlPoints.size(); i++) {
+		delete controlPoints[i];
+	}
+	controlPoints.clear();
+}
+
 BezierCurve::~BezierCurve() {
 
 }
 
 void BezierCurve::addControlPoint(Number p1x, Number p1y, Number p1z, Number p2x, Number p2y, Number p2z, Number p3x, Number p3y, Number p3z) {
 	BezierPoint* newPoint = new BezierPoint(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z);
-	controlPoints.push_back(newPoint);
+	
+	bool inserted = false;
+	for(int i=0; i < controlPoints.size(); i++) {
+		if(controlPoints[i] == insertPoint) {
+			controlPoints.insert(controlPoints.begin()+i, newPoint);
+			inserted = true;
+			break;
+		}
+	}
+	
+	if(!inserted) {
+		controlPoints.push_back(newPoint);
+	}
+	
 	distances.push_back(0);
 	recalculateDistances();
 	buffersDirty = true;	
@@ -108,7 +135,7 @@ Vector3 BezierCurve::getPointBetween(Number a, BezierPoint *bp1, BezierPoint *bp
 	
 	retVector.x = bp1->p2.x*a*a*a + bp1->p3.x*3*a*a*b + bp2->p1.x*3*a*b*b + bp2->p2.x*b*b*b;
 	retVector.y = bp1->p2.y*a*a*a + bp1->p3.y*3*a*a*b + bp2->p1.y*3*a*b*b + bp2->p2.y*b*b*b;
-	retVector.z = bp1->p2.z*a*a*a + bp1->p3.z*3*a*a*b + bp2->p1.z*3*a*b*b + bp2->p2.z*b*b*b;	
+	retVector.z = bp1->p2.z*a*a*a + bp1->p3.z*3*a*a*b + bp2->p1.z*3*a*b*b + bp2->p2.z*b*b*b;
 
 	return retVector;
 }
@@ -121,6 +148,16 @@ unsigned int BezierCurve::getNumControlPoints() {
 	return controlPoints.size();
 }
 
+void BezierCurve::removePoint(BezierPoint *point) {
+	for(int i=0; i < controlPoints.size(); i++) {
+		if(controlPoints[i] == point) {
+			delete point;
+			controlPoints.erase(controlPoints.begin() + i);
+			break;
+		}
+	}
+}
+
 Number BezierCurve::getHeightAt(Number a) {
 	if( a< 0) a = 0;
 	if(a > 1) a = 1;
@@ -128,7 +165,11 @@ Number BezierCurve::getHeightAt(Number a) {
 	if (buffersDirty) 
 		rebuildBuffers();
 	
-	int index = ((Number)(BUFFER_CACHE_PRECISION)) * a;	
+	int unsigned index = ((Number)(BUFFER_CACHE_PRECISION)) * a;	
+	
+	if(index > BUFFER_CACHE_PRECISION-1)
+		index = BUFFER_CACHE_PRECISION-1;
+	
 	return heightBuffer[index];
 	
 //	return getPointAt(a).y;
@@ -145,8 +186,7 @@ Vector3 BezierCurve::getPointAt(Number a) {
 	if(a < 0)
 		a = 0;
 	if(a > 1)
-		a = 1;
-		
+		a = 1;		
 		
 	if(controlPoints.size() < 2)
 		return Vector3(0,0,0);

+ 3 - 0
Core/Contents/Source/PolyCocoaCore.mm

@@ -384,6 +384,9 @@ void CocoaCore::setCursor(int cursorType) {
 		case CURSOR_RESIZE_UP_DOWN:
 			newCursor = [NSCursor resizeUpDownCursor];			
 		break;
+		case CURSOR_OPEN_HAND:
+			newCursor = [NSCursor openHandCursor];			
+		break;		
 		default:
 			newCursor = [NSCursor arrowCursor];			
 		break;

+ 6 - 3
Core/Contents/Source/PolyCoreServices.cpp

@@ -216,17 +216,20 @@ void CoreServices::Update(int elapsed) {
 	materialManager->Update(elapsed);
 		
 	if(drawScreensFirst) {
-		renderer->clearScreen();	
+		if(renderer->doClearBuffer)
+			renderer->clearScreen();	
 		renderer->setPerspectiveMode();
 		sceneManager->UpdateVirtual();
-		renderer->clearScreen();					
+		if(renderer->doClearBuffer)		
+			renderer->clearScreen();					
 		screenManager->Update();
 		renderer->setPerspectiveMode();
 		sceneManager->Update();	
 	} else {
 		renderer->setPerspectiveMode();
 		sceneManager->UpdateVirtual();
-		renderer->clearScreen();		
+		if(renderer->doClearBuffer)		
+			renderer->clearScreen();		
 		sceneManager->Update();
 		screenManager->Update();	
 	}	

+ 137 - 24
Core/Contents/Source/PolyEntity.cpp

@@ -44,6 +44,7 @@ Entity::Entity() {
 	matrixAdj = 1.0f;
 	billboardMode = false;
 	billboardRoll = false;
+	billboardIgnoreScale = false;
 	backfaceCulled = true;
 	depthOnly = false;
 	depthWrite = true;
@@ -56,8 +57,45 @@ Entity::Entity() {
 	visibilityAffectsChildren = true;
 	ownsChildren = false;
 	enableScissor = false;
+	
+	editorOnly = false; 
+}
+
+Entity *Entity::getEntityById(String id, bool recursive) {
+	for(int i=0;i<children.size();i++) {
+		if(children[i]->id == id) {
+			return children[i];
+		} else {
+			if(recursive) {
+				Entity *ret = children[i]->getEntityById(id, recursive);
+				if(ret) {
+					return ret;
+				}
+			}
+		}
+	}
+	return NULL;
+}
+
+std::vector<Entity*> Entity::getEntitiesByTag(String tag, bool recursive) {
+
+	std::vector<Entity*> retVector;
+
+	for(int i=0;i<children.size();i++) {
+		if(children[i]->hasTag(tag)) {
+			retVector.push_back(children[i]);
+		}
+		
+		if(recursive) {
+			std::vector<Entity*> childVector = children[i]->getEntitiesByTag(tag, recursive);			
+			retVector.insert(retVector.end(), childVector.begin(), childVector.end());
+		}		
+	}
+	
+	return retVector;
 }
 
+
 void Entity::setUserData(void *userData) {
 	this->userData = userData;
 }
@@ -296,27 +334,62 @@ void Entity::transformAndRender() {
 		renderer->drawToColorBuffer(false);
 	}
 	
+	bool isScissorEnabled;
+	Polycode::Rectangle oldScissorBox;
+	
 	if(enableScissor) {
+		isScissorEnabled = renderer->isScissorEnabled();
+		oldScissorBox = renderer->getScissorBox();
 		renderer->enableScissor(true);
-		renderer->setScissorBox(scissorBox);
+		
+		Polycode::Rectangle finalScrissorBox = scissorBox;		
+		
+		// make sure that our scissor box is constrained to the parent one if it exists
+		if(isScissorEnabled) {
+			if(finalScrissorBox.x < oldScissorBox.x)
+				finalScrissorBox.x = oldScissorBox.x;
+			if(finalScrissorBox.x > oldScissorBox.x + oldScissorBox.w)
+				finalScrissorBox.x = oldScissorBox.x + oldScissorBox.w;
+
+				
+			if(finalScrissorBox.x+finalScrissorBox.w > oldScissorBox.x + oldScissorBox.w)
+				finalScrissorBox.w = oldScissorBox.x - finalScrissorBox.x;
+
+			if(finalScrissorBox.y < oldScissorBox.y)
+				finalScrissorBox.y = oldScissorBox.y;
+			if(finalScrissorBox.y > oldScissorBox.y + oldScissorBox.h)
+				finalScrissorBox.y = oldScissorBox.y + oldScissorBox.h;
+
+			if(finalScrissorBox.y+finalScrissorBox.h > oldScissorBox.y + oldScissorBox.h)
+				finalScrissorBox.h = oldScissorBox.y - finalScrissorBox.y;
+
+		}
+		
+		renderer->setScissorBox(finalScrissorBox);
 	}
 		
 	renderer->pushMatrix();
 	if(ignoreParentMatrix && parentEntity) {
 		renderer->multModelviewMatrix(parentEntity->getConcatenatedMatrix().inverse());
-		renderer->setCurrentModelMatrix(parentEntity->getConcatenatedMatrix().inverse());
-	}else {
+//		renderer->setCurrentModelMatrix(parentEntity->getConcatenatedMatrix().inverse());
+	}
+
 		renderer->multModelviewMatrix(transformMatrix);
 		renderer->setCurrentModelMatrix(transformMatrix);
-	}
+		
 	renderer->setVertexColor(color.r,color.g,color.b,color.a);
+	
 	if(billboardMode) {
-		renderer->billboardMatrixWithScale(getCompoundScale());
+		if(billboardIgnoreScale) {
+			renderer->billboardMatrix();
+		} else {
+			renderer->billboardMatrixWithScale(getCompoundScale());
+		}
 		if(billboardRoll) {
 			renderer->multModelviewMatrix(getConcatenatedRollMatrix());
 		}
 	}
-
+	
 	if(!depthWrite)
 		renderer->enableDepthWrite(false);
 	else
@@ -362,7 +435,8 @@ void Entity::transformAndRender() {
 	}	
 	
 	if(enableScissor) {
-		renderer->enableScissor(false);
+		renderer->enableScissor(isScissorEnabled);
+		renderer->setScissorBox(oldScissorBox);
 	}
 }
 
@@ -406,6 +480,18 @@ Vector3 Entity::getScale() const {
 	return scale;
 }
 
+Matrix4 Entity::getConcatenatedMatrixRelativeTo(Entity *relativeEntity) {
+	checkTransformSetters();
+	
+	if(matrixDirty)
+		rebuildTransformMatrix();
+
+	if(parentEntity != NULL && parentEntity != relativeEntity) 
+		return transformMatrix * parentEntity->getConcatenatedMatrixRelativeTo(relativeEntity);
+	else
+		return transformMatrix;
+}
+
 Matrix4 Entity::getConcatenatedMatrix() {
 	checkTransformSetters();
 	if(matrixDirty)
@@ -456,6 +542,21 @@ void Entity::rebuildRotation() {
 	rotationQuat.fromAxes(_rotation.pitch, _rotation.yaw, _rotation.roll);
 }
 
+void Entity::setEntityProp(const String& propName, const String& propValue) {
+
+	for(int i=0; i < entityProps.size(); i++) {
+		if(entityProps[i].propName == propName) {
+			entityProps[i].propValue = propValue;
+			return;
+		}
+	}		
+
+	EntityProp entityProp;
+	entityProp.propName = propName;
+	entityProp.propValue = propValue;
+	entityProps.push_back(entityProp);
+}
+
 String Entity::getEntityProp(const String& propName) {
 	for(int i=0; i < entityProps.size(); i++) {
 		if(entityProps[i].propName == propName) {
@@ -492,21 +593,6 @@ void Entity::setTransformByMatrixPure(const Matrix4& matrix) {
 	transformMatrix = matrix;
 }
 
-void Entity::setTransformByMatrix(const Matrix4& matrix) {
-	setPosition(matrix.getPosition());	
-	Number x,y,z;
-	matrix.getEulerAngles(&x,&y,&z);
-
-	setPitch(x);
-	setYaw(y);
-	setRoll(z);
-	
-//	setYaw(-asin(matrix.m[0][2]) * TODEGREES);	
-///	setPitch(atan2(-matrix.m[0][1], matrix.m[0][0]) * TODEGREES);
-//	setRoll(atan2(-matrix.m[1][2], matrix.m[2][2]) * TODEGREES);
-	matrixDirty = true;
-}
-
 void Entity::setPosition(const Vector3 &posVec) {
 	position = posVec;
 	matrixDirty = true;
@@ -604,6 +690,33 @@ Number Entity::getCombinedRoll() const {
 	if(parentEntity != NULL)
 		return parentEntity->getCombinedRoll()+rotation.roll;
 	else
-		return rotation.roll;
-	
+		return rotation.roll;	
+}
+
+unsigned int Entity::getNumTags() const {
+	return tags.size();
+}
+
+String Entity::getTagAtIndex(unsigned int index) const {
+	if(index < tags.size())
+		return tags[index];
+	return "";
 }
+
+bool Entity::hasTag(String tag) const {
+
+	for(int i=0; i < tags.size(); i++) {
+		if(tags[i] == tag)
+			return true;
+	}
+	return false;
+}
+			
+void Entity::clearTags() {
+	tags.clear();
+}
+
+void Entity::addTag(String tag) {
+	tags.push_back(tag);
+}
+

+ 15 - 0
Core/Contents/Source/PolyFont.cpp

@@ -27,6 +27,9 @@
 using namespace Polycode;
 
 Font::Font(const String& fileName) {
+
+	this->fileName = fileName;
+
 	FT_Library FTLibrary;
 	FT_Init_FreeType(&FTLibrary);
 	
@@ -54,6 +57,18 @@ Font::Font(const String& fileName) {
 	}
 }
 
+String Font::getFontPath() {
+	return  fileName;
+}
+
+void Font::setFontName(String fontName) {
+	this->fontName = fontName;
+}
+
+String Font::getFontName() {
+	return fontName;
+}
+
 bool Font::isValid() const {
 	return valid;
 }

+ 36 - 0
Core/Contents/Source/PolyFontManager.cpp

@@ -37,18 +37,54 @@ FontManager::~FontManager() {
 	fonts.clear();
 }
 
+unsigned int FontManager::getNumFonts() const {
+	return fonts.size();
+}
+
+FontEntry *FontManager::getFontEntryByIndex(const unsigned int index) {
+	if(index < fonts.size()) {
+		return &fonts[index];
+	} else {
+		return NULL;
+	}
+}
+
+void FontManager::removeFontEntry(FontEntry *entry, bool deleteFont) {
+	for(int i=0; i < fonts.size(); i++) {
+		FontEntry *listEntry = &fonts[i];
+		if(listEntry == entry) {
+			if(deleteFont) {
+				delete listEntry->font;
+			}		
+			fonts.erase(fonts.begin()+i);
+			return;
+		}
+	}
+}
+
 void FontManager::registerFont(const String& fontName, const String& fontPath) {
 	Font *font = new Font(fontPath);
 	if(font->loaded) {
 		FontEntry newEntry;
 		newEntry.font = font;
 		newEntry.fontName = fontName;
+		font->setFontName(fontName);
 		fonts.push_back(newEntry);
 	} else {
 		delete font;
 	}
 }
 
+FontEntry *FontManager::getFontEntryByFontPath(const String &fontPath) {
+	for(int i=0; i < fonts.size(); i++) {
+		FontEntry *entry = &fonts[i];
+		if(entry->font->getFontPath() == fontPath) {
+			return entry;
+		}
+	}
+	return NULL;
+}
+
 Font *FontManager::getFontByName(const String& fontName) {
 	for(int i=0; i < fonts.size(); i++) {
 		FontEntry entry = fonts[i];

+ 20 - 5
Core/Contents/Source/PolyGLRenderer.cpp

@@ -362,9 +362,12 @@ void OpenGLRenderer::drawVertexBuffer(VertexBuffer *buffer, bool enableColorBuff
 					break;
 			}
 			break;
-		case Mesh::LINE_MESH:
+		case Mesh::LINE_STRIP_MESH:
 			mode = GL_LINE_STRIP;
 			break;	
+		case Mesh::LINE_MESH:
+			mode = GL_LINES;
+			break;				
 		case Mesh::POINT_MESH:
 			mode = GL_POINTS;
 			break;
@@ -387,10 +390,12 @@ void OpenGLRenderer::enableScissor(bool val) {
 	} else {
 		glDisable(GL_SCISSOR_TEST);	
 	}
+	Renderer::enableScissor(val);
 }
 
 void OpenGLRenderer::setScissorBox(Polycode::Rectangle box) {
 	glScissor(box.x, yRes-box.y-box.h, box.w, box.h);
+	Renderer::setScissorBox(box);
 }
 
 void OpenGLRenderer::enableFog(bool enable) {
@@ -489,7 +494,7 @@ void OpenGLRenderer::_setOrthoMode(Number orthoSizeX, Number orthoSizeY) {
 	glLoadIdentity();	
 }
 
-void OpenGLRenderer::setOrthoMode(Number xSize, Number ySize) {
+void OpenGLRenderer::setOrthoMode(Number xSize, Number ySize, bool centered) {
 	
 	if(xSize == 0)
 		xSize = xRes;
@@ -504,7 +509,12 @@ void OpenGLRenderer::setOrthoMode(Number xSize, Number ySize) {
 		glDisable(GL_CULL_FACE);
 		glPushMatrix();
 		glLoadIdentity();
-		glOrtho(0.0f,xSize,ySize,0,-1.0f,1.0f);
+		
+		if(centered) {
+			glOrtho(-xSize*0.5,xSize*0.5,ySize*0.5,-ySize*0.5,-1.0f,1.0f);		
+		} else {
+			glOrtho(0.0f,xSize,ySize,0,-1.0f,1.0f);
+		}
 		orthoMode = true;
 	}
 	glMatrixMode(GL_MODELVIEW);	
@@ -537,7 +547,9 @@ void OpenGLRenderer::setPerspectiveMode() {
 }
 
 void OpenGLRenderer::BeginRender() {
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	if(doClearBuffer) {
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	}
 	glLoadIdentity();
 	currentTexture = NULL;
 }
@@ -1001,9 +1013,12 @@ void OpenGLRenderer::drawArrays(int drawType) {
 					break;
 			}
 			break;
-		case Mesh::LINE_MESH:
+		case Mesh::LINE_STRIP_MESH:
 			mode = GL_LINE_STRIP;
 			break;	
+		case Mesh::LINE_MESH:
+			mode = GL_LINES;
+			break;				
 		case Mesh::POINT_MESH:
 			mode = GL_POINTS;
 		break;

+ 273 - 134
Core/Contents/Source/PolyLabel.cpp

@@ -21,11 +21,24 @@
 */
 
 #include "PolyLabel.h"
-#include "PolyFont.h"
-
+  
 using namespace Polycode;
 
-#define NORMAL_FT_FLAGS FT_LOAD_TARGET_LIGHT
+//#define NORMAL_FT_FLAGS FT_LOAD_TARGET_LIGHT
+//#define NORMAL_FT_FLAGS FT_LOAD_TARGET_LCD
+
+GlyphData::GlyphData() {
+	glyphs = NULL;
+	positions = NULL;
+	num_glyphs = 0;	
+	trailingAdvance = 0;
+}
+
+GlyphData::~GlyphData() {
+	delete glyphs;
+	delete positions;
+}
+
 
 ColorRange::ColorRange(Color color, unsigned int rangeStart, unsigned int rangeEnd) {
 	this->color = color;
@@ -36,13 +49,12 @@ ColorRange::ColorRange(Color color, unsigned int rangeStart, unsigned int rangeE
 
 Label::Label(Font *font, const String& text, int size, int antiAliasMode, bool premultiplyAlpha) : Image() {
 		setPixelType(Image::IMAGE_RGBA);
+		
 		this->font = font;
 		this->size = size;
 		this->premultiplyAlpha = premultiplyAlpha;
 		imageData = NULL;
 		this->antiAliasMode = antiAliasMode;
-		currentTextWidth = 0;
-		currentTextHeight = 0;
 		setText(text);
 }
 
@@ -50,79 +62,121 @@ Label::~Label() {
 
 }
 
-int Label::getTextWidth(Font *font, const String& text, int size) {
-	FT_Vector delta;
-	FT_UInt previous = 0;
-	FT_UInt glyph_index;
-	FT_GlyphSlot slot = font->getFace()->glyph;
-	FT_Set_Pixel_Sizes(font->getFace(), 0,  size);
-	int width = 0;
-	
-	String actualString = text; //StringUtil::replace(text, "\t", TAB_REPLACE);
-	
-	for(int i=0; i< actualString.length();i++)
-	{
-		if(actualString[i] == '\t') {
-			glyph_index = FT_Get_Char_Index( font->getFace(), ' ');			
-			FT_Load_Glyph( font->getFace(), glyph_index, NORMAL_FT_FLAGS );
-			for(int k=0 ; k < 4; k++) {
-					FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);		
-					width += slot->advance.x >> 6;				
-			}
-			
-		} else {
-			glyph_index = FT_Get_Char_Index( font->getFace(), actualString[i] );
-			if(previous && glyph_index) {
-				FT_Get_Kerning(font->getFace(), previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-				width += delta.x >> 6;
-			}
-			FT_Load_Glyph( font->getFace(), glyph_index, NORMAL_FT_FLAGS );
-			
-			FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
+unsigned int Label::getSize() const {
+	return size;
+}
 
-		width += slot->advance.x >> 6;
-		}
-	}
+void Label::setSize(int newSize) {
+	size = newSize;
+}
 
-	// +5 pixels safety zone :)
-	return width+5;
+int Label::getAntialiasMode() const {
+	return antiAliasMode;
 }
 
-int Label::getTextHeight(Font *font, const String& text, int size) {
-	
-	String actualString = text; //StringUtil::replace(text, "\t", TAB_REPLACE);
+void Label::setAntialiasMode(int newMode) {
+	antiAliasMode = newMode;
+}
+
+int Label::getTextWidthForString(const String& text) {
+	if(!font)
+		return 0;
+	if(!font->isValid())
+		return 0;
 	
-	int height = 0;
+	GlyphData data;
+	precacheGlyphs(text, &data);
+
+	FT_BBox bbox;
+	computeStringBbox(&data, &bbox);	
 	
-	FT_UInt glyph_index;
-	FT_GlyphSlot slot = font->getFace()->glyph;
-	FT_Set_Pixel_Sizes(font->getFace(), 0,  size);
+	return (bbox.xMax -  bbox.xMin);
+
+}
+
+int Label::getTextHeightForString(const String& text) {
+	if(!font)
+		return 0;
+	if(!font->isValid())
+		return 0;
+
+	GlyphData data;
+	precacheGlyphs(text, &data);
+
+	FT_BBox bbox;
+	computeStringBbox(&data, &bbox);	
 	
-	for(int i=0; i< actualString.length();i++)
-	{
-		glyph_index = FT_Get_Char_Index( font->getFace(), actualString[i] );
-		FT_Load_Glyph(font->getFace(), glyph_index, NORMAL_FT_FLAGS );
-		FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
-		
-		if(slot->bitmap_top > height)
-			height = slot->bitmap_top;
-	}
-		
-	return height;
+	return (bbox.yMax -  bbox.yMin);
+}
+
+void Label::computeStringBbox(GlyphData *glyphData, FT_BBox *abbox) {
+
+	FT_BBox  bbox;
+    /* initialize string bbox to "empty" values */
+    bbox.xMin = bbox.yMin =  32000;
+    bbox.xMax = bbox.yMax = -32000;
+
+    /* for each glyph image, compute its bounding box, */
+    /* translate it, and grow the string bbox          */
+    for (int n = 0; n < glyphData->num_glyphs; n++ )
+    {
+      FT_BBox  glyph_bbox;
+
+
+      FT_Glyph_Get_CBox( glyphData->glyphs[n], ft_glyph_bbox_pixels,
+                         &glyph_bbox );
+
+      glyph_bbox.xMin += glyphData->positions[n].x;
+      glyph_bbox.xMax += glyphData->positions[n].x;
+      glyph_bbox.yMin += glyphData->positions[n].y;
+      glyph_bbox.yMax += glyphData->positions[n].y;
+
+      if ( glyph_bbox.xMin < bbox.xMin )
+        bbox.xMin = glyph_bbox.xMin;
+
+      if ( glyph_bbox.yMin < bbox.yMin )
+        bbox.yMin = glyph_bbox.yMin;
+
+      if ( glyph_bbox.xMax > bbox.xMax )
+        bbox.xMax = glyph_bbox.xMax;
+
+      if ( glyph_bbox.yMax > bbox.yMax )
+        bbox.yMax = glyph_bbox.yMax;
+    }
+
+    /* check that we really grew the string bbox */
+    if ( bbox.xMin > bbox.xMax )
+    {
+      bbox.xMin = 0;
+      bbox.yMin = 0;
+      bbox.xMax = 0;
+      bbox.yMax = 0;
+    }
+
+	bbox.xMax += glyphData->trailingAdvance;
+
+    /* return string bbox */
+        *abbox = bbox;
 }
 
 Number Label::getTextWidth() const {
-	return currentTextWidth;
+	return width;
 }
 
 Number Label::getTextHeight() const {
-	return currentTextHeight;
+	return height;
 }
 
 Font *Label::getFont() const {
 	return font;
 }
 
+void Label::setFont(Font *newFont) {
+	if(!newFont)
+		return;
+	font = newFont;
+}
+
 const String& Label::getText() const {
 	return text;
 }
@@ -144,82 +198,108 @@ Color Label::getColorForIndex(unsigned int index) {
 	return Color(1.0,1.0,1.0,1.0);
 }
 
-void Label::setText(const String& text) {
-//	Logger::logw((char*)text.c_str());
-	
-	this->text = text;
-	
-	if(!font)
-		return;
-	
-	if(!font->isValid())
-		return;
-	
-	String actualString = text; //StringUtil::replace(text, "\t", TAB_REPLACE);
+void Label::precacheGlyphs(String text, GlyphData *glyphData) {
+	if(glyphData->glyphs)
+		free(glyphData->glyphs);
+	if(glyphData->positions)
+		free(glyphData->positions);
+		
+	int num_chars = text.length();
+		
+		
+	glyphData->glyphs = (FT_Glyph*) malloc(sizeof(FT_Glyph) * num_chars);
+	glyphData->positions = (FT_Vector*) malloc(sizeof(FT_Vector) * num_chars);
+	memset(glyphData->positions, 0, sizeof(FT_Vector) * num_chars);
 	
-	int textWidth = getTextWidth(font, actualString, size);
-	int textHeight = size+getTextHeight(font, actualString, size);
-	currentTextHeight = 0;
+	FT_Face face = font->getFace();
+	FT_GlyphSlot  slot = face->glyph;
+	FT_UInt       glyph_index;
+	FT_Bool       use_kerning;
+	FT_UInt       previous;
+
+	FT_Error error;
+
+	int pen_x = 0;
+	int pen_y = 0;
+
+	glyphData->num_glyphs  = 0;
+	use_kerning = FT_HAS_KERNING(font->getFace());
+	previous    = 0;
 	
-	createEmpty(textWidth,textHeight);
+	FT_Set_Pixel_Sizes(face, 0,  size);
 	
-	int penX = 0;
-	int xoff = 0;
-//	int x,y;
-	FT_Vector delta;
-	FT_UInt previous = 0;
-	FT_UInt glyph_index;
-	FT_GlyphSlot slot = font->getFace()->glyph;
-	FT_Set_Pixel_Sizes(font->getFace(), 0,  size);
-
-	// copy the freetype data into the texture
-	for(int i=0; i< actualString.length();i++)
-	{
-		if(actualString[i] == (wchar_t)'\t') {
-			glyph_index = FT_Get_Char_Index( font->getFace(), ' ');			
-			FT_Load_Glyph( font->getFace(), glyph_index, NORMAL_FT_FLAGS );
-			for(int k=0 ; k < 4; k++) {
-				FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);		
-				penX += slot->advance.x >> 6;
-				currentTextWidth = penX;
-				previous = glyph_index;				
-			}
-			
-		} else {	
-		glyph_index = FT_Get_Char_Index( font->getFace(), (FT_ULong)actualString[i]);
-		if(previous && glyph_index) {
-			FT_Get_Kerning(font->getFace(), previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-			penX += delta.x >> 6;
+	int advanceMultiplier;
+	for(int n = 0; n < num_chars; n++ ) {
+		if(text[n] == '\t') {
+			glyph_index = FT_Get_Char_Index(face, ' ');		
+			advanceMultiplier = 4;			
+		} else {
+			glyph_index = FT_Get_Char_Index(face, (FT_ULong)text[n]);		
+			advanceMultiplier = 1;
+		}
+
+		
+		if(use_kerning && previous && glyph_index) {
+			FT_Vector delta;
+			FT_Get_Kerning( face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
+			pen_x += delta.x >> 6;
 		}
-		FT_Load_Glyph(font->getFace(), glyph_index, NORMAL_FT_FLAGS);
+
+		glyphData->positions[glyphData->num_glyphs].x = pen_x;
+		glyphData->positions[glyphData->num_glyphs].y = pen_y;
+
 		switch(antiAliasMode) {
 			case ANTIALIAS_FULL:
-				FT_Render_Glyph(slot, FT_RENDER_MODE_LIGHT );			
+				error = FT_Load_Glyph( face, glyph_index, FT_LOAD_TARGET_LIGHT);			
 			break;
-			case ANTIALIAS_NONE:
-				FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
+			default:
+				error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT);			
 			break;
 		}
 		
-		Color glyphColor = getColorForIndex(i);
+		if (error) {
+			continue;
+		}
+		
+		error = FT_Get_Glyph( face->glyph, &glyphData->glyphs[glyphData->num_glyphs] );
+		if ( error ) {
+			continue;
+		}
+		
+		if(n == num_chars-1 && (text[n] == ' ' || text[n] == '\t')) {
+			glyphData->trailingAdvance = (slot->advance.x >> 6) * advanceMultiplier;
+		}
 
-		int lineoffset = ((size-slot->bitmap_top) * (textWidth*4));
-		xoff = ((penX + slot->bitmap_left)*4);
+		pen_x += (slot->advance.x >> 6) * advanceMultiplier;
+		previous = glyph_index;
+		glyphData->num_glyphs++;
 		
-		switch(antiAliasMode) {
-			case ANTIALIAS_FULL:
-				for(int j = 0; j < ((slot->bitmap.width * slot->bitmap.rows)); j++) {
-					if(!(j%slot->bitmap.width) && j !=0)
-						lineoffset += (textWidth*4)-(slot->bitmap.width * 4);
+	}
+}
+
+int Label::getBaselineAdjust() {
+	return baseLineAdjust;
+}
+
+void Label::drawGlyphBitmap(FT_Bitmap *bitmap, unsigned int x, unsigned int y, Color glyphColor) {
 
-						int newVal = imageData[xoff+lineoffset+3] + slot->bitmap.buffer[j];
+	int lineoffset = (height-y) * (width*4);
+	int xoff = (x*4);
+
+	switch(antiAliasMode) {
+			case ANTIALIAS_FULL:
+				for(int j = 0; j < ((bitmap->width * bitmap->rows)); j++) {
+					if(!(j % bitmap->width) && j !=0)
+						lineoffset -= ((width*4)+(bitmap->width * 4));
+						
+						int newVal = imageData[xoff+lineoffset+3] + bitmap->buffer[j];
 						if(newVal > 255)
 							newVal = 255;
-							
-						newVal = (int)(((Number)newVal) * glyphColor.a);
-						
+
+//						newVal = (int)(((Number)newVal) * glyphColor.a);
+
 						imageData[xoff+lineoffset+3] = newVal;
-													
+
 						if(premultiplyAlpha) {
 							imageData[xoff+lineoffset] = (int)((255.0 * glyphColor.r) * ((Number)imageData[xoff+lineoffset+3])/255.0);
 							imageData[xoff+lineoffset+1] =  (int)((255.0 * glyphColor.g) * ((Number)imageData[xoff+lineoffset+3])/255.0);
@@ -227,18 +307,17 @@ void Label::setText(const String& text) {
 						} else {
 							imageData[xoff+lineoffset] = (int)(255.0 * glyphColor.r);
 							imageData[xoff+lineoffset+1] =  (int)(255.0 * glyphColor.g);
-							imageData[xoff+lineoffset+2] =  (int)(255.0 * glyphColor.b);						
-						} 	
-							
+							imageData[xoff+lineoffset+2] =  (int)(255.0 * glyphColor.b);	
+						} 
 						xoff += 4;
 				}
 			break;
 			case ANTIALIAS_NONE:
-				unsigned char *src =  slot->bitmap.buffer;
-				for(int j=0; j <slot->bitmap.rows;j++) {
+				unsigned char *src = bitmap->buffer;
+				for(int j=0; j < bitmap->rows;j++) {
 					unsigned char b;
 					unsigned char *bptr =  src;
-					for(int k=0; k < slot->bitmap.width ; k++){					
+					for(int k=0; k < bitmap->width ; k++){					
 						if (k%8==0){ b = (*bptr++);}
 						imageData[xoff+lineoffset] = (int)(255.0 * glyphColor.r);
 						imageData[xoff+lineoffset+1] =  (int)(255.0 * glyphColor.g);
@@ -247,19 +326,79 @@ void Label::setText(const String& text) {
 						xoff += 4;
 						b <<= 1;
 					}
-					lineoffset += (textWidth*4)-(slot->bitmap.width * 4);
-					src += slot->bitmap.pitch;
-				}
+					lineoffset -= ((width*4)+(bitmap->width * 4));
+					src += bitmap->pitch;
+				}			
 			break;
 		}
+	
+}
+
+void Label::renderGlyphs(GlyphData *glyphData) {
+
+	bool useColorRanges = false;
+	if(colorRanges.size() > 0) {
+		useColorRanges = true;
+	}
+	
+	Color glyphColor = Color(1.0, 1.0, 1.0, 1.0);
+
+	int start_x = 0; //( ( my_target_width  - string_width  ) / 2 ) * 64;
+	int start_y = 0; //( ( my_target_height - string_height ) / 2 ) * 64;
+	
+	FT_Error error;
+	
+	for (int n = 0; n < glyphData->num_glyphs; n++ ) {
+		FT_Glyph   image;
+		FT_Vector  pen;
 		
-		if(slot->bitmap_top > currentTextHeight)
-			currentTextHeight = slot->bitmap_top;
-		
-		penX += slot->advance.x >> 6;
-		currentTextWidth = penX;
-		previous = glyph_index;
+		image = glyphData->glyphs[n];
+
+		pen.x = (start_x + glyphData->positions[n].x) * 64;
+		pen.y = (start_y + glyphData->positions[n].y) * 64;		
+
+		if(antiAliasMode == ANTIALIAS_FULL) {
+			error = FT_Glyph_To_Bitmap( &image, FT_RENDER_MODE_LIGHT, &pen, 0 );		
+		} else {
+			error = FT_Glyph_To_Bitmap( &image, FT_RENDER_MODE_MONO, &pen, 0 );				
+		}
+				
+		if(!error ) {
+			if(useColorRanges) {
+				glyphColor = getColorForIndex(n);
+			}
+			
+			FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;
+			drawGlyphBitmap(&bit->bitmap,
+					bit->left - xAdjustOffset,
+					height - bit->top + baseLineOffset, glyphColor);
+
+			FT_Done_Glyph( image );			
 		}
 	}
+}
+
+void Label::setText(const String& text) {
+
+	if(!font)
+		return;
+	if(!font->isValid())
+		return;
+
+	this->text = text;
 
+	precacheGlyphs(text, &labelData);
+
+	FT_BBox bbox;
+	computeStringBbox(&labelData, &bbox);	
+	
+	unsigned int textWidth = (bbox.xMax -  bbox.xMin)+1;
+	unsigned int textHeight = (bbox.yMax -  bbox.yMin)+1;
+	
+	baseLineOffset = bbox.yMin;
+	xAdjustOffset = bbox.xMin;
+	baseLineAdjust = bbox.yMax;
+	
+	createEmpty(textWidth,textHeight);	
+	renderGlyphs(&labelData);
 }

+ 255 - 0
Core/Contents/Source/PolyObject.cpp

@@ -23,6 +23,8 @@
 #include "PolyObject.h"
 #include "tinyxml.h"
 #include <sstream>
+#include <stdio.h>
+#include <string.h>
 
 using namespace Polycode;
 
@@ -293,3 +295,256 @@ void Object::createFromXMLElement(TiXmlElement *element, ObjectEntry *entry) {
 
 	entry->setTypedName(element->Value()); // Set name last because we might override type
 }
+
+
+bool Object::loadFromBinary(const String& fileName) {
+	BinaryObjectReader objectReader(fileName, this);	
+	bool success = objectReader.success;
+	return success;
+}
+
+BinaryObjectReader::BinaryObjectReader(const String& fileName, Object *object) {
+	this->object = object;
+	success = false;
+	inFile = OSBasics::open(fileName, "rb");
+	if(inFile) {
+		success = readFile();
+		OSBasics::close(inFile);
+	}
+}
+
+String BinaryObjectReader::getKeyByIndex(unsigned int index) {
+	if(index < keys.size()) {
+		return keys[index];
+	} else {
+		return "nil";
+	}
+}
+
+bool BinaryObjectReader::parseEntryFromFile(ObjectEntry *entry) {	
+	uint16_t keyIndex;
+	OSBasics::read(&keyIndex, sizeof(uint16_t), 1, inFile);	
+	entry->name = getKeyByIndex(keyIndex);
+	
+	uint8_t type;
+	OSBasics::read(&type, sizeof(uint8_t), 1, inFile);
+	entry->type = type;
+
+//	printf("Loading %s of type %u\n", entry->name.c_str(), entry->type);
+	
+	uint32_t data32;
+	switch(entry->type) {
+		case ObjectEntry::STRING_ENTRY:
+		{
+			OSBasics::read(&data32, sizeof(uint32_t), 1, inFile);
+			char *buffer = (char*) malloc(data32 + 1);
+			OSBasics::read(buffer, 1, data32, inFile);
+			buffer[data32] = '\0';
+			entry->stringVal = String(buffer);
+			free(buffer);			
+		}
+		break;
+		case ObjectEntry::FLOAT_ENTRY:
+		{
+			float val;
+			OSBasics::read(&val, sizeof(uint32_t), 1, inFile);
+			entry->intVal = val;
+			entry->NumberVal = val;			
+		}
+		break;
+		case ObjectEntry::INT_ENTRY:
+		{
+			int32_t intval;
+			OSBasics::read(&intval, sizeof(int32_t), 1, inFile);
+			entry->intVal = intval;
+			entry->NumberVal = intval;
+		}
+		break;
+		case ObjectEntry::BOOL_ENTRY:
+		{
+			OSBasics::read(&data32, sizeof(uint32_t), 1, inFile);		
+			if(data32 == 0) {
+				entry->boolVal = false;
+				entry->intVal = data32;
+				entry->NumberVal = data32;				
+			} else {
+				entry->boolVal = true;
+				entry->NumberVal = data32;
+			}
+		}
+		break;
+		default:
+			OSBasics::read(&data32, sizeof(uint32_t), 1, inFile);			
+		break;
+	}	
+
+	OSBasics::read(&data32, sizeof(uint32_t), 1, inFile);
+	
+	bool retVal = true;
+	
+//	if(data32 > 0){ 
+//		printf("Loading %u children\n", data32);
+//	}
+
+	for(int i=0; i < data32; i++) {
+		ObjectEntry *childEntry = entry->addChild("nil");
+		retVal = parseEntryFromFile(childEntry);
+	}	
+	
+	return retVal;
+}
+			
+bool BinaryObjectReader::readFile() {
+	char header[5];
+	OSBasics::read(header, 1, 4, inFile);
+	header[4] = '\0';
+//	printf("HEADER: [%s]\n", header);
+	if(String(header) != "PBOF") {
+		return false;
+	}
+	
+	uint32_t data32;
+	OSBasics::read(&data32, sizeof(uint32_t), 1, inFile);
+	
+	for(int i=0; i < data32; i++) {
+		uint16_t data16;
+		OSBasics::read(&data16, sizeof(uint16_t), 1, inFile);
+		char *buffer = (char*)malloc(data16+1);
+		OSBasics::read(buffer, 1, data16, inFile);
+		buffer[data16] = '\0';
+		keys.push_back(String(buffer));
+		free(buffer);
+	}
+	
+	OSBasics::read(&data32, sizeof(uint32_t), 1, inFile);	
+	
+	return parseEntryFromFile(&object->root);
+	
+}
+
+BinaryObjectReader::~BinaryObjectReader() {
+
+}
+
+
+void Object::saveToBinary(const String& fileName) {
+	BinaryObjectWriter objectWriter(this);
+	objectWriter.writeToFile(fileName);
+}
+
+BinaryObjectWriter::BinaryObjectWriter(Object *object) {
+	this->object = object;
+	parseKeysFromObjectEntry(&object->root);
+}
+
+unsigned int BinaryObjectWriter::addKey(const String &key) {
+	for(int i=0; i < keys.size(); i++) {
+		if(keys[i] == key)
+			return i;
+	}
+	keys.push_back(key);
+	return keys.size()-1;
+}
+
+unsigned int BinaryObjectWriter::getKeyIndex(const String &key) {
+	for(int i=0; i < keys.size(); i++) {
+		if(keys[i] == key)
+			return i;
+	}
+	return 0;
+}
+			
+void BinaryObjectWriter::parseKeysFromObjectEntry(ObjectEntry *entry) {
+	addKey(entry->name);
+	for(int i=0; i < entry->children.size(); i++) {
+		parseKeysFromObjectEntry(entry->children[i]);		
+	}
+}
+
+BinaryObjectWriter::~BinaryObjectWriter() {
+
+}
+
+void BinaryObjectWriter::writeEntryToFile(ObjectEntry *entry) {
+
+	uint16_t keyIndex = getKeyIndex(entry->name);
+	OSBasics::write(&keyIndex, sizeof(uint16_t), 1, outFile);
+
+	uint8_t type = (uint8_t)entry->type;
+	OSBasics::write(&type, sizeof(uint8_t), 1, outFile);
+	
+	uint32_t data32;
+	
+	switch(entry->type) {
+		case ObjectEntry::STRING_ENTRY:
+			data32 = entry->stringVal.length();
+			OSBasics::write(&data32, sizeof(uint32_t), 1, outFile);
+			OSBasics::write(entry->stringVal.c_str(), 1, data32, outFile);
+		break;
+		case ObjectEntry::FLOAT_ENTRY:
+		{
+			float val = (float)entry->NumberVal;
+			OSBasics::write(&val, sizeof(uint32_t), 1, outFile);		
+		}
+		break;
+		case ObjectEntry::INT_ENTRY:
+		{
+			int32_t intval = (int32_t)entry->intVal;
+			OSBasics::write(&intval, sizeof(int32_t), 1, outFile);		
+		}
+		break;
+		case ObjectEntry::BOOL_ENTRY:
+			if(entry->boolVal) {
+				data32 = 1;
+			} else {
+				data32 = 0;			
+			}
+			OSBasics::write(&data32, sizeof(uint32_t), 1, outFile);		
+		break;
+		default:
+			data32 = 0;
+			OSBasics::write(&data32, sizeof(uint32_t), 1, outFile);			
+		break;
+	}
+	
+	data32 = entry->children.size();
+	OSBasics::write(&data32, sizeof(uint32_t), 1, outFile);
+	
+	for(int i=0; i < entry->children.size(); i++) {
+		writeEntryToFile(entry->children[i]);
+	}	
+	
+	numEntriesWritten++;
+}
+			
+bool BinaryObjectWriter::writeToFile(const String& fileName) {
+	outFile = OSBasics::open(fileName, "wb");
+	
+	OSBasics::write("PBOF", 1, 4, outFile);
+
+	uint32_t data32 = keys.size();
+	OSBasics::write(&data32, sizeof(uint32_t), 1, outFile);
+
+	for(int i=0; i < keys.size(); i++) {
+		uint16_t data16 = keys[i].length();
+		OSBasics::write(&data16, sizeof(uint16_t), 1, outFile);
+		OSBasics::write(keys[i].c_str(), 1, data16, outFile);
+	}
+	
+	size_t offset = OSBasics::tell(outFile);
+
+	numEntriesWritten = 0;
+	
+	data32 = 0;
+	OSBasics::write(&data32, sizeof(uint32_t), 1, outFile);
+	
+	writeEntryToFile(&object->root);
+	
+	OSBasics::seek(outFile,  offset, SEEK_SET);
+	data32 = numEntriesWritten;
+	OSBasics::write(&data32, sizeof(uint32_t), 1, outFile);	
+	
+	OSBasics::close(outFile);
+}
+
+

+ 1 - 1
Core/Contents/Source/PolyParticle.cpp

@@ -103,7 +103,7 @@ void Particle::createSceneParticle(int particleType, Material *material, Mesh *p
 
 void Particle::createScreenParticle(int particleType, Texture *texture, Mesh *particleMesh) {
 	
-	ScreenShape *primitive = new ScreenShape(ScreenShape::SHAPE_RECT, 10.0f, 10.0f);
+	ScreenShape *primitive = new ScreenShape(ScreenShape::SHAPE_RECT, 1.0, 1.0f);
 	primitive->setTexture(texture);	
 //	primitive->billboardMode = true;
 //	primitive->billboardRoll = true;

+ 106 - 21
Core/Contents/Source/PolyParticleEmitter.cpp

@@ -30,16 +30,17 @@
 #include "PolyTimer.h"
 #include "PolyMaterialManager.h"
 #include "PolyResourceManager.h"
+#include "PolyScreenMesh.h"
+#include "PolyRenderer.h"
 
 using namespace Polycode;
 
-SceneParticleEmitter::SceneParticleEmitter(const String& materialName, Scene *particleParentScene, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh, SceneMesh *emitter)
+SceneParticleEmitter::SceneParticleEmitter(const String& materialName, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh, SceneMesh *emitter)
 : ParticleEmitter(materialName, particleMesh, particleType, emitterType, lifespan, numParticles,  direction, gravity, deviation, emitterRadius),
 SceneEntity()
 {
 	isScreenEmitter = false;
 	emitterMesh = emitter;	
-	this->particleParentScene = particleParentScene;	
 	createParticles();	
 }
 
@@ -50,7 +51,7 @@ SceneParticleEmitter::~SceneParticleEmitter() {
 void SceneParticleEmitter::respawnSceneParticles() {
 	for(int i=0; i < particles.size(); i++) {
 		Particle *particle = particles[i];
-		particleParentScene->removeEntity((SceneEntity*)particle->particleBody);
+		removeChild((SceneEntity*)particle->particleBody);
 		addParticleBody(particle->particleBody);
 		resetParticle(particle);				
 		particle->life = lifespan * ((Number)rand()/RAND_MAX);		
@@ -59,7 +60,8 @@ void SceneParticleEmitter::respawnSceneParticles() {
 }
 
 void SceneParticleEmitter::addParticleBody(Entity *particleBody) {
-	particleParentScene->addEntity((SceneEntity*)particleBody);	
+	addEntity((SceneEntity*)particleBody);	
+	particleBody->editorOnly = true;
 }
 
 void SceneParticleEmitter::dispatchTriggerCompleteEvent() {
@@ -76,20 +78,19 @@ void SceneParticleEmitter::Update() {
 }
 
 
-ScreenParticleEmitter::ScreenParticleEmitter(const String& imageFile, Screen *particleParentScreen, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh, ScreenMesh *emitter)
+ScreenParticleEmitter::ScreenParticleEmitter(const String& imageFile, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh, ScreenMesh *emitter)
 		: ParticleEmitter(imageFile, particleMesh, particleType, emitterType, lifespan, numParticles,  direction, gravity, deviation, emitterRadius),
 ScreenEntity()
 {
+	particleSize = 10.0; 
 	isScreenEmitter = true;
 	emitterMesh = emitter;	
-	this->particleParentScreen = particleParentScreen;	
 	createParticles();
 }
 
 ScreenParticleEmitter::~ScreenParticleEmitter(){ 
-	particleParentScreen->removeChild(this);
 	for(int i=0;i < particles.size(); i++) {
-		particleParentScreen->removeChild((ScreenEntity*)particles[i]->particleBody);
+		removeChild((ScreenEntity*)particles[i]->particleBody);
 		delete particles[i];
 	}
 }
@@ -99,7 +100,8 @@ void ScreenParticleEmitter::Update() {
 }
 
 void ScreenParticleEmitter::addParticleBody(Entity *particleBody) {
-	particleParentScreen->addChild((ScreenEntity*)particleBody);
+	addChild((ScreenEntity*)particleBody);
+	particleBody->editorOnly = true;	
 }
 
 void ScreenParticleEmitter::dispatchTriggerCompleteEvent() {
@@ -131,6 +133,26 @@ ParticleEmitter::ParticleEmitter(const String& imageFile, Mesh *particleMesh, in
 	isEmitterEnabled = true;
 	allAtOnce = false;
 	
+	blendingMode = Renderer::BLEND_MODE_NORMAL;
+	
+	particleSize = 1.0;
+	
+	scaleCurve.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
+	scaleCurve.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);	
+
+	colorCurveR.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
+	colorCurveR.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);	
+
+	colorCurveG.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
+	colorCurveG.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);	
+
+	colorCurveB.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
+	colorCurveB.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);	
+
+	colorCurveA.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
+	colorCurveA.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);	
+	
+	
 	this->particleType = particleType;
 	
 	this->numParticles = numParticles;
@@ -145,6 +167,17 @@ ParticleEmitter::ParticleEmitter(const String& imageFile, Mesh *particleMesh, in
 	useScaleCurves = false;	
 }
 
+Texture *ParticleEmitter::getParticleTexture() {
+	return particleTexture;
+}
+
+void ParticleEmitter::setParticleTexture(Texture *texture) {
+	particleTexture = texture;
+	for(int i=0; i < particles.size(); i++) {
+		((ScreenMesh*)particles[i]->particleBody)->setTexture(particleTexture);
+	}
+}
+			
 void ParticleEmitter::createParticles() {
 	
 	if(isScreenEmitter)
@@ -156,6 +189,7 @@ void ParticleEmitter::createParticles() {
 	Particle *particle;	
 	for(int i=0; i < numParticles; i++) {
 		particle = new Particle(particleType, isScreenEmitter, particleMaterial, particleTexture, pMesh);
+		particle->particleBody->ignoreParentMatrix = true;
 		particle->velVector = dirVector;
 		particle->dirVector = dirVector;
 		particle->deviation = deviation;
@@ -193,11 +227,16 @@ void ParticleEmitter::setParticleVisibility(bool val) {
 }
 
 void ParticleEmitter::setParticleBlendingMode(int mode) {
+	blendingMode = mode;
 	for(int i=0;i < particles.size(); i++) {
 		particles[i]->particleBody->setBlendingMode(mode);
 	}
 }
 
+int ParticleEmitter::getParticleBlendingMode() const {
+	return blendingMode;
+}
+
 void ParticleEmitter::setAlphaTest(bool val) {
 	for(int i=0;i < particles.size(); i++) {
 		particles[i]->particleBody->alphaTest = val;
@@ -237,6 +276,7 @@ void ParticleEmitter::setParticleCount(int count) {
 		Particle *particle;
 		for(int i=0; i  < oldSize; i++) {
 			particle = new Particle(particleType, isScreenEmitter, particleMaterial, particleTexture, pMesh);
+			particle->particleBody->ignoreParentMatrix = true;			
 			particle->velVector = dirVector;
 			particle->dirVector = dirVector;
 			particle->deviation = deviation;
@@ -253,7 +293,7 @@ void ParticleEmitter::setParticleCount(int count) {
 		else
 			particles[i]->particleBody->visible = false;
 	}
-
+	resetAll();
 }
 
 void ParticleEmitter::setPerlinModSize(Number size) {
@@ -286,6 +326,7 @@ void ParticleEmitter::resetParticle(Particle *particle) {
 //	particle->particleBody->visible = true;
 	particle->lifespan  = lifespan;
 	Matrix4 concatMatrix = getBaseMatrix();
+	
 	Vector3	startVector;
 	
 	particle->dirVector = dirVector;
@@ -296,6 +337,7 @@ void ParticleEmitter::resetParticle(Particle *particle) {
 //	} else {
 		startVector = Vector3(-(emitterRadius.x/2.0f)+emitterRadius.x*((Number)rand()/RAND_MAX),-(emitterRadius.y/2.0f)+emitterRadius.y*((Number)rand()/RAND_MAX),-(emitterRadius.z/2.0f)+emitterRadius.z*((Number)rand()/RAND_MAX));	
 //	}
+		
 	
 	particle->Reset(emitterType != TRIGGERED_EMITTER);	
 	particle->velVector = particle->dirVector;
@@ -308,15 +350,19 @@ void ParticleEmitter::resetParticle(Particle *particle) {
 	
 	particle->brightnessDeviation = 1.0f - ( (-brightnessDeviation) + ((brightnessDeviation*2) * ((Number)rand()/RAND_MAX)));
 	
-	particle->velVector = concatMatrix.rotateVector(particle->velVector);	
-	particle->particleBody->setTransformByMatrix(concatMatrix);
+//	particle->velVector = concatMatrix.rotateVector(particle->velVector);	
+	
+	particle->particleBody->setPosition(concatMatrix.getPosition());
+//	particle->particleBody->setPosition(0.0, 0.0, 0.0);
 	particle->particleBody->Translate(startVector);
 	particle->particleBody->rebuildTransformMatrix();	
 	
 	if(useScaleCurves) {
-		particle->particleBody->setScale(scaleCurve.getHeightAt(0),
-									 scaleCurve.getHeightAt(0),
-									 scaleCurve.getHeightAt(0));
+		particle->particleBody->setScale(scaleCurve.getHeightAt(0) * particleSize,
+									 scaleCurve.getHeightAt(0) * particleSize,
+									 scaleCurve.getHeightAt(0) * particleSize);
+	} else {
+		particle->particleBody->setScale(particleSize, particleSize, particleSize);
 	}
 	
 	if(useColorCurves) {
@@ -324,13 +370,22 @@ void ParticleEmitter::resetParticle(Particle *particle) {
 										   colorCurveG.getHeightAt(0),
 										   colorCurveB.getHeightAt(0),
 										   colorCurveA.getHeightAt(0));
+	} else {
+		particle->particleBody->color.setColor(1.0, 1.0, 1.0, 1.0);
 	}
 	
 			
 }
 
-void ParticleEmitter::setAllAtOnce(bool val) {
-	allAtOnce = val;
+Vector3 ScreenParticleEmitter::getParticleCompoundScale() {
+	return getCompoundScale();
+}
+
+Vector3 ParticleEmitter::getParticleCompoundScale() {
+	return Vector3();
+}
+			
+void ParticleEmitter::resetAll() {
 	for(int i=0;i < particles.size(); i++) {
 		if(allAtOnce)
 			particles[i]->life = 0;
@@ -339,6 +394,24 @@ void ParticleEmitter::setAllAtOnce(bool val) {
 	}
 }
 
+void ParticleEmitter::setAllAtOnce(bool val) {
+	allAtOnce = val;
+	resetAll();
+}
+
+unsigned int ParticleEmitter::getNumParticles() const {
+	return numParticles;
+}
+
+Particle *ParticleEmitter::getParticleAtIndex(unsigned int index) const {
+	if(index < particles.size()) {
+		return particles[index];
+	} else {
+		return NULL;
+	}
+}
+
+
 void ParticleEmitter::updateEmitter() {	
 	
 	Vector3 translationVector;
@@ -347,6 +420,8 @@ void ParticleEmitter::updateEmitter() {
 	Particle *particle;
 	Number normLife;
 	
+	Vector3 compoundScale = getParticleCompoundScale();
+	
 	for(int i=0;i < numParticles; i++) {	
 		particle = particles[i];
 		
@@ -371,7 +446,9 @@ void ParticleEmitter::updateEmitter() {
 		
 		if(rotationFollowsPath)  {
 			if(isScreenEmitter) {
-				particle->particleBody->lookAt(particle->particleBody->getPosition() + translationVector, Vector3(1,0,0));													
+				Number angle = atan2(translationVector.x, translationVector.y);
+				particle->particleBody->setRoll(360 - ((angle * TODEGREES)+180));
+			
 			} else {
 				particle->particleBody->lookAt(particle->particleBody->getPosition() + translationVector, Vector3(1,0,0));			
 			}
@@ -393,14 +470,22 @@ void ParticleEmitter::updateEmitter() {
 											   colorCurveG.getHeightAt(normLife)*particle->brightnessDeviation,
 											   colorCurveB.getHeightAt(normLife)*particle->brightnessDeviation,
 											   colorCurveA.getHeightAt(normLife)*particle->brightnessDeviation);
+		} else {
+			particle->particleBody->color.setColor(particle->brightnessDeviation,
+											   particle->brightnessDeviation,
+											   particle->brightnessDeviation,
+											   1.0);		
 		}
 	
 		if(useScaleCurves) {
-			particle->particleBody->setScale(scaleCurve.getHeightAt(normLife),
-										 scaleCurve.getHeightAt(normLife),
-										 scaleCurve.getHeightAt(normLife));
+			particle->particleBody->setScale(scaleCurve.getHeightAt(normLife) * particleSize * compoundScale.x,
+										 scaleCurve.getHeightAt(normLife) * particleSize * compoundScale.y,
+										 scaleCurve.getHeightAt(normLife) * particleSize * compoundScale.z);
 		
+		} else {
+			particle->particleBody->setScale(particleSize*compoundScale.x, particleSize*compoundScale.y, particleSize*compoundScale.z);
 		}
+		
 		if(particle->life > particle->lifespan && isEmitterEnabled) {
 			if(emitterType == CONTINUOUS_EMITTER) {
 				resetParticle(particle);

+ 19 - 0
Core/Contents/Source/PolyRenderer.cpp

@@ -46,7 +46,10 @@ Renderer::Renderer() : currentTexture(NULL), xRes(0), yRes(0), renderMode(0), or
 	fov = 45.0;
 	setAmbientColor(0.0,0.0,0.0);
 	cullingFrontFaces = false;
+	scissorEnabled = false;
 	
+	
+	doClearBuffer = true;
 }
 
 Renderer::~Renderer() {
@@ -287,6 +290,22 @@ void Renderer::setCameraPosition(Vector3 pos) {
 	this->translate3D(&pos);
 }
 
+void Renderer::enableScissor(bool val) {
+	scissorEnabled = val;
+}
+
+void Renderer::setScissorBox(Polycode::Rectangle box) {
+	scissorBox = box;
+}
+
+Polycode::Rectangle Renderer::getScissorBox() {
+	return scissorBox;
+}
+
+bool Renderer::isScissorEnabled() {
+	return scissorEnabled;
+}
+
 void Renderer::billboardMatrixWithScale(Vector3 scale) {
 	Matrix4 matrix = getModelviewMatrix();
 	matrix.m[0][0] = 1.0f*scale.x;

+ 0 - 4
Core/Contents/Source/PolySceneLabel.cpp

@@ -66,10 +66,6 @@ void SceneLabel::setText(const String& newText) {
 	bBox.z = 0;
 	
 	
-	for(int i=0; i < mesh->getPolygonCount(); i++) {
-		mesh->getPolygon(i)->flipUVY();
-	}
-	
 	if(useVertexBuffer)
 		CoreServices::getInstance()->getRenderer()->createVertexBufferForMesh(mesh);
 	

+ 28 - 157
Core/Contents/Source/PolyScreen.cpp

@@ -36,8 +36,6 @@
 using namespace Polycode;
 
 Screen::Screen() : EventDispatcher() {
-	offset.x = 0;
-	offset.y = 0;
 	enabled = true;
 	focusChild = NULL;
 	originalSceneTexture = NULL;
@@ -45,21 +43,16 @@ Screen::Screen() : EventDispatcher() {
 	filterShaderMaterial = NULL;
 	_hasFilterShader = false;
 	useNormalizedCoordinates = false;
-	rootEntity = new ScreenEntity();
-	addChild(rootEntity);
 	processTouchEventsAsMouse = false;
 	ownsChildren = false;
-	snapToPixelsByDefault = false;
+
+	rootEntity.processInputEvents = true;
+
+	rootEntity.setRenderer(renderer);
+	rootEntity.setDefaultScreenOptions(false);		
 }
 
 Screen::~Screen() {
-	if(ownsChildren) {
-		for(int i=0; i < children.size(); i++) {	
-			delete children[i];
-		}
-	} else {
-		delete rootEntity;
-	}
 	CoreServices::getInstance()->getScreenManager()->removeScreen(this);
 
 	for(int i=0; i < localShaderOptions.size(); i++) {
@@ -75,110 +68,43 @@ void Screen::setNormalizedCoordinates(bool newVal, Number yCoordinateSize) {
 
 void Screen::handleInputEvent(InputEvent *inputEvent) {
 	
-	for(int i=children.size()-1; i >= 0; i--) {
 		switch(inputEvent->getEventCode()) {
 		
 			case InputEvent::EVENT_TOUCHES_BEGAN:
 				if(processTouchEventsAsMouse) {
 					for(int j=0; j < inputEvent->touches.size(); j++) {
-						children[i]->_onMouseDown(inputEvent->touches[j].position.x-offset.x, inputEvent->touches[j].position.y-offset.y, CoreInput::MOUSE_BUTTON1, inputEvent->timestamp);
+						rootEntity._onMouseDown(inputEvent->touches[j].position.x, inputEvent->touches[j].position.y, CoreInput::MOUSE_BUTTON1, inputEvent->timestamp);
 					}
 				}
 			break;
 			case InputEvent::EVENT_MOUSEDOWN:
-				if(children[i]->_onMouseDown(inputEvent->mousePosition.x-offset.x, inputEvent->mousePosition.y-offset.y, inputEvent->mouseButton, inputEvent->timestamp) &&
-				children[i]->blockMouseInput)
-					return;
+				rootEntity._onMouseDown(inputEvent->mousePosition.x, inputEvent->mousePosition.y, inputEvent->mouseButton, inputEvent->timestamp);
 			break;
 			case InputEvent::EVENT_MOUSEMOVE:
-				children[i]->_onMouseMove(inputEvent->mousePosition.x-offset.x, inputEvent->mousePosition.y-offset.y, inputEvent->timestamp);
+				rootEntity._onMouseMove(inputEvent->mousePosition.x, inputEvent->mousePosition.y, inputEvent->timestamp);
 			break;
 			case InputEvent::EVENT_MOUSEUP:
-				if(children[i]->_onMouseUp(inputEvent->mousePosition.x-offset.x, inputEvent->mousePosition.y-offset.y, inputEvent->mouseButton, inputEvent->timestamp) &&
-				children[i]->blockMouseInput)
-					return;
+				rootEntity._onMouseUp(inputEvent->mousePosition.x, inputEvent->mousePosition.y, inputEvent->mouseButton, inputEvent->timestamp);
 			break;
 			case InputEvent::EVENT_MOUSEWHEEL_UP:
-				children[i]->_onMouseWheelUp(inputEvent->mousePosition.x-offset.x, inputEvent->mousePosition.y-offset.y, inputEvent->timestamp);
+				rootEntity._onMouseWheelUp(inputEvent->mousePosition.x, inputEvent->mousePosition.y, inputEvent->timestamp);
 			break;
 			case InputEvent::EVENT_MOUSEWHEEL_DOWN:
-				children[i]->_onMouseWheelDown(inputEvent->mousePosition.x-offset.x, inputEvent->mousePosition.y-offset.y,inputEvent->timestamp);				
+				rootEntity._onMouseWheelDown(inputEvent->mousePosition.x, inputEvent->mousePosition.y,inputEvent->timestamp);	
 			break;				
 			case InputEvent::EVENT_KEYDOWN:
-				children[i]->_onKeyDown(inputEvent->key, inputEvent->charCode);
+				rootEntity._onKeyDown(inputEvent->key, inputEvent->charCode);
 			break;
 			case InputEvent::EVENT_KEYUP:
-				children[i]->_onKeyUp(inputEvent->key, inputEvent->charCode);
+				rootEntity._onKeyUp(inputEvent->key, inputEvent->charCode);
 			break;			
 		}
-	}
 }
 
 void Screen::setRenderer(Renderer *renderer) {
 	this->renderer = renderer;
 }
 
-void Screen::setScreenOffset(Number x, Number y) {
-	offset.x = x;
-	offset.y = y;
-}
-
-Vector2 Screen::getScreenOffset() const {
-	return offset;
-}
-
-int Screen::getHighestZIndex() const {
-	int highestZ = 1;
-	for(int i=0; i<children.size();i++) {
-		if(children[i]->zindex > highestZ)
-			highestZ = children[i]->zindex;
-	}
-	return highestZ;
-}
-
-bool Screen::cmpZindex(const ScreenEntity *left, const ScreenEntity *right) {
-	return (left->zindex < right->zindex);
-}
-
-void Screen::sortChildren() {
-	std::sort(children.begin(), children.end(), Screen::cmpZindex);
-	int newz = 1;
-	for(int i=0; i<children.size();i++) {
-		children[i]->zindex = newz;
-		newz++;
-	}
-}
-
-void Screen::handleEvent(Event *event) {
-	if(event->getEventType() == "ScreenEvent") {
-	for(int i=0; i<children.size();i++) {
-		if(children[i] == event->getDispatcher()) {
-			ScreenEvent *screenEvent = (ScreenEvent*)event;
-			int highestZ;
-			switch(screenEvent->getEventCode()) {
-				case ScreenEvent::ENTITY_MOVE_TOP:
-					highestZ = getHighestZIndex();
-					children[i]->zindex = highestZ+1;
-					sortChildren();
-				break;
-				case ScreenEvent::ENTITY_MOVE_BOTTOM:
-					children[i]->zindex = 0;
-					sortChildren();
-				break;
-				case ScreenEvent::ENTITY_MOVE_UP:
-					children[i]->zindex++;
-					sortChildren();
-				break;
-				case ScreenEvent::ENTITY_MOVE_DOWN:
-					children[i]->zindex--;
-					sortChildren();
-				break;
-			}
-		}
-	}
-	}
-}
-
 void Screen::setScreenShader(const String& shaderName) {
 	filterShaderMaterial = (Material*)CoreServices::getInstance()->getResourceManager()->getResource(Resource::RESOURCE_MATERIAL, shaderName);
 	if(!filterShaderMaterial)
@@ -219,8 +145,6 @@ void Screen::drawFilter() {
 	CoreServices::getInstance()->getRenderer()->bindFrameBufferTexture(originalSceneTexture);
 	
 	Render();
-	//CoreServices::getInstance()->getRenderer()->renderToTexture(originalSceneTexture);	
-	
 	CoreServices::getInstance()->getRenderer()->unbindFramebuffers();
 	
 	ShaderBinding* materialBinding;		
@@ -229,76 +153,43 @@ void Screen::drawFilter() {
 		CoreServices::getInstance()->getRenderer()->applyMaterial(filterShaderMaterial, localShaderOptions[i], i);	
 			
 		if(i==filterShaderMaterial->getNumShaders()-1) {
-	//		CoreServices::getInstance()->getRenderer()->clearScreen();
 			CoreServices::getInstance()->getRenderer()->loadIdentity();
 			CoreServices::getInstance()->getRenderer()->drawScreenQuad(CoreServices::getInstance()->getRenderer()->getXRes(), CoreServices::getInstance()->getRenderer()->getYRes());		
 		} else {
 			for(int j=0; j < materialBinding->getNumOutTargetBindings(); j++) {
-				//				CoreServices::getInstance()->getRenderer()->clearScreen();
-				//				CoreServices::getInstance()->getRenderer()->loadIdentity();
 				CoreServices::getInstance()->getRenderer()->bindFrameBufferTexture(materialBinding->getOutTargetBinding(j)->texture);
-				//				Logger::log("drawing quad (%s) %f,%f\n", materialBinding->getOutTargetBinding(j)->texture->getResourceName().c_str(), materialBinding->getOutTargetBinding(j)->width, materialBinding->getOutTargetBinding(j)->height);		
 				
 				CoreServices::getInstance()->getRenderer()->drawScreenQuad(materialBinding->getOutTargetBinding(j)->width, materialBinding->getOutTargetBinding(j)->height);
 				CoreServices::getInstance()->getRenderer()->unbindFramebuffers();
-				
-				//				CoreServices::getInstance()->getRenderer()->renderToTexture(materialBinding->getOutTargetBinding(j)->texture);
 			}						
 		}
 		CoreServices::getInstance()->getRenderer()->clearShader();
 		CoreServices::getInstance()->getRenderer()->loadIdentity();
 		
 		CoreServices::getInstance()->getRenderer()->setOrthoMode();
-		/*
-		 CoreServices::getInstance()->getRenderer()->renderToTexture(filterTexture);
-		 CoreServices::getInstance()->getRenderer()->clearScreen();
-		 CoreServices::getInstance()->getRenderer()->loadIdentity();
-		 CoreServices::getInstance()->getRenderer()->drawScreenQuad();
-		 CoreServices::getInstance()->getRenderer()->clearShader();
-		 CoreServices::getInstance()->getRenderer()->loadIdentity();
-		 */
 	}
 	
 }
 
+void Screen::setScreenOffset(Number x, Number y) {
+	offset.x = x;
+	offset.y = y;	
+}
+
 bool Screen::hasFilterShader() const {
 	return _hasFilterShader;
 }
 
-ScreenEntity* Screen::addEntity(ScreenEntity *newEntity) {
-	if(!newEntity)
-		return NULL;
-	children.push_back(newEntity);
-	newEntity->setRenderer(renderer);
-	newEntity->addEventListener(this, ScreenEvent::ENTITY_MOVE_TOP);
-	newEntity->addEventListener(this, ScreenEvent::ENTITY_MOVE_BOTTOM);
-	newEntity->addEventListener(this, ScreenEvent::ENTITY_MOVE_DOWN);
-	newEntity->addEventListener(this, ScreenEvent::ENTITY_MOVE_UP);
-	newEntity->zindex = getHighestZIndex()+1;
-	newEntity->setDefaultScreenOptions(snapToPixelsByDefault);
-	
-	sortChildren();
-	return newEntity;
+void Screen::addEntity(ScreenEntity *newEntity) {
+	rootEntity.addChild(newEntity);
 }
 
-ScreenEntity* Screen::addChild(ScreenEntity *newEntity) {
-	return addEntity(newEntity);
+void Screen::addChild(ScreenEntity *newEntity) {
+	addEntity(newEntity);
 }
 
-ScreenEntity* Screen::removeChild(ScreenEntity *entityToRemove) {
-	if(!entityToRemove)
-		return NULL;
-	
-	entityToRemove->removeEventListener(this, ScreenEvent::ENTITY_MOVE_TOP);
-	entityToRemove->removeEventListener(this, ScreenEvent::ENTITY_MOVE_BOTTOM);
-	entityToRemove->removeEventListener(this, ScreenEvent::ENTITY_MOVE_DOWN);
-	entityToRemove->removeEventListener(this, ScreenEvent::ENTITY_MOVE_UP);
-	for(int i=0;i<children.size();i++) {
-		if(children[i] == entityToRemove) {
-			children.erase(children.begin()+i);
-		}
-	}
-	return entityToRemove;
+void Screen::removeChild(ScreenEntity *entityToRemove) {
+	rootEntity.removeChild(entityToRemove);
 }
 
 void Screen::Shutdown() {
@@ -309,32 +200,12 @@ void Screen::Update() {
 
 }
 
-ScreenEntity *Screen::getEntityAt(Number x, Number y) {
-	for(int i=children.size()-1; i >= 0;i--) {
-		if(children[i]->hitTest(x,y))
-			return children[i];
-	}
-	return NULL;
-}
-
 void Screen::Render() {
 	Update();
 	renderer->loadIdentity();
 	renderer->translate2D(offset.x, offset.y);
-	
-	renderer->multModelviewMatrix(rootEntity->getConcatenatedMatrix());
-	
-	for(int i=0; i<children.size();i++) {
-		if(children[i]->hasFocus && focusChild != children[i] && children[i]->isFocusable()) {
-			if(focusChild != NULL) {
-				focusChild->hasFocus = false;
-				focusChild->onLoseFocus();
-			}
-			focusChild = children[i];
-			focusChild->onGainFocus();			
-		}
-		children[i]->doUpdates();
-		children[i]->updateEntityMatrix();
-		children[i]->transformAndRender();
-	}
+
+	rootEntity.doUpdates();
+	rootEntity.updateEntityMatrix();
+	rootEntity.transformAndRender();	
 }

+ 147 - 98
Core/Contents/Source/PolyScreenEntity.cpp

@@ -27,6 +27,7 @@
 #include "PolyVertex.h"
 #include "PolyRenderer.h"
 #include "PolyCoreServices.h"
+#include "PolyLogger.h"
 
 inline double round(double x) { return floor(x + 0.5); }
 
@@ -45,7 +46,6 @@ ScreenEntity::ScreenEntity() : Entity(), EventDispatcher() {
 	dragOffsetX = 0;
 	dragOffsetY = 0;
 	parentEntity = NULL;
-	zindex = 0;
 	
 	depthWrite = false;
 	depthTest = false;
@@ -120,6 +120,48 @@ void ScreenEntity::focusChild(ScreenEntity *child) {
 	((ScreenEntity*)CoreServices::getInstance()->focusedChild)->onGainFocus();
 }
 
+void ScreenEntity::moveChildUp(ScreenEntity *child) {
+	for(int i=0; i < children.size(); i++) {
+		if(children[i] == child && i < children.size()-1) {
+			ScreenEntity *next = (ScreenEntity*)children[i+1];
+			children[i+1] = child;
+			children[i] = next;
+			break;
+		}
+	}
+}
+
+void ScreenEntity::moveChildDown(ScreenEntity *child) {
+	for(int i=0; i < children.size(); i++) {
+		if(children[i] == child && i > 0) {
+			ScreenEntity *prev = (ScreenEntity*)children[i-1];
+			children[i-1] = child;
+			children[i] = prev;
+			break;
+		}
+	}
+}
+
+void ScreenEntity::moveChildTop(ScreenEntity *child) {
+	for(int i=0; i < children.size(); i++) {
+		if(children[i] == child && i < children.size()-1) {
+			children.erase(children.begin()+i);
+			children.push_back(child);
+			break;
+		}
+	}
+}
+
+void ScreenEntity::moveChildBottom(ScreenEntity *child) {
+	for(int i=0; i < children.size(); i++) {
+		if(children[i] == child && i > 0) {
+			children.erase(children.begin()+i);
+			children.insert(children.begin(), child);
+			break;
+		}
+	}
+}
+
 bool ScreenEntity::isFocusable() const {
 	return focusable;
 }
@@ -205,6 +247,7 @@ bool isPointInsidePolygon2D(Polycode::Polygon *poly, const Vector2 &p) {
 		return true;
 }
 
+
 bool ScreenEntity::hitTest(const Number x, const Number y) {
 
 	Vector3 v;	
@@ -297,7 +340,7 @@ Matrix4 ScreenEntity::getScreenConcatenatedMatrix() {
 	}	
 }
 
-void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp, Vector2 parentAdjust) {
+MouseEventResult ScreenEntity::_onMouseMove(Number x, Number y, int timestamp, Vector2 parentAdjust) {
 
 	if(isDragged) {
 	
@@ -321,16 +364,12 @@ void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp, Vector2 paren
 		}
 	}
 	
-	
-	bool doTest = true;	
-	
-//	if(hasMask) {
-//		if(!((ScreenEntity*)maskEntity)->hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
-//			doTest = false;
-//		}	
-//	}
-	
-	if(doTest) {
+
+	MouseEventResult ret;
+	ret.hit = false;
+	ret.blocked = false;
+
+
 	if(processInputEvents && enabled) {
 	if(hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
 	
@@ -355,7 +394,12 @@ void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp, Vector2 paren
 				dispatchEvent(new InputEvent(Vector2(localCoordinate.x,localCoordinate.y)-parentAdjust, timestamp), InputEvent::EVENT_MOUSEOVER);
 				mouseOver = true;
 		}
-			
+		ret.hit = true;
+		if(blockMouseInput) {
+			ret.blocked = true;
+		}
+
+		
 	} else {
 		if(mouseOver) {
 		
@@ -376,29 +420,27 @@ void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp, Vector2 paren
 		for(int i=children.size()-1;i>=0;i--) {			
 			Vector2 adjust = parentAdjust;
 			if(positionMode == POSITION_TOPLEFT)
-			adjust += Vector2(width/2.0, height/2.0);
-			((ScreenEntity*)children[i])->_onMouseMove(x,y, timestamp, adjust);
-			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-				if(((ScreenEntity*)children[i])->hitTest(x+adjust.x,y+adjust.y))
-				   break;
-			}
+				adjust += Vector2(width/2.0, height/2.0);
+			
+			MouseEventResult childRes = ((ScreenEntity*)children[i])->_onMouseMove(x,y, timestamp, adjust);
+			if(childRes.hit)
+				ret.hit = true;
+			if(childRes.blocked)
+				ret.blocked = true;
+			if(childRes.blocked)
+				break;
 		}
 	}
-	}		
+	
+	return ret;
 }
 
-bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust) {
-	bool retVal = false;
-	
-	bool doTest = true;	
-	
-//	if(hasMask) {
-//		if(!((ScreenEntity*)maskEntity)->hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
-//			doTest = false;
-//		}	
-//	}
+MouseEventResult ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust) {
+	MouseEventResult ret;
+	ret.hit = false;
+	ret.blocked = false;
+
 	
-	if(doTest) {
 	if(processInputEvents && enabled) {
 	if(hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
 		Vector3 localCoordinate = Vector3(x+(parentAdjust.x*2.0),y+(parentAdjust.y*2.0),0);
@@ -416,7 +458,11 @@ bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp
 		inputEvent->mouseButton = mouseButton;
 		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP);
 		
-		retVal = true;
+		ret.hit = true;
+		if(blockMouseInput) {
+			ret.blocked = true;
+		}
+
 	} else {
 		Vector3 localCoordinate = Vector3(x+(parentAdjust.x*2.0),y+(parentAdjust.y*2.0),0);
 		
@@ -436,31 +482,27 @@ bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp
 		for(int i=children.size()-1;i>=0;i--) {			
 			Vector2 adjust = parentAdjust;
 			if(positionMode == POSITION_TOPLEFT)
-				adjust += Vector2(width/2.0, height/2.0);
-			((ScreenEntity*)children[i])->_onMouseUp(x,y, mouseButton, timestamp, adjust);;
-			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-				if(((ScreenEntity*)children[i])->hitTest(x+adjust.x,y+adjust.y))
-				   break;
-			}
+				adjust += Vector2(width/2.0, height/2.0);			
+			MouseEventResult childRes = ((ScreenEntity*)children[i])->_onMouseUp(x,y, mouseButton, timestamp, adjust);
+			if(childRes.hit)
+				ret.hit = true;
+			if(childRes.blocked)
+				ret.blocked = true;
+			if(childRes.blocked)
+				break;
+			
 		}
 	}
-	}		
 	
-	return retVal;
+	return ret;
 }
 
-void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp, Vector2 parentAdjust) {
-	bool retVal = false;
-	
-	bool doTest = true;	
-	
-//	if(hasMask) {
-//		if(!((ScreenEntity*)maskEntity)->hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
-//			doTest = false;
-//		}	
-//	}
+MouseEventResult ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp, Vector2 parentAdjust) {
+
+	MouseEventResult ret;
+	ret.hit = false;
+	ret.blocked = false;
 	
-	if(doTest) {
 	if(processInputEvents && enabled) {
 	if(hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
 		Vector3 localCoordinate = Vector3(x+(parentAdjust.x*2.0),y+(parentAdjust.y*2.0),0);
@@ -478,35 +520,34 @@ void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp, Vector2 pa
 		InputEvent *inputEvent = new InputEvent(Vector2(localCoordinate.x,localCoordinate.y)-parentAdjust, timestamp);		
 		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEWHEEL_UP);
 		
-		retVal = true;
+		ret.hit = true;
+		if(blockMouseInput) {
+			ret.blocked = true;
+		}
+
 	}
 
 		for(int i=children.size()-1;i>=0;i--) {			
 			Vector2 adjust = parentAdjust;
 			if(positionMode == POSITION_TOPLEFT)
-				adjust += Vector2(width/2.0, height/2.0);
-			((ScreenEntity*)children[i])->_onMouseWheelUp(x,y, timestamp, adjust);;
-			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-				if(((ScreenEntity*)children[i])->hitTest(x+adjust.x,y+adjust.y))
-				   break;
-			}
+				adjust += Vector2(width/2.0, height/2.0);		
+			MouseEventResult childRes = ((ScreenEntity*)children[i])->_onMouseWheelUp(x,y, timestamp, adjust);
+			if(childRes.hit)
+				ret.hit = true;
+			if(childRes.blocked)
+				ret.blocked = true;
+			if(childRes.blocked)
+				break;
 		}
 	}
-	}		
+	return ret;	
 }
 
-void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp, Vector2 parentAdjust) {
-	bool retVal = false;
+MouseEventResult ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp, Vector2 parentAdjust) {
+	MouseEventResult ret;
+	ret.hit = false;
+	ret.blocked = false;
 	
-	bool doTest = true;	
-	
-//	if(hasMask) {
-//		if(!((ScreenEntity*)maskEntity)->hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
-//			doTest = false;
-//		}	
-//	}
-	
-	if(doTest) {
 	if(processInputEvents && enabled) {
 	if(hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
 		Vector3 localCoordinate = Vector3(x+(parentAdjust.x*2.0),y+(parentAdjust.y*2.0),0);
@@ -524,37 +565,37 @@ void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp, Vector2
 		InputEvent *inputEvent = new InputEvent(Vector2(localCoordinate.x,localCoordinate.y)-parentAdjust, timestamp);		
 		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEWHEEL_DOWN);
 		
-		retVal = true;
+		ret.hit = true;
+		if(blockMouseInput) {
+			ret.blocked = true;
+		}
 	}
 
 		for(int i=children.size()-1;i>=0;i--) {			
 			Vector2 adjust = parentAdjust;
 			if(positionMode == POSITION_TOPLEFT)
 				adjust += Vector2(width/2.0, height/2.0);
-			((ScreenEntity*)children[i])->_onMouseWheelDown(x,y, timestamp, adjust);;
-			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-				if(((ScreenEntity*)children[i])->hitTest(x+adjust.x,y+adjust.y))
-				   break;
-			}
+			
+			MouseEventResult childRes = ((ScreenEntity*)children[i])->_onMouseWheelDown(x,y, timestamp, adjust);
+			if(childRes.hit)
+				ret.hit = true;
+			if(childRes.blocked)
+				ret.blocked = true;
+			if(childRes.blocked)
+				break;
+			
 		}
 	}
-	}		
 	
+	return ret;
 }
 
 
-bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust) {
-	bool retVal = false;
-	
-	bool doTest = true;	
-	
-//	if(hasMask) {
-//		if(!((ScreenEntity*)maskEntity)->hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
-//			doTest = false;
-//		}	
-//	}
-	
-	if(doTest) {
+MouseEventResult ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp, Vector2 parentAdjust) {
+	MouseEventResult ret;
+	ret.hit = false;
+	ret.blocked = false;
+			
 	if(processInputEvents && enabled) {
 	if(hitTest(x+parentAdjust.x,y+parentAdjust.y)) {
 		Vector3 localCoordinate = Vector3(x+(parentAdjust.x*2.0),y+(parentAdjust.y*2.0),0);
@@ -580,23 +621,27 @@ bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timesta
 			dispatchEvent(inputEvent, InputEvent::EVENT_DOUBLECLICK);
 		}
 		lastClickTicks = timestamp;		
-		retVal = true;
+		ret.hit = true;
+		if(blockMouseInput) {
+			ret.blocked = true;
+		}
 	}
 
 	for(int i=children.size()-1;i>=0;i--) {			
 			Vector2 adjust = parentAdjust;
 			if(positionMode == POSITION_TOPLEFT)
 				adjust += Vector2(width/2.0, height/2.0);
-			((ScreenEntity*)children[i])->_onMouseDown(x,y, mouseButton, timestamp, adjust);;
-			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
-				if(((ScreenEntity*)children[i])->hitTest(x+adjust.x,y+adjust.y))
-				   break;
-			}
+			MouseEventResult childRes = ((ScreenEntity*)children[i])->_onMouseDown(x,y, mouseButton, timestamp, adjust);
+			if(childRes.hit)
+				ret.hit = true;
+			if(childRes.blocked)
+				ret.blocked = true;
+			if(childRes.blocked)
+				break;
 		}
-	}
 	}		
 	
-	return retVal;
+	return ret;
 }
 
 Vector2 ScreenEntity::getScreenPosition() const {
@@ -617,6 +662,10 @@ Vector2 ScreenEntity::getPosition2D() const {
 	return Vector2(position.x, position.y);
 }
 
+Vector2 ScreenEntity::getScale2D() const {
+	return Vector2(scale.x, scale.y);
+}
+
 Matrix4 ScreenEntity::buildPositionMatrix() {
 
 	Matrix4 posMatrix;
@@ -651,4 +700,4 @@ void ScreenEntity::adjustMatrixForChildren() {
 			renderer->translate2D(-width/2.0f, -height/2.0f);	
 		}
 	}
-}
+}

+ 300 - 0
Core/Contents/Source/PolyScreenEntityInstance.cpp

@@ -0,0 +1,300 @@
+/*
+ Copyright (C) 2011 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "PolyScreenEntityInstance.h"
+#include "PolyLogger.h"
+
+using namespace Polycode;
+
+ScreenEntityInstance::ScreenEntityInstance(const String& fileName) : ScreenEntity() {
+	rootEntity = NULL;
+	setPositionMode(ScreenEntity::POSITION_CENTER);
+	loadFromFile(fileName);
+}
+
+ScreenEntityInstance::~ScreenEntityInstance() {
+
+}
+
+void ScreenEntityInstance::applyScreenShape(ObjectEntry *entry, ScreenShape *shape) {
+	if(!entry) 
+		return;
+		
+	Number swidth = (*entry)["width"]->NumberVal;
+	Number sheight = (*entry)["height"]->NumberVal;
+	int type = (*entry)["type"]->intVal;
+	
+	shape->setShapeType(type);
+	shape->setShapeSize(swidth, sheight);
+
+	Number strokeColorR = (*entry)["strokeColorR"]->NumberVal;
+	Number strokeColorG = (*entry)["strokeColorG"]->NumberVal;
+	Number strokeColorB = (*entry)["strokeColorB"]->NumberVal;
+	Number strokeColorA = (*entry)["strokeColorA"]->NumberVal;
+
+	bool strokeEnabled = (*entry)["strokeEnabled"]->boolVal;					
+	Number strokeWidth = (*entry)["strokeWidth"]->NumberVal;
+	
+	shape->strokeEnabled = strokeEnabled;
+	shape->strokeWidth = strokeWidth;
+	shape->strokeColor = Color(strokeColorR, strokeColorG, strokeColorB, strokeColorA);
+	
+	
+}
+
+void ScreenEntityInstance::parseObjectIntoCurve(ObjectEntry *entry, BezierCurve *curve) {
+	curve->clearControlPoints();
+	ObjectEntry *controlPoints =(*entry)["controlPoints"];
+	if(controlPoints) {
+		for(int i=0; i < controlPoints->length; i++) {		
+			ObjectEntry *controlPoint = ((*controlPoints))[i];		
+			if(controlPoint) {
+				Vector2 vpt1;
+				Vector2 vpt2;
+				Vector2 vpt3;
+												
+				ObjectEntry *pt1 = ((*controlPoint))["pt1"];
+				if(pt1) {
+					vpt1.x = ((*pt1))["x"]->NumberVal;
+					vpt1.y = ((*pt1))["y"]->NumberVal;					
+				}
+
+				ObjectEntry *pt2 = ((*controlPoint))["pt2"];
+				if(pt2) {
+					vpt2.x = ((*pt2))["x"]->NumberVal;
+					vpt2.y = ((*pt2))["y"]->NumberVal;					
+				}
+
+				ObjectEntry *pt3 = ((*controlPoint))["pt3"];
+				if(pt3) {
+					vpt3.x = ((*pt3))["x"]->NumberVal;
+					vpt3.y = ((*pt3))["y"]->NumberVal;					
+				}
+
+				curve->addControlPoint(vpt1.x, vpt1.y, 0.0, vpt2.x, vpt2.y, 0.0, vpt3.x, vpt3.y, 0.0);
+			}
+		}
+	}
+	
+}
+
+ScreenEntity *ScreenEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry) {
+
+	ScreenEntity *entity = NULL;
+	
+	ObjectEntry *entityType = (*entry)["type"];
+	if(entityType) {
+	
+		if(entityType->stringVal == "ScreenImage") {
+			ObjectEntry *screenImageEntry = (*entry)["ScreenImage"];			
+			String imagePath = (*screenImageEntry)["filePath"]->stringVal;
+			ScreenImage *image = new ScreenImage(imagePath);
+			
+			ObjectEntry *screenShapeEntry = (*entry)["ScreenShape"];
+			applyScreenShape(screenShapeEntry, image);
+			entity = image;
+		}
+		
+		if(entityType->stringVal == "ScreenParticleEmitter") {
+			ObjectEntry *emitterEntry = (*entry)["ScreenParticleEmitter"];
+									
+			ScreenParticleEmitter *placingEmitter = new ScreenParticleEmitter((*emitterEntry)["texturePath"]->stringVal, Particle::BILLBOARD_PARTICLE, ParticleEmitter::CONTINUOUS_EMITTER, (*emitterEntry)["lifespan"]->NumberVal, (*emitterEntry)["particleCount"]->NumberVal, Vector3((*emitterEntry)["dirX"]->NumberVal, (*emitterEntry)["dirY"]->NumberVal, 0.0), Vector3((*emitterEntry)["gravX"]->NumberVal, (*emitterEntry)["gravY"]->NumberVal, 0.0), Vector3((*emitterEntry)["deviationX"]->NumberVal, (*emitterEntry)["deviationY"]->NumberVal, 0.0), Vector3((*emitterEntry)["radiusX"]->NumberVal, (*emitterEntry)["radiusY"]->NumberVal, 0.0));
+			
+				placingEmitter->brightnessDeviation = (*emitterEntry)["brightnessDeviation"]->NumberVal;
+				placingEmitter->particleSize = (*emitterEntry)["particleSize"]->NumberVal;
+				placingEmitter->perlinModSize = (*emitterEntry)["perlinModSize"]->NumberVal;
+				placingEmitter->perlinEnabled = (*emitterEntry)["perlinEnabled"]->boolVal;
+				placingEmitter->particleSpeedMod = (*emitterEntry)["particleSpeedMod"]->NumberVal;
+
+				placingEmitter->rotationSpeed = (*emitterEntry)["rotationSpeed"]->NumberVal;
+				placingEmitter->rotationFollowsPath = (*emitterEntry)["rotationFollowsPath"]->boolVal;
+				placingEmitter->useScaleCurves = (*emitterEntry)["useScaleCurves"]->boolVal;
+				placingEmitter->useColorCurves = (*emitterEntry)["useColorCurves"]->boolVal;
+									
+				placingEmitter->setParticleBlendingMode((*emitterEntry)["particleBlendMode"]->intVal);			
+				
+				placingEmitter->setWidth(placingEmitter->emitterRadius.x);
+				placingEmitter->setHeight(placingEmitter->emitterRadius.y);	
+				
+				parseObjectIntoCurve((*emitterEntry)["scaleCurve"], &placingEmitter->scaleCurve);
+				parseObjectIntoCurve((*emitterEntry)["colorCurveR"], &placingEmitter->colorCurveR);
+				parseObjectIntoCurve((*emitterEntry)["colorCurveG"], &placingEmitter->colorCurveG);
+				parseObjectIntoCurve((*emitterEntry)["colorCurveB"], &placingEmitter->colorCurveB);
+				parseObjectIntoCurve((*emitterEntry)["colorCurveA"], &placingEmitter->colorCurveA);										
+			
+			entity = placingEmitter;
+		
+		}		
+
+		if(entityType->stringVal == "ScreenSprite") {
+			ObjectEntry *screenSpriteEntry = (*entry)["ScreenSprite"];			
+			String filePath = (*screenSpriteEntry)["filePath"]->stringVal;
+			
+			ScreenSprite *sprite = new ScreenSprite(filePath);
+			
+			String animName = (*screenSpriteEntry)["anim"]->stringVal;
+			sprite->playAnimation(animName, -1, false);
+		
+
+			ObjectEntry *screenShapeEntry = (*entry)["ScreenShape"];
+			applyScreenShape(screenShapeEntry, sprite);
+			entity = sprite;
+		}
+
+
+		if(entityType->stringVal == "ScreenEntityInstance") {
+			ObjectEntry *screenInstanceEntry = (*entry)["ScreenEntityInstance"];
+			String filePath = (*screenInstanceEntry)["filePath"]->stringVal;
+			ScreenEntityInstance *instance = new ScreenEntityInstance(filePath);			
+			entity = instance;
+		}
+		
+
+		if(entityType->stringVal == "ScreenShape") {
+			ObjectEntry *screenShapeEntry = (*entry)["ScreenShape"];
+			ScreenShape *shape = new ScreenShape(0, 1, 1);
+			applyScreenShape(screenShapeEntry, shape);
+			entity = shape;
+		}
+		
+		if(entityType->stringVal == "ScreenSound") {
+			ObjectEntry *screenSoundEntry = (*entry)["ScreenSound"];
+			
+			String filePath = (*screenSoundEntry)["filePath"]->stringVal;
+			Number refDistance = (*screenSoundEntry)["refDistance"]->NumberVal;
+			Number maxDistance = (*screenSoundEntry)["maxDistance"]->NumberVal;
+			Number volume = (*screenSoundEntry)["volume"]->NumberVal;
+			Number pitch = (*screenSoundEntry)["pitch"]->NumberVal;
+															
+			ScreenSound *sound = new ScreenSound(filePath, refDistance, maxDistance);
+			sound->getSound()->setVolume(volume);
+			sound->getSound()->setPitch(pitch);	
+			
+			sound->setWidth(50);
+			sound->setHeight(50);				
+										
+			entity = sound;
+		}		
+		
+
+		if(entityType->stringVal == "ScreenLabel") {
+			ObjectEntry *screenLabelEntry = (*entry)["ScreenLabel"];
+			
+			String text = (*screenLabelEntry)["text"]->stringVal;
+			String font = (*screenLabelEntry)["font"]->stringVal;
+			int size = (*screenLabelEntry)["size"]->intVal;
+			int aaMode = (*screenLabelEntry)["aaMode"]->intVal;
+												
+			ScreenLabel *label = new ScreenLabel(text, size, font, aaMode);
+			label->positionAtBaseline = false;
+			
+			ObjectEntry *screenShapeEntry = (*entry)["ScreenShape"];			
+			applyScreenShape(screenShapeEntry, label);
+			entity = label;
+		}
+	
+	} 
+
+	if(!entity) {
+		entity = new ScreenEntity();
+	}
+	
+	entity->ownsChildren = true;
+	
+	entity->setPositionMode(ScreenEntity::POSITION_CENTER);
+	
+	entity->color.r = (*entry)["colorR"]->NumberVal;
+	entity->color.g = (*entry)["colorG"]->NumberVal;
+	entity->color.b = (*entry)["colorB"]->NumberVal;
+	entity->color.a = (*entry)["colorA"]->NumberVal;
+
+	entity->blendingMode = (*entry)["blendMode"]->intVal;
+
+	entity->scale.x = (*entry)["scaleX"]->NumberVal;
+	entity->scale.y = (*entry)["scaleY"]->NumberVal;
+
+	entity->position.x = (*entry)["posX"]->NumberVal;
+	entity->position.y = (*entry)["posY"]->NumberVal;
+
+	entity->setRotation((*entry)["rotation"]->NumberVal);
+	
+	entity->id = (*entry)["id"]->stringVal;
+	
+	String tagString = (*entry)["tags"]->stringVal; 
+	
+	if(tagString != "") {
+		std::vector<String> tags = tagString.split(",");
+		for(int i=0; i < tags.size(); i++) {
+			entity->addTag(tags[i]);
+		}
+	}
+	
+	ObjectEntry *props = (*entry)["props"];
+	if(props) {
+		for(int i=0; i < props->length; i++) {		
+			ObjectEntry *prop = ((*props))[i];		
+			if(prop) {
+				entity->setEntityProp((*prop)["name"]->stringVal, (*prop)["value"]->stringVal);
+			}
+		}
+	}
+														
+	ObjectEntry *children = (*entry)["children"];
+	
+	if(children) {
+		for(int i=0; i < children->length; i++) {
+			ObjectEntry *childEntry = ((*children))[i];
+			ScreenEntity *childEntity = loadObjectEntryIntoEntity(childEntry);
+			entity->addChild(childEntity);				
+		}
+	}
+		
+	return entity;
+}
+
+ScreenEntity *ScreenEntityInstance::getRootEntity() {
+	return rootEntity;
+}
+
+String ScreenEntityInstance::getFileName() const {
+	return fileName;
+}
+
+bool ScreenEntityInstance::loadFromFile(const String& fileName) {
+
+	if(rootEntity) {
+		removeChild(rootEntity);
+		delete rootEntity;		
+	}
+
+	this->fileName = fileName;
+	Object loadObject;
+	if(!loadObject.loadFromBinary(fileName)) {
+		Logger::log("Error loading entity instance.\n");
+	}	
+	ObjectEntry *root = loadObject.root["root"];
+	
+	if(root) {
+		rootEntity = loadObjectEntryIntoEntity(root);				
+		addChild(rootEntity);		
+	}
+}

+ 19 - 6
Core/Contents/Source/PolyScreenLabel.cpp

@@ -29,6 +29,7 @@
 #include "PolyMesh.h"
 #include "PolyPolygon.h"
 #include "PolyScreenImage.h"
+#include "PolyRenderer.h"
 
 using namespace Polycode;
 
@@ -36,11 +37,11 @@ ScreenLabel::ScreenLabel(const String& text, int size, const String& fontName, i
 	label = new Label(CoreServices::getInstance()->getFontManager()->getFontByName(fontName), text, size, amode, premultiplyAlpha);
 	dropShadowImage = NULL;
 	texture = NULL;
-	setText(text);		
-	mesh->getPolygon(0)->flipUVY();	
+	updateTexture();
 	positionMode = POSITION_TOPLEFT;	
 	dropShadowImage = NULL;
 	colorAffectsChildren = false;
+	positionAtBaseline = true;
 }
 
 ScreenLabel::~ScreenLabel() {
@@ -69,8 +70,7 @@ const String& ScreenLabel::getText() const {
 	return label->getText();
 }	
 
-void ScreenLabel::setText(const String& newText) {
-	label->setText(newText);
+void ScreenLabel::updateTexture() {
 	
 	if(texture) {
 		CoreServices::getInstance()->getMaterialManager()->deleteTexture(texture);
@@ -83,7 +83,20 @@ void ScreenLabel::setText(const String& newText) {
 		return;				
 	
 	texture = CoreServices::getInstance()->getMaterialManager()->createTextureFromImage(label, true, false);
-	width = label->getWidth();
-	height = label->getHeight();
+	setWidth(label->getWidth());
+	setHeight(label->getHeight());
 	setShapeSize(width, height);
+
+}
+
+void ScreenLabel::Render() {
+	if(positionAtBaseline) {
+		CoreServices::getInstance()->getRenderer()->translate2D(0.0, -label->getBaselineAdjust() + label->getSize());
+	}
+	ScreenShape::Render();
+}
+
+void ScreenLabel::setText(const String& newText) {
+	label->setText(newText);	
+	updateTexture();
 }

+ 24 - 7
Core/Contents/Source/PolyScreenLine.cpp

@@ -28,14 +28,14 @@
 
 using namespace Polycode;
 
-ScreenLine::ScreenLine(Vector2* start, Vector2* end) : ScreenMesh(Mesh::LINE_MESH) {
+ScreenLine::ScreenLine(Vector2 start, Vector2 end) : ScreenMesh(Mesh::LINE_MESH) {
 	target1 = NULL;
 	initMesh();
 		
-	startVertex->x = start->x;
-	startVertex->y = start->y;
-	endVertex->x = end->x;
-	endVertex->y = end->y;
+	startVertex->x = start.x;
+	startVertex->y = start.y;
+	endVertex->x = end.x;
+	endVertex->y = end.y;
 	lineWidth = 1.0f;
 	mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;	
 }
@@ -53,6 +53,18 @@ ScreenLine::ScreenLine(ScreenEntity* target1, ScreenEntity* target2) : ScreenMes
 
 }
 
+void ScreenLine::setStart(Vector2 point) {
+	startVertex->x = point.x;
+	startVertex->y = point.y;
+	mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;
+}
+
+void ScreenLine::setEnd(Vector2 point) {
+	endVertex->x = point.x;
+	endVertex->y = point.y;
+	mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;	
+}
+
 void ScreenLine::initMesh() {
 	Polygon *poly = new Polygon();
 	startVertex = poly->addVertex(0, 0, 0, 0,0);
@@ -82,14 +94,17 @@ void ScreenLine::Update() {
 	endVertex->x = pos2.x-pos1.x;
 	endVertex->y = pos2.y-pos1.y;
 
-	mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;			
-	
+	mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;				
 }
 
 
 void ScreenLine::Render() {
 	Renderer *renderer = CoreServices::getInstance()->getRenderer();
 	renderer->setLineSize(lineWidth);
+	if(lineSmooth) {
+		renderer->setLineSmooth(true);
+	}
+	
 	renderer->setTexture(texture);
 	if(mesh->useVertexColors) {
 		renderer->pushDataArrayForMesh(mesh, RenderDataArray::COLOR_DATA_ARRAY);
@@ -97,4 +112,6 @@ void ScreenLine::Render() {
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::VERTEX_DATA_ARRAY);
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::TEXCOORD_DATA_ARRAY);	
 	renderer->drawArrays(mesh->getMeshType());
+	
+	renderer->setLineSmooth(false);	
 }

+ 2 - 2
Core/Contents/Source/PolyScreenManager.cpp

@@ -82,11 +82,11 @@ void ScreenManager::Update() {
 	for(int i=0;i<screens.size();i++) {
 		if(screens[i]->enabled) {
 			if(!screens[i]->usesNormalizedCoordinates()) {
-				renderer->setOrthoMode(renderer->getXRes(), renderer->getYRes());
+				renderer->setOrthoMode(renderer->getXRes(), renderer->getYRes(), false);
 			} else {
 				Number yCoordinateSize = screens[i]->getYCoordinateSize();
 				Number ratio = ((Number)renderer->getXRes())/((Number)renderer->getYRes());
-				renderer->setOrthoMode(ratio*yCoordinateSize, yCoordinateSize);								
+				renderer->setOrthoMode(ratio*yCoordinateSize, yCoordinateSize, true);				
 			}
 		
 			if(screens[i]->hasFilterShader()) {

+ 72 - 28
Core/Contents/Source/PolyScreenShape.cpp

@@ -28,8 +28,8 @@
 
 using namespace Polycode;
 
+
 ScreenShape::ScreenShape(int shapeType, Number option1, Number option2, Number option3, Number option4) : ScreenMesh(Mesh::QUAD_MESH) {
-	Number DEG2RAD = 3.14159/180;
 	strokeWidth = 1.0f;
 	this->shapeType = shapeType;
 	width = option1;
@@ -43,14 +43,56 @@ ScreenShape::ScreenShape(int shapeType, Number option1, Number option2, Number o
 	this->option4 = option4;
 	lineSmooth = false;
 		
+	buildShapeMesh();
+	
+	positionMode = POSITION_CENTER;
+	strokeEnabled = false;
+}
+
+void ScreenShape::operator=(const ScreenShape& copy) {
+	strokeWidth = copy.strokeWidth;
+	shapeType = copy.getShapeType();
+	
+	width = copy.getWidth();
+	height = copy.getHeight();
+	
+	setHitbox(width, height);
+
+	this->option3 = copy.option3;
+	this->option4 = copy.option4;
+	lineSmooth = copy.lineSmooth;
+		
+	buildShapeMesh();
+	
+	strokeColor = copy.strokeColor;
+	
+	positionMode = POSITION_CENTER;
+	strokeEnabled = copy.strokeEnabled;	
+
+}
+
+void ScreenShape::buildShapeMesh() {
+
+	mesh->clearMesh();
+	
 	switch(shapeType) {
 		case SHAPE_RECT: {
 			mesh->setMeshType(Mesh::QUAD_MESH);
+			
+			Number whalf = width/2.0f;
+			Number hhalf = height/2.0f;
+			
+			if(snapToPixels) {
+				whalf = floor(whalf);
+				hhalf = floor(hhalf);				
+			}
+		
 			Polygon *poly = new Polygon();
-			poly->addVertex(-width/2.0f,-height/2.0f,0,0,1);
-			poly->addVertex(width/2.0f,-height/2.0f,0, 1, 1);
-			poly->addVertex(width/2.0f,height/2.0f,0, 1, 0);
-			poly->addVertex(-width/2.0f,height/2.0f,0,0,0);
+			
+			poly->addVertex(-whalf,-hhalf,0,0,1);
+			poly->addVertex(-whalf+width,-hhalf,0, 1, 1);
+			poly->addVertex(-whalf+width,-hhalf+height,0, 1, 0);
+			poly->addVertex(-whalf,-hhalf+height,0,0,0);
 						
 			mesh->addPolygon(poly);
 			}
@@ -63,14 +105,12 @@ ScreenShape::ScreenShape(int shapeType, Number option1, Number option2, Number o
 				step = ceil(360/option3);
 			else
 				step = 1;
-			if(shapeType == SHAPE_CIRCLE)
-				poly->addVertex(0,0,0,0.5,0.5);
-			else
-				poly->addVertex(cosf(0)*(width/2),sinf(0)*(height/2), 0, (cosf(0)*0.5) + 0.5,(sinf(0) * 0.5)+ 0.5);
+			
+			poly->addVertex(cosf(0)*(width/2),sinf(0)*(height/2), 0, (cosf(0)*0.5) + 0.5,(sinf(0) * 0.5)+ 0.5);
 			
 			for (int i=0; i < 361; i+= step) {
-				Number degInRad = i*DEG2RAD;
-				poly->addVertex(cos(degInRad)*(width/2),sin(degInRad)*(height/2), 0, (cos(degInRad) * 0.5)+ 0.5 ,(sin(degInRad) * 0.5)+ 0.5);
+				Number degInRad = i*TORADIANS;
+				poly->addVertex(cos(degInRad)*(width/2),sin(degInRad)*(height/2), 0, (cos(degInRad) * 0.5)+ 0.5 , 1.0- ((sin(degInRad) * 0.5)+ 0.5));
 			}
 			mesh->addPolygon(poly);
 			}
@@ -83,24 +123,31 @@ ScreenShape::ScreenShape(int shapeType, Number option1, Number option2, Number o
 		default:
 		break;
 	}
-	
-	positionMode = POSITION_CENTER;
-	strokeEnabled = false;
+
+	mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;	
+}
+
+int ScreenShape::getShapeType() const {
+	return shapeType;
+}
+
+void ScreenShape::setShapeType(unsigned int type) {
+	shapeType = type;
+	buildShapeMesh();
 }
 
 void ScreenShape::setShapeSize(Number newWidth, Number newHeight) {
 
 	setWidth(newWidth);
 	setHeight(newHeight);
-
-	
-	Number whalf = floor(width/2.0f);
-	Number hhalf = floor(height/2.0f);
-	Polygon *polygon;
-	Vertex *vertex;
 	
-	switch(shapeType) {
-		case SHAPE_RECT: {	
+
+	if(shapeType == SHAPE_RECT) {
+			Number whalf = floor(width/2.0f);
+			Number hhalf = floor(height/2.0f);
+			Polygon *polygon;
+			Vertex *vertex;
+
 			polygon = mesh->getPolygon(0);	
 			vertex = polygon->getVertex(0);
 			vertex->set(-whalf,-hhalf,0);			
@@ -110,14 +157,11 @@ void ScreenShape::setShapeSize(Number newWidth, Number newHeight) {
 			vertex->set(-whalf+width,-hhalf+height,0);			
 			vertex = polygon->getVertex(3);	
 			vertex->set(-whalf,-hhalf+height,0);				
-		}			
-		break;
-		default:
-		break;
+			mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;	
+	} else {	
+		buildShapeMesh();
 	}
-	
 		
-	mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;
 	rebuildTransformMatrix();
 	matrixDirty = true;
 }

+ 136 - 14
Core/Contents/Source/PolyScreenSprite.cpp

@@ -30,17 +30,87 @@
 using std::vector;
 using namespace Polycode;
 
+ScreenSprite::ScreenSprite(const String& fileName) : ScreenShape(ScreenShape::SHAPE_RECT, 1, 1) {
+
+	currentFrame = 0;
+	currentAnimation = NULL;	
+	paused = false;
+
+	loadFromFile(fileName);
+}
+
+bool ScreenSprite::loadFromFile(const String& fileName) {
+	Object loadObject;
+	
+	animations.clear();
+	
+	if(!loadObject.loadFromXML(fileName)) {
+		return false;
+	}
+	
+	this->fileName = fileName;
+	
+	ObjectEntry *image = loadObject.root["image"];
+	if(image) {
+		ObjectEntry *frameWidth = (*image)["frameWidth"];
+		ObjectEntry *frameHeight = (*image)["frameHeight"];	
+		ObjectEntry *fileName = (*image)["fileName"];
+		
+		if(fileName) {
+			loadTexture(fileName->stringVal);
+		}
+
+		if(frameWidth && frameHeight) {
+			setShapeSize(frameWidth->NumberVal, frameHeight->NumberVal);
+			setSpriteSize(frameWidth->NumberVal, frameHeight->NumberVal);
+		}
+	}
+	
+	ObjectEntry *animationsEntry = loadObject.root["animations"];
+	
+	if(animationsEntry) {
+		for(int i=0; i < animationsEntry->length; i++) {
+			ObjectEntry *animation = (*animationsEntry)[i];
+			if(animation) {
+				ObjectEntry *name = (*animation)["name"];
+				ObjectEntry *frames = (*animation)["frames"];	
+				ObjectEntry *speed = (*animation)["speed"];
+				
+				if(name && frames && speed) {
+					addAnimation(name->stringVal, frames->stringVal, speed->NumberVal);
+				} else {
+					printf("Error parsing animation node\n");
+				}
+			}
+		}
+	}
+	
+	recalculateSpriteDimensions();
+
+	return true;
+}
+
+unsigned int ScreenSprite::getNumAnimations() {
+	return animations.size();
+}
+
+SpriteAnimation *ScreenSprite::getAnimationAtIndex(unsigned int index) {
+	if(index < animations.size()) {
+		return animations[index];
+	} else {
+		return NULL;
+	}
+}
+
+
 ScreenSprite::ScreenSprite(const String& fileName, Number spriteWidth, Number spriteHeight) : ScreenShape(ScreenShape::SHAPE_RECT, spriteWidth, spriteHeight) {
 	this->spriteWidth = spriteWidth;
 	this->spriteHeight = spriteHeight;	
 	loadTexture(fileName);
 		
-	spriteUVWidth = 1.0f / ((Number) texture->getWidth() / spriteWidth);
-	spriteUVHeight = 1.0f / ((Number) texture->getHeight() / spriteHeight);
-	
+	recalculateSpriteDimensions();
 	currentFrame = 0;
-	currentAnimation = NULL;
-	
+	currentAnimation = NULL;	
 	paused = false;
 }
 
@@ -48,13 +118,44 @@ ScreenSprite::~ScreenSprite() {
 	
 }
 
-void ScreenSprite::addAnimation(const String& name, const String& frames, Number speed) {
-	SpriteAnimation *newAnimation = new SpriteAnimation();
+void ScreenSprite::recalculateSpriteDimensions() {
+	if(!texture)
+		return;
+		
+	spriteUVWidth = 1.0f / ((Number) texture->getWidth() / spriteWidth);
+	spriteUVHeight = 1.0f / ((Number) texture->getHeight() / spriteHeight);
 	
-	vector<String> frameNumbers = frames.split(",");
+	for(int i =0 ; i < animations.size(); i++) {
+		animations[i]->numFramesX = texture->getWidth() / spriteWidth;	
+		animations[i]->numFramesY = texture->getHeight() / spriteHeight;
+		animations[i]->spriteUVWidth = spriteUVWidth;
+		animations[i]->spriteUVHeight = spriteUVHeight;	
+		animations[i]->setOffsetsFromFrameString(animations[i]->frames);
+	}
+}
+
+Vector2 ScreenSprite::getSpriteSize() {
+	return Vector2(spriteWidth, spriteHeight);
+}
+
+String ScreenSprite::getFileName() const {
+	return fileName;
+}
+
+void ScreenSprite::setSpriteSize(const Number spriteWidth, const Number spriteHeight) {
+	this->spriteWidth = spriteWidth;
+	this->spriteHeight = spriteHeight;	
 	
-	int numFramesX = texture->getWidth() / spriteWidth;
-	int numFramesY = texture->getHeight() / spriteHeight;
+	recalculateSpriteDimensions();	
+}
+
+SpriteAnimation *ScreenSprite::getCurrentAnimation() {
+	return currentAnimation;
+}
+
+void SpriteAnimation::setOffsetsFromFrameString(const String& frames) {
+	framesOffsets.clear();
+	vector<String> frameNumbers = frames.split(",");
 	
 	int frameNumber;
 	int frameX;
@@ -64,13 +165,29 @@ void ScreenSprite::addAnimation(const String& name, const String& frames, Number
 		frameNumber = atoi(frameNumbers[i].c_str());
 		frameX = frameNumber % numFramesX;
 		frameY = frameNumber/numFramesX;
-		newAnimation->framesOffsets.push_back(Vector2(spriteUVWidth * frameX, spriteUVHeight * frameY));		
+		framesOffsets.push_back(Vector2(spriteUVWidth * frameX, spriteUVHeight * frameY));		
 	}
 	
+	this->frames = frames;
+	numFrames = frameNumbers.size();
+
+}
+
+SpriteAnimation *ScreenSprite::addAnimation(const String& name, const String& frames, Number speed) {
+	SpriteAnimation *newAnimation = new SpriteAnimation();	
+	
+	
+	newAnimation->numFramesX = texture->getWidth() / spriteWidth;	
+	newAnimation->numFramesY = texture->getHeight() / spriteHeight;
+	newAnimation->spriteUVWidth = spriteUVWidth;
+	newAnimation->spriteUVHeight = spriteUVHeight;
+	
+	newAnimation->setOffsetsFromFrameString(frames);
+			
 	newAnimation->speed = speed;
 	newAnimation->name = name;
-	newAnimation->numFrames = frameNumbers.size();
 	animations.push_back(newAnimation);
+	return newAnimation;
 }
 
 void ScreenSprite::playAnimation(const String& name, int startFrame, bool once) {
@@ -81,8 +198,13 @@ void ScreenSprite::playAnimation(const String& name, int startFrame, bool once)
 				return;
 			currentFrame = 0;			
 			currentAnimation = animations[i];
-			if(currentFrame < currentAnimation->numFrames)
-				currentFrame = startFrame;
+			if(startFrame == -1) {
+				currentFrame = rand() % currentAnimation->numFrames;
+			} else {
+				if(startFrame < currentAnimation->numFrames) {
+					currentFrame = startFrame;
+				}
+			}
 			playingOnce = once;
 			lastTick = 0;
 		}

+ 80 - 12
Core/Contents/Source/PolySound.cpp

@@ -53,31 +53,78 @@ long custom_tellfunc(void *datasource) {
 }
 
 Sound::Sound(const String& fileName) : sampleLength(-1) {
+	soundLoaded = false;		
+	loadFile(fileName);
+	setIsPositional(false);
+	
+	setVolume(1.0);
+	setPitch(1.0);
+}
+
+Sound::Sound(const char *data, int size, int channels, int freq, int bps) : sampleLength(-1) {
+	ALuint buffer = loadBytes(data, size, freq, channels, bps);
+	
+	soundSource = GenSource(buffer);
+	setIsPositional(false);
+	soundLoaded = true;
+		
+	setVolume(1.0);
+	setPitch(1.0);
+}
+
+void Sound::loadFile(String fileName) {
+
+	if(soundLoaded) {
+		alDeleteSources(1,&soundSource);	
+	}
+
+	String actualFilename = fileName;
+	OSFILE *test = OSBasics::open(fileName, "rb");
+	if(!test) {
+		actualFilename = "default/default.wav";
+	} else {
+		OSBasics::close(test);	
+	}
+	
 	String extension;
 	size_t found;
-	found=fileName.rfind(".");
+	found=actualFilename.rfind(".");
 	if (found!=string::npos) {
-		extension = fileName.substr(found+1);
+		extension = actualFilename.substr(found+1);
 	} else {
 		extension = "";
 	}
-
+	
 	ALuint buffer;
 	if(extension == "wav" || extension == "WAV") {
-		buffer = loadWAV(fileName);			
+		buffer = loadWAV(actualFilename);			
 	} else if(extension == "ogg" || extension == "OGG") {
-		buffer = loadOGG(fileName);			
+		buffer = loadOGG(actualFilename);			
 	}
 	
-	soundSource = GenSource(buffer);
-	setIsPositional(false);
+	this->fileName = actualFilename;
+	
+	soundSource = GenSource(buffer);	
+	
+	setVolume(volume);
+	setPitch(pitch);
+	
+	setReferenceDistance(referenceDistance);
+	setMaxDistance(maxDistance);
+	
+	soundLoaded = true;
 }
 
-Sound::Sound(const char *data, int size, int channels, int freq, int bps) : sampleLength(-1) {
-	ALuint buffer = loadBytes(data, size, freq, channels, bps);
-	
-	soundSource = GenSource(buffer);
-	setIsPositional(false);
+String Sound::getFileName() {
+	return fileName;
+}
+
+Number Sound::getVolume() {
+	return volume;
+}
+
+Number Sound::getPitch() {
+	return pitch;
 }
 
 Sound::~Sound() {
@@ -127,10 +174,12 @@ bool Sound::isPlaying() {
 
 
 void Sound::setVolume(Number newVolume) {
+	this->volume = newVolume;
 	alSourcef(soundSource, AL_GAIN, newVolume);
 }
 
 void Sound::setPitch(Number newPitch) {
+	this->pitch = newPitch;
 	alSourcef(soundSource, AL_PITCH, newPitch);
 }
 
@@ -197,9 +246,28 @@ int Sound::getSampleLength() {
 }
 
 void Sound::setPositionalProperties(Number referenceDistance, Number maxDistance) { 
+	setReferenceDistance(referenceDistance);
+	setMaxDistance(maxDistance);
+}
+
+void Sound::setReferenceDistance(Number referenceDistance) {
+	this->referenceDistance = referenceDistance;
 	alSourcef(soundSource,AL_REFERENCE_DISTANCE, referenceDistance);
+}
+
+void Sound::setMaxDistance(Number maxDistance) {
+	this->maxDistance = maxDistance;
 	alSourcef(soundSource,AL_MAX_DISTANCE, maxDistance);	
 }
+		
+Number Sound::getReferenceDistance() {
+	return referenceDistance;
+}
+
+Number Sound::getMaxDistance() {
+	return maxDistance;
+}
+
 
 void Sound::setIsPositional(bool isPositional) {
 	this->isPositional = isPositional;

+ 26 - 0
Documentation/Misc/binary_object.txt

@@ -0,0 +1,26 @@
+
+// STRUCTURES
+
+KEY {
+	16 STRING_LEN
+	STRING_LEN STRING
+}
+
+ENTRY {
+	16 KEY_INDEX
+	8 TYPE
+	32 DATA	
+	DATA STRING (ONLY IF TYPE IS STRING)
+	32 NUM_CHILDREN
+	NUM_CHILDREN*SIZEOF(ENTRY) CHILDREN
+}
+
+// FILE STRUCTURE
+
+32 HEADER = "PBOF"
+16 NUMKEYS
+NUMKEYS * SIZEOF(KEY) KEYS
+
+32 NUMENTRIES
+NUMENTRIES * SIZEOF(ENTRY) ENTRIES
+

+ 2 - 173
IDE/Build/Mac OS X/English.lproj/MainMenu.xib

@@ -280,8 +280,7 @@
 								<object class="NSMenuItem" id="355684970">
 									<reference key="NSMenu" ref="720053764"/>
 									<string key="NSTitle">Remove File</string>
-									<string type="base64-UTF8" key="NSKeyEquiv">CA</string>
-									<int key="NSKeyEquivModMask">1048576</int>
+									<string key="NSKeyEquiv"/>
 									<int key="NSMnemonicLoc">2147483647</int>
 									<reference key="NSOnImage" ref="35465992"/>
 									<reference key="NSMixedImage" ref="502551668"/>
@@ -677,7 +676,6 @@
 							<object class="NSPSMatrix" key="NSDrawMatrix"/>
 							<string key="NSFrameSize">{800, 600}</string>
 							<reference key="NSSuperview" ref="439893737"/>
-							<reference key="NSWindow"/>
 							<object class="NSOpenGLPixelFormat" key="NSPixelFormat">
 								<object class="NSMutableData" key="NSPixelAttributes">
 									<bytes key="NS.bytes">AAAAYAAAAAA</bytes>
@@ -687,7 +685,6 @@
 					</object>
 					<string key="NSFrameSize">{800, 600}</string>
 					<reference key="NSSuperview"/>
-					<reference key="NSWindow"/>
 					<reference key="NSNextKeyView" ref="633009941"/>
 				</object>
 				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
@@ -1899,175 +1896,7 @@
 			<nil key="sourceID"/>
 			<int key="maxID">591</int>
 		</object>
-		<object class="IBClassDescriber" key="IBDocument.Classes">
-			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-				<object class="IBPartialClassDescription">
-					<string key="className">PolycodeAppDelegate</string>
-					<string key="superclassName">NSObject</string>
-					<object class="NSMutableDictionary" key="actions">
-						<bool key="EncodedWithXMLCoder">YES</bool>
-						<object class="NSArray" key="dict.sortedKeys">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<string>browseExamples:</string>
-							<string>closeProject:</string>
-							<string>exportProject:</string>
-							<string>findText:</string>
-							<string>newFile:</string>
-							<string>newGroup:</string>
-							<string>newProject:</string>
-							<string>openProject:</string>
-							<string>refreshProject:</string>
-							<string>removeFile:</string>
-							<string>renameFile:</string>
-							<string>runProject:</string>
-							<string>saveFile:</string>
-						</object>
-						<object class="NSArray" key="dict.values">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-							<string>id</string>
-						</object>
-					</object>
-					<object class="NSMutableDictionary" key="actionInfosByName">
-						<bool key="EncodedWithXMLCoder">YES</bool>
-						<object class="NSArray" key="dict.sortedKeys">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<string>browseExamples:</string>
-							<string>closeProject:</string>
-							<string>exportProject:</string>
-							<string>findText:</string>
-							<string>newFile:</string>
-							<string>newGroup:</string>
-							<string>newProject:</string>
-							<string>openProject:</string>
-							<string>refreshProject:</string>
-							<string>removeFile:</string>
-							<string>renameFile:</string>
-							<string>runProject:</string>
-							<string>saveFile:</string>
-						</object>
-						<object class="NSArray" key="dict.values">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<object class="IBActionInfo">
-								<string key="name">browseExamples:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">closeProject:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">exportProject:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">findText:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">newFile:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">newGroup:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">newProject:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">openProject:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">refreshProject:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">removeFile:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">renameFile:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">runProject:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-							<object class="IBActionInfo">
-								<string key="name">saveFile:</string>
-								<string key="candidateClassName">id</string>
-							</object>
-						</object>
-					</object>
-					<object class="NSMutableDictionary" key="outlets">
-						<bool key="EncodedWithXMLCoder">YES</bool>
-						<object class="NSArray" key="dict.sortedKeys">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<string>polycodeView</string>
-							<string>projectMenu</string>
-							<string>window</string>
-						</object>
-						<object class="NSArray" key="dict.values">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<string>PolycodeView</string>
-							<string>NSMenu</string>
-							<string>NSWindow</string>
-						</object>
-					</object>
-					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
-						<bool key="EncodedWithXMLCoder">YES</bool>
-						<object class="NSArray" key="dict.sortedKeys">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<string>polycodeView</string>
-							<string>projectMenu</string>
-							<string>window</string>
-						</object>
-						<object class="NSArray" key="dict.values">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<object class="IBToOneOutletInfo">
-								<string key="name">polycodeView</string>
-								<string key="candidateClassName">PolycodeView</string>
-							</object>
-							<object class="IBToOneOutletInfo">
-								<string key="name">projectMenu</string>
-								<string key="candidateClassName">NSMenu</string>
-							</object>
-							<object class="IBToOneOutletInfo">
-								<string key="name">window</string>
-								<string key="candidateClassName">NSWindow</string>
-							</object>
-						</object>
-					</object>
-					<object class="IBClassDescriptionSource" key="sourceIdentifier">
-						<string key="majorKey">IBProjectSource</string>
-						<string key="minorKey">./Classes/PolycodeAppDelegate.h</string>
-					</object>
-				</object>
-				<object class="IBPartialClassDescription">
-					<string key="className">PolycodeView</string>
-					<string key="superclassName">NSOpenGLView</string>
-					<object class="IBClassDescriptionSource" key="sourceIdentifier">
-						<string key="majorKey">IBProjectSource</string>
-						<string key="minorKey">./Classes/PolycodeView.h</string>
-					</object>
-				</object>
-			</object>
-		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes"/>
 		<int key="IBDocument.localizationMode">0</int>
 		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
 		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">

+ 18 - 0
IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj

@@ -19,6 +19,8 @@
 		6D56156814C5430300FC8BD4 /* PolycodeScreenEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D56156714C5430300FC8BD4 /* PolycodeScreenEditor.cpp */; };
 		6D6D3FA614B446A600219173 /* PolycodeToolLauncher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D6D3FA514B446A600219173 /* PolycodeToolLauncher.cpp */; };
 		6D70AB2A12B29BF200EB6D94 /* NewFileWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D70AB2912B29BF200EB6D94 /* NewFileWindow.cpp */; };
+		6D79732E167F0D4600646407 /* PolycodeSpriteEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D79732D167F0D4600646407 /* PolycodeSpriteEditor.cpp */; };
+		6D797333167F0EB100646407 /* PolycodeProps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D797332167F0EB100646407 /* PolycodeProps.cpp */; };
 		6D80B0CE163B14CB00EF3C04 /* PolycodeMaterialEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80B0CD163B14CB00EF3C04 /* PolycodeMaterialEditor.cpp */; };
 		6D80E91E12AB53FB0037A708 /* PolycodeFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80E91912AB53FB0037A708 /* PolycodeFrame.cpp */; };
 		6D80E91F12AB53FB0037A708 /* PolycodeIDEApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80E91A12AB53FB0037A708 /* PolycodeIDEApp.cpp */; };
@@ -29,6 +31,7 @@
 		6D8A55B914B3EABB005F6411 /* main_icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 6D8A55B814B3EABB005F6411 /* main_icon.icns */; };
 		6D8A55BC14B3EACB005F6411 /* PolycodeView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D8A55BB14B3EACB005F6411 /* PolycodeView.mm */; };
 		6D91B3B512AF2B1D00261ED4 /* PolycodeTextEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D91B3B412AF2B1D00261ED4 /* PolycodeTextEditor.cpp */; };
+		6DC67A541656F693004FD1EF /* TextureBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DC67A531656F693004FD1EF /* TextureBrowser.cpp */; };
 		6DC825791648571E006AFC03 /* ExportProjectWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DC825781648571E006AFC03 /* ExportProjectWindow.cpp */; };
 		6DCAFD4314B519C900039F34 /* ExampleBrowserWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCAFD4214B519C900039F34 /* ExampleBrowserWindow.cpp */; };
 		6DCE857A12AE018800566FAE /* PolycodeEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCE857812AE018800566FAE /* PolycodeEditor.cpp */; };
@@ -91,6 +94,10 @@
 		6D6D3FA814B446AF00219173 /* PolycodeToolLauncher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeToolLauncher.h; sourceTree = "<group>"; };
 		6D70AB2812B29BEC00EB6D94 /* NewFileWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewFileWindow.h; sourceTree = "<group>"; };
 		6D70AB2912B29BF200EB6D94 /* NewFileWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFileWindow.cpp; sourceTree = "<group>"; };
+		6D79732D167F0D4600646407 /* PolycodeSpriteEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeSpriteEditor.cpp; sourceTree = "<group>"; };
+		6D797330167F0D4D00646407 /* PolycodeSpriteEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeSpriteEditor.h; sourceTree = "<group>"; };
+		6D797331167F0EA500646407 /* PolycodeProps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeProps.h; sourceTree = "<group>"; };
+		6D797332167F0EB100646407 /* PolycodeProps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeProps.cpp; sourceTree = "<group>"; };
 		6D80B0CD163B14CB00EF3C04 /* PolycodeMaterialEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeMaterialEditor.cpp; sourceTree = "<group>"; };
 		6D80B0D0163B14D100EF3C04 /* PolycodeMaterialEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeMaterialEditor.h; sourceTree = "<group>"; };
 		6D80E91312AB53FB0037A708 /* PolycodeFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeFrame.h; sourceTree = "<group>"; };
@@ -111,6 +118,8 @@
 		6D8A55BB14B3EACB005F6411 /* PolycodeView.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = PolycodeView.mm; path = ../../../Release/Darwin/Framework/Core/PolycodeView/PolycodeView.mm; sourceTree = "<group>"; };
 		6D91B3B312AF2B1600261ED4 /* PolycodeTextEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeTextEditor.h; sourceTree = "<group>"; };
 		6D91B3B412AF2B1D00261ED4 /* PolycodeTextEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeTextEditor.cpp; sourceTree = "<group>"; };
+		6DC67A531656F693004FD1EF /* TextureBrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureBrowser.cpp; sourceTree = "<group>"; };
+		6DC67A561656F699004FD1EF /* TextureBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureBrowser.h; sourceTree = "<group>"; };
 		6DC825781648571E006AFC03 /* ExportProjectWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExportProjectWindow.cpp; sourceTree = "<group>"; };
 		6DC8257B16485726006AFC03 /* ExportProjectWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExportProjectWindow.h; sourceTree = "<group>"; };
 		6DCAFD4214B519C900039F34 /* ExampleBrowserWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExampleBrowserWindow.cpp; sourceTree = "<group>"; };
@@ -262,11 +271,14 @@
 		6D80E91212AB53FB0037A708 /* Include */ = {
 			isa = PBXGroup;
 			children = (
+				6DC67A561656F699004FD1EF /* TextureBrowser.h */,
 				6DC8257B16485726006AFC03 /* ExportProjectWindow.h */,
 				6D80B0D0163B14D100EF3C04 /* PolycodeMaterialEditor.h */,
 				6DD1835F1628A4D2005A5682 /* PolycodeRemoteDebugger.h */,
 				6D3DC79F16220440003ED2C9 /* PolycodeConsole.h */,
+				6D797330167F0D4D00646407 /* PolycodeSpriteEditor.h */,
 				6D56156514C542FB00FC8BD4 /* PolycodeScreenEditor.h */,
+				6D797331167F0EA500646407 /* PolycodeProps.h */,
 				6D2AC99D14B8500A00BB63DA /* PolycodeProjectEditor.h */,
 				6D3B6C5C14B820B000727F17 /* ToolWindows.h */,
 				6DCAFD4614B51A2D00039F34 /* ExampleBrowserWindow.h */,
@@ -292,11 +304,14 @@
 		6D80E91812AB53FB0037A708 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				6DC67A531656F693004FD1EF /* TextureBrowser.cpp */,
+				6D79732D167F0D4600646407 /* PolycodeSpriteEditor.cpp */,
 				6DC825781648571E006AFC03 /* ExportProjectWindow.cpp */,
 				6D80B0CD163B14CB00EF3C04 /* PolycodeMaterialEditor.cpp */,
 				6DD1835C1628A4CC005A5682 /* PolycodeRemoteDebugger.cpp */,
 				6D3DC79C1622043A003ED2C9 /* PolycodeConsole.cpp */,
 				6D56156714C5430300FC8BD4 /* PolycodeScreenEditor.cpp */,
+				6D797332167F0EB100646407 /* PolycodeProps.cpp */,
 				6D2AC99A14B8500400BB63DA /* PolycodeProjectEditor.cpp */,
 				6D3B6C5A14B820A900727F17 /* ToolWindows.cpp */,
 				6DCAFD4214B519C900039F34 /* ExampleBrowserWindow.cpp */,
@@ -426,6 +441,9 @@
 				6DD1835D1628A4CC005A5682 /* PolycodeRemoteDebugger.cpp in Sources */,
 				6D80B0CE163B14CB00EF3C04 /* PolycodeMaterialEditor.cpp in Sources */,
 				6DC825791648571E006AFC03 /* ExportProjectWindow.cpp in Sources */,
+				6DC67A541656F693004FD1EF /* TextureBrowser.cpp in Sources */,
+				6D79732E167F0D4600646407 /* PolycodeSpriteEditor.cpp in Sources */,
+				6D797333167F0EB100646407 /* PolycodeProps.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 3 - 2
IDE/Contents/Include/PolycodeConsole.h

@@ -115,10 +115,11 @@ class PolycodeConsole : public UIElement {
 	
 		UIHSizer *backtraceSizer;
 	
-		PolycodeRemoteDebugger *debugger;
-		
+		PolycodeRemoteDebugger *debugger;		
 		static PolycodeConsole *instance;
 		
+		
+		
 		UITextInput *debugTextInput;
 		UITextInput *consoleTextInput;		
 };

+ 2 - 0
IDE/Contents/Include/PolycodeEditor.h

@@ -37,6 +37,8 @@ public:
 	virtual bool openFile(OSFileEntry filePath){ this->filePath = filePath.fullPath; }
 	virtual void Resize(int x, int y);
 	
+	virtual void Activate() {};
+	
 	virtual void saveFile(){};
 	
 	virtual void handleDroppedFile(OSFileEntry file, Number x, Number y) {};

+ 116 - 1
IDE/Contents/Include/PolycodeFrame.h

@@ -26,13 +26,118 @@
 #include "PolycodeEditor.h"
 #include "PolycodeConsole.h"
 #include "NewProjectWindow.h"
+#include "TextureBrowser.h"
 #include "ExportProjectWindow.h"
 #include "ExampleBrowserWindow.h"
 #include "NewFileWindow.h"
 #include "ToolWindows.h"
+#include "PolycodeProjectManager.h"
 
 using namespace Polycode;
 
+#define CURVE_SIZE 160.0
+
+class EditPoint : public ScreenEntity {
+	public:
+		EditPoint(BezierPoint *point, unsigned int type);
+		~EditPoint();
+		
+		void handleEvent(Event *event);
+		
+		void updatePosition();
+		void updateCurvePoint();
+		
+		void setMode(unsigned int mode);
+
+		void limitPoint(ScreenImage *point);
+								
+		ScreenImage *pointHandle;
+		
+		ScreenImage *controlHandle1;
+		ScreenImage *controlHandle2;
+		
+		ScreenLine *connectorLine1;
+		ScreenLine *connectorLine2;
+				
+		static const int TYPE_START_POINT = 0;		
+		static const int TYPE_POINT = 1;
+		static const int TYPE_END_POINT = 2;				
+		
+		ScreenImage *draggingPoint;
+		bool dragging;
+		Vector2 basePosition;
+		Vector2 basePointPosition;
+		
+		Vector2 baseControl1;
+		Vector2 baseControl2;	
+		
+		unsigned int mode;
+				
+		unsigned int type;				
+		BezierPoint *point;
+};
+
+class EditCurve : public UIElement {
+	public:
+		EditCurve(BezierCurve *targetCurve, Color curveColor);
+		~EditCurve();
+		
+		void updateCurve();
+		void updatePoints();
+		
+		void setMode(unsigned int mode);
+		
+		void Activate();
+		void Deactivate();
+		
+		void Update();
+				
+		void handleEvent(Event *event);
+		
+		BezierCurve *targetCurve;
+		ScreenMesh *visMesh;
+		Polycode::Polygon *poly;	
+		
+		EditPoint *pointToRemove;
+		UIElement *pointsBase;
+		vector<EditPoint*> points;
+		
+		unsigned int mode;
+};
+
+class CurveEditor : public UIWindow {
+	public:
+		CurveEditor();
+		~CurveEditor();
+		
+		void handleEvent(Event *event);		
+		void setMode(unsigned int mode);
+		
+		void addCurve(String name, BezierCurve *curve, Color curveColor);
+
+		void onClose();
+
+		void clearCurves();
+		
+		UIImageButton *selectButton;
+		UIImageButton *addButton;
+		UIImageButton *removeButton;
+				
+		ScreenImage	*selectorImage;
+		
+		static const int MODE_SELECT = 0;		
+		static const int MODE_ADD = 1;
+		static const int MODE_REMOVE = 2;
+		
+		UITreeContainer *treeContainer;
+		
+		unsigned int mode;
+		ScreenImage *bg;
+		
+		EditCurve *selectedCurve;
+		std::vector<EditCurve*> curves;
+};
+
 class EditorHolder : public UIElement {
 	public:
 		EditorHolder();
@@ -60,6 +165,10 @@ public:
 	void addEditor(PolycodeEditor *editor);
 	void showEditor(PolycodeEditor *editor);
 	
+	void showAssetBrowser(std::vector<String> extensions);
+	
+	void showCurveEditor();
+	
 	PolycodeProjectBrowser *getProjectBrowser();
 	
 	NewProjectWindow *newProjectWindow;	
@@ -67,6 +176,8 @@ public:
 	NewFileWindow *newFileWindow;
 	ExportProjectWindow *exportProjectWindow;
 	
+	AssetBrowser *assetBrowser;
+	
 	TextInputPopup *textInputPopup;
 	
 	ScreenEntity *welcomeEntity;	
@@ -78,7 +189,11 @@ public:
 	UIHSizer *mainSizer;
 	
 	PolycodeConsole *console;
-						
+	
+	PolycodeProjectManager *projectManager;
+		
+	CurveEditor *curveEditor;
+	
 private:
 	
 	int frameSizeX;

+ 2 - 1
IDE/Contents/Include/PolycodeIDEApp.h

@@ -36,6 +36,7 @@
 #include "PolycodeFontEditor.h"
 #include "PolycodeTextEditor.h"
 #include "PolycodeProjectEditor.h"
+#include "PolycodeSpriteEditor.h"
 
 #include "PolycodeToolLauncher.h"
 
@@ -72,7 +73,7 @@ public:
 	void saveFile();
 	void findText();
 	void runProject();
-	void exportProject();
+	void exportProject();	
 	
 	// system callbacks
 	

+ 2 - 3
IDE/Contents/Include/PolycodeMaterialEditor.h

@@ -82,7 +82,7 @@ class MaterialTextureSlot : public UIElement {
 
 class MaterialPropertySlot : public UIElement {
 	public:
-		MaterialPropertySlot(UIColorPicker *colorPicker, ShaderBinding *binding, ProgramParam param);
+		MaterialPropertySlot(ShaderBinding *binding, ProgramParam param);
 		~MaterialPropertySlot();
 		
 		void handleEvent(Event *event);
@@ -104,7 +104,7 @@ class MaterialPropertySlot : public UIElement {
 
 class MaterialEditorPane : public UIWindow {
 	public:
-		MaterialEditorPane(UIColorPicker *colorPicker);
+		MaterialEditorPane();
 		~MaterialEditorPane();
 		
 		void setMaterial(Material *material);
@@ -138,7 +138,6 @@ class MaterialEditorPane : public UIWindow {
 		ScreenShape *previewShape;
 		
 		UIComboBox *shaderSelector;
-		UIColorPicker *colorPicker;		
 
 		UIComboBox *blendSelector;
 		

+ 14 - 1
IDE/Contents/Include/PolycodeProject.h

@@ -27,6 +27,18 @@
 
 using namespace Polycode;
 
+class ProjectFontData {
+	public:
+		ProjectFontData();
+		ProjectFontData(String fontName, String fontPath) {
+			this->fontName = fontName;		
+			this->fontPath = fontPath;
+		}
+		
+		String fontName;
+		String fontPath;
+};
+
 class ProjectData {
 	public:
 		String entryPoint;
@@ -37,7 +49,8 @@ class ProjectData {
 		unsigned int aaLevel;
 		unsigned int frameRate;
 		
-		std::vector<String> modules;
+		std::vector<String> modules;		
+		std::vector<ProjectFontData> fonts;
 		
 		Number backgroundColorR;
 		Number backgroundColorG;

+ 6 - 1
IDE/Contents/Include/PolycodeProjectBrowser.h

@@ -43,8 +43,9 @@ class PolycodeProjectBrowserEvent : public Event {
 	public:
 		PolycodeProjectBrowserEvent() : Event() {eventType = "PolycodeProjectBrowserEvent";}
 		~PolycodeProjectBrowserEvent() {}
-		static const int SHOW_MENU = 0;
+		static const int HANDLE_MENU_COMMAND = 0;
 		
+		String command;
 		
 };
 
@@ -73,6 +74,10 @@ public:
 	UITreeContainer *treeContainer;
 			
 protected:
+
+		ScreenShape *headerBg;
+	
+		UIMenu *contextMenu;
 	
 		BrowserUserData *selectedData;
 };	

+ 28 - 4
IDE/Contents/Include/PolycodeProjectEditor.h

@@ -31,17 +31,36 @@
 
 using namespace Polycode;
 
+class ProjectFontEntry : public UIElement {
+	public:
+		ProjectFontEntry(String fontPath, String fontName);
+		~ProjectFontEntry();
+		
+		void handleEvent(Event *event);
+		
+		UITextInput *fontNameInput;
+		ScreenLabel *fontFileLabel;
+		
+		UIImageButton *removeButton;
+		
+		String fontPath;
+};
+
 class PolycodeProjectEditor : public PolycodeEditor {
 	public:
 	PolycodeProjectEditor(PolycodeProjectManager *projectManager);
 	virtual ~PolycodeProjectEditor();
 	
+	void handleEvent(Event *event);
+	
 	bool openFile(OSFileEntry filePath);
 	void Resize(int x, int y);
 	void saveFile();
 		
 	protected:
 	
+	void refreshFontEntries();
+	
 	PolycodeProjectManager *projectManager;
 	
 	ScreenImage *grid;
@@ -50,9 +69,14 @@ class PolycodeProjectEditor : public PolycodeEditor {
 	
 	std::vector<UICheckBox*> moduleCheckboxes;
 	
-	UIWindow *mainSettingsWindow;
-	UIWindow *moduleSettingsWindow;
-		
+	UIElement *mainSettingsWindow;
+	UIElement *moduleSettingsWindow;
+	
+	ScreenShape *headerBg;
+	
+	UIElement *fontEntryBase;	
+	std::vector<ProjectFontEntry*> fontEntries;
+				
 	UICheckBox *vSyncCheckBox;
 	UITextInput *defaultWidthInput;
 	UITextInput *defaultHeightInput;	
@@ -62,7 +86,7 @@ class PolycodeProjectEditor : public PolycodeEditor {
 	UITextInput *entryPointInput;	
 	UIColorBox *bgColorBox;
 	
-	UIColorPicker *colorPicker;
+	UIButton *addFontButton;
 	
 	PolycodeProject *associatedProject;
 	

+ 453 - 0
IDE/Contents/Include/PolycodeProps.h

@@ -0,0 +1,453 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "PolycodeGlobals.h"
+#include "PolycodeUI.h"
+#include "Polycode.h"
+#include "OSBasics.h"
+
+using namespace Polycode;
+
+
+class PropProp : public UIElement {
+	public:
+		PropProp(String caption);
+		~PropProp();
+		
+		ScreenLabel *label;
+		ScreenEntity *propContents;
+};
+
+class Vector2Prop : public PropProp {
+	public:
+		Vector2Prop(String caption);
+		~Vector2Prop();		
+		void handleEvent(Event *event);
+		void set(Vector2 position);
+		Vector2 get();
+				
+		UITextInput *positionX;
+		UITextInput *positionY;						
+};
+
+class SliderProp : public PropProp {
+	public:
+		SliderProp(String caption, Number min, Number max);
+		~SliderProp();		
+		void handleEvent(Event *event);
+		void set(Number number);
+		Number get();
+				
+		UIHSlider *slider;
+		ScreenLabel *valueLabel;
+};
+
+
+class NumberProp : public PropProp {
+	public:
+		NumberProp(String caption);
+		~NumberProp();		
+		void handleEvent(Event *event);
+		void set(Number number);
+		Number get();
+				
+		UITextInput *numberEntry;
+};
+
+class StringProp : public PropProp {
+	public:
+		StringProp(String caption);
+		~StringProp();		
+		void handleEvent(Event *event);
+		void set(String str);
+		String get();
+				
+		UITextInput *stringEntry;
+};
+
+class ColorProp : public PropProp {
+	public:
+		ColorProp(String caption);
+		~ColorProp();		
+		void handleEvent(Event *event);
+		
+		void set(Color color);
+		Color get();
+				
+		UIColorBox *colorEntry;
+};
+
+class ComboProp : public PropProp {
+	public:
+		ComboProp(String caption);
+		~ComboProp();		
+		void handleEvent(Event *event);
+		
+		void set(unsigned int index);
+		unsigned int get();
+				
+		UIComboBox *comboEntry;
+};
+
+class BoolProp : public PropProp {
+	public:
+		BoolProp(String caption);
+		~BoolProp();		
+		void handleEvent(Event *event);
+		
+		void set(bool val);
+		bool get();
+				
+		UICheckBox *checkEntry;
+};
+
+class SoundProp : public PropProp {
+	public:
+		SoundProp(String caption);
+		~SoundProp();
+		void handleEvent(Event *event);			
+		
+		void set(String soundPath);
+		String get();
+		
+		Sound *previewSound;
+		ScreenLabel *soundFile;		
+		UIButton *changeButton;
+		UIButton *playButton;		
+};
+
+class BezierRGBACurveProp : public PropProp {
+	public:
+		BezierRGBACurveProp(String caption);
+		~BezierRGBACurveProp();
+
+		void handleEvent(Event *event);	
+		
+		BezierCurve *curveR;
+		BezierCurve *curveG;
+		BezierCurve *curveB;
+		BezierCurve *curveA;					
+		UIButton *changeButton;
+};
+
+class BezierCurveProp : public PropProp {
+	public:
+		BezierCurveProp(String caption, String curveName);
+		~BezierCurveProp();
+
+		void handleEvent(Event *event);	
+		
+		String curveName;
+		BezierCurve *curve;
+		UIButton *changeButton;
+};
+
+class TextureProp : public PropProp {
+	public:
+		TextureProp(String caption);
+		~TextureProp();
+		void handleEvent(Event *event);	
+		
+		void set(Texture *texture);
+		Texture* get();
+				
+		ScreenShape *previewShape;
+		UIButton *changeButton;
+};
+
+class ScreenSpriteProp : public PropProp {
+	public:
+		ScreenSpriteProp(String caption);
+		~ScreenSpriteProp();
+		void handleEvent(Event *event);			
+		
+		void set(String fileName);
+		String get();		
+				
+		ScreenSprite *previewSprite;
+		UIButton *changeButton;
+};
+
+
+class ScreenEntityInstanceProp : public PropProp {
+	public:
+		ScreenEntityInstanceProp(String caption);
+		~ScreenEntityInstanceProp();
+		void handleEvent(Event *event);			
+		
+		void set(String fileName);
+		String get();		
+				
+		ScreenEntityInstance *previewInstance;
+		UIButton *changeButton;
+};
+
+
+class PropSheet : public UIElement {
+	public:
+		PropSheet(String caption, String type);
+		~PropSheet();		
+		void Resize(Number width, Number height);
+		
+		void handleEvent(Event *event);
+		
+		void setCollapsed(bool val);
+		
+		void addProp(PropProp *prop);
+		
+		String caption;
+		String type;
+		
+		Number propHeight;				
+		ScreenEntity *contents;
+		
+		ScreenShape *bg;
+		
+		UIImageButton *collapseButton;
+		UIImageButton *expandButton;
+		
+		bool collapsed;
+		
+		std::vector<PropProp*> props;
+};
+
+class EntitySheet : public PropSheet {
+	public:
+		EntitySheet();
+		~EntitySheet();
+		
+		void handleEvent(Event *event);
+		void Update();
+				
+		Entity *entity;
+		Entity *lastEntity;
+		
+		StringProp *idProp;
+		StringProp *tagProp;
+		ColorProp *colorProp;
+		ComboProp *blendingProp;
+};
+
+class ShapeSheet : public PropSheet {
+	public:
+		ShapeSheet();
+		~ShapeSheet();
+		
+		void handleEvent(Event *event);
+		void Update();
+				
+		ScreenShape *shape;
+	
+		ComboProp *typeProp;
+		Vector2Prop *shapeSize;
+		BoolProp *strokeProp;
+		ColorProp *strokeColorProp;
+		NumberProp *strokeSize;
+						
+		bool lastStrokeVal;
+		int lastShapeType;
+		Vector2 lastShapeSize;
+		Color lastStrokeColor;
+		Number lastStrokeSize;
+};
+
+class ScreenLabelSheet : public PropSheet {
+	public:
+		ScreenLabelSheet();
+		~ScreenLabelSheet();
+		
+		void refreshFonts();
+		
+		void handleEvent(Event *event);
+		void Update();
+				
+		ScreenLabel *label;	
+		
+		int lastSize;
+		String lastFont;
+		
+		StringProp *caption;
+		NumberProp *size;
+		ComboProp *font;
+		BoolProp *enableAA;
+};
+
+
+class ScreenImageSheet : public PropSheet {
+	public:
+		ScreenImageSheet();
+		~ScreenImageSheet();
+		
+		void handleEvent(Event *event);
+		void Update();
+				
+		ScreenImage *image;
+		
+		TextureProp *texture;
+		
+};
+
+class ScreenSpriteSheet : public PropSheet {
+	public:
+		ScreenSpriteSheet();
+		~ScreenSpriteSheet();
+		
+		void handleEvent(Event *event);
+		void Update();
+				
+		ScreenSprite *sprite;	
+		ScreenSpriteProp *spriteProp;
+		ComboProp *defaultAnimationProp;
+		
+		ScreenSprite *lastAnimationCheck;
+		
+};
+
+
+class ScreenEntityInstanceSheet : public PropSheet {
+	public:
+		ScreenEntityInstanceSheet();
+		~ScreenEntityInstanceSheet();
+		
+		void handleEvent(Event *event);
+		void Update();
+				
+		ScreenEntityInstance *instance;
+		ScreenEntityInstanceProp *instanceProp;
+};
+
+
+class SoundSheet : public PropSheet {
+	public:
+		SoundSheet();
+		~SoundSheet();
+		
+		void handleEvent(Event *event);
+		void Update();
+				
+		ScreenSound *sound;
+
+		SoundProp *soundProp;		
+		NumberProp *referenceDistance;
+		NumberProp *maxDistance;		
+		NumberProp *volume;
+		NumberProp *pitch;
+		
+		String lastSoundPath;
+		Number lastReferenceDistance;
+		Number lastMaxDistance;
+		Number lastVolume;
+		Number lastPitch;
+};
+
+class ScreenParticleSheet : public PropSheet {
+	public:
+		ScreenParticleSheet();
+		~ScreenParticleSheet();		
+		
+		void handleEvent(Event *event);
+		
+		void Update();
+
+		TextureProp *textureProp;
+		ComboProp *blendingProp;
+		NumberProp *numParticlesProp;
+		NumberProp *lifespanProp;
+		NumberProp *particleScaleProp;		
+		Vector2Prop *sizeProp;
+		Vector2Prop *dirProp;
+		Vector2Prop *gravProp;		
+		Vector2Prop *deviationProp;	
+		SliderProp *brightnessDeviationProp;
+		BoolProp *perlinEnableProp;
+		NumberProp *perlinModSizeProp;
+		SliderProp *speedModProp;
+		NumberProp *rotationSpeedProp;
+		BoolProp *rotationFollowsPathProp;		
+		BoolProp *useScaleCurvesProp;		
+		BezierCurveProp *scaleCurveProp;
+		
+		BoolProp *useColorCurvesProp;		
+		BezierRGBACurveProp *colorCurveProp;
+				
+		Number lastParticleScale;		
+		Number lastRotationSpeed;
+		Number lastNumParticles;
+		Number lastLifespan;
+		Vector3 lastSize;
+		Vector3 lastDeviation;
+		Vector3 lastDir;
+		Vector3 lastGrav;				
+		Number lastBrightnessDeviation;
+		bool lastEnableProp;
+		Number lastPerlinSize;
+		Number lastSpeedMod;
+		bool lastRotationFollowsPath;
+		bool lastUseScaleCurves;
+		bool lastUseColorCurves;		
+		BezierCurve *lastScaleCurve;
+		
+		ScreenParticleEmitter *emitter;
+};
+
+class Transform2DSheet : public PropSheet {
+	public:
+		Transform2DSheet();
+		~Transform2DSheet();		
+		
+		void handleEvent(Event *event);
+		
+		void Update();
+		
+		Vector2Prop *positionProp;
+		Vector2Prop *scaleProp;	
+		NumberProp *rotationProp;
+		
+		Vector2 lastPositon;
+		Vector2 lastScale;
+		Number lastRotation;
+		
+		ScreenEntity *entity;
+};
+
+class PropList : public UIElement {
+	public:
+		PropList(String caption="PROPERTIES");
+		~PropList();
+		
+		void updateProps();
+		
+		void addPropSheet(PropSheet *sheet);
+		void handleEvent(Event *event);
+		void Resize(Number width, Number height);
+		
+		UIScrollContainer *scrollContainer;		
+	protected:
+	
+		ScreenEntity *propContents;
+	
+		std::vector<PropSheet*> props;	
+		ScreenShape *bg;
+		ScreenShape *bg2;				
+};

+ 266 - 13
IDE/Contents/Include/PolycodeScreenEditor.h

@@ -25,43 +25,296 @@
 #include "PolycodeEditor.h"
 #include <Polycode.h>
 #include <PolycodeUI.h>
+#include "PolycodeProps.h"
 
 using namespace Polycode;
 
-class PolycodeScreenEditor : public PolycodeEditor {
+class EntityBrowserData  {
 	public:
-	PolycodeScreenEditor();
-	virtual ~PolycodeScreenEditor();
+		Entity *entity;
+};
+
+class EntityTreeView : public UIElement {
+	public:
+		EntityTreeView(Entity *rootEntity);
+		~EntityTreeView();
+		
+		void Resize(Number width, Number height);
+		void handleEvent(Event *event);	
+		
+		void syncNodeToEntity(UITree *node, Entity *entity);
+		
+		void Refresh();
+
+		Entity *selectedEntity;
+		Entity *targetLayer;
+		
+		UIImageButton *newLayerButton;
+		UIImageButton *targetLayerButton;
+		
+		Entity *rootEntity;
+						
+	protected:	
 	
-	bool openFile(OSFileEntry filePath);
-	void Resize(int x, int y);
+		bool dontSendSelectionEvent;
 	
-	void syncTransformToSelected();
+		UITreeContainer *treeContainer;
+			
+		ScreenShape *headerBg;		
+		ScreenShape *bg;		
+				
+};
+
+class PropertiesSizer : public UIElement {
+	public:
+		PropertiesSizer();
+		~PropertiesSizer();
+		
+		void Resize(Number width, Number height);
+		
+		UIVSizer *sizer;
+};
+
+
+class ScreenEntityNameDisplay : public ScreenEntity {
+	public:
+		ScreenEntityNameDisplay(ScreenEntity *targetEntity);
+		~ScreenEntityNameDisplay();
+		
+		void Update();
+		
+		ScreenLabel *label;
+		ScreenLabel *tagsLabel;		
+		ScreenEntity *targetEntity;
+};
+
+class PolycodeScreenEditorMain : public UIElement {
+	public:
+		
+		PolycodeScreenEditorMain();
+		virtual ~PolycodeScreenEditorMain();	
+			
+		void Resize(Number width, Number height);	
+		void syncTransformToSelected();	
+		ScreenEntity *addNewLayer(String layerName);	
+		void updateCursor();		
+		void selectEntity(ScreenEntity *entity);		
+		void setMode(int newMode);	
+		void handleEvent(Event *event);	
+		void resizePreviewScreen();		
+		void handleDroppedFile(OSFileEntry file, Number x, Number y);		
+		bool hasSelected(ScreenEntity *entity);
 	
-	void handleEvent(Event *event);
+		void applyEditorOnly(ScreenEntity *entity);
+		void applyEditorProperties(ScreenEntity *entity);
+			
+		void processEventForEntity(ScreenEntity *childEntity, InputEvent *inputEvent);
 	
-	void handleDroppedFile(OSFileEntry file, Number x, Number y);
+		void createParticleRef(ScreenParticleEmitter *target);
+		void createSoundRef(ScreenSound *target);
+		void createEntityRef(ScreenEntity *entity);
 	
+		void handleMouseDown(Vector2 position);
+		void handleMouseMove(Vector2 position);
+		void handleMouseUp(Vector2 position);
+		
+		void setGrid(int gridSize);
+				
+		static const int MODE_SELECT = 0;
+		static const int MODE_SHAPE = 1;
+		static const int MODE_ZOOM = 2;
+		static const int MODE_PAN = 3;
+		static const int MODE_IMAGE = 4;
+		static const int MODE_TEXT = 5;
+		static const int MODE_PARENT = 6;
+		static const int MODE_ENTITY = 7;
+		static const int MODE_SOUND = 8;
+		static const int MODE_LINK = 9;
+		static const int MODE_SPRITE = 10;
+		static const int MODE_PARTICLES = 11;
+																
+		std::vector<ScreenEntity*> layers;
+		
+		ScreenEntity *currentLayer;
+		
+		PropList *entityProps;
+		
+		ScreenEntity *layerBaseEntity;		
+						
+		ScreenEntity *selectedEntity;
+		std::vector<ScreenEntity*> selectedEntities;		
+		
+		Transform2DSheet *transform2dSheet;
+		EntitySheet *entitySheet;
+		ShapeSheet *shapeSheet;
+		ScreenImageSheet *imageSheet;
+		ScreenLabelSheet *labelSheet;
+		SoundSheet *soundSheet;
+		ScreenEntityInstanceSheet *instanceSheet;
+		ScreenSpriteSheet *spriteSheet;
+		ScreenParticleSheet *particleSheet;
+		
+		EntityTreeView *treeView;
+		
+		ScreenEntity *objectBaseEntity;		
+		ScreenEntity *placingPreviewEntity;												
 	protected:
+	
+		bool multiSelect;
+	
+		int gridSize;
+		bool gridSnap;
+	
+		ScreenShape *previewShape;
+		ScreenImage *previewImage;
+		ScreenEntityInstance *previewInstance;		
+		ScreenLabel *previewLabel;							
+		ScreenEntity *previewEntity;
+		ScreenParticleEmitter *previewEmitter;
+							
+		ScreenSound *previewSound;
+		ScreenSprite *previewSprite;
+											
+		ScreenMesh *grid;
+
+		bool firstResize;
+		
+		int placementCount;
+	
+		
+		Number previewAspectRatio;
+
+		bool placing;
+		bool moving;
+		bool scalingY;
+		bool scalingX;		
+		bool rotating;
+		bool panning;
+		bool zooming;
+		
+		bool parenting;
+		ScreenEntity *parentingChild;
+		ScreenLine *parentingLine;
+		
+		
+		int lastMode;
+		
+		Vector2 basePanPosition;
+		
+		Number baseZoomScale;
+		
+		Number baseRotateAngle;
+		
+		int selectedEntityPositionMode;
+		
+		Vector3 baseScale;
+		
+		Vector2 mouseBase;
+		std::vector<Vector2> baseEntityPositions;
+		Number baseAngle;
+	
+		ScreenShape *placingShape;	
+		Vector2 placingAnchor;
 		
 		UIColorBox *entityColorBox;
 		UIWindow *entityInfoWindow;
 		
+		ScreenShape *screenPreviewShape;
+		
 		Vector2 dragOffset;
 		bool isDraggingEntity;
 		bool isScalingEntity;
 		
-		ScreenEntity *selectedEntity;
 		ScreenEntity *baseEntity;
+
 		
-		UIBox *screenTransform;
-	
+		ScreenEntity *screenTransform;
+		ScreenShape *screenTransformShape;
+		ScreenImage *transformRotator;
+
+		ScreenImage *transformScalerY;
+		ScreenImage *transformScalerX;		
+					
 		ScreenImage *centerImage;
-		ScreenImage *grid;	
+		
+		ScreenEntity *properties;
+		ScreenShape *propertiesBg;
+
+		ScreenEntity *viewOptions;
+		ScreenShape *viewOptionsBg;
+		
+		UITextInput *gridSizeInput;
+		UICheckBox *gridCheckBox;
+		
+		UICheckBox *pixelSnapBox;
+		UICheckBox *gridSnapBox;
+		
+		UITextInput *scaleInput;
+		
+		ScreenEntity *toolPalette;
+		ScreenShape *toolPaletteBg;
+		
+		UIButton *resetZoom;
+		
+		UIImageButton *arrowToolButton;
+		UIImageButton *shapeToolButton;
+		UIImageButton *zoomToolButton;
+		UIImageButton *panToolButton;
+		UIImageButton *imageToolButton;
+		UIImageButton *textToolButton;
+		UIImageButton *parentToolButton;
+		UIImageButton *entityToolButton;
+		UIImageButton *soundToolButton;
+		UIImageButton *spriteToolButton;
+		UIImageButton *particlesToolButton;
+				
+		UIImageButton *linkToolButton;
+						
+		UIComboBox *aspectComboBox;
+		UIComboBox *zoomComboBox;
+		
+		UIButton *moveUpButton;
+		UIButton *moveDownButton;
+		UIButton *moveTopButton;
+		UIButton *moveBottomButton;
+		UIButton *unparentButton;
+								
+		Number zooms[16];
+						
+		Number aspects[16];
+				
+		ScreenImage *selectorImage;
+		int mode;	
+};
+
+class PolycodeScreenEditor : public PolycodeEditor {
+	public:
+		PolycodeScreenEditor();
+		virtual ~PolycodeScreenEditor();
+	
+		bool openFile(OSFileEntry filePath);
+		void Resize(int x, int y);
+		
+		void Activate();		
+		
+		void saveCurveToObject(ObjectEntry *entry, BezierCurve *curve);
+		void saveEntityToObjectEntry(ScreenEntity *entity, ObjectEntry *entry);
+		void saveFile();
+					
+		void handleDroppedFile(OSFileEntry file, Number x, Number y);
+
+		void handleEvent(Event *event);
+
+	protected:
+
+		UIHSizer *mainSizer;
+		PropertiesSizer *propSizer;
+		EntityTreeView *treeView;
+		PolycodeScreenEditorMain *editorMain;
 };
 
 class PolycodeScreenEditorFactory : public PolycodeEditorFactory {
 	public:
-		PolycodeScreenEditorFactory() : PolycodeEditorFactory() { extensions.push_back("screen"); }
+		PolycodeScreenEditorFactory() : PolycodeEditorFactory() { extensions.push_back("entity2d"); }
 		PolycodeEditor *createEditor() { return new PolycodeScreenEditor(); }
 };

+ 87 - 0
IDE/Contents/Include/PolycodeSpriteEditor.h

@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+ 
+#pragma once
+
+#include "PolycodeEditor.h"
+#include <Polycode.h>
+#include "PolycodeProps.h"
+
+using namespace Polycode;
+
+class SpriteAnimationEntry : public UIElement {
+	public:
+		SpriteAnimationEntry(SpriteAnimation *animation);
+		~SpriteAnimationEntry();
+		
+		void handleEvent(Event *event);
+		
+		UITextInput *nameInput;
+		UITextInput *framesInput;
+		UITextInput *speedInput;
+						
+		UIImageButton *removeButton;
+		UIImageButton *playButton;	
+		
+		SpriteAnimation *animation;
+};
+
+class PolycodeSpriteEditor : public PolycodeEditor {
+	public:
+	PolycodeSpriteEditor();
+	virtual ~PolycodeSpriteEditor();
+	
+	void handleEvent(Event *event);
+	
+	bool openFile(OSFileEntry filePath);
+	void Resize(int x, int y);
+	
+	void saveFile();
+			
+	protected:
+	
+	void refreshAnimationEntries();
+	
+	std::vector<SpriteAnimationEntry*> animationEntries;
+	
+	UIElement *animationsAnchor;
+	
+	UIButton *addAnimationButton;
+	
+	PropList *propList;
+	
+	ScreenShape *headerBg;	
+	
+	UIComboBox *zoomBox;
+	
+	TextureProp *textureProp;
+	NumberProp *widthProp;
+	NumberProp *heightProp;	
+	
+	ScreenSprite *previewSprite;
+};
+
+class PolycodeSpriteEditorFactory : public PolycodeEditorFactory {
+	public:
+		PolycodeSpriteEditorFactory() : PolycodeEditorFactory() { extensions.push_back("sprite"); }
+		PolycodeEditor *createEditor() { return new PolycodeSpriteEditor(); }
+};

+ 109 - 0
IDE/Contents/Include/TextureBrowser.h

@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "PolycodeGlobals.h"
+#include "PolycodeUI.h"
+#include "Polycode.h"
+#include "PolycodeProject.h"
+#include "OSBasics.h"
+
+using namespace Polycode;
+
+class FolderUserData  {
+public:
+	String folderPath;
+	int type;
+};
+
+class AssetEntry : public UIElement {
+	public:
+		AssetEntry(String assetPath, String assetName, String extension);
+		~AssetEntry();
+		
+		ScreenShape *imageShape;
+		ScreenLabel *nameLabel;
+		
+		String assetPath;
+		
+		ScreenShape *selectShape;
+};
+
+class AssetList : public UIElement {
+	public:
+		AssetList();
+		~AssetList();
+		
+		void handleEvent(Event *event);
+		
+		bool hasExtension(String extension);
+		
+		void showFolder(String folderPath);
+		String selectedPath;
+		
+		void setExtensions(std::vector<String> extensions);
+		
+	protected:
+	
+		String currentFolderPath;
+		ScreenShape *bgShape;
+	
+		AssetEntry *currentEntry;		
+		std::vector<AssetEntry*> assetEntries;
+		
+		std::vector<String> extensions;
+};
+
+class AssetBrowser : public UIWindow {
+	public:
+		AssetBrowser();
+		~AssetBrowser();
+	
+		String getSelectedAssetPath();
+	
+		void parseFolderIntoTree(UITree *tree, OSFileEntry folder);
+
+		String getTemplatePath();
+		String getFileName();
+		
+		void setExtensions(std::vector<String> extensions);
+		
+		void setProject(PolycodeProject *project);
+		
+		void handleEvent(Event *event);
+	
+	protected:
+	
+		AssetList *assetList;
+		UIScrollContainer *listContainer;
+	
+		PolycodeProject *currentProject;
+	
+		UIButton *cancelButton;
+		UIButton *okButton;
+		
+		String templatePath;
+			
+		UITreeContainer *templateContainer;	
+		UITree *defaultTemplateTree;
+};

BIN
IDE/Contents/Resources/FileTemplates/2D/2D Entity.entity2d


+ 6 - 0
IDE/Contents/Resources/FileTemplates/2D/Sprite.sprite

@@ -0,0 +1,6 @@
+<?xml version="1.0" ?>
+<sprite>
+    <image frameWidth="32" frameHeight="32" fileName="default/default.png" />
+    <animations>
+    </animations>
+</sprite>

BIN
IDE/Contents/Resources/Images/ScreenEditor/arrow.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/entity_marker.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/image.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/link.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/pan.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/screenCenter.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/screen_entity.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/screen_sound.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/screen_sound_icon.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/selector.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/shape.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/sound.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/sprite_icon.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/text.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/transform_base.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/transform_rotator.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/transform_scaler.png


BIN
IDE/Contents/Resources/Images/ScreenEditor/zoom.png


BIN
IDE/Contents/Resources/Images/arrow_add.png


BIN
IDE/Contents/Resources/Images/arrow_remove.png


BIN
IDE/Contents/Resources/Images/bezier_handle.png


BIN
IDE/Contents/Resources/Images/bezier_point.png


BIN
IDE/Contents/Resources/Images/collapse.png


BIN
IDE/Contents/Resources/Images/curve_editor_bg.png


BIN
IDE/Contents/Resources/Images/curve_icon.png


BIN
IDE/Contents/Resources/Images/entity_icon.png


BIN
IDE/Contents/Resources/Images/expand.png


BIN
IDE/Contents/Resources/Images/font_icon.png


BIN
IDE/Contents/Resources/Images/invisible.png


BIN
IDE/Contents/Resources/Images/link_entity.png


BIN
IDE/Contents/Resources/Images/new_layer.png


BIN
IDE/Contents/Resources/Images/particle_system_icon.png


BIN
IDE/Contents/Resources/Images/particle_system_icon_editor.png


Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff