Procházet zdrojové kódy

Added new SceneSprite into Polycode proper, made SpriteSets into ResourcePools, added ability to link SpriteSets to entities in entity editor, adding sprites now looks for sprites in linked resource pools

Ivan Safrin před 11 roky
rodič
revize
207ed4ddbf

+ 2 - 2
Core/Contents/Include/PolyResource.h

@@ -57,8 +57,8 @@ namespace Polycode {
 			static const int RESOURCE_PROGRAM = 3;
 			static const int RESOURCE_MESH = 5;
 			static const int RESOURCE_CUBEMAP = 6;
-			static const int RESOURCE_SCREEN_SPRITE = 7;	
-			static const int RESOURCE_SCREEN_ENTITY_INSTANCE = 8;
+			static const int RESOURCE_SPRITE = 7;
+			static const int RESOURCE_ENTITY_INSTANCE = 8;
 			
 			bool reloadOnFileModify;
         

+ 156 - 143
Core/Contents/Include/PolySceneSprite.h

@@ -23,154 +23,167 @@ THE SOFTWARE.
 #pragma once
 #include "PolyGlobals.h"
 #include "PolyScenePrimitive.h"
+#include "PolyCore.h"
+#include "PolyResourceManager.h"
 #include <vector>
 
 namespace Polycode {
 
-class SceneSpriteResourceEntry;
-
-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;
-};
-
-/**
-* Animated 2D image sprite. This screen entity can load spritesheet images and play back animations.
-*/
-class _PolyExport SceneSprite : public ScenePrimitive 
-{
-	public:
-	
-		/**
-		* Create a sprite from a sprite file format
-		* @param fileName Sprite file to load
-		*/
-		SceneSprite(const String& fileName);
-	
-		/**
-		* Create a sprite from a spritesheet image of specified size.
-		* @param fileName Image file to load spritesheet from.
-		* @param spriteWidth Pixel width of each sprite cell.
-		* @param spriteWidth Pixel height of each sprite cell.		
-		*/
-		SceneSprite(const String& fileName, Number spriteWidth, Number spriteHeight);
-		
-		/**
-		* Create a sprite from a spritesheet image of specified size.
-		* @param fileName Image file to load spritesheet from.
-		* @param spriteWidth Pixel width of each sprite cell.
-		* @param spriteWidth Pixel height of each sprite cell.		
-		*/		
-		static SceneSprite* SceneSpriteFromImageFile(const String& fileName, Number spriteWidth, Number spriteHeight);
-		
-		virtual ~SceneSprite();
-		
-		virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly) const;
-		virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) const;
-
-		/**
-		* Adds a new animation to the sprite. Animations are added by specifying a list of frame indexes and then can be played back by the specified name.
-		* @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
-		*/
-		SpriteAnimation *addAnimation(const String& name, const String& frames, Number speed);
-		
-		/**
-		* Shows a specific frame of the current animation.
-		* @param frameIndex Frame index of the frame to show.
-		*/
-		void showFrame(unsigned int frameIndex);
-		
-		/**
-		* Play back a previously created animation by name.
-		* @param name Name of the animation to play.
-		* @param startFrame Starting frame for playback.
-		* @param once If true, only plays once, otherwise loops.
-		*/
-		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 setSpriteFilename(String fileName);
-	
-		void recalculateSpriteDimensions();
     
-        void setActualSpriteSize(Number width, Number height);
-        Vector2 getActualSpriteSize();
+    class SpriteFrame {
+    public:
+        Polycode::Rectangle coordinates;
+        Vector2 anchorPoint;
+        unsigned int frameID;
+    };
     
-		bool loadFromFile(const String& fileName);
-		
-		void reloadSprite();
-		
-		void removeAnimation(SpriteAnimation *animation);
-	
-		/**
-		* Pauses or unpauses the current sprite animation.
-		* @param val If true, pauses the current animation, if false, resumes playing it.
-		*/ 
-		void Pause(bool val);
-		
-		unsigned int getNumAnimations();		
-		SpriteAnimation *getAnimationAtIndex(unsigned int index);
-		
-		SpriteAnimation *getCurrentAnimation();
-		unsigned int getCurrentAnimationFrame();
-		bool isCurrentAnimationFinished();
-		
-		void updateSprite();
-		
-		SceneSpriteResourceEntry *getResourceEntry();
-		
-	protected:
-	
-		String fileName;
-        Vector2 actualSpriteSize;
+    class SpriteSet;
     
-		bool paused;
-	
-		Number spriteWidth;
-		Number spriteHeight;
-			
-		bool playingOnce;
-		double lastTick;
-		
-		SceneSpriteResourceEntry *resourceEntry;
-		
-		Number spriteUVWidth;
-		Number spriteUVHeight;
-		int currentFrame;
-		SpriteAnimation *currentAnimation;
-		
-		std::vector<SpriteAnimation*> animations;
-};
-
-class SceneSpriteResourceEntry : public Resource {
-	public:
-		SceneSpriteResourceEntry(SceneSprite *sprite);
-		virtual ~SceneSpriteResourceEntry();		
-		SceneSprite *getSprite();
-		void reloadResource();
-		
-	protected:
-		SceneSprite* sprite;
-};
-	
+    class SpriteState {
+    public:
+        SpriteState(SpriteSet *spriteSet, String name);
+        
+        void setName(String name);
+        String getName() const;
+        
+        void POLYIGNORE appendFrames(std::vector<unsigned int> newFrameIDs);
+        
+        unsigned int getNumFrameIDs();
+        unsigned int getFrameIDAtIndex(unsigned int index);
+        
+        Mesh *getMeshForFrameIndex(unsigned int index);
+        
+        void insertFrame(unsigned int index, unsigned int frameID);
+        
+        void POLYIGNORE setNewFrameIDs(std::vector<unsigned int> newIDs);
+        
+        void removeFrameByIndex(unsigned int frameIndex);
+        void POLYIGNORE removeFrameIndices(std::vector<unsigned int> indices);
+        void clearFrames();
+        
+        void setPixelsPerUnit(Number ppu);
+        Number getPixelsPerUnit();
+        
+        void rebuildStateMeshes();
+        
+        void setStateFPS(Number fps);
+        Number getStateFPS();
+        
+        void setBoundingBox(Vector2 boundingBox);
+        Vector2 getBoundingBox();
+        
+        Vector2 getSpriteOffset();
+        void setSpriteOffset(const Vector2 &offset);
+        
+    protected:
+        
+        Vector2 boundingBox;
+        Vector2 spriteOffset;
+        Number pixelsPerUnit;
+        Number stateFPS;
+        SpriteSet *spriteSet;
+        String name;
+        std::vector<unsigned int> frameIDs;
+        std::vector<Mesh*> frameMeshes;
+    };
+    
+    class SpriteSet;
+    
+    class Sprite : public Resource {
+    public:
+        Sprite(String name);
+        ~Sprite();
+        
+        String getName();
+        void setName(String name);
+        
+        void addSpriteState(SpriteState *state);
+        void removeSpriteState(SpriteState *state);
+        
+        unsigned int getNumStates();
+        SpriteState *getState(unsigned int index);
+        
+        void setParentSpritSet(SpriteSet *spriteSet);
+        SpriteSet *getParentSpriteSet();
+        
+    protected:
+        String name;
+        SpriteSet *parentSpriteSet;
+        std::vector<SpriteState*> states;
+    };
+    
+    class SpriteSet : public ResourcePool {
+    public:
+        SpriteSet(String imageFileName, ResourcePool *parentPool);
+        ~SpriteSet();
+        
+        void setTexture(Texture *texture);
+        Texture *getTexture();
+        Texture *loadTexture(String imageFileName);
+        
+        void addSpriteEntry(Sprite *newEntry);
+        unsigned int getNumSpriteEntries() const;
+        Sprite *getSpriteEntry(unsigned int index) const;
+        void removeSprite(Sprite *sprite);
+        
+        void loadSpriteSet(String fileName);
+        
+        // frame manipulation
+        void addSpriteFrame(const SpriteFrame &frame, bool assignID = true);
+        unsigned int getNumFrames() const;
+        SpriteFrame getSpriteFrame(unsigned int index) const;
+        
+        SpriteFrame getSpriteFrameByID(unsigned int frameID) const;
+        void removeFrameByID(unsigned int frameID);
+        
+        void setSpriteFrame(const SpriteFrame &frame);
+        
+        void clearFrames();
+        
+        // automatic frame generation
+        void createGridFrames(Number width, Number height, const Vector2 &defaultAnchor);
+        void createFramesFromIslands(unsigned int minDistance, const Vector2 &defaultAnchor);
+        
+    protected:
+        
+        unsigned int nextFrameIDIndex;
+        Texture *spriteTexture;
+        std::vector<SpriteFrame> frames;
+        std::vector<Sprite*> sprites;
+    };
+    
+    class SceneSprite : public SceneMesh {
+    public:
+        SceneSprite(SpriteSet *spriteSet);
+        ~SceneSprite();
+        
+        SpriteSet *getSpriteSet();
+        Sprite *getCurrentSprite();
+        
+        void setCurrentFrame(unsigned int frameIndex);
+        unsigned int getCurrentFrame();
+        void Update();
+        void Render();
+        
+        void setPaused(bool val);
+        bool isPaused();
+        
+        void setSprite(Sprite *spriteEntry);
+        void setSpriteState(SpriteState *spriteState);
+        SpriteState *getCurrentSpriteState();
+        
+        
+    protected:
+        
+        bool paused;
+        Core *core;
+        unsigned int currentFrame;
+        Mesh *defaultMesh;
+        Sprite *currentSprite;
+        SpriteState *currentSpriteState;
+        SpriteSet *spriteSet;
+        Number spriteTimer;
+        Number spriteTimerVal;
+        
+    };
 }

+ 31 - 15
Core/Contents/Source/PolySceneEntityInstance.cpp

@@ -33,7 +33,7 @@
 
 using namespace Polycode;
 
-SceneEntityInstanceResourceEntry::SceneEntityInstanceResourceEntry(SceneEntityInstance *instance)  : Resource(Resource::RESOURCE_SCREEN_ENTITY_INSTANCE) {
+SceneEntityInstanceResourceEntry::SceneEntityInstanceResourceEntry(SceneEntityInstance *instance)  : Resource(Resource::RESOURCE_ENTITY_INSTANCE) {
 	this->instance = instance;
 }
 
@@ -285,6 +285,7 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit
             SceneEntityInstance *instance = new SceneEntityInstance(parentScene, filePath);
             entity = instance;
          } else if(entityType->stringVal == "SceneSprite") {
+             /*
 			ObjectEntry *spriteEntry = (*entry)["SceneSprite"];
 			String filePath = (*spriteEntry)["filePath"]->stringVal;
 			
@@ -294,6 +295,7 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit
 			sprite->playAnimation(animName, -1, false);
 			entity = sprite;
             applySceneMesh((*entry)["SceneMesh"], sprite);
+              */
         } else 	if(entityType->stringVal == "SceneLabel") {
 			ObjectEntry *labelEntry = (*entry)["SceneLabel"];
 			
@@ -635,21 +637,35 @@ bool SceneEntityInstance::loadFromFile(const String& fileName) {
                 }
             }
         }
-        ObjectEntry *matFiles = (*settings)["matFiles"];
-        for(int i=0; i < matFiles->length; i++) {
-            ObjectEntry *matFile = (*matFiles)[i];
-            if(matFile) {
-                ObjectEntry *path = (*matFile)["path"];
-                if(path) {
-                    ResourcePool *newPool = CoreServices::getInstance()->getResourceManager()->getResourcePoolByName(path->stringVal);
-                    if(!newPool) {
-                        newPool = new ResourcePool(path->stringVal,  CoreServices::getInstance()->getResourceManager()->getGlobalPool());
-                        newPool->deleteOnUnsubscribe = true;
-                        CoreServices::getInstance()->getMaterialManager()->loadMaterialLibraryIntoPool(newPool, path->stringVal);
-                        CoreServices::getInstance()->getResourceManager()->addResourcePool(newPool);
+        ObjectEntry *resPools = (*settings)["linkedResourcePools"];
+        if(resPools) {
+            for(int i=0; i < resPools->length; i++) {
+                ObjectEntry *resPool = (*resPools)[i];
+                if(resPool) {
+                    ObjectEntry *path = (*resPool)["path"];
+                    if(path) {
+                        ResourcePool *newPool = CoreServices::getInstance()->getResourceManager()->getResourcePoolByName(path->stringVal);
+                        
+                        if(!newPool) {
+                            
+                            String extension = path->stringVal.substr(path->stringVal.find_last_of(".")+1, path->stringVal.length());
+                            
+                            if(extension == "mat") {
+                                newPool = new ResourcePool(path->stringVal,  CoreServices::getInstance()->getResourceManager()->getGlobalPool());
+                                newPool->deleteOnUnsubscribe = true;
+                                CoreServices::getInstance()->getMaterialManager()->loadMaterialLibraryIntoPool(newPool, path->stringVal);
+                            } else if( extension == "sprites") {
+                                SpriteSet *spriteSet = new SpriteSet(path->stringVal,  CoreServices::getInstance()->getResourceManager()->getGlobalPool());
+                                spriteSet->deleteOnUnsubscribe = true;
+                                newPool = spriteSet;
+                                
+                            }
+                            
+                            CoreServices::getInstance()->getResourceManager()->addResourcePool(newPool);
+                        }
+                        
+                        linkResourcePool(newPool);
                     }
-                    
-                    linkResourcePool(newPool);
                 }
             }
         }

+ 640 - 333
Core/Contents/Source/PolySceneSprite.cpp

@@ -25,405 +25,712 @@
 #include "PolyCoreServices.h"
 #include "PolyMesh.h"
 #include "PolyTexture.h"
+#include "PolyLogger.h"
 
 using std::vector;
 using namespace Polycode;
 
-SceneSpriteResourceEntry::SceneSpriteResourceEntry(SceneSprite *sprite)  : Resource(Resource::RESOURCE_SCREEN_ENTITY_INSTANCE) {
-	this->sprite = sprite;
+
+SceneSprite::SceneSprite(SpriteSet *spriteSet) : SceneMesh(Mesh::QUAD_MESH) {
+    currentSprite = NULL;
+    currentSpriteState = NULL;
+    this->spriteSet = spriteSet;
+    defaultMesh = mesh;
+    currentFrame = 0;
+    core = Services()->getCore();
+    spriteTimer = 0.0;
+    paused = false;
+    spriteTimerVal = 0.1;
+    setTexture(spriteSet->getTexture());
 }
 
-SceneSpriteResourceEntry::~SceneSpriteResourceEntry() {
+SpriteState *SceneSprite::getCurrentSpriteState() {
+    return currentSpriteState;
+}
 
+SpriteSet *SceneSprite::getSpriteSet() {
+    return spriteSet;
 }
 
-SceneSprite *SceneSpriteResourceEntry::getSprite() {
-	return sprite;
+Sprite *SceneSprite::getCurrentSprite() {
+    return currentSprite;
 }
 
-void SceneSpriteResourceEntry::reloadResource() {
-	sprite->reloadSprite();
-	Resource::reloadResource();
+void SceneSprite::setPaused(bool val) {
+    paused = val;
 }
 
-SceneSprite* SceneSprite::SceneSpriteFromImageFile(const String& fileName, Number spriteWidth, Number spriteHeight) {
-	return new SceneSprite(fileName, spriteWidth, spriteHeight);
+bool SceneSprite::isPaused() {
+    return paused;
 }
 
-SceneSprite::SceneSprite(const String& fileName) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
+void SceneSprite::setCurrentFrame(unsigned int frameIndex) {
+    currentFrame = frameIndex;
+}
 
-	currentFrame = 0;
-	currentAnimation = NULL;	
-	paused = false;
+void SceneSprite::setSprite(Sprite *spriteEntry) {
+    currentSprite = spriteEntry;
+}
 
-	resourceEntry = new SceneSpriteResourceEntry(this);
-	loadFromFile(fileName);
-	resourceEntry->setResourceName(fileName);
-	resourceEntry->setResourcePath(fileName);	
+void SceneSprite::setSpriteState(SpriteState *spriteState) {
+    currentSpriteState = spriteState;
+    
+    if(!currentSpriteState) {
+        return;
+    }
+    
+    Vector2 bBox = spriteState->getBoundingBox();
+    setLocalBoundingBox(bBox.x / spriteState->getPixelsPerUnit(), bBox.y / spriteState->getPixelsPerUnit(), 0.001);
 }
 
-SceneSprite::SceneSprite(const String& fileName, Number spriteWidth, Number spriteHeight) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
-	this->spriteWidth = spriteWidth;
-	this->spriteHeight = spriteHeight;
-	loadTexture(fileName);
-    resourceEntry = NULL;
+void SceneSprite::Update() {
     
-	currentFrame = 0;
-	currentAnimation = NULL;
-	paused = false;
-    actualSpriteSize.x = spriteWidth;
-    actualSpriteSize.y = spriteHeight;
+    if(!currentSprite || !currentSpriteState) {
+        return;
+    }
     
-    setSpriteSize(spriteWidth, spriteHeight);
-	setPrimitiveOptions(ScenePrimitive::TYPE_VPLANE, spriteWidth, spriteHeight);
+    setTexture(spriteSet->getTexture());
+    
+    if(paused) {
+        return;
+    }
     
-    recalculateSpriteDimensions();
+    spriteTimer += core->getElapsed();
+    
+    if(spriteTimer > 1.0/currentSpriteState->getStateFPS()) {
+        spriteTimer = 0.0;
+        currentFrame++;
+        if(currentFrame >= currentSpriteState->getNumFrameIDs()) {
+            currentFrame = 0;
+        }
+    }
 }
 
-Entity *SceneSprite::Clone(bool deepClone, bool ignoreEditorOnly) const {
-	SceneSprite *newSprite = new SceneSprite(getTexture()->getResourcePath(), spriteWidth, spriteHeight);
-	for(int i=0; i < animations.size(); i++) {
-		newSprite->addAnimation(animations[i]->name, animations[i]->frames, animations[i]->speed);
-	}
-	if(currentAnimation) {
-		newSprite->playAnimation(currentAnimation->name, currentFrame, playingOnce);
-	}
+unsigned int SceneSprite::getCurrentFrame() {
+    return currentFrame;
+}
+
+void SceneSprite::Render() {
+    
+    if(!currentSprite || !currentSpriteState) {
+        return;
+    }
+    
+    Mesh *stateMesh = currentSpriteState->getMeshForFrameIndex(currentFrame);
+    if(stateMesh) {
+        setMesh(stateMesh);
+    } else {
+        setMesh(defaultMesh);
+    }
+    
+    SceneMesh::Render();
+}
+
+SceneSprite::~SceneSprite() {
+    
+}
+
+SpriteState::SpriteState(SpriteSet *spriteSet, String name) {
+    this->spriteSet = spriteSet;
+    this->name = name;
+    stateFPS = 60.0;
+    pixelsPerUnit = 1.0;
+}
+
+void SpriteState::setBoundingBox(Vector2 boundingBox) {
+    this->boundingBox = boundingBox;
+    rebuildStateMeshes();
+}
+
+void SpriteState::clearFrames() {
+    frameIDs.clear();
+    rebuildStateMeshes();
+}
+
+Vector2 SpriteState::getBoundingBox() {
+    return boundingBox;
+}
+
+Vector2 SpriteState::getSpriteOffset() {
+    return spriteOffset;
+}
+
+void SpriteState::setSpriteOffset(const Vector2 &offset) {
+    spriteOffset = offset;
+    rebuildStateMeshes();
+}
+
+
+void SpriteState::setPixelsPerUnit(Number ppu) {
+    pixelsPerUnit = ppu;
+    rebuildStateMeshes();
+}
+
+Number SpriteState::getPixelsPerUnit() {
+    return pixelsPerUnit;
+}
+
+void SpriteState::removeFrameByIndex(unsigned int index) {
+    if(index < frameIDs.size()) {
+        frameIDs.erase(frameIDs.begin()+index);
+    }
+    rebuildStateMeshes();
+}
+
+void SpriteState::removeFrameIndices(std::vector<unsigned int> indices) {
+    std::vector<unsigned int> newFrames;
     
-    newSprite->setSpriteFilename(fileName);
-	applyClone(newSprite, deepClone, ignoreEditorOnly);
+    for(int i=0; i < frameIDs.size(); i++) {
+        bool hasIndex = false;
+        for(int j=0; j < indices.size(); j++) {
+            if(indices[j] == i) {
+                hasIndex = true;
+                break;
+            }
+        }
+        if(!hasIndex) {
+            newFrames.push_back(frameIDs[i]);
+        }
+    }
     
-    newSprite->setActualSpriteSize(actualSpriteSize.x, actualSpriteSize.y);
+    frameIDs = newFrames;
+    rebuildStateMeshes();
+}
+
+void SpriteState::setStateFPS(Number fps) {
+    stateFPS = fps;
+}
+
+Number SpriteState::getStateFPS() {
+    return stateFPS;
+}
+
+void SpriteState::setName(String name) {
+    this->name = name;
+}
+
+void SpriteState::setNewFrameIDs(std::vector<unsigned int> newIDs) {
+    frameIDs = newIDs;
+    rebuildStateMeshes();
+}
+
+void SpriteState::insertFrame(unsigned int index, unsigned int frameID) {
+    if(index < frameIDs.size()) {
+        frameIDs.insert(frameIDs.begin()+index, frameID);
+    }
+    rebuildStateMeshes();
+}
+
+Mesh *SpriteState::getMeshForFrameIndex(unsigned int index) {
+    if(index < frameMeshes.size()) {
+        return frameMeshes[index];
+    } else {
+        return NULL;
+    }
+}
+
+void SpriteState::rebuildStateMeshes() {
+    for(int i=0; i < frameMeshes.size(); i++) {
+        delete frameMeshes[i];
+    }
+    frameMeshes.clear();
     
-	return newSprite;
+    for(int i=0; i < frameIDs.size(); i++) {
+        Mesh *frameMesh = new Mesh(Mesh::QUAD_MESH);
+        SpriteFrame frame = spriteSet->getSpriteFrameByID(frameIDs[i]);
+        
+        frameMesh->indexedMesh = true;
+        
+        Number aspectRatio = frame.coordinates.w / frame.coordinates.h;
+        Number textureAspectRatio = ((Number)spriteSet->getTexture()->getWidth()) / ((Number)spriteSet->getTexture()->getHeight());
+        
+        
+        Number frameHeight = frame.coordinates.h * ((Number)spriteSet->getTexture()->getHeight()) / pixelsPerUnit;
+        
+        Number frameWidth = frameHeight * aspectRatio * textureAspectRatio;
+        
+        
+        
+        Vector2 meshOffset;
+        meshOffset.x = boundingBox.x * spriteOffset.x / pixelsPerUnit;
+        meshOffset.y = boundingBox.y * spriteOffset.y / pixelsPerUnit;
+        
+        meshOffset.x -= frameWidth * frame.anchorPoint.x;
+        meshOffset.y += frameHeight * frame.anchorPoint.y;
+        
+        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y);
+        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y  - frame.coordinates.h);
+        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0- frame.coordinates.y  - frame.coordinates.h);
+        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0-frame.coordinates.y);
+        
+        frameMesh->addIndexedFace(0,1);
+        frameMesh->addIndexedFace(1,2);
+        frameMesh->addIndexedFace(2,3);
+        frameMesh->addIndexedFace(3,0);
+        
+        frameMesh->dirtyArrays();
+        
+        frameMeshes.push_back(frameMesh);
+    }
+}
+
+String SpriteState::getName() const {
+    return name;
+}
+
+unsigned int SpriteState::getNumFrameIDs() {
+    return frameIDs.size();
+}
+
+unsigned int SpriteState::getFrameIDAtIndex(unsigned int index) {
+    if(index < frameIDs.size()) {
+        return frameIDs[index];
+    } else {
+        return 0;
+    }
 }
 
-void SceneSprite::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) const {
-	ScenePrimitive::applyClone(clone, deepClone, ignoreEditorOnly);
+void SpriteState::appendFrames(std::vector<unsigned int> newFrameIDs) {
+    frameIDs.insert( frameIDs.end(), newFrameIDs.begin(), newFrameIDs.end());
+    rebuildStateMeshes();
 }
 
-void SceneSprite::setSpriteFilename(String fileName) {
-    this->fileName = fileName;
-    if(!resourceEntry) {
-        resourceEntry = new SceneSpriteResourceEntry(this);
+unsigned int Sprite::getNumStates() {
+    return states.size();
+}
+
+SpriteState *Sprite::getState(unsigned int index) {
+    if(index < states.size()) {
+        return states[index];
+    } else {
+        return NULL;
     }
-    resourceEntry->setResourceName(fileName);
-    resourceEntry->setResourcePath(fileName);
 }
 
-bool SceneSprite::loadFromFile(const String& fileName) {
+void Sprite::addSpriteState(SpriteState *state) {
+    states.push_back(state);
+}
+
+Sprite::Sprite(String name) : Resource(Resource::RESOURCE_SPRITE){
+    this->name = name;
+    this->setResourceName(name);
+}
+
+void Sprite::setParentSpritSet(SpriteSet *spriteSet) {
+    parentSpriteSet = spriteSet;
+}
+
+SpriteSet *Sprite::getParentSpriteSet() {
+    return parentSpriteSet;
+}
+
+void Sprite::removeSpriteState(SpriteState *state) {
+    for(int i=0; i < states.size(); i++) {
+        if(states[i] == state) {
+            states.erase(states.begin() + i);
+            return;
+        }
+    }
+}
+
+Sprite::~Sprite() {
+    for(int i=0; i < states.size(); i++) {
+        delete states[i];
+    }
+}
+
+String Sprite::getName() {
+    return name;
+}
+
+void Sprite::setName(String name) {
+    this->name = name;
+}
+
+
+SpriteSet::SpriteSet(String fileName, ResourcePool *parentPool) : ResourcePool(fileName, parentPool) {
+    nextFrameIDIndex = 0;
+    loadSpriteSet(fileName);
+    
+}
+
+void SpriteSet::loadSpriteSet(String fileName) {
 	Object loadObject;
-	
-	animations.clear();
-	
-	if(!loadObject.loadFromXML(fileName)) {
-		return false;
+	if(!loadObject.loadFromBinary(fileName)) {
+        if(!loadObject.loadFromXML(fileName)) {
+            Logger::log("Error loading sprite sheet: %s.\n", fileName.c_str());
+            return;
+        }
 	}
-	
-	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) {
-			actualSpriteSize.x = frameWidth->NumberVal;
-			actualSpriteSize.y = frameHeight->NumberVal;
-			setPrimitiveOptions(ScenePrimitive::TYPE_VPLANE, 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();
+    
+    ObjectEntry *spriteSheetEntry = loadObject.root["sprite_sheet"];
+    if(spriteSheetEntry) {
+        ObjectEntry *fileNameEntry = (*spriteSheetEntry)["fileName"];
+        if(fileNameEntry) {
+            loadTexture(fileNameEntry->stringVal);
+        }
+        
+        ObjectEntry *framesEntry = (*spriteSheetEntry)["frames"];
+        if(framesEntry) {
+            for(int i=0; i < framesEntry->length; i++) {
+                ObjectEntry *frameEntry = (*framesEntry)[i];
+                
+                if(frameEntry) {
+                    SpriteFrame frame;
+                    
+                    ObjectEntry *idEntry = (*frameEntry)["id"];
+                    if(idEntry) {
+                        frame.frameID = idEntry->intVal;
+                    }
+                    
+                    ObjectEntry *xEntry = (*frameEntry)["x"];
+                    if(xEntry) {
+                        frame.coordinates.x = xEntry->NumberVal;
+                    }
+                    ObjectEntry *yEntry = (*frameEntry)["y"];
+                    if(yEntry) {
+                        frame.coordinates.y = yEntry->NumberVal;
+                    }
+                    ObjectEntry *wEntry = (*frameEntry)["w"];
+                    if(wEntry) {
+                        frame.coordinates.w = wEntry->NumberVal;
+                    }
+                    ObjectEntry *hEntry = (*frameEntry)["h"];
+                    if(hEntry) {
+                        frame.coordinates.h = hEntry->NumberVal;
+                    }
+                    ObjectEntry *axEntry = (*frameEntry)["ax"];
+                    if(axEntry) {
+                        frame.anchorPoint.x = axEntry->NumberVal;
+                    }
+                    ObjectEntry *ayEntry = (*frameEntry)["ay"];
+                    if(ayEntry) {
+                        frame.anchorPoint.y = ayEntry->NumberVal;
+                    }
+                    
+                    addSpriteFrame(frame, false);
+                }
+                
+            }
+        }
+        
+    } else {
+        return;
+    }
+    
+    ObjectEntry *spritesEntry = loadObject.root["sprites"];
+    if(spritesEntry) {
+        for(int i=0; i < spritesEntry->length; i++) {
+            ObjectEntry *spriteEntry = (*spritesEntry)[i];
+            if(spriteEntry) {
+                ObjectEntry *nameEntry = (*spriteEntry)["name"];
+                String spriteName;
+                if(nameEntry) {
+                    spriteName = nameEntry->stringVal;
+                }
+                Sprite *newSprite = new Sprite(spriteName);
+                addSpriteEntry(newSprite);
+                
+                ObjectEntry *statesEntry = (*spriteEntry)["states"];
+                
+                if(statesEntry) {
+                    for(int j=0; j < statesEntry->length; j++) {
+                        ObjectEntry *stateEntry = (*statesEntry)[j];
+                        if(stateEntry) {
+                            SpriteState *newState = new SpriteState(this, "");
+                            
+                            ObjectEntry *nameEntry = (*stateEntry)["name"];
+                            if(nameEntry) {
+                                newState->setName(nameEntry->stringVal);
+                            }
+                            
+                            ObjectEntry *fpsEntry = (*stateEntry)["fps"];
+                            if(fpsEntry) {
+                                newState->setStateFPS(fpsEntry->NumberVal);
+                            }
+                            
+                            ObjectEntry *scaleEntry = (*stateEntry)["scale"];
+                            if(scaleEntry) {
+                                newState->setPixelsPerUnit(scaleEntry->NumberVal);
+                            }
+                            
+                            ObjectEntry *widthEntry = (*stateEntry)["width"];
+                            ObjectEntry *heightEntry = (*stateEntry)["height"];
+                            if(widthEntry && heightEntry) {
+                                newState->setBoundingBox(Vector2(widthEntry->NumberVal, heightEntry->NumberVal));
+                            }
+                            
+                            ObjectEntry *xOffsetEntry = (*stateEntry)["offset_x"];
+                            ObjectEntry *yOffsetEntry = (*stateEntry)["offset_y"];
+                            if(xOffsetEntry && yOffsetEntry) {
+                                newState->setSpriteOffset(Vector2(xOffsetEntry->NumberVal, yOffsetEntry->NumberVal));
+                            }
+                            
+                            ObjectEntry *frameIDsEntry = (*stateEntry)["frame_ids"];
+                            
+                            if(frameIDsEntry) {
+                                std::vector<String> frameIDs = frameIDsEntry->stringVal.split(",");
+                                
+                                std::vector<unsigned int> frameIDInts;
+                                for(int f=0; f < frameIDs.size(); f++) {
+                                    frameIDInts.push_back(frameIDs[f].toInteger());
+                                }
+                                
+                                newState->appendFrames(frameIDInts);
+                            }
+                            
+                            newSprite->addSpriteState(newState);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    
+}
 
-	return true;
+void SpriteSet::removeFrameByID(unsigned int frameID) {
+    for(int i=0; i < frames.size(); i++) {
+        if(frames[i].frameID == frameID) {
+            frames.erase(frames.begin() + i);
+            return;
+        }
+    }
 }
 
-unsigned int SceneSprite::getNumAnimations() {
-	return animations.size();
+void SpriteSet::removeSprite(Sprite *sprite) {
+    for(int i=0; i < sprites.size(); i++) {
+        if(sprites[i] == sprite) {
+            removeResource(sprites[i]);
+            sprites.erase(sprites.begin()+i);
+            return;
+        }
+    }
 }
 
-SpriteAnimation *SceneSprite::getAnimationAtIndex(unsigned int index) {
-	if(index < animations.size()) {
-		return animations[index];
-	} else {
-		return NULL;
-	}
+Texture *SpriteSet::loadTexture(String imageFileName) {
+    Texture *spriteTexture = Services()->getMaterialManager()->createTextureFromFile(imageFileName, true, Services()->getMaterialManager()->mipmapsDefault);
+    setTexture(spriteTexture);
+    return spriteTexture;
 }
 
-void SceneSprite::reloadSprite() {
-	
-	String _animName = "";
-	int _currentFrame;
-	bool _playingOnce;
-	
-	if(currentAnimation) {
-		_animName = currentAnimation->name;
-		_currentFrame = currentFrame;
-		_playingOnce = playingOnce;
-	}
-	loadFromFile(fileName);
-	
-	if(_animName != "") {
-		playAnimation(_animName, _currentFrame, _playingOnce);
-	}
+void SpriteSet::addSpriteFrame(const SpriteFrame &frame, bool assignID) {
+    
+    // do not add existing frames
+    for(int i=0; i < frames.size(); i++) {
+        SpriteFrame existingFrame = frames[i];
+        
+        if(existingFrame.coordinates == frame.coordinates) {
+            return;
+        }
+        
+    }
+    
+    frames.push_back(frame);
+    if(assignID) {
+        frames[frames.size()-1].frameID = nextFrameIDIndex;
+        nextFrameIDIndex++;
+    } else {
+        nextFrameIDIndex = frame.frameID + 1;
+    }
+    
 }
 
-SceneSpriteResourceEntry *SceneSprite::getResourceEntry() {
-	return resourceEntry;
+void SpriteSet::setSpriteFrame(const SpriteFrame &frame) {
+    for(int i=0 ;i < frames.size(); i++) {
+        if(frames[i].frameID == frame.frameID) {
+            frames[i].coordinates = frame.coordinates;
+            frames[i].anchorPoint = frame.anchorPoint;
+            return;
+        }
+    }
 }
 
-SceneSprite::~SceneSprite() {
-	
+SpriteFrame SpriteSet::getSpriteFrameByID(unsigned int frameID) const {
+    for(int i=0; i < frames.size(); i++) {
+        if(frames[i].frameID == frameID ){
+            return frames[i];
+        }
+    }
+    return SpriteFrame();
 }
 
-void SceneSprite::removeAnimation(SpriteAnimation *animation) {
-	for(int i=0; i < animations.size(); i++) {
-		if(animations[i] == animation) {
-			animations.erase(animations.begin()+i);
-			return;
-		}
-	}
+unsigned int SpriteSet::getNumFrames() const {
+    return frames.size();
 }
 
-void SceneSprite::setActualSpriteSize(Number width, Number height) {
-    actualSpriteSize.x = width;
-    actualSpriteSize.y = height;
-	setPrimitiveOptions(ScenePrimitive::TYPE_VPLANE, actualSpriteSize.x, actualSpriteSize.y);
-}
-
-Vector2 SceneSprite::getActualSpriteSize() {
-    return actualSpriteSize;
-}
-
-void SceneSprite::recalculateSpriteDimensions() {
-	if(!texture)
-		return;
-		
-	spriteUVWidth = 1.0f / ((Number) texture->getWidth() / spriteWidth);
-	spriteUVHeight = 1.0f / ((Number) texture->getHeight() / spriteHeight);
-	
-	for(int i =0 ; i < animations.size(); i++) {
-		animations[i]->numFramesX = texture->getWidth() / spriteWidth;	
-		if(animations[i]->numFramesX < 1) {
-			animations[i]->numFramesX = 1;
-		}
-		animations[i]->numFramesY = texture->getHeight() / spriteHeight;
-		if(animations[i]->numFramesY < 1) {
-			animations[i]->numFramesY = 1;
-		}		
-		animations[i]->spriteUVWidth = spriteUVWidth;
-		animations[i]->spriteUVHeight = spriteUVHeight;	
-		animations[i]->setOffsetsFromFrameString(animations[i]->frames);
-	}
+SpriteFrame SpriteSet::getSpriteFrame(unsigned int index) const {
+    if(index < frames.size()) {
+        return frames[index];
+    } else {
+        return SpriteFrame();
+    }
 }
 
-Vector2 SceneSprite::getSpriteSize() {
-	return Vector2(spriteWidth, spriteHeight);
-}
-
-String SceneSprite::getFileName() const {
-	return fileName;
-}
-
-void SceneSprite::setSpriteSize(const Number spriteWidth, const Number spriteHeight) {
-	this->spriteWidth = spriteWidth;
-	this->spriteHeight = spriteHeight;	
-	
-	recalculateSpriteDimensions();	
-}
-
-SpriteAnimation *SceneSprite::getCurrentAnimation() {
-	return currentAnimation;
-}
-
-unsigned int SceneSprite::getCurrentAnimationFrame() { 
-   return currentFrame; 
-}
-
-bool SceneSprite::isCurrentAnimationFinished() {
-    if(currentAnimation) {
-        if(currentFrame >= currentAnimation->numFrames)
-            return true;
-    }
-    return false;
-}
-
-void SpriteAnimation::setOffsetsFromFrameString(const String& frames) {
-	framesOffsets.clear();
-	vector<String> frameNumbers = frames.split(",");
-	
-	int frameNumber;
-	int frameX;
-	int frameY;
-	
-	numFrames = 0;
-	
-	for(int i=0; i < frameNumbers.size(); i++) {
-		if(frameNumbers[i].find_first_of("-") != -1) {
-			vector<String> _frameNumbers = frameNumbers[i].split("-");
-			if(_frameNumbers.size() > 1) {
-				int frameNumberStart = atoi(_frameNumbers[0].c_str());
-				int frameNumberEnd = atoi(_frameNumbers[1].c_str());
-				int dir = 1;
-				if(frameNumberEnd < frameNumberStart) {
-					dir = -1;
-				}				
-				for(int j=frameNumberStart; j != frameNumberEnd + dir; j += dir) {
-					frameX = j % numFramesX;
-					frameY = j/numFramesX;
-					framesOffsets.push_back(Vector2(spriteUVWidth * frameX, spriteUVHeight * frameY));
-					numFrames++;
-				}
-			}
-		} else if(frameNumbers[i].find_first_of("x") != -1) {
-			vector<String> _frameNumbers = frameNumbers[i].split("x");
-			if(_frameNumbers.size() > 1) {
-				int _frameNumber = atoi(_frameNumbers[0].c_str());
-				int frameNumberCount = atoi(_frameNumbers[1].c_str());				
-				for(int j=0; j < frameNumberCount; j++) {
-					frameX = _frameNumber % numFramesX;
-					frameY = _frameNumber/numFramesX;
-					framesOffsets.push_back(Vector2(spriteUVWidth * frameX, spriteUVHeight * frameY));
-					numFrames++;					
-				}
-			}				
-		} else {	
-			frameNumber = atoi(frameNumbers[i].c_str());
-			frameX = frameNumber % numFramesX;
-			frameY = frameNumber/numFramesX;
-			framesOffsets.push_back(Vector2(spriteUVWidth * frameX, spriteUVHeight * frameY));
-			numFrames++;			
-		}
-	}
-	
-	this->frames = frames;
+void SpriteSet::addSpriteEntry(Sprite *newEntry) {
+    addResource(newEntry);
+    newEntry->setParentSpritSet(this);
+    sprites.push_back(newEntry);
+}
 
+unsigned int SpriteSet::getNumSpriteEntries() const {
+    return sprites.size();
 }
 
-SpriteAnimation *SceneSprite::addAnimation(const String& name, const String& frames, Number speed) {
-	SpriteAnimation *newAnimation = new SpriteAnimation();	
-	
-	
-	newAnimation->numFramesX = texture->getWidth() / spriteWidth;	
-	if(newAnimation->numFramesX < 1) {
-		newAnimation->numFramesX = 1;
-	}
-	newAnimation->numFramesY = texture->getHeight() / spriteHeight;
-	if(newAnimation->numFramesY < 1) {
-		newAnimation->numFramesY = 1;
-	}	
-	newAnimation->spriteUVWidth = spriteUVWidth;
-	newAnimation->spriteUVHeight = spriteUVHeight;
-	
-	newAnimation->setOffsetsFromFrameString(frames);
-			
-	newAnimation->speed = speed;
-	newAnimation->name = name;
-	animations.push_back(newAnimation);
-	return newAnimation;
-}
-
-void SceneSprite::playAnimation(const String& name, int startFrame, bool once) {
-	paused = false;
-	for(int i=0; i < animations.size(); i++) {
-		if(animations[i]->name == name) {
-			if(currentAnimation == animations[i] && !playingOnce && !once)
-				return;
-			currentFrame = 0;			
-			currentAnimation = animations[i];
-			if(startFrame == -1) {
-				currentFrame = rand() % currentAnimation->numFrames;
-			} else {
-				if(startFrame < currentAnimation->numFrames) {
-					currentFrame = startFrame;
-				}
-			}
-			playingOnce = once;
-			lastTick = 0;
-		}
-	}
+Sprite *SpriteSet::getSpriteEntry(unsigned int index) const {
+    if(index < sprites.size()) {
+        return sprites[index];
+    } else {
+        return NULL;
+    }
 }
 
-void SceneSprite::Pause(bool val) {
-	paused = val;
+void SpriteSet::setTexture(Texture *texture) {
+    spriteTexture = texture;
 }
 
-void SceneSprite::showFrame(unsigned int frameIndex) {
-	if(!currentAnimation)
-		return;
+Texture *SpriteSet::getTexture() {
+    return spriteTexture;
+}
 
-	if(frameIndex < currentAnimation->numFrames) {
-		currentFrame = frameIndex;
-		updateSprite();
-	}
+SpriteSet::~SpriteSet() {
+    
 }
 
-void SceneSprite::Update() {
-	if(!currentAnimation)
-		return;
-	
-	double newTick = CoreServices::getInstance()->getCore()->getTicksFloat();
-	
-	Number elapsed = Number(newTick - lastTick);
-	
-	if(paused)
-		return;
-	
-	if(elapsed > currentAnimation->speed) {
-	currentFrame++;
-	if(currentFrame >= currentAnimation->numFrames) {
-		if(playingOnce) {
-			dispatchEvent(new Event(), Event::COMPLETE_EVENT);
-			return;			
-		} else {
-			currentFrame = 0;
-		}
-	}
-	
-	updateSprite();
-			
-	lastTick = newTick;
-		
-	}
+void SpriteSet::clearFrames() {
+    frames.clear();
+    nextFrameIDIndex = 0;
 }
 
-void SceneSprite::updateSprite() {
-	Number xOffset = currentAnimation->framesOffsets[currentFrame].x;
-	Number yOffset = 1.0f - currentAnimation->framesOffsets[currentFrame].y - spriteUVHeight;
+void SpriteSet::createGridFrames(Number width, Number height, const Vector2 &defaultAnchor) {
+    
+    for(Number x = 0.0; x+width <= 1.0; x += width) {
+        for(Number y = 0.0; y+height <= 1.0; y += height) {
+            SpriteFrame frame;
+            frame.coordinates = Polycode::Rectangle(x, y, width, height);
+            frame.anchorPoint = defaultAnchor;
+            addSpriteFrame(frame);
+        }
+    }
+}
 
-	mesh->getVertex(0)->setTexCoord(xOffset, yOffset);
-	mesh->getVertex(1)->setTexCoord(xOffset+spriteUVWidth, yOffset);
-	mesh->getVertex(2)->setTexCoord(xOffset+spriteUVWidth, yOffset+spriteUVHeight);
-	
-	mesh->getVertex(3)->setTexCoord(xOffset, yOffset);	;
-	mesh->getVertex(4)->setTexCoord(xOffset+spriteUVWidth, yOffset+spriteUVHeight);
-	mesh->getVertex(5)->setTexCoord(xOffset, yOffset+spriteUVHeight);
+Polycode::Rectangle createBoxAtCoordinate(Image *image, unsigned int x, unsigned int y) {
+    Polycode::Rectangle rect;
+    
+    rect.x = x;
+    rect.y = y;
+    
+    while(x < image->getWidth()) {
+        if(image->getPixel(x, y).a == 0.0) {
+            break;
+        }
+        x++;
+    }
+    rect.w = x - rect.x;
+    
+    // look down at first x
+    Number y1 = y;
+    while(y1 < image->getHeight()) {
+        if(image->getPixel(rect.x, y1).a == 0.0) {
+            break;
+        }
+        y1++;
+    }
+    Number h1 = y1;
+    
+    // look down at last x
+    while(y < image->getHeight()) {
+        if(image->getPixel(x, y).a == 0.0) {
+            break;
+        }
+        y++;
+    }
+    Number h2 = y;
+    
+    if(h1 > h2) {
+        h2 = h1;
+    }
+    
+    rect.h = h2 - rect.y;
+    
     
-	mesh->arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;
+    
+    return rect;
+}
 
+bool rectIntersect(const Polycode::Rectangle &r1, const Polycode::Rectangle &r2, Number minDistance) {
+    return !(r2.x - minDistance > r1.x + r1.w ||
+             r2.x + r2.w + minDistance < r1.x ||
+             r2.y - minDistance > r1.y + r1.h ||
+             r2.y + r2.h + minDistance < r1.y);
+}
+
+void SpriteSet::createFramesFromIslands(unsigned int minDistance, const Vector2 &defaultAnchor) {
+    String imageFileName = getTexture()->getResourcePath();
+    
+    Image *image = new Image(imageFileName);
+    
+    
+    std::vector<Polycode::Rectangle> rects;
+    
+    for(int y=0; y < image->getHeight(); y++) {
+        for(int x=0; x < image->getWidth(); x++) {
+            if(image->getPixel(x, y).a > 0.0) {
+                Polycode::Rectangle rect = createBoxAtCoordinate(image,x,y);
+                rects.push_back(rect);
+                x += rect.w;
+            }
+        }
+    }
+    
+    while(rects.size() > 1) {
+        
+        bool intersected = false;
+        for(int i=0; i < rects.size(); i++) {
+            for(int i2=0; i2 < rects.size(); i2++) {
+                if(i != i2) {
+                    if(rectIntersect(rects[i], rects[i2], minDistance)) {
+                        
+                        Polycode::Rectangle newRect;
+                        
+                        newRect.x = std::min(rects[i].x, rects[i2].x);
+                        newRect.y = std::min(rects[i].y, rects[i2].y);
+                        
+                        newRect.w = std::max(rects[i].x + rects[i].w, rects[i2].x + rects[i2].w) - newRect.x;
+                        newRect.h = std::max(rects[i].y + rects[i].h, rects[i2].y + rects[i2].h) - newRect.y;
+                        
+                        rects[i] = newRect;
+                        rects.erase(rects.begin() + i2);
+                        
+                        intersected = true;
+                        
+                        break;
+                    }
+                }
+            }
+        }
+        
+        if(!intersected) {
+            break;
+        }
+        
+    }
+    
+    
+    for(int i=0; i < rects.size(); i++) {
+        SpriteFrame frame;
+        frame.coordinates = rects[i];
+        
+        frame.coordinates.x = frame.coordinates.x / ((Number)image->getWidth());
+        frame.coordinates.y = frame.coordinates.y / ((Number)image->getHeight());
+        frame.coordinates.w = frame.coordinates.w / ((Number)image->getWidth());
+        frame.coordinates.h = frame.coordinates.h / ((Number)image->getHeight());
+        
+        frame.anchorPoint = defaultAnchor;
+        
+        addSpriteFrame(frame);
+    }
+    
+    delete image;
 }

+ 1 - 1
IDE/Contents/Include/EntityEditorPropertyView.h

@@ -56,7 +56,7 @@ class EntityEditorPropertyView : public UIElement {
         SceneLightSheet *lightSheet;
         ParticleEmitterSheet *particleSheet;
         SceneLabelSheet *labelSheet;
-        SceneSpriteSheet *spriteSheet;
+    //    SceneSpriteSheet *spriteSheet;
         SoundSheet *soundSheet;
         CameraSheet *cameraSheet;
         EntityPropSheet *propSheet;

+ 4 - 3
IDE/Contents/Include/PolycodeProps.h

@@ -427,7 +427,7 @@ class TextureProp : public PropProp {
 		String lastData;
 		String currentData;
 };
-
+/*
 class SceneSpriteProp : public PropProp {
 	public:
 		SceneSpriteProp(String caption);
@@ -445,7 +445,7 @@ class SceneSpriteProp : public PropProp {
 		String lastData;
 		String currentData;
 };
-
+*/
 
 class SceneEntityInstanceProp : public PropProp {
 	public:
@@ -806,7 +806,7 @@ class SceneLabelSheet : public PropSheet {
 		ComboProp *font;
 		BoolProp *enableAA;
 };
-
+/*
 class SceneSpriteSheet : public PropSheet {
 	public:
 		SceneSpriteSheet();
@@ -821,6 +821,7 @@ class SceneSpriteSheet : public PropSheet {
         NumberProp *spriteWidthProp;
         NumberProp *spriteHeightProp;
 };
+*/
 
 class CameraSheet : public PropSheet {
     public:

+ 6 - 158
IDE/Contents/Include/PolycodeSpriteEditor.h

@@ -28,158 +28,6 @@
 
 using namespace Polycode;
 
-class SpriteFrame {
-    public:
-        Polycode::Rectangle coordinates;
-        Vector2 anchorPoint;
-        unsigned int frameID;
-};
-
-class SpriteSet;
-
-class SpriteState {
-    public:
-        SpriteState(SpriteSet *spriteSet, String name);
-    
-        void setName(String name);
-        String getName() const;
-    
-        void appendFrames(std::vector<unsigned int> newFrameIDs);
-    
-        unsigned int getNumFrameIDs();
-        unsigned int getFrameIDAtIndex(unsigned int index);
-    
-        Mesh *getMeshForFrameIndex(unsigned int index);
-    
-        void insertFrame(unsigned int index, unsigned int frameID);
-    
-        void setNewFrameIDs(std::vector<unsigned int> newIDs);
-    
-        void removeFrameByIndex(unsigned int frameIndex);
-        void removeFrameIndices(std::vector<unsigned int> indices);
-        void clearFrames();
-    
-        void setPixelsPerUnit(Number ppu);
-        Number getPixelsPerUnit();
-    
-        void rebuildStateMeshes();
-    
-        void setStateFPS(Number fps);
-        Number getStateFPS();
-    
-        void setBoundingBox(Vector2 boundingBox);
-        Vector2 getBoundingBox();
-    
-        Vector2 getSpriteOffset();
-        void setSpriteOffset(const Vector2 &offset);
-    
-    protected:
-    
-        Vector2 boundingBox;
-        Vector2 spriteOffset;
-        Number pixelsPerUnit;
-        Number stateFPS;
-        SpriteSet *spriteSet;
-        String name;
-        std::vector<unsigned int> frameIDs;
-        std::vector<Mesh*> frameMeshes;
-};
-
-class Sprite {
-    public:
-        Sprite(String name);
-        ~Sprite();
-    
-        String getName();
-        void setName(String name);
-    
-        void addSpriteState(SpriteState *state);
-        void removeSpriteState(SpriteState *state);
-    
-        unsigned int getNumStates();
-        SpriteState *getState(unsigned int index);
-    
-    protected:
-        String name;
-        std::vector<SpriteState*> states;
-};
-
-class SpriteSet {
-    public:
-        SpriteSet(String imageFileName);
-        ~SpriteSet();
-
-        void setTexture(Texture *texture);
-        Texture *getTexture();
-        Texture *loadTexture(String imageFileName);
-    
-        void addSpriteEntry(Sprite *newEntry);
-        unsigned int getNumSpriteEntries() const;
-        Sprite *getSpriteEntry(unsigned int index) const;
-        void removeSprite(Sprite *sprite);
-    
-        void loadSpriteSet(String fileName);
-    
-        // frame manipulation
-        void addSpriteFrame(const SpriteFrame &frame, bool assignID = true);
-        unsigned int getNumFrames() const;
-        SpriteFrame getSpriteFrame(unsigned int index) const;
-    
-        SpriteFrame getSpriteFrameByID(unsigned int frameID) const;
-        void removeFrameByID(unsigned int frameID);
-    
-        void setSpriteFrame(const SpriteFrame &frame);
-    
-        void clearFrames();
-    
-        // automatic frame generation
-        void createGridFrames(Number width, Number height, const Vector2 &defaultAnchor);
-        void createFramesFromIslands(unsigned int minDistance, const Vector2 &defaultAnchor);
-    
-    protected:
-    
-        unsigned int nextFrameIDIndex;
-        Texture *spriteTexture;
-        std::vector<SpriteFrame> frames;
-        std::vector<Sprite*> sprites;
-};
-
-
-class SceneSpriteRewrite : public SceneMesh {
-    public:
-        SceneSpriteRewrite(SpriteSet *spriteSet);
-        ~SceneSpriteRewrite();
-    
-        SpriteSet *getSpriteSet();
-        Sprite *getCurrentSprite();
-    
-        void setCurrentFrame(unsigned int frameIndex);
-        unsigned int getCurrentFrame();
-        void Update();
-        void Render();
-    
-        void setPaused(bool val);
-        bool isPaused();
-    
-        void setSprite(Sprite *spriteEntry);
-        void setSpriteState(SpriteState *spriteState);
-        SpriteState *getCurrentSpriteState();
-
-    
-    protected:
-    
-        bool paused;
-        Core *core;
-        unsigned int currentFrame;
-        Mesh *defaultMesh;
-        Sprite *currentSprite;
-        SpriteState *currentSpriteState;
-        SpriteSet *spriteSet;
-        Number spriteTimer;
-        Number spriteTimerVal;
-    
-};
-
 class SpritePreview : public UIElement {
     public:
         SpritePreview(SpriteSet *spriteSet);
@@ -189,13 +37,13 @@ class SpritePreview : public UIElement {
     
         void handleEvent(Event *event);
     
-        SceneSpriteRewrite *getSceneSprite();
+        SceneSprite *getSceneSprite();
         void Resize(Number width, Number height);
     
     protected:
         UIRect *headerBg;    
         UIImage *previewBg;
-        SceneSpriteRewrite *sprite;
+        SceneSprite *sprite;
     
         UIIconSelector *bgSelector;
     
@@ -362,7 +210,7 @@ class SpriteStateEditBar : public UIElement {
     
         void Update();
     
-        void setSceneSprite(SceneSpriteRewrite *sprite);
+        void setSceneSprite(SceneSprite *sprite);
         void setSpriteState(SpriteState *state);
     
     protected:
@@ -378,7 +226,7 @@ class SpriteStateEditBar : public UIElement {
         Number zoomScale;
         SpriteState *spriteState;
         SpriteSet *spriteSet;
-        SceneSpriteRewrite *sceneSprite;
+        SceneSprite *sceneSprite;
     
         Number defaultFrameWidth;
     
@@ -422,7 +270,7 @@ class SpriteStateEditorDetails : public UIElement {
         void setSpriteState(SpriteState *state);
         SpriteState *getSpriteState();
     
-        void setSceneSprite(SceneSpriteRewrite *spritePreview);
+        void setSceneSprite(SceneSprite *spritePreview);
     
         void refreshState();
     
@@ -435,7 +283,7 @@ class SpriteStateEditorDetails : public UIElement {
     
         SpriteState *spriteState;
         SpriteSet *spriteSet;
-        SceneSpriteRewrite *sceneSprite;
+        SceneSprite *sceneSprite;
     
         UITextInput *fpsInput;
         UITextInput *scaleInput;

+ 3 - 3
IDE/Contents/Source/EntityEditorPropertyView.cpp

@@ -59,11 +59,11 @@ EntityEditorPropertyView::EntityEditorPropertyView() : UIElement() {
     particleSheet = new ParticleEmitterSheet();
     entityProps->addPropSheet(particleSheet);
     particleSheet->addEventListener(this, PropEvent::EVENT_PROP_CHANGE);
-    
+  /*
     spriteSheet = new SceneSpriteSheet();
     entityProps->addPropSheet(spriteSheet);
     spriteSheet->addEventListener(this, PropEvent::EVENT_PROP_CHANGE);
-    
+    */
     primitiveSheet = new ScenePrimitiveSheet();
     entityProps->addPropSheet(primitiveSheet);
     primitiveSheet->addEventListener(this, PropEvent::EVENT_PROP_CHANGE);
@@ -149,7 +149,7 @@ void EntityEditorPropertyView::setEntity(Entity *entity) {
     labelSheet->setSceneLabel(sceneLabel);
 
     SceneSprite *sceneSprite = dynamic_cast<SceneSprite*>(entity);
-    spriteSheet->setSprite(sceneSprite);
+//    spriteSheet->setSprite(sceneSprite);
 
     ScenePrimitive *scenePrimitive = dynamic_cast<ScenePrimitive*>(entity);
     

+ 35 - 5
IDE/Contents/Source/PolycodeEntityEditor.cpp

@@ -870,9 +870,12 @@ void EntityEditorMainView::addEntityFromMenu(String command) {
     if(command == "add_sprite") {
         assetSelectType = "sprite";
         globalFrame->assetBrowser->addEventListener(this, UIEvent::OK_EVENT);
-        std::vector<String> extensions;
-        extensions.push_back("sprite");
-        globalFrame->showAssetBrowser(extensions);
+		std::vector<ResourcePool*> pools;
+        pools.push_back(CoreServices::getInstance()->getResourceManager()->getGlobalPool());
+        for(int i=0; i < objectRootInstance->getNumLinkedResourePools(); i++) {
+            pools.push_back(objectRootInstance->getLinkedResourcePoolAtIndex(i));
+        }
+		globalFrame->showAssetBrowserForPools(pools, Resource::RESOURCE_SPRITE);
         return;
     }
     
@@ -1128,6 +1131,30 @@ void EntityEditorMainView::handleEvent(Event *event) {
                 didPlaceEntity(newImage);
                 selectEntity(newImage, false, false);
             } else if(assetSelectType == "sprite") {
+                
+                Resource *selectedResource = globalFrame->assetBrowser->getSelectedResource();
+                
+                if(selectedResource) {
+                    Sprite *sprite = (Sprite*) selectedResource;
+                    
+                    SceneSprite *newSprite = new SceneSprite(sprite->getParentSpriteSet());
+                    newSprite->setSprite(sprite);
+                    if(sprite->getNumStates() > 0) {
+                        newSprite->setSpriteState(sprite->getState(0));
+                    }
+                    
+                    newSprite->setMaterialByName("Unlit");
+                    if(newSprite->getLocalShaderOptions()) {
+                        newSprite->getLocalShaderOptions()->addTexture("diffuse", newSprite->getTexture());
+                    }
+                    sceneObjectRoot->addChild(newSprite);
+                    setEditorProps(newSprite);
+                    newSprite->setPosition(cursorPosition);
+                    didPlaceEntity(newSprite);
+                    selectEntity(newSprite, false, false);
+                }
+                
+                /*
                 SceneSprite *newSprite = new SceneSprite(globalFrame->assetBrowser->getSelectedAssetPath());
                 
                 if(newSprite->getNumAnimations()) {
@@ -1143,6 +1170,7 @@ void EntityEditorMainView::handleEvent(Event *event) {
                 newSprite->setPosition(cursorPosition);
                 didPlaceEntity(newSprite);
                 selectEntity(newSprite, false, false);
+                 */
             } else if(assetSelectType == "entity") {
                 SceneEntityInstance *newEntity = new SceneEntityInstance(mainScene, globalFrame->assetBrowser->getSelectedAssetPath());
                 sceneObjectRoot->addChild(newEntity);
@@ -1796,6 +1824,7 @@ void PolycodeEntityEditor::saveEntityToObjectEntry(Entity *entity, ObjectEntry *
     }
     
     if(dynamic_cast<SceneSprite*>(entity)) {
+        /*
         if(!(*(entry))["type"])
             entry->addChild("type", "SceneSprite");
         SceneSprite *sprite = (SceneSprite*) entity;
@@ -1808,6 +1837,7 @@ void PolycodeEntityEditor::saveEntityToObjectEntry(Entity *entity, ObjectEntry *
             animName = sprite->getCurrentAnimation()->name;
         }
         spriteEntry->addChild("anim", animName);
+        */
     }
     
     if(dynamic_cast<SceneLabel*>(entity)) {
@@ -2059,10 +2089,10 @@ void PolycodeEntityEditor::saveFile() {
     Object saveObject;
     
     ObjectEntry *settings = saveObject.root.addChild("settings");
-    ObjectEntry *linkedMaterialFiles = settings->addChild("matFiles");
+    ObjectEntry *linkedMaterialFiles = settings->addChild("linkedResourcePools");
     for(int i=0; i < loadedInstance->getNumLinkedResourePools(); i++) {
         ResourcePool *pool = loadedInstance->getLinkedResourcePoolAtIndex(i);
-        linkedMaterialFiles->addChild("matFile")->addChild("path", pool->getName());
+        linkedMaterialFiles->addChild("resourcePool")->addChild("path", pool->getName());
     }
     
     ObjectEntry *layersEntry = settings->addChild("layers");

+ 26 - 11
IDE/Contents/Source/PolycodeProps.cpp

@@ -1388,7 +1388,7 @@ void TextureProp::set(Texture *texture) {
 Texture* TextureProp::get() {
 	return previewShape->getTexture();
 }
-
+/*
 SceneSpriteProp::SceneSpriteProp(String caption) : PropProp(caption, "SceneSprite"){
 
 		previewSprite = new SceneSprite("default/default.sprite");
@@ -1459,7 +1459,7 @@ void SceneSpriteProp::set(String fileName) {
 String SceneSpriteProp::get() {
 	return previewSprite->getFileName();
 }
-
+*/
 SceneEntityInstanceProp::SceneEntityInstanceProp(String caption) : PropProp(caption, "SceneEntityInstance"){
 //	previewInstance = new SceneEntityInstance("default/default.entity");
 	previewInstance->setAnchorPoint(-1.0, -1.0, 0.0);
@@ -3360,7 +3360,7 @@ void CameraSheet::setCamera(Camera *camera) {
     }
 }
 
-
+/*
 SceneSpriteSheet::SceneSpriteSheet() : PropSheet("SPRITE", "SceneSprite") {
 	sprite = NULL;
     enabled = false;
@@ -3450,6 +3450,7 @@ void SceneSpriteSheet::setSprite(SceneSprite *sprite) {
 		enabled = false;
 	}
 }
+*/
 
 SceneEntityInstanceSheet::SceneEntityInstanceSheet() : PropSheet("ENTITY INSTANCE", "SceneEntityInstance") {
 	instance = NULL;
@@ -3732,28 +3733,42 @@ void LinkedMaterialsSheet::handleEvent(Event *event) {
 		globalFrame->assetBrowser->addEventListener(this, UIEvent::OK_EVENT);
 		std::vector<String> extensions;
 		extensions.push_back("mat");
+		extensions.push_back("sprites");
 		globalFrame->showAssetBrowser(extensions);
         
     } else if(event->getDispatcher() == globalFrame->assetBrowser) {
-		String materialPath = globalFrame->assetBrowser->getSelectedAssetPath();
+		String resourcePath = globalFrame->assetBrowser->getSelectedAssetPath();
 
-		String fullMaterialPath = globalFrame->assetBrowser->getFullSelectedAssetPath();
+		String fullResourcePath = globalFrame->assetBrowser->getFullSelectedAssetPath();
 		        
         globalFrame->assetBrowser->removeAllHandlersForListener(this);
         globalFrame->hideModal();
         
-        ResourcePool *newPool = CoreServices::getInstance()->getResourceManager()->getResourcePoolByName(materialPath);
+        ResourcePool *newPool = CoreServices::getInstance()->getResourceManager()->getResourcePoolByName(resourcePath);
         
         if(!newPool) {
-            newPool = new ResourcePool(materialPath,  CoreServices::getInstance()->getResourceManager()->getGlobalPool());
-            newPool->reloadResourcesOnModify = true;
-            newPool->deleteOnUnsubscribe = true;
-            CoreServices::getInstance()->getMaterialManager()->loadMaterialLibraryIntoPool(newPool, fullMaterialPath);
+            String extension = resourcePath.substr(resourcePath.find_last_of(".")+1, resourcePath.length());
+
+            if(extension == "mat") {
+                
+                newPool = new ResourcePool(resourcePath,  CoreServices::getInstance()->getResourceManager()->getGlobalPool());
+                newPool->reloadResourcesOnModify = true;
+                newPool->deleteOnUnsubscribe = true;
+                
+                CoreServices::getInstance()->getMaterialManager()->loadMaterialLibraryIntoPool(newPool, fullResourcePath);
+            } else if( extension == "sprites") {
+                SpriteSet *spriteSet = new SpriteSet(resourcePath,  CoreServices::getInstance()->getResourceManager()->getGlobalPool());
+                spriteSet->reloadResourcesOnModify = true;
+                spriteSet->deleteOnUnsubscribe = true;
+                newPool = spriteSet;
+            }
+            
             CoreServices::getInstance()->getResourceManager()->addResourcePool(newPool);
+            
         }
         
         instance->linkResourcePool(newPool);
-         updateMaterials();
+        updateMaterials();
     }
     PropSheet::handleEvent(event);
 }

+ 16 - 697
IDE/Contents/Source/PolycodeSpriteEditor.cpp

@@ -27,697 +27,6 @@ extern UIColorPicker *globalColorPicker;
 extern PolycodeFrame *globalFrame;
 extern UIGlobalMenu *globalMenu;
 
-
-SceneSpriteRewrite::SceneSpriteRewrite(SpriteSet *spriteSet) : SceneMesh(Mesh::QUAD_MESH) {
-    currentSprite = NULL;
-    currentSpriteState = NULL;
-    this->spriteSet = spriteSet;
-    defaultMesh = mesh;
-    currentFrame = 0;
-    core = Services()->getCore();
-    spriteTimer = 0.0;
-    paused = false;
-    spriteTimerVal = 0.1;
-}
-
-SpriteState *SceneSpriteRewrite::getCurrentSpriteState() {
-    return currentSpriteState;
-}
-
-SpriteSet *SceneSpriteRewrite::getSpriteSet() {
-    return spriteSet;
-}
-
-void SceneSpriteRewrite::setPaused(bool val) {
-    paused = val;
-}
-
-bool SceneSpriteRewrite::isPaused() {
-    return paused;
-}
-
-void SceneSpriteRewrite::setCurrentFrame(unsigned int frameIndex) {
-    currentFrame = frameIndex;
-}
-
-
-void SceneSpriteRewrite::setSprite(Sprite *spriteEntry) {
-    currentSprite = spriteEntry;
-}
-
-void SceneSpriteRewrite::setSpriteState(SpriteState *spriteState) {
-    currentSpriteState = spriteState;
-    
-    if(!currentSpriteState) {
-        return;
-    }
-    
-    Vector2 bBox = spriteState->getBoundingBox();
-    setLocalBoundingBox(bBox.x / spriteState->getPixelsPerUnit(), bBox.y / spriteState->getPixelsPerUnit(), 0.001);
-}
-
-void SceneSpriteRewrite::Update() {
-
-    if(!currentSprite || !currentSpriteState) {
-        return;
-    }
-    
-    setTexture(spriteSet->getTexture());
-    
-    if(paused) {
-        return;
-    }
-    
-    spriteTimer += core->getElapsed();
-    
-    if(spriteTimer > 1.0/currentSpriteState->getStateFPS()) {
-        spriteTimer = 0.0;
-        currentFrame++;
-        if(currentFrame >= currentSpriteState->getNumFrameIDs()) {
-            currentFrame = 0;
-        }
-    }
-    
-}
-
-unsigned int SceneSpriteRewrite::getCurrentFrame() {
-    return currentFrame;
-}
-
-void SceneSpriteRewrite::Render() {
-    
-    if(!currentSprite || !currentSpriteState) {
-        return;
-    }
-    
-    Mesh *stateMesh = currentSpriteState->getMeshForFrameIndex(currentFrame);
-    if(stateMesh) {
-        setMesh(stateMesh);
-    } else {
-        setMesh(defaultMesh);
-    }
-
-    SceneMesh::Render();
-}
-
-SceneSpriteRewrite::~SceneSpriteRewrite() {
-    
-}
-
-SpriteState::SpriteState(SpriteSet *spriteSet, String name) {
-    this->spriteSet = spriteSet;
-    this->name = name;
-    stateFPS = 60.0;
-    pixelsPerUnit = 1.0;
-}
-
-void SpriteState::setBoundingBox(Vector2 boundingBox) {
-    this->boundingBox = boundingBox;
-    rebuildStateMeshes();
-}
-
-void SpriteState::clearFrames() {
-    frameIDs.clear();
-    rebuildStateMeshes();
-}
-
-Vector2 SpriteState::getBoundingBox() {
-    return boundingBox;
-}
-
-Vector2 SpriteState::getSpriteOffset() {
-    return spriteOffset;
-}
-
-void SpriteState::setSpriteOffset(const Vector2 &offset) {
-    spriteOffset = offset;
-    rebuildStateMeshes();
-}
-
-
-void SpriteState::setPixelsPerUnit(Number ppu) {
-    pixelsPerUnit = ppu;
-    rebuildStateMeshes();
-}
-
-Number SpriteState::getPixelsPerUnit() {
-    return pixelsPerUnit;
-}
-
-void SpriteState::removeFrameByIndex(unsigned int index) {
-    if(index < frameIDs.size()) {
-        frameIDs.erase(frameIDs.begin()+index);
-    }
-    rebuildStateMeshes();
-}
-
-void SpriteState::removeFrameIndices(std::vector<unsigned int> indices) {
-    std::vector<unsigned int> newFrames;
-    
-    for(int i=0; i < frameIDs.size(); i++) {
-        bool hasIndex = false;
-        for(int j=0; j < indices.size(); j++) {
-            if(indices[j] == i) {
-                hasIndex = true;
-                break;
-            }
-        }
-        if(!hasIndex) {
-            newFrames.push_back(frameIDs[i]);
-        }
-    }
-    
-    frameIDs = newFrames;
-    rebuildStateMeshes();
-}
-
-void SpriteState::setStateFPS(Number fps) {
-    stateFPS = fps;
-}
-
-Number SpriteState::getStateFPS() {
-    return stateFPS;
-}
-
-void SpriteState::setName(String name) {
-    this->name = name;
-}
-
-void SpriteState::setNewFrameIDs(std::vector<unsigned int> newIDs) {
-    frameIDs = newIDs;
-    rebuildStateMeshes();
-}
-
-void SpriteState::insertFrame(unsigned int index, unsigned int frameID) {
-    if(index < frameIDs.size()) {
-        frameIDs.insert(frameIDs.begin()+index, frameID);
-    }
-    rebuildStateMeshes();
-}
-
-Mesh *SpriteState::getMeshForFrameIndex(unsigned int index) {
-    if(index < frameMeshes.size()) {
-        return frameMeshes[index];
-    } else {
-        return NULL;
-    }
-}
-
-void SpriteState::rebuildStateMeshes() {
-    for(int i=0; i < frameMeshes.size(); i++) {
-        delete frameMeshes[i];
-    }
-    frameMeshes.clear();
-    
-    for(int i=0; i < frameIDs.size(); i++) {
-        Mesh *frameMesh = new Mesh(Mesh::QUAD_MESH);
-        SpriteFrame frame = spriteSet->getSpriteFrameByID(frameIDs[i]);
-        
-        frameMesh->indexedMesh = true;
-        
-        Number aspectRatio = frame.coordinates.w / frame.coordinates.h;
-        Number textureAspectRatio = ((Number)spriteSet->getTexture()->getWidth()) / ((Number)spriteSet->getTexture()->getHeight());
-        
-        
-        Number frameHeight = frame.coordinates.h * ((Number)spriteSet->getTexture()->getHeight()) / pixelsPerUnit;
-        
-        Number frameWidth = frameHeight * aspectRatio * textureAspectRatio;
-        
-        
-        
-        Vector2 meshOffset;
-        meshOffset.x = boundingBox.x * spriteOffset.x / pixelsPerUnit;
-        meshOffset.y = boundingBox.y * spriteOffset.y / pixelsPerUnit;
-        
-        meshOffset.x -= frameWidth * frame.anchorPoint.x;
-        meshOffset.y += frameHeight * frame.anchorPoint.y;
-        
-        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y);
-        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y  - frame.coordinates.h);
-        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0- frame.coordinates.y  - frame.coordinates.h);
-        frameMesh->addVertex(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0-frame.coordinates.y);
-        
-        frameMesh->addIndexedFace(0,1);
-        frameMesh->addIndexedFace(1,2);
-        frameMesh->addIndexedFace(2,3);
-        frameMesh->addIndexedFace(3,0);
-        
-        frameMesh->dirtyArrays();
-        
-        frameMeshes.push_back(frameMesh);
-    }
-}
-
-String SpriteState::getName() const {
-    return name;
-}
-
-unsigned int SpriteState::getNumFrameIDs() {
-    return frameIDs.size();
-}
-
-unsigned int SpriteState::getFrameIDAtIndex(unsigned int index) {
-    if(index < frameIDs.size()) {
-        return frameIDs[index];
-    } else {
-        return 0;
-    }
-}
-
-void SpriteState::appendFrames(std::vector<unsigned int> newFrameIDs) {
-    frameIDs.insert( frameIDs.end(), newFrameIDs.begin(), newFrameIDs.end());
-    rebuildStateMeshes();
-}
-
-unsigned int Sprite::getNumStates() {
-    return states.size();
-}
-
-SpriteState *Sprite::getState(unsigned int index) {
-    if(index < states.size()) {
-        return states[index];
-    } else {
-        return NULL;
-    }
-}
-
-void Sprite::addSpriteState(SpriteState *state) {
-    states.push_back(state);
-}
-
-Sprite::Sprite(String name) {
-    this->name = name;
-}
-
-void Sprite::removeSpriteState(SpriteState *state) {
-    for(int i=0; i < states.size(); i++) {
-        if(states[i] == state) {
-            states.erase(states.begin() + i);
-            return;
-        }
-    }
-}
-
-Sprite::~Sprite() {
-    for(int i=0; i < states.size(); i++) {
-        delete states[i];
-    }
-}
-
-String Sprite::getName() {
-    return name;
-}
-
-void Sprite::setName(String name) {
-    this->name = name;
-}
-
-
-SpriteSet::SpriteSet(String fileName) {
-//    loadTexture(imageFileName);
-    nextFrameIDIndex = 0;
-    loadSpriteSet(fileName);
-
-}
-
-void SpriteSet::loadSpriteSet(String fileName) {
-	Object loadObject;
-	if(!loadObject.loadFromBinary(fileName)) {
-        if(!loadObject.loadFromXML(fileName)) {
-            Logger::log("Error loading sprite sheet: %s.\n", fileName.c_str());
-            return;
-        }
-	}
-    
-    ObjectEntry *spriteSheetEntry = loadObject.root["sprite_sheet"];
-    if(spriteSheetEntry) {
-        ObjectEntry *fileNameEntry = (*spriteSheetEntry)["fileName"];
-        if(fileNameEntry) {
-            loadTexture(fileNameEntry->stringVal);
-        }
-        
-        ObjectEntry *framesEntry = (*spriteSheetEntry)["frames"];
-        if(framesEntry) {
-            for(int i=0; i < framesEntry->length; i++) {
-                ObjectEntry *frameEntry = (*framesEntry)[i];
-                
-                if(frameEntry) {
-                    SpriteFrame frame;
-
-                    ObjectEntry *idEntry = (*frameEntry)["id"];
-                    if(idEntry) {
-                        frame.frameID = idEntry->intVal;
-                    }
-                    
-                    ObjectEntry *xEntry = (*frameEntry)["x"];
-                    if(xEntry) {
-                        frame.coordinates.x = xEntry->NumberVal;
-                    }
-                    ObjectEntry *yEntry = (*frameEntry)["y"];
-                    if(yEntry) {
-                        frame.coordinates.y = yEntry->NumberVal;
-                    }
-                    ObjectEntry *wEntry = (*frameEntry)["w"];
-                    if(wEntry) {
-                        frame.coordinates.w = wEntry->NumberVal;
-                    }
-                    ObjectEntry *hEntry = (*frameEntry)["h"];
-                    if(hEntry) {
-                        frame.coordinates.h = hEntry->NumberVal;
-                    }
-                    ObjectEntry *axEntry = (*frameEntry)["ax"];
-                    if(axEntry) {
-                        frame.anchorPoint.x = axEntry->NumberVal;
-                    }
-                    ObjectEntry *ayEntry = (*frameEntry)["ay"];
-                    if(ayEntry) {
-                        frame.anchorPoint.y = ayEntry->NumberVal;
-                    }
-                    
-                    addSpriteFrame(frame, false);
-                }
-                
-            }
-        }
-        
-    } else {
-        return;
-    }
-    
-    ObjectEntry *spritesEntry = loadObject.root["sprites"];
-    if(spritesEntry) {
-        for(int i=0; i < spritesEntry->length; i++) {
-            ObjectEntry *spriteEntry = (*spritesEntry)[i];
-            if(spriteEntry) {
-                ObjectEntry *nameEntry = (*spriteEntry)["name"];
-                String spriteName;
-                if(nameEntry) {
-                    spriteName = nameEntry->stringVal;
-                }
-                Sprite *newSprite = new Sprite(spriteName);
-                addSpriteEntry(newSprite);
-                
-                ObjectEntry *statesEntry = (*spriteEntry)["states"];
-                
-                if(statesEntry) {
-                    for(int j=0; j < statesEntry->length; j++) {
-                        ObjectEntry *stateEntry = (*statesEntry)[j];
-                        if(stateEntry) {
-                            SpriteState *newState = new SpriteState(this, "");
-                            
-                            ObjectEntry *nameEntry = (*stateEntry)["name"];
-                            if(nameEntry) {
-                                newState->setName(nameEntry->stringVal);
-                            }
-                            
-                            ObjectEntry *fpsEntry = (*stateEntry)["fps"];
-                            if(fpsEntry) {
-                                newState->setStateFPS(fpsEntry->NumberVal);
-                            }
-
-                            ObjectEntry *scaleEntry = (*stateEntry)["scale"];
-                            if(scaleEntry) {
-                                newState->setPixelsPerUnit(scaleEntry->NumberVal);
-                            }
-
-                            ObjectEntry *widthEntry = (*stateEntry)["width"];
-                            ObjectEntry *heightEntry = (*stateEntry)["height"];
-                            if(widthEntry && heightEntry) {
-                                newState->setBoundingBox(Vector2(widthEntry->NumberVal, heightEntry->NumberVal));
-                            }
-                            
-                            ObjectEntry *xOffsetEntry = (*stateEntry)["offset_x"];
-                            ObjectEntry *yOffsetEntry = (*stateEntry)["offset_y"];
-                            if(xOffsetEntry && yOffsetEntry) {
-                                newState->setSpriteOffset(Vector2(xOffsetEntry->NumberVal, yOffsetEntry->NumberVal));
-                            }
-                            
-                            ObjectEntry *frameIDsEntry = (*stateEntry)["frame_ids"];
-                            
-                            if(frameIDsEntry) {
-                                std::vector<String> frameIDs = frameIDsEntry->stringVal.split(",");
-                                
-                                std::vector<unsigned int> frameIDInts;
-                                for(int f=0; f < frameIDs.size(); f++) {
-                                    frameIDInts.push_back(frameIDs[f].toInteger());
-                                }
-                                
-                                newState->appendFrames(frameIDInts);
-                            }
-                            
-                            newSprite->addSpriteState(newState);
-                        }
-                    }
-                }
-            }
-        }
-    }
-    
-
-}
-
-void SpriteSet::removeFrameByID(unsigned int frameID) {
-    for(int i=0; i < frames.size(); i++) {
-        if(frames[i].frameID == frameID) {
-            frames.erase(frames.begin() + i);
-            return;
-        }
-    }
-}
-
-void SpriteSet::removeSprite(Sprite *sprite) {
-    for(int i=0; i < sprites.size(); i++) {
-        if(sprites[i] == sprite) {
-            sprites.erase(sprites.begin()+i);
-            return;
-        }
-    }
-}
-
-Texture *SpriteSet::loadTexture(String imageFileName) {
-    Texture *spriteTexture = Services()->getMaterialManager()->createTextureFromFile(imageFileName, true, Services()->getMaterialManager()->mipmapsDefault);
-    setTexture(spriteTexture);
-    return spriteTexture;
-}
-
-void SpriteSet::addSpriteFrame(const SpriteFrame &frame, bool assignID) {
-    
-    // do not add existing frames
-    for(int i=0; i < frames.size(); i++) {
-        SpriteFrame existingFrame = frames[i];
-        
-        if(existingFrame.coordinates == frame.coordinates) {
-            return;
-        }
-        
-    }
-    
-    frames.push_back(frame);
-    if(assignID) {
-        frames[frames.size()-1].frameID = nextFrameIDIndex;
-        nextFrameIDIndex++;
-    } else {
-        nextFrameIDIndex = frame.frameID + 1;
-    }
-    
-}
-
-void SpriteSet::setSpriteFrame(const SpriteFrame &frame) {
-    for(int i=0 ;i < frames.size(); i++) {
-        if(frames[i].frameID == frame.frameID) {
-            frames[i].coordinates = frame.coordinates;
-            frames[i].anchorPoint = frame.anchorPoint;
-            return;
-        }
-    }
-}
-
-SpriteFrame SpriteSet::getSpriteFrameByID(unsigned int frameID) const {
-    for(int i=0; i < frames.size(); i++) {
-        if(frames[i].frameID == frameID ){
-            return frames[i];
-        }
-    }
-    return SpriteFrame();
-}
-
-unsigned int SpriteSet::getNumFrames() const {
-    return frames.size();
-}
-
-SpriteFrame SpriteSet::getSpriteFrame(unsigned int index) const {
-    if(index < frames.size()) {
-        return frames[index];
-    } else {
-        return SpriteFrame();
-    }
-}
-
-void SpriteSet::addSpriteEntry(Sprite *newEntry) {
-    sprites.push_back(newEntry);
-}
-
-unsigned int SpriteSet::getNumSpriteEntries() const {
-    return sprites.size();
-}
-
-Sprite *SpriteSet::getSpriteEntry(unsigned int index) const {
-    if(index < sprites.size()) {
-        return sprites[index];
-    } else {
-        return NULL;
-    }
-}
-
-void SpriteSet::setTexture(Texture *texture) {
-    spriteTexture = texture;
-}
-
-Texture *SpriteSet::getTexture() {
-    return spriteTexture;
-}
-
-SpriteSet::~SpriteSet() {
-    
-}
-
-void SpriteSet::clearFrames() {
-    frames.clear();
-    nextFrameIDIndex = 0;
-}
-
-void SpriteSet::createGridFrames(Number width, Number height, const Vector2 &defaultAnchor) {
-    
-    for(Number x = 0.0; x+width <= 1.0; x += width) {
-        for(Number y = 0.0; y+height <= 1.0; y += height) {
-            SpriteFrame frame;
-            frame.coordinates = Polycode::Rectangle(x, y, width, height);
-            frame.anchorPoint = defaultAnchor;
-            addSpriteFrame(frame);
-        }
-    }
-}
-
-Polycode::Rectangle createBoxAtCoordinate(Image *image, unsigned int x, unsigned int y) {
-    Polycode::Rectangle rect;
-    
-    rect.x = x;
-    rect.y = y;
-    
-    while(x < image->getWidth()) {
-        if(image->getPixel(x, y).a == 0.0) {
-            break;
-        }
-        x++;
-    }
-    rect.w = x - rect.x;
-    
-    // look down at first x
-    Number y1 = y;
-    while(y1 < image->getHeight()) {
-        if(image->getPixel(rect.x, y1).a == 0.0) {
-            break;
-        }
-        y1++;
-    }
-    Number h1 = y1;
-    
-    // look down at last x
-    while(y < image->getHeight()) {
-        if(image->getPixel(x, y).a == 0.0) {
-            break;
-        }
-        y++;
-    }
-    Number h2 = y;
-
-    if(h1 > h2) {
-        h2 = h1;
-    }
-    
-    rect.h = h2 - rect.y;
-    
-
-    
-    return rect;
-}
-
-bool rectIntersect(const Polycode::Rectangle &r1, const Polycode::Rectangle &r2, Number minDistance) {
-    return !(r2.x - minDistance > r1.x + r1.w ||
-             r2.x + r2.w + minDistance < r1.x ||
-             r2.y - minDistance > r1.y + r1.h ||
-             r2.y + r2.h + minDistance < r1.y);
-}
-
-void SpriteSet::createFramesFromIslands(unsigned int minDistance, const Vector2 &defaultAnchor) {
-    String imageFileName = getTexture()->getResourcePath();
-    
-    Image *image = new Image(imageFileName);
-    
-    
-    std::vector<Polycode::Rectangle> rects;
-    
-    for(int y=0; y < image->getHeight(); y++) {
-        for(int x=0; x < image->getWidth(); x++) {
-            if(image->getPixel(x, y).a > 0.0) {
-                Polycode::Rectangle rect = createBoxAtCoordinate(image,x,y);
-                rects.push_back(rect);
-                x += rect.w;
-            }
-        }
-    }
-    
-    while(rects.size() > 1) {
-
-        bool intersected = false;
-        for(int i=0; i < rects.size(); i++) {
-            for(int i2=0; i2 < rects.size(); i2++) {
-                if(i != i2) {
-                    if(rectIntersect(rects[i], rects[i2], minDistance)) {
-
-                        Polycode::Rectangle newRect;
-                        
-                        newRect.x = std::min(rects[i].x, rects[i2].x);
-                        newRect.y = std::min(rects[i].y, rects[i2].y);
-                        
-                        newRect.w = std::max(rects[i].x + rects[i].w, rects[i2].x + rects[i2].w) - newRect.x;
-                        newRect.h = std::max(rects[i].y + rects[i].h, rects[i2].y + rects[i2].h) - newRect.y;
-                        
-                        rects[i] = newRect;
-                        rects.erase(rects.begin() + i2);
-                        
-                        intersected = true;
-                        
-                        break;
-                    }
-                }
-            }
-        }
-
-        if(!intersected) {
-            break;
-        }
-  
-    }
-    
-    
-    for(int i=0; i < rects.size(); i++) {
-        SpriteFrame frame;
-        frame.coordinates = rects[i];
-        
-        frame.coordinates.x = frame.coordinates.x / ((Number)image->getWidth());
-        frame.coordinates.y = frame.coordinates.y / ((Number)image->getHeight());
-        frame.coordinates.w = frame.coordinates.w / ((Number)image->getWidth());
-        frame.coordinates.h = frame.coordinates.h / ((Number)image->getHeight());
-        
-        frame.anchorPoint = defaultAnchor;
-        
-        addSpriteFrame(frame);
-    }
-    
-    delete image;
-}
-
 TransformGrips::TransformGrips() : UIElement() {
     
     mainRect = new UIRect(1.0, 1.0);
@@ -1651,7 +960,7 @@ SpriteStateEditorDetails::SpriteStateEditorDetails(SpriteSet *spriteSet) : UIEle
     enabled = false;
 }
 
-void SpriteStateEditBar::setSceneSprite(SceneSpriteRewrite *sprite) {
+void SpriteStateEditBar::setSceneSprite(SceneSprite *sprite) {
     sceneSprite = sprite;
 }
 
@@ -1659,7 +968,7 @@ SpriteStateEditBar *SpriteStateEditorDetails::getEditBar() {
     return editBar;
 }
 
-void SpriteStateEditorDetails::setSceneSprite(SceneSpriteRewrite *sceneSprite) {
+void SpriteStateEditorDetails::setSceneSprite(SceneSprite *sceneSprite) {
     this->sceneSprite = sceneSprite;
     editBar->setSceneSprite(sceneSprite);
 }
@@ -2458,7 +1767,7 @@ SpritePreview::SpritePreview(SpriteSet *spriteSet) : UIElement() {
     previewBg->processInputEvents = true;
     previewBg->setPosition(0.0, 30.0);
     
-    sprite = new SceneSpriteRewrite(spriteSet);
+    sprite = new SceneSprite(spriteSet);
     addChild(sprite);
     sprite->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
@@ -2489,7 +1798,7 @@ SpritePreview::SpritePreview(SpriteSet *spriteSet) : UIElement() {
     
 }
 
-SceneSpriteRewrite *SpritePreview::getSceneSprite() {
+SceneSprite *SpritePreview::getSceneSprite() {
     return sprite;
 }
 
@@ -2608,12 +1917,22 @@ void PolycodeSpriteEditor::handleEvent(Event *event) {
 }
 
 PolycodeSpriteEditor::~PolycodeSpriteEditor() {
-
+    CoreServices::getInstance()->getResourceManager()->unsubscibeFromResourcePool(sprite);
 }
 
 bool PolycodeSpriteEditor::openFile(OSFileEntry filePath) {
 	
-    sprite = new SpriteSet(filePath.fullPath);
+    String resourceName = filePath.fullPath.replace(parentProject->getRootFolder()+"/", "");
+    
+    sprite = (SpriteSet*) CoreServices::getInstance()->getResourceManager()->getResourcePoolByName(resourceName);
+    
+    if(!sprite) {
+        sprite = new SpriteSet(filePath.fullPath, CoreServices::getInstance()->getResourceManager()->getGlobalPool());
+        sprite->reloadResourcesOnModify = true;
+        sprite->deleteOnUnsubscribe = true;
+        
+    }
+    CoreServices::getInstance()->getResourceManager()->subscribeToResourcePool(sprite);
     
     mainSizer = new UIVSizer(100, 100, 200, false);
     addChild(mainSizer);

+ 22 - 2
IDE/Contents/Source/TextureBrowser.cpp

@@ -51,7 +51,7 @@ AssetEntry::AssetEntry(String assetPath, String assetName, String extension, Res
 		imageShape->loadTexture("browserIcons/sound_icon.png");
 	} else if(extension == "entity") {
 		imageShape->loadTexture("browserIcons/entity_icon.png");
-	} else if(extension == "sprite") {
+	} else if(extension == "sprites") {
 		imageShape->loadTexture("browserIcons/sprite_icon.png");
 	} else if(extension == "ttf" || extension == "otf") {
 		imageShape->loadTexture("browserIcons/font_icon.png");
@@ -63,7 +63,10 @@ AssetEntry::AssetEntry(String assetPath, String assetName, String extension, Res
 		imageShape->loadTexture("browserIcons/materials_icon.png");
     } else if(extension == "material_resource") {
 		imageShape->loadTexture("browserIcons/material_resource_icon.png");
+    } else if(extension == "sprite_resource") {
+		imageShape->loadTexture("browserIcons/sprite_icon.png");
     }
+
 	
 	imageShape->setPosition(28, 10);
     imageShape->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
@@ -130,6 +133,8 @@ void AssetList::showResourcePool(ResourcePool *pool, int resourceFilter) {
     
     if(resourceFilter == Resource::RESOURCE_MATERIAL ) {
         extension = "material_resource";
+    } else if(resourceFilter == Resource::RESOURCE_SPRITE ) {
+        extension = "sprite_resource";
     }
     
 	for(int i=0; i < resources.size(); i++) {
@@ -274,6 +279,11 @@ void AssetBrowser::setResourcePools(std::vector<ResourcePool*> pools, int resour
     
 	templateContainer->getRootNode()->clearTree();
 	templateContainer->getRootNode()->setLabelText("Resource pools");
+
+    FolderUserData *userData = (FolderUserData*) templateContainer->getRootNode()->getUserData();
+    if(userData) {
+        delete userData;
+    }
 	templateContainer->getRootNode()->setUserData(NULL);
     
     
@@ -298,7 +308,17 @@ void AssetBrowser::setProject(PolycodeProject *project) {
 
 	vector<OSFileEntry> templates = OSBasics::parseFolder(project->getRootFolder(), false);
 	templateContainer->getRootNode()->setLabelText(project->getProjectName());
-		
+	
+    FolderUserData *userData = (FolderUserData*) templateContainer->getRootNode()->getUserData();
+    if(userData) {
+        delete userData;
+    }
+    
+	FolderUserData *rootData = new FolderUserData();
+    rootData->folderPath = project->getRootFolder();
+    rootData->type = 0;
+    templateContainer->getRootNode()->setUserData(rootData);
+    
 	for(int i=0; i < templates.size(); i++) {
 		OSFileEntry entry = templates[i];
 		if(entry.type == OSFileEntry::TYPE_FOLDER) {