Kaynağa Gözat

Merge branch 'master' of https://github.com/ivansafrin/Polycode

Ivan Safrin 10 yıl önce
ebeveyn
işleme
5e61ebd5e5

+ 3 - 0
Core/Contents/Include/PolyCocoaCore.h

@@ -59,6 +59,9 @@ namespace Polycode {
 		int mouseX;
 		int mouseX;
 		int mouseY;
 		int mouseY;
 		
 		
+        std::vector<TouchInfo> touches;
+        TouchInfo touch;
+        
 		PolyKEY keyCode;
 		PolyKEY keyCode;
 		wchar_t unicodeChar;
 		wchar_t unicodeChar;
 		
 		

+ 5 - 2
Core/Contents/Include/PolyEvent.h

@@ -60,6 +60,9 @@ namespace Polycode {
 			void setEventCode(int eventCode);			
 			void setEventCode(int eventCode);			
 			void setDispatcher(EventDispatcher *dispatcher);
 			void setDispatcher(EventDispatcher *dispatcher);
 			const String& getEventType() const;
 			const String& getEventType() const;
+        
+        
+            void cancelEvent();
 			
 			
 			// In order to prevent "namespace" collisions between events of different types, all event integers must be unique.
 			// In order to prevent "namespace" collisions between events of different types, all event integers must be unique.
 			// This is managed by arbitrarily assigning each class a "base" constant, and adding it to all its event type constants.
 			// This is managed by arbitrarily assigning each class a "base" constant, and adding it to all its event type constants.
@@ -91,12 +94,12 @@ namespace Polycode {
 			static const int EVENTBASE_NONPOLYCODE = 0x10000;
 			static const int EVENTBASE_NONPOLYCODE = 0x10000;
 		
 		
 			bool deleteOnDispatch;
 			bool deleteOnDispatch;
-						
+            bool cancelEventFlag;
+        
 		protected:
 		protected:
 			
 			
 			String eventType;
 			String eventType;
 			EventDispatcher *dispatcher;
 			EventDispatcher *dispatcher;
 			int eventCode;
 			int eventCode;
-			
 	};
 	};
 }
 }

+ 1 - 1
Core/Contents/Include/PolyObject.h

@@ -38,7 +38,7 @@ namespace Polycode {
 		/**
 		/**
 		* Default constructor
 		* Default constructor
 		*/
 		*/
-		ObjectEntry() { type = UNKNOWN_ENTRY; length = 0; }
+        ObjectEntry();
 				
 				
 		/**
 		/**
 		* Type of entry. Possible values are (FLOAT_ENTRY, INT_ENTRY, BOOL_ENTRY, ARRAY_ENTRY, STRING_ENTRY, CONTAINER_ENTRY).
 		* Type of entry. Possible values are (FLOAT_ENTRY, INT_ENTRY, BOOL_ENTRY, ARRAY_ENTRY, STRING_ENTRY, CONTAINER_ENTRY).

+ 1 - 1
Core/Contents/Include/PolySceneSprite.h

@@ -119,7 +119,7 @@ namespace Polycode {
     
     
     class SpriteSet : public ResourcePool {
     class SpriteSet : public ResourcePool {
     public:
     public:
-        SpriteSet(String imageFileName, ResourcePool *parentPool = CoreServices::getInstance()->getResourceManager()->getGlobalPool());
+        SpriteSet(const String &fileName, ResourcePool *parentPool = CoreServices::getInstance()->getResourceManager()->getGlobalPool());
         ~SpriteSet();
         ~SpriteSet();
         
         
         void setTexture(Texture *texture);
         void setTexture(Texture *texture);

+ 151 - 1
Core/Contents/PolycodeView/Mac OS X/PolycodeView.mm

@@ -46,7 +46,9 @@
 	contextLock = [[NSLock alloc] init];
 	contextLock = [[NSLock alloc] init];
 	
 	
 	[[self window] setAcceptsMouseMovedEvents:YES];
 	[[self window] setAcceptsMouseMovedEvents:YES];
-	[[self window] makeFirstResponder:self];	
+	[[self window] makeFirstResponder:self];
+    
+    [self setAcceptsTouchEvents:YES];
 
 
 	[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(windowResized:) name:NSWindowDidResizeNotification object:[self window]];
 	[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(windowResized:) name:NSWindowDidResizeNotification object:[self window]];
 	
 	
@@ -417,6 +419,154 @@
 	
 	
 }
 }
 
 
+- (void)touchesBeganWithEvent:(NSEvent *)event
+{
+    if(core == NULL)
+        return;
+    
+    core->lockMutex(core->eventMutex);
+
+    NSSet *touches = [event touchesMatchingPhase:NSTouchPhaseAny inView:self];
+    NSArray *touchArray = [touches allObjects];
+    
+    std::vector<TouchInfo> touchInfos;
+    
+    for(NSTouch *touch in touchArray) {
+        TouchInfo info;
+        long touchID = (long)[touch identity];
+        info.id = touchID;
+        info.position.x = [touch normalizedPosition].x * core->getXRes();
+        info.position.y = (1.0-[touch normalizedPosition].y) * core->getYRes();
+        touchInfos.push_back(info);
+    }
+
+    unsigned int index = 0;
+    for(NSTouch *touch in touchArray) {
+        if([touch phase] == NSTouchPhaseBegan) {
+            CocoaEvent newEvent;
+            newEvent.eventCode = InputEvent::EVENT_TOUCHES_BEGAN;
+            newEvent.eventGroup = CocoaEvent::INPUT_EVENT;
+            newEvent.touches = touchInfos;
+            newEvent.touch = touchInfos[index];
+            core->cocoaEvents.push_back(newEvent);
+        }
+        index++;
+    }
+    core->unlockMutex(core->eventMutex);	
+
+}
+
+- (void)touchesMovedWithEvent:(NSEvent *)event
+{
+    
+    if(core == NULL)
+        return;
+    
+    core->lockMutex(core->eventMutex);
+    
+    NSSet *touches = [event touchesMatchingPhase:NSTouchPhaseAny inView:self];
+    NSArray *touchArray = [touches allObjects];
+    
+    std::vector<TouchInfo> touchInfos;
+    
+    for(NSTouch *touch in touchArray) {
+        TouchInfo info;
+        long touchID = (long)[touch identity];
+        info.id = touchID;
+        info.position.x = [touch normalizedPosition].x * core->getXRes();
+        info.position.y = (1.0-[touch normalizedPosition].y) * core->getYRes();
+        touchInfos.push_back(info);
+    }
+    
+    unsigned int index = 0;
+    for(NSTouch *touch in touchArray) {
+        if([touch phase] == NSTouchPhaseMoved) {
+            CocoaEvent newEvent;
+            newEvent.eventCode = InputEvent::EVENT_TOUCHES_MOVED;
+            newEvent.eventGroup = CocoaEvent::INPUT_EVENT;
+            newEvent.touches = touchInfos;
+            newEvent.touch = touchInfos[index];
+            core->cocoaEvents.push_back(newEvent);
+        }
+        index++;
+    }
+    core->unlockMutex(core->eventMutex);
+    
+}
+
+- (void)touchesEndedWithEvent:(NSEvent *)event
+{
+    if(core == NULL)
+        return;
+    
+    core->lockMutex(core->eventMutex);
+    
+    NSSet *touches = [event touchesMatchingPhase:NSTouchPhaseAny inView:self];
+    NSArray *touchArray = [touches allObjects];
+    
+    std::vector<TouchInfo> touchInfos;
+    
+    for(NSTouch *touch in touchArray) {
+        TouchInfo info;
+        long touchID = (long)[touch identity];
+        info.id = touchID;
+        info.position.x = [touch normalizedPosition].x * core->getXRes();
+        info.position.y = (1.0-[touch normalizedPosition].y) * core->getYRes();
+        touchInfos.push_back(info);
+    }
+    
+    unsigned int index = 0;
+    for(NSTouch *touch in touchArray) {
+        if([touch phase] == NSTouchPhaseEnded) {
+            CocoaEvent newEvent;
+            newEvent.eventCode = InputEvent::EVENT_TOUCHES_ENDED;
+            newEvent.eventGroup = CocoaEvent::INPUT_EVENT;
+            newEvent.touches = touchInfos;
+            newEvent.touch = touchInfos[index];
+            core->cocoaEvents.push_back(newEvent);
+        }
+        index++;
+    }
+    core->unlockMutex(core->eventMutex);
+    
+}
+
+- (void)touchesCancelledWithEvent:(NSEvent *)event
+{
+    if(core == NULL)
+        return;
+    
+    core->lockMutex(core->eventMutex);
+    
+    NSSet *touches = [event touchesMatchingPhase:NSTouchPhaseAny inView:self];
+    NSArray *touchArray = [touches allObjects];
+    
+    std::vector<TouchInfo> touchInfos;
+    
+    for(NSTouch *touch in touchArray) {
+        TouchInfo info;
+        long touchID = (long)[touch identity];
+        info.id = touchID;
+        info.position.x = [touch normalizedPosition].x * core->getXRes();
+        info.position.y = (1.0-[touch normalizedPosition].y) * core->getYRes();
+        touchInfos.push_back(info);
+    }
+    
+    unsigned int index = 0;
+    for(NSTouch *touch in touchArray) {
+        if([touch phase] == NSTouchPhaseCancelled) {
+            CocoaEvent newEvent;
+            newEvent.eventCode = InputEvent::EVENT_TOUCHES_ENDED;
+            newEvent.eventGroup = CocoaEvent::INPUT_EVENT;
+            newEvent.touches = touchInfos;
+            newEvent.touch = touchInfos[index];
+            core->cocoaEvents.push_back(newEvent);
+        }
+        index++;
+    }
+    core->unlockMutex(core->eventMutex);
+}
+
 - (void) mouseDown:(NSEvent *) event
 - (void) mouseDown:(NSEvent *) event
 {
 {
 	
 	

+ 10 - 1
Core/Contents/Source/PolyCocoaCore.mm

@@ -509,7 +509,16 @@ void CocoaCore::checkEvents() {
 						break;
 						break;
 					case InputEvent::EVENT_KEYUP:
 					case InputEvent::EVENT_KEYUP:
 						input->setKeyState(event.keyCode, event.unicodeChar, false, getTicks());
 						input->setKeyState(event.keyCode, event.unicodeChar, false, getTicks());
-						break;						
+                    break;
+                    case InputEvent::EVENT_TOUCHES_BEGAN:
+                        input->touchesBegan(event.touch, event.touches, getTicks());
+                        break;
+                    case InputEvent::EVENT_TOUCHES_ENDED:
+                        input->touchesEnded(event.touch, event.touches, getTicks());
+                        break;
+                    case InputEvent::EVENT_TOUCHES_MOVED:
+                        input->touchesMoved(event.touch, event.touches, getTicks());
+                    break;
 				}
 				}
 				break;
 				break;
 				case CocoaEvent::FOCUS_EVENT:
 				case CocoaEvent::FOCUS_EVENT:

+ 8 - 1
Core/Contents/Source/PolyEvent.cpp

@@ -26,9 +26,11 @@ namespace Polycode {
 	
 	
 	Event::Event() {
 	Event::Event() {
 			deleteOnDispatch = true;
 			deleteOnDispatch = true;
+            cancelEventFlag = false;
 	}
 	}
 	
 	
-	Event::Event(int eventCode) {	
+	Event::Event(int eventCode) {
+        cancelEventFlag = false;
 		setEventCode(eventCode);
 		setEventCode(eventCode);
 	}
 	}
 	
 	
@@ -55,4 +57,9 @@ namespace Polycode {
 	void Event::setEventCode(int eventCode) {
 	void Event::setEventCode(int eventCode) {
 		this->eventCode = eventCode;
 		this->eventCode = eventCode;
 	}
 	}
+    
+    void Event::cancelEvent() {
+        cancelEventFlag = true;
+    }
+
 }
 }

+ 3 - 0
Core/Contents/Source/PolyEventDispatcher.cpp

@@ -87,6 +87,9 @@ void EventDispatcher::__dispatchEvent(Event *event, int eventCode) {
     for(int i=0;i<handlerEntries.size();i++) {
     for(int i=0;i<handlerEntries.size();i++) {
         if(handlerEntries[i].eventCode == eventCode) {
         if(handlerEntries[i].eventCode == eventCode) {
             handlerEntries[i].handler->handleEvent(event);
             handlerEntries[i].handler->handleEvent(event);
+            if(event->cancelEventFlag) {
+                break;
+            }
         }
         }
     }	
     }	
 }
 }

+ 1 - 0
Core/Contents/Source/PolyLogger.cpp

@@ -75,6 +75,7 @@ void Logger::log(const char *format, ...) {
 		if (Logger::getInstance()->getLogFile()){
 		if (Logger::getInstance()->getLogFile()){
 			va_start(args, format);
 			va_start(args, format);
 			vfprintf(Logger::getInstance()->getLogFile(), format, args);
 			vfprintf(Logger::getInstance()->getLogFile(), format, args);
+            fflush(Logger::getInstance()->getLogFile());
 			va_end(args);
 			va_end(args);
 		} else {
 		} else {
 			time_t t = time(NULL);
 			time_t t = time(NULL);

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

@@ -28,6 +28,15 @@
 
 
 using namespace Polycode;
 using namespace Polycode;
 
 
+ObjectEntry::ObjectEntry() :
+type(UNKNOWN_ENTRY),
+NumberVal(0.0),
+length(0),
+intVal(0)
+{
+    
+}
+
 void ObjectEntry::Clear() {
 void ObjectEntry::Clear() {
 	for(int i=0; i < children.size(); i++) {
 	for(int i=0; i < children.size(); i++) {
 		children[i]->Clear();
 		children[i]->Clear();
@@ -132,6 +141,7 @@ TiXmlElement *Object::createElementFromObjectEntry(ObjectEntry *entry) {
 						break;
 						break;
 						case ObjectEntry::FLOAT_ENTRY: {
 						case ObjectEntry::FLOAT_ENTRY: {
 							std::ostringstream o; // Avoid NumberToString, it truncates
 							std::ostringstream o; // Avoid NumberToString, it truncates
+                            o << std::fixed;
 							o << childEntry->NumberVal;
 							o << childEntry->NumberVal;
 							newElement->SetAttribute(childTypedName.c_str(), o.str().c_str());
 							newElement->SetAttribute(childTypedName.c_str(), o.str().c_str());
 						} break;
 						} break;

+ 3 - 4
Core/Contents/Source/PolySceneSprite.cpp

@@ -524,10 +524,9 @@ void Sprite::setName(String name) {
 }
 }
 
 
 
 
-SpriteSet::SpriteSet(String fileName, ResourcePool *parentPool) : ResourcePool(fileName, parentPool) {
+SpriteSet::SpriteSet(const String &fileName, ResourcePool *parentPool) : ResourcePool(fileName, parentPool) {
     nextFrameIDIndex = 0;
     nextFrameIDIndex = 0;
     loadSpriteSet(fileName);
     loadSpriteSet(fileName);
-    
 }
 }
 
 
 void SpriteSet::loadSpriteSet(String fileName) {
 void SpriteSet::loadSpriteSet(String fileName) {
@@ -790,8 +789,8 @@ void SpriteSet::clearFrames() {
 
 
 void SpriteSet::createGridFrames(Number width, Number height, const Vector2 &defaultAnchor) {
 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) {
+    for(Number y = 0.0; y+height <= 1.0; y += height) {
+        for(Number x = 0.0; x+width <= 1.0; x += width) {
             SpriteFrame frame;
             SpriteFrame frame;
             frame.coordinates = Polycode::Rectangle(x, y, width, height);
             frame.coordinates = Polycode::Rectangle(x, y, width, height);
             frame.anchorPoint = defaultAnchor;
             frame.anchorPoint = defaultAnchor;

BIN
Examples/Lua/Graphics/Sprites/Resources/explosion.png


+ 31 - 0
Examples/Lua/Graphics/Sprites/Resources/sprite_set.sprites

@@ -0,0 +1,31 @@
+<?xml version="1.0" ?>
+<sprite_set>
+    <sprite_sheet fileName="Resources/explosion.png">
+        <frames>
+            <frame id="0" x="0" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="1" x="0.0555556" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="2" x="0.111111" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="3" x="0.166667" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="4" x="0.222222" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="5" x="0.277778" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="6" x="0.333333" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="7" x="0.388889" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="8" x="0.444444" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="9" x="0.5" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="10" x="0.555556" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="11" x="0.611111" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="12" x="0.666667" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="13" x="0.722222" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="14" x="0.777778" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="15" x="0.833333" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+            <frame id="16" x="0.888889" y="0" w="0.0555556" h="1" ax="0" ay="0" />
+        </frames>
+    </sprite_sheet>
+    <sprites>
+        <sprite name="Explosion">
+            <states>
+                <state name="default" fps="20" scale="1" width="32" height="32" offset_x="0" offset_y="0" frame_ids="0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16" />
+            </states>
+        </sprite>
+    </sprites>
+</sprite_set>

+ 10 - 0
Examples/Lua/Graphics/Sprites/Scripts/Main.lua

@@ -0,0 +1,10 @@
+scene = Scene(Scene.SCENE_2D)
+scene:getActiveCamera():setOrthoSize(640, 480)
+    
+spriteSet = SpriteSet("Resources/sprite_set.sprites", Services.ResourceManager:getGlobalPool())
+sceneSprite = SceneSprite(spriteSet)
+sceneSprite:setScale(4, 4)
+scene:addEntity(sceneSprite)
+    
+sceneSprite:setSpriteByName("Explosion")
+sceneSprite:setSpriteStateByName("default", 0, false)

+ 8 - 0
Examples/Lua/Graphics/Sprites/Sprites.polyproject

@@ -0,0 +1,8 @@
+<?xml version="1.0" ?>
+<PolycodeProject defaultWidth="640" defaultHeight="480" antiAliasingLevel="0" entryPoint="Scripts/Main.lua" textureFiltering="linear" vSync="false" anisotropyLevel="0" frameRate="60">
+    <backgroundColor red="0.25" green="0.25" blue="0.25" />
+    <polyarray:packedItems>
+        <item type="folder" path="Resources" />
+        <item type="folder" path="Scripts" />
+    </polyarray:packedItems>
+</PolycodeProject>

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

@@ -65,6 +65,7 @@ class SpriteSheetEditor : public UIElement {
     
     
         void deleteSelectedFrames();
         void deleteSelectedFrames();
     
     
+        void selectAll();
         void clearSelected();
         void clearSelected();
         bool hasSelectedID(unsigned int frameID);
         bool hasSelectedID(unsigned int frameID);
         std::vector<unsigned int> getSelectedFrameIDs();
         std::vector<unsigned int> getSelectedFrameIDs();
@@ -312,6 +313,8 @@ class PolycodeSpriteEditor : public PolycodeEditor {
 		bool openFile(OSFileEntry filePath);
 		bool openFile(OSFileEntry filePath);
 		void Resize(int x, int y);
 		void Resize(int x, int y);
 		void saveFile();
 		void saveFile();
+    
+        void selectAll();
 				
 				
 	protected:
 	protected:
 	
 	

+ 37 - 9
IDE/Contents/Source/PolycodeSpriteEditor.cpp

@@ -422,6 +422,17 @@ void SpriteSheetEditor::handleEvent(Event *event) {
                             if(!hasSelectedID(frame.frameID)) {
                             if(!hasSelectedID(frame.frameID)) {
                                 selectedIDs.push_back(frame.frameID);
                                 selectedIDs.push_back(frame.frameID);
                                 willCreateFrame = false;
                                 willCreateFrame = false;
+                            } else {
+                                
+                                if(Services()->getCore()->getInput()->getKeyState(KEY_LSHIFT) ||
+                                   Services()->getCore()->getInput()->getKeyState(KEY_LSHIFT)) {
+                                    for(int f=0; f < selectedIDs.size(); f++) {
+                                        if(selectedIDs[f] == frame.frameID)
+                                        {
+                                            selectedIDs.erase(selectedIDs.begin() + f);
+                                            break;
+                                        }}
+                                }
                             }
                             }
                             break;
                             break;
                         }
                         }
@@ -491,6 +502,16 @@ void SpriteSheetEditor::handleEvent(Event *event) {
     }
     }
 }
 }
 
 
+void SpriteSheetEditor::selectAll() {
+    if(previewBg->hasFocus) {
+        clearSelected();
+        for(int i=0; i < sprite->getNumFrames(); i++) {
+            SpriteFrame frame = sprite->getSpriteFrame(i);
+            selectedIDs.push_back(frame.frameID);
+        }
+    }
+}
+
 void SpriteSheetEditor::deleteSelectedFrames() {
 void SpriteSheetEditor::deleteSelectedFrames() {
  
  
     for(int i=0; i < selectedIDs.size(); i++) {
     for(int i=0; i < selectedIDs.size(); i++) {
@@ -557,7 +578,7 @@ void SpriteSheetEditor::Resize(Number width, Number height) {
 }
 }
 
 
 void SpriteSheetEditor::Render() {
 void SpriteSheetEditor::Render() {
-    if(sprite->getNumFrames() > 0 && selectedIDs.size() > 0) {
+    if(sprite->getNumFrames() > 0 && selectedIDs.size() == 1) {
         
         
         transformGrips->visible = true;
         transformGrips->visible = true;
         transformGrips->enabled = true;
         transformGrips->enabled = true;
@@ -616,11 +637,7 @@ SpriteBrowser::SpriteBrowser(SpriteSet *spriteSet) : UIElement () {
     addChild(spriteTreeView);
     addChild(spriteTreeView);
     
     
     spriteTreeView->getRootNode()->toggleCollapsed();
     spriteTreeView->getRootNode()->toggleCollapsed();
-    
     spriteTreeView->getRootNode()->addEventListener(this, UITreeEvent::SELECTED_EVENT);
     spriteTreeView->getRootNode()->addEventListener(this, UITreeEvent::SELECTED_EVENT);
-    
-	globalFrame->textInputPopup->addEventListener(this, UIEvent::OK_EVENT);
-	globalFrame->yesNoPopup->addEventListener(this, UIEvent::OK_EVENT);
 }
 }
 
 
 void SpriteBrowser::handleEvent(Event *event) {
 void SpriteBrowser::handleEvent(Event *event) {
@@ -629,6 +646,7 @@ void SpriteBrowser::handleEvent(Event *event) {
 		globalFrame->textInputPopup->setCaption("New sprite name");
 		globalFrame->textInputPopup->setCaption("New sprite name");
 		globalFrame->textInputPopup->setValue("New Sprite");
 		globalFrame->textInputPopup->setValue("New Sprite");
 		globalFrame->showModal(globalFrame->textInputPopup);
 		globalFrame->showModal(globalFrame->textInputPopup);
+        globalFrame->textInputPopup->addEventListener(this, UIEvent::OK_EVENT);
     } else if(event->getDispatcher() == globalFrame->textInputPopup) {
     } else if(event->getDispatcher() == globalFrame->textInputPopup) {
         if(event->getEventCode() == UIEvent::OK_EVENT) {
         if(event->getEventCode() == UIEvent::OK_EVENT) {
             if(globalFrame->textInputPopup->action == "newSprite") {
             if(globalFrame->textInputPopup->action == "newSprite") {
@@ -644,6 +662,7 @@ void SpriteBrowser::handleEvent(Event *event) {
                 selectedEntry->setName(globalFrame->textInputPopup->getValue());
                 selectedEntry->setName(globalFrame->textInputPopup->getValue());
                 refreshSprites();
                 refreshSprites();
             }
             }
+            globalFrame->textInputPopup->removeAllHandlersForListener(this);
         }
         }
     } else if(event->getDispatcher() == globalFrame->yesNoPopup) {
     } else if(event->getDispatcher() == globalFrame->yesNoPopup) {
         if(event->getEventCode() == UIEvent::OK_EVENT) {
         if(event->getEventCode() == UIEvent::OK_EVENT) {
@@ -656,10 +675,12 @@ void SpriteBrowser::handleEvent(Event *event) {
                 }
                 }
             }
             }
         }
         }
+        globalFrame->yesNoPopup->removeAllHandlersForListener(this);
     } else if(event->getDispatcher() == removeSpriteButton) {
     } else if(event->getDispatcher() == removeSpriteButton) {
         if(selectedEntry) {
         if(selectedEntry) {
             globalFrame->yesNoPopup->setCaption("Are you sure you want to remove sprite \""+selectedEntry->getName()+"\"?");
             globalFrame->yesNoPopup->setCaption("Are you sure you want to remove sprite \""+selectedEntry->getName()+"\"?");
             globalFrame->yesNoPopup->action = "removeSprite";
             globalFrame->yesNoPopup->action = "removeSprite";
+            globalFrame->yesNoPopup->addEventListener(this, UIEvent::OK_EVENT);
             globalFrame->showModal(globalFrame->yesNoPopup);
             globalFrame->showModal(globalFrame->yesNoPopup);
 
 
         }
         }
@@ -674,6 +695,7 @@ void SpriteBrowser::handleEvent(Event *event) {
                 globalFrame->textInputPopup->action = "renameSprite";
                 globalFrame->textInputPopup->action = "renameSprite";
                 globalFrame->textInputPopup->setCaption("New sprite name");
                 globalFrame->textInputPopup->setCaption("New sprite name");
                 globalFrame->textInputPopup->setValue(selectedEntry->getName());
                 globalFrame->textInputPopup->setValue(selectedEntry->getName());
+                globalFrame->textInputPopup->addEventListener(this, UIEvent::OK_EVENT);
                 globalFrame->showModal(globalFrame->textInputPopup);
                 globalFrame->showModal(globalFrame->textInputPopup);
             }
             }
         }
         }
@@ -1509,9 +1531,6 @@ SpriteStateEditor::SpriteStateEditor(SpriteSet *spriteSet) : UIElement() {
     stateTreeView = stateBrowser->stateTreeView;
     stateTreeView = stateBrowser->stateTreeView;
     stateTreeView->getRootNode()->addEventListener(this, UITreeEvent::SELECTED_EVENT);
     stateTreeView->getRootNode()->addEventListener(this, UITreeEvent::SELECTED_EVENT);
     
     
-	globalFrame->textInputPopup->addEventListener(this, UIEvent::OK_EVENT);
-	globalFrame->yesNoPopup->addEventListener(this, UIEvent::OK_EVENT);
-    
     selectedState = NULL;
     selectedState = NULL;
     
     
     visible = false;
     visible = false;
@@ -1554,6 +1573,7 @@ void SpriteStateEditor::handleEvent(Event *event) {
         globalFrame->textInputPopup->action = "newState";
         globalFrame->textInputPopup->action = "newState";
 		globalFrame->textInputPopup->setCaption("New state name");
 		globalFrame->textInputPopup->setCaption("New state name");
 		globalFrame->textInputPopup->setValue("New State");
 		globalFrame->textInputPopup->setValue("New State");
+        globalFrame->textInputPopup->addEventListener(this, UIEvent::OK_EVENT);
         globalFrame->showModal(globalFrame->textInputPopup);
         globalFrame->showModal(globalFrame->textInputPopup);
         
         
     } else if(event->getDispatcher() == globalFrame->textInputPopup) {
     } else if(event->getDispatcher() == globalFrame->textInputPopup) {
@@ -1567,6 +1587,7 @@ void SpriteStateEditor::handleEvent(Event *event) {
                 refreshStates();
                 refreshStates();
             }
             }
         }
         }
+        globalFrame->textInputPopup->removeAllHandlersForListener(this);
     } else if(event->getDispatcher() == globalFrame->yesNoPopup) {
     } else if(event->getDispatcher() == globalFrame->yesNoPopup) {
         if(event->getEventCode() == UIEvent::OK_EVENT) {
         if(event->getEventCode() == UIEvent::OK_EVENT) {
             if(globalFrame->yesNoPopup->action == "removeState") {
             if(globalFrame->yesNoPopup->action == "removeState") {
@@ -1580,12 +1601,13 @@ void SpriteStateEditor::handleEvent(Event *event) {
                 }
                 }
             }
             }
         }
         }
+        globalFrame->yesNoPopup->removeAllHandlersForListener(this);
     } else if(event->getDispatcher() == stateBrowser->removeStateButton) {
     } else if(event->getDispatcher() == stateBrowser->removeStateButton) {
         if(selectedState) {
         if(selectedState) {
             globalFrame->yesNoPopup->setCaption("Are you sure you want to remove state \""+selectedState->getName()+"\"?");
             globalFrame->yesNoPopup->setCaption("Are you sure you want to remove state \""+selectedState->getName()+"\"?");
             globalFrame->yesNoPopup->action = "removeState";
             globalFrame->yesNoPopup->action = "removeState";
+            globalFrame->yesNoPopup->addEventListener(this, UIEvent::OK_EVENT);
             globalFrame->showModal(globalFrame->yesNoPopup);
             globalFrame->showModal(globalFrame->yesNoPopup);
-            
         }
         }
     } else if(event->getDispatcher() == stateBrowser->moreButton) {
     } else if(event->getDispatcher() == stateBrowser->moreButton) {
         stateMoreMenu = globalMenu->showMenuAtMouse(100.0);
         stateMoreMenu = globalMenu->showMenuAtMouse(100.0);
@@ -1598,6 +1620,7 @@ void SpriteStateEditor::handleEvent(Event *event) {
                 globalFrame->textInputPopup->action = "renameState";
                 globalFrame->textInputPopup->action = "renameState";
                 globalFrame->textInputPopup->setCaption("New state name");
                 globalFrame->textInputPopup->setCaption("New state name");
                 globalFrame->textInputPopup->setValue(selectedState->getName());
                 globalFrame->textInputPopup->setValue(selectedState->getName());
+                globalFrame->textInputPopup->addEventListener(this, UIEvent::OK_EVENT);
                 globalFrame->showModal(globalFrame->textInputPopup);
                 globalFrame->showModal(globalFrame->textInputPopup);
             }
             }
         }
         }
@@ -1798,6 +1821,7 @@ void PolycodeSpriteEditor::handleEvent(Event *event) {
             state->rebuildStateMeshes();
             state->rebuildStateMeshes();
         }
         }
     }
     }
+    PolycodeEditor::handleEvent(event);
 }
 }
 
 
 PolycodeSpriteEditor::~PolycodeSpriteEditor() {
 PolycodeSpriteEditor::~PolycodeSpriteEditor() {
@@ -1863,6 +1887,10 @@ bool PolycodeSpriteEditor::openFile(OSFileEntry filePath) {
     return true;
     return true;
 }
 }
 
 
+void PolycodeSpriteEditor::selectAll() {
+    spriteSheetEditor->selectAll();
+}
+
 void PolycodeSpriteEditor::saveFile() {
 void PolycodeSpriteEditor::saveFile() {
     Object fileObject;
     Object fileObject;
     fileObject.root.name = "sprite_set";
     fileObject.root.name = "sprite_set";