فهرست منبع

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

Paul Smith 13 سال پیش
والد
کامیت
4dfa861e6a
44فایلهای تغییر یافته به همراه673 افزوده شده و 320 حذف شده
  1. 1 0
      Bindings/Scripts/create_lua_library/create_lua_library.py
  2. 14 0
      Core/Contents/Include/PolyEntity.h
  3. 1 1
      Core/Contents/Include/PolyInputKeys.h
  4. 3 0
      Core/Contents/Include/PolyParticleEmitter.h
  5. 1 1
      Core/Contents/Include/PolyRenderer.h
  6. 4 2
      Core/Contents/Include/PolyScreenEntity.h
  7. 11 4
      Core/Contents/Include/PolyScreenEntityInstance.h
  8. 4 0
      Core/Contents/Include/PolyScreenImage.h
  9. 3 0
      Core/Contents/Include/PolyScreenLabel.h
  10. 4 1
      Core/Contents/Include/PolyScreenShape.h
  11. 4 0
      Core/Contents/Include/PolyScreenSound.h
  12. 3 0
      Core/Contents/Include/PolyScreenSprite.h
  13. 2 0
      Core/Contents/Include/PolyWinCore.h
  14. 0 279
      Core/Contents/Include/PolyWinCore.h~
  15. 48 0
      Core/Contents/Source/PolyEntity.cpp
  16. 1 1
      Core/Contents/Source/PolyGLRenderer.cpp
  17. 43 0
      Core/Contents/Source/PolyParticleEmitter.cpp
  18. 3 3
      Core/Contents/Source/PolyRenderer.cpp
  19. 21 0
      Core/Contents/Source/PolyScreenEntity.cpp
  20. 30 1
      Core/Contents/Source/PolyScreenEntityInstance.cpp
  21. 10 0
      Core/Contents/Source/PolyScreenImage.cpp
  22. 12 0
      Core/Contents/Source/PolyScreenLabel.cpp
  23. 13 0
      Core/Contents/Source/PolyScreenShape.cpp
  24. 9 0
      Core/Contents/Source/PolyScreenSound.cpp
  25. 17 0
      Core/Contents/Source/PolyScreenSprite.cpp
  26. 38 1
      Core/Contents/Source/PolyWinCore.cpp
  27. 1 1
      IDE/Build/Linux/Makefile
  28. 6 0
      IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj
  29. 2 0
      IDE/Build/Windows/Polycode.vcxproj
  30. 6 0
      IDE/Build/Windows/Polycode.vcxproj.filters
  31. 50 0
      IDE/Contents/Include/PolycodeClipboard.h
  32. 11 2
      IDE/Contents/Include/PolycodeEditor.h
  33. 1 0
      IDE/Contents/Include/PolycodeIDEApp.h
  34. 30 2
      IDE/Contents/Include/PolycodeScreenEditor.h
  35. 51 0
      IDE/Contents/Source/PolycodeClipboard.cpp
  36. 31 1
      IDE/Contents/Source/PolycodeEditor.cpp
  37. 14 9
      IDE/Contents/Source/PolycodeIDEApp.cpp
  38. 17 1
      IDE/Contents/Source/PolycodeProjectManager.cpp
  39. 81 1
      IDE/Contents/Source/PolycodeScreenEditor.cpp
  40. 8 2
      Modules/Contents/UI/Include/PolyUIMenuBar.h
  41. 2 2
      Modules/Contents/UI/Include/PolyUITree.h
  42. 52 2
      Modules/Contents/UI/Source/PolyUIMenuBar.cpp
  43. 2 2
      Modules/Contents/UI/Source/PolyUITree.cpp
  44. 8 1
      Tools/Contents/polybuild/Source/polybuild.cpp

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

@@ -137,6 +137,7 @@ def createLUABindings(inputPath, prefix, mainInclude, libSmallName, libName, api
 		wrappersHeaderOut += "		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));\n"
 		wrappersHeaderOut += "		*userdataPtr = (PolyBase*)e;\n"
 		wrappersHeaderOut += "		lua_pcall(L, 2, 0, errH);\n"
+		wrappersHeaderOut += "		lua_settop(L, 0);\n"
 		wrappersHeaderOut += "	}\n"
 		wrappersHeaderOut += "	int wrapperIndex;\n"
 		wrappersHeaderOut += "	lua_State *L;\n"

+ 14 - 0
Core/Contents/Include/PolyEntity.h

@@ -79,6 +79,20 @@ namespace Polycode {
 
 			void renderChildren();					
 		
+			
+			/**
+ 			* Clones the entity, return an exact copy. This method must be implemented in an Entity subclass for you to be able to clone it.
+ 			* @param deepClone If true, perform a deep clone, cloning all the children.
+ 			* @param ignoreEditorOnly If true, ignore all child entities where editorOnly is set to true (will still clone the entity you call Clone() on even if its editorOnly flag is set to true.
+ 			* @return The clone of the entity.
+ 			*/
+			virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+
+			/**
+ 			* This method must be implemented by all subvlasses implementing Clone.
+ 			*/
+			virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+		
 		
 			// ----------------------------------------------------------------------------------------------------------------
 			/** @name Matrix operations.

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

@@ -286,4 +286,4 @@ namespace Polycode {
 	} PolyKEY;
 
 };
-	
+	

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

@@ -326,6 +326,9 @@ namespace Polycode {
 		ScreenParticleEmitter(const String& imageFile, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh = NULL, ScreenMesh *emitter = NULL);
 		virtual ~ScreenParticleEmitter();		
 		
+		virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+		virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+		
 		/**
 		* Returns the emitter (helper method for LUA).
 		*/ 		

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

@@ -111,7 +111,7 @@ namespace Polycode {
 		virtual void setTexture(Texture *texture) = 0;		
 		virtual void enableBackfaceCulling(bool val) = 0;
 		
-		virtual void setClearColor(Number r, Number g, Number b);
+		virtual void setClearColor(Number r, Number g, Number b, Number a = 1.0);
 		virtual void setClearColor(Color color);
 		
 		virtual void setAmbientColor(Number r, Number g, Number b);

+ 4 - 2
Core/Contents/Include/PolyScreenEntity.h

@@ -51,7 +51,9 @@ class _PolyExport ScreenEntity : public Entity {
 		ScreenEntity();
 		virtual ~ScreenEntity();
 		
-		
+		virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+		virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+
 		void addEntity(Entity *newChild);
 		
 		/**
@@ -230,4 +232,4 @@ class _PolyExport ScreenEntity : public Entity {
 
 };
 
-}
+}

+ 11 - 4
Core/Contents/Include/PolyScreenEntityInstance.h

@@ -39,8 +39,13 @@ namespace Polycode {
 class ScreenEntityInstance : public ScreenEntity {
 	public:
 		ScreenEntityInstance(const String& fileName);
+		ScreenEntityInstance();
+
 		~ScreenEntityInstance();
-		
+	
+		virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+		virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+
 		void parseObjectIntoCurve(ObjectEntry *entry, BezierCurve *curve);
 		void applyScreenShape(ObjectEntry *entry, ScreenShape *shape);
 		ScreenEntity *loadObjectEntryIntoEntity(ObjectEntry *entry);
@@ -50,9 +55,11 @@ class ScreenEntityInstance : public ScreenEntity {
 		
 		String getFileName() const;
 		
-	protected:
-		ScreenEntity *rootEntity;		
+		bool cloneUsingReload;
+
 		String fileName;
+
+		ScreenEntity *rootEntity;		
 };
 
-}
+}

+ 4 - 0
Core/Contents/Include/PolyScreenImage.h

@@ -49,8 +49,12 @@ namespace Polycode {
 		 */		
 		ScreenImage(Texture *texture);		
 		
+
 		virtual ~ScreenImage();
 		
+		virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+		virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+
 		/**
 		* Changes which part of the image is displayed.
 		* @param x X position of the display rectangle.

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

@@ -45,6 +45,9 @@ namespace Polycode {
 			ScreenLabel(const String& text, int size, const String& fontName = "sans", int amode = 0, bool premultiplyAlpha = false);
 			virtual ~ScreenLabel();		
 		
+			virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+			virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+		
 			/**
 			* Adds a drop shadow to the label.
 			* @param color Color of the drop shadow.

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

@@ -43,7 +43,10 @@ namespace Polycode {
 			* @param option4 Reserved.
 			*/
 			ScreenShape(int shapeType, Number option1=0, Number option2=0, Number option3=0, Number option4=0);
-						
+		
+			virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+			virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+				
 			virtual ~ScreenShape();
 			void Render();
 

+ 4 - 0
Core/Contents/Include/PolyScreenSound.h

@@ -46,6 +46,10 @@ namespace Polycode {
 		public:
 			ScreenSound(const String& fileName, Number referenceDistance, Number maxDistance);
 			virtual ~ScreenSound();			
+
+			virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+			virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+
 			void Update();			
 			
 			/**

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

@@ -66,6 +66,9 @@ class _PolyExport ScreenSprite : public ScreenShape
 		ScreenSprite(const String& fileName, Number spriteWidth, Number spriteHeight);
 		virtual ~ScreenSprite();
 		
+		virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly);
+		virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly);
+
 		/**
 		* 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.

+ 2 - 0
Core/Contents/Include/PolyWinCore.h

@@ -249,6 +249,8 @@ public:
 
 	private:
 
+		bool checkSpecialKeyEvents(PolyKEY key);
+
 		unsigned int nextDeviceID;
 		PolyKEY keyMap[1024];
 		unsigned int lastGamepadDetect;

+ 0 - 279
Core/Contents/Include/PolyWinCore.h~

@@ -1,279 +0,0 @@
-/*
- Copyright (C) 2011 by Ivan Safrin
- 
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- 
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-*/
-
-
-#pragma once
-#include "PolyGlobals.h"
-#include "PolyCore.h"
-#include "PolyInputKeys.h"
-#include "PolyInputEvent.h"
-#include "PolyRectangle.h"
-
-#include <winsock2.h>
-#include <windows.h>
-#include <windowsx.h>
-#include <WinUser.h>
-
-#include <MMSystem.h>
-#include <regstr.h>
-
-
-#include <vector>
-
-#ifndef VK_0
-#define VK_0	'0'
-#define VK_1	'1'
-#define VK_2	'2'
-#define VK_3	'3'
-#define VK_4	'4'
-#define VK_5	'5'
-#define VK_6	'6'
-#define VK_7	'7'
-#define VK_8	'8'
-#define VK_9	'9'
-#define VK_A	'A'
-#define VK_B	'B'
-#define VK_C	'C'
-#define VK_D	'D'
-#define VK_E	'E'
-#define VK_F	'F'
-#define VK_G	'G'
-#define VK_H	'H'
-#define VK_I	'I'
-#define VK_J	'J'
-#define VK_K	'K'
-#define VK_L	'L'
-#define VK_M	'M'
-#define VK_N	'N'
-#define VK_O	'O'
-#define VK_P	'P'
-#define VK_Q	'Q'
-#define VK_R	'R'
-#define VK_S	'S'
-#define VK_T	'T'
-#define VK_U	'U'
-#define VK_V	'V'
-#define VK_W	'W'
-#define VK_X	'X'
-#define VK_Y	'Y'
-#define VK_Z	'Z'
-#endif /* VK_0 */
-
-/* These keys haven't been defined, but were experimentally determined */
-#define VK_SEMICOLON	0xBA
-#define VK_EQUALS	0xBB
-#define VK_COMMA	0xBC
-#define VK_MINUS	0xBD
-#define VK_PERIOD	0xBE
-#define VK_SLASH	0xBF
-#define VK_GRAVE	0xC0
-#define VK_LBRACKET	0xDB
-#define VK_BACKSLASH	0xDC
-#define VK_RBRACKET	0xDD
-#define VK_APOSTROPHE	0xDE
-#define VK_BACKTICK	0xDF
-#define VK_OEM_102	0xE2
-
-#define EXTENDED_KEYMASK	(1<<24)
-
-#ifdef _MINGW
-#define NO_TOUCH_API 1
-#endif
-
-namespace Polycode {
-
-	class _PolyExport Win32Mutex : public CoreMutex {
-	public:
-		HANDLE winMutex; 
-	};
-
-	class _PolyExport Win32Event {
-	public:
-		int eventGroup;
-		int eventCode;		
-		int mouseX;
-		int mouseY;
-		TouchInfo touch;
-		std::vector<TouchInfo> touches;
-		PolyKEY keyCode;
-		wchar_t unicodeChar;		
-		char mouseButton;	
-		static const int INPUT_EVENT = 0;
-	};
-	
-	
-	class HIDGamepadAxis {
-		public:
-		//IOHIDElementCookie cookie;
-		//CFIndex logicalMin;
-		//CFIndex logicalMax;
-		bool hasNullState;
-		bool isHatSwitch;
-		bool isHatSwitchSecondAxis;
-	};
-
-	class HIDGamepadButton {
-		public:
-		//IOHIDElementCookie cookie;
-		int something;
-	};	
-	
-class Gamepad_devicePrivate {
-public:
-	UINT joystickID;
-	JOYINFOEX lastState;
-	int xAxisIndex;
-	int yAxisIndex;
-	int zAxisIndex;
-	int rAxisIndex;
-	int uAxisIndex;
-	int vAxisIndex;
-	int povXAxisIndex;
-	int povYAxisIndex;
-	UINT (* axisRanges)[2];
-};
-
-
-	class GamepadDeviceEntry  {
-		public:
-			GamepadDeviceEntry() {
-				numAxes = 0;
-			}
-			std::vector<HIDGamepadAxis> axisElements;
-			std::vector<HIDGamepadButton> buttonElements;			
-			unsigned int deviceID;
-			//IOHIDDeviceRef device;
-			unsigned int numAxes;
-			unsigned int numButtons;	
-			Gamepad_devicePrivate *privateData;
-		//	CoreInput *input;		
-	};
-
-	class _PolyExport Win32Core : public Core {
-		
-	public:
-		
-		Win32Core(PolycodeViewBase *view, int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate,  int monitorIndex = -1);
-		~Win32Core();
-
-		void enableMouse(bool newval);
-		void warpCursor(int x, int y);
-		unsigned int getTicks();		
-		bool Update();
-
-		void setVSync(bool vSyncVal);
-
-		void handleKeyDown(LPARAM lParam, WPARAM wParam, wchar_t unicodeChar);
-		void handleKeyUp(LPARAM lParam, WPARAM wParam);
-		void handleMouseMove(LPARAM lParam, WPARAM wParam);
-		void handleMouseWheel(LPARAM lParam, WPARAM wParam);
-		void handleMouseDown(int mouseCode,LPARAM lParam, WPARAM wParam);
-		void handleMouseUp(int mouseCode,LPARAM lParam, WPARAM wParam);
-		void handleTouchEvent(LPARAM lParam, WPARAM wParam);
-
-		bool isMultiTouchEnabled() { return hasMultiTouch; }
-
-		void setVideoMode(int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel);
-		
-		void initContext(bool usePixelFormat, unsigned int pixelFormat);
-		void destroyContext();
-
-		void createThread(Threaded *target);
-
-		PolyKEY mapKey(LPARAM lParam, WPARAM wParam);
-
-		void lockMutex(CoreMutex *mutex);
-		void unlockMutex(CoreMutex *mutex);
-		CoreMutex *createMutex();
-
-		void checkEvents();
-		void initKeymap();
-
-		void platformSleep(int msecs);
-
-		std::vector<Polycode::Rectangle> getVideoModes();
-
-		void handleAxisChange(GamepadDeviceEntry * device, int axisIndex, DWORD value);
-		void handleButtonChange(GamepadDeviceEntry * device, DWORD lastValue, DWORD value);
-		void handlePOVChange(GamepadDeviceEntry * device, DWORD lastValue, DWORD value);
-
-		void detectGamepads();
-		void initGamepad();
-		void shutdownGamepad();
-		void Gamepad_processEvents();
-
-		void initTouch();
-
-		// NEED TO IMPLEMENT:
-
-		String executeExternalCommand(String command) { return "";}
-
-		void openURL(String url) {}
-		void setCursor(int cursorType){ }
-		void copyStringToClipboard(const String& str) { }
-		String getClipboardString() { return ""; }
-
-		void createFolder(const String& folderPath) {}
-		void copyDiskItem(const String& itemPath, const String& destItemPath) {}
-		void moveDiskItem(const String& itemPath, const String& destItemPath) {}
-		String openFolderPicker()  { return "";}
-		void removeDiskItem(const String& itemPath)  {}
-		std::vector<String> openFilePicker(std::vector<CoreFileExtension> extensions, bool allowMultiple) { std::vector<String> ret; return ret;}
-		void resizeTo(int xRes, int yRes) { }
-		
-		std::vector<GamepadDeviceEntry*> gamepads;
-
-	private:
-
-		unsigned int nextDeviceID;
-		PolyKEY keyMap[1024];
-		unsigned int lastGamepadDetect;
-
-		std::vector<Win32Event> win32Events;
-
-		void initMultisample(int numSamples);
-
-		HWND hWnd;
-
-		int lastMouseX;
-		int lastMouseY;
-
-		bool isFullScreen;
-
-		HDC hDC;
-		HGLRC hRC;
-		unsigned int PixelFormat;
-		PIXELFORMATDESCRIPTOR pfd;
-		
-		// Tracks whether the system supports multitouch at runtime
-		bool hasMultiTouch;
-		
-#ifndef NO_TOUCH_API
-		// Create generic reference to any multitouch functions we need, so that we
-		// can make them available at runtime if the operating system supports it
-		// while still allowing fallback for older systems
-		// See: http://msdn.microsoft.com/en-us/library/ms683212(v=vs.85).aspx
-		typedef bool (WINAPI *GetTouchInputInfoType)(HTOUCHINPUT,UINT,PTOUCHINPUT,int);
-		GetTouchInputInfoType GetTouchInputInfoFunc;
-#endif	
-	};
-}

+ 48 - 0
Core/Contents/Source/PolyEntity.cpp

@@ -77,6 +77,54 @@ Entity *Entity::getEntityById(String id, bool recursive) {
 	return NULL;
 }
 
+Entity *Entity::Clone(bool deepClone, bool ignoreEditorOnly) {
+	Entity *newEntity = new Entity();
+	applyClone(newEntity, deepClone, ignoreEditorOnly);
+	return newEntity;
+}
+
+void Entity::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	clone->ownsChildren = ownsChildren;
+	clone->position = position;
+	clone->rotation = rotation;
+	clone->scale = scale;
+	clone->color = color;
+	clone->custEntityType = custEntityType;
+	clone->billboardMode = billboardMode;	
+	clone->billboardRoll = billboardRoll;
+	clone->alphaTest = alphaTest;
+	clone->backfaceCulled = backfaceCulled;
+	clone->renderWireframe = renderWireframe;
+	clone->depthWrite = depthWrite;
+	clone->depthTest = depthTest;
+	clone->blendingMode = blendingMode;
+	clone->colorAffectsChildren;
+	clone->visibilityAffectsChildren = visibilityAffectsChildren;
+	clone->depthOnly = depthOnly;
+	clone->setUserData(getUserData());
+	clone->entityProps = entityProps;
+	clone->bBox = bBox;
+	clone->ignoreParentMatrix = ignoreParentMatrix;
+	clone->enableScissor = enableScissor;
+	clone->scissorBox = scissorBox;
+	clone->editorOnly = editorOnly;	
+	clone->id = id;
+	for(int i=0; i < tags.size(); i++) {	
+		clone->addTag(tags[i]);
+	}
+	clone->setRenderer(renderer);
+
+	if(deepClone) {
+		for(int i=0; i < children.size(); i++) {
+			if(children[i]->editorOnly && ignoreEditorOnly) {
+			} else {
+				Entity *childClone = children[i]->Clone(deepClone, ignoreEditorOnly);
+				clone->addChild(childClone);
+			}
+		}
+	}
+}
+
 std::vector<Entity*> Entity::getEntitiesByTag(String tag, bool recursive) {
 
 	std::vector<Entity*> retVector;

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

@@ -549,8 +549,8 @@ void OpenGLRenderer::setPerspectiveMode() {
 
 void OpenGLRenderer::BeginRender() {
 	if(doClearBuffer) {
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 		glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	}
 	glLoadIdentity();
 	currentTexture = NULL;

+ 43 - 0
Core/Contents/Source/PolyParticleEmitter.cpp

@@ -96,6 +96,49 @@ ScreenParticleEmitter::~ScreenParticleEmitter(){
 	}
 }
 
+Entity *ScreenParticleEmitter::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenParticleEmitter *newEmitter = new ScreenParticleEmitter("default.png", Particle::BILLBOARD_PARTICLE, ParticleEmitter::CONTINUOUS_EMITTER, 2.0, 0, Vector3(0.0, -40.0, 0.0), Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), Vector3(10.0, 10.0, 0.0));
+	applyClone(newEmitter, deepClone, ignoreEditorOnly);
+	return newEmitter;
+}
+
+void ScreenParticleEmitter::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	ScreenParticleEmitter *_clone = (ScreenParticleEmitter*) clone;
+
+	_clone->emitterRadius = this->emitterRadius;
+	_clone->dirVector = this->dirVector;
+	_clone->gravVector = this->gravVector;
+	_clone->deviation = this->deviation;
+				
+	_clone->brightnessDeviation = this->brightnessDeviation;
+	_clone->particleSize = this->particleSize;
+	_clone->perlinModSize = this->perlinModSize;
+	_clone->perlinEnabled = this->perlinEnabled;
+	_clone->particleSpeedMod = this->particleSpeedMod;
+				
+	_clone->rotationSpeed = this->rotationSpeed;
+	_clone->lifespan = this->lifespan;
+	_clone->particleSpeedMod = this->particleSpeedMod;
+	_clone->setParticleCount(this->getNumParticles());						
+
+	_clone->rotationFollowsPath = this->rotationFollowsPath;
+	_clone->useScaleCurves = this->useScaleCurves;
+	_clone->scaleCurve = this->scaleCurve;
+
+	_clone->useColorCurves = this->useColorCurves;
+				
+	_clone->colorCurveR = this->colorCurveR;
+	_clone->colorCurveG = this->colorCurveG;
+	_clone->colorCurveB = this->colorCurveB;
+	_clone->colorCurveA = this->colorCurveA;																
+	_clone->setParticleBlendingMode(this->getParticleBlendingMode());
+	_clone->setParticleTexture(this->getParticleTexture());
+	_clone->setWidth(_clone->emitterRadius.x);
+	_clone->setHeight(_clone->emitterRadius.y);			
+	
+	ScreenEntity::applyClone(clone, false, ignoreEditorOnly);
+}
+
 void ScreenParticleEmitter::Update() {
 	updateEmitter();
 }

+ 3 - 3
Core/Contents/Source/PolyRenderer.cpp

@@ -385,12 +385,12 @@ void Renderer::setAmbientColor(Number r, Number g, Number b) {
 	ambientColor.setColor(r,g,b,1.0f);
 }
 
-void Renderer::setClearColor(Number r, Number g, Number b) {
-	clearColor.setColor(r,g,b,1.0f);	
+void Renderer::setClearColor(Number r, Number g, Number b, Number a) {
+	clearColor.setColor(r,g,b,a);	
 }
 
 void Renderer::setClearColor(Color color) {
-	setClearColor(color.r, color.g, color.b);
+	setClearColor(color.r, color.g, color.b, color.a);
 }
 
 void Renderer::setRenderMode(int newRenderMode) {

+ 21 - 0
Core/Contents/Source/PolyScreenEntity.cpp

@@ -67,6 +67,27 @@ ScreenEntity::ScreenEntity() : Entity() {
 	
 }
 
+Entity *ScreenEntity::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenEntity *newEntity = new ScreenEntity();
+	applyClone(newEntity, deepClone, ignoreEditorOnly);
+	return newEntity;
+}
+
+void ScreenEntity::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	Entity::applyClone(clone, deepClone, ignoreEditorOnly);
+
+	ScreenEntity *_clone = (ScreenEntity*) clone;
+	_clone->width = width;
+	_clone->height = height;
+	_clone->setHitbox(hit.x, hit.y, hit.w, hit.h);
+	_clone->positionMode = positionMode;
+	_clone->focusable = focusable;
+	_clone->blockMouseInput = blockMouseInput;
+	_clone->snapToPixels = snapToPixels;
+	_clone->processInputEvents = processInputEvents;
+	
+}
+
 void ScreenEntity::addEntity(Entity *newChild) {
 	((ScreenEntity*)newChild)->setDefaultScreenOptions(snapToPixels);
 	Entity::addEntity(newChild);

+ 30 - 1
Core/Contents/Source/PolyScreenEntityInstance.cpp

@@ -29,10 +29,39 @@ ScreenEntityInstance::ScreenEntityInstance(const String& fileName) : ScreenEntit
 	rootEntity = NULL;
 	setPositionMode(ScreenEntity::POSITION_CENTER);
 	loadFromFile(fileName);
+	cloneUsingReload = false;
+}
+
+ScreenEntityInstance::ScreenEntityInstance() {
+	rootEntity = NULL;
+	cloneUsingReload = true;
 }
 
 ScreenEntityInstance::~ScreenEntityInstance() {
+}
+
+Entity *ScreenEntityInstance::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenEntityInstance *newEntity;
+	if(cloneUsingReload) {
+		newEntity = new ScreenEntityInstance(fileName);
+	} else {
+		newEntity = new ScreenEntityInstance();
+	}
+	applyClone(newEntity, deepClone, ignoreEditorOnly);
+	return newEntity;
+}
 
+void ScreenEntityInstance::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	if(cloneUsingReload) {
+		ScreenEntity::applyClone(clone, false, ignoreEditorOnly);
+	} else {
+		ScreenEntity::applyClone(clone, deepClone, ignoreEditorOnly);
+		ScreenEntityInstance *_clone = (ScreenEntityInstance*) clone;
+		_clone->fileName = fileName;
+		if(_clone->getNumChildren() > 0) {
+			_clone->rootEntity = (ScreenEntity*)_clone->getChildAtIndex(0);
+		}
+	}
 }
 
 void ScreenEntityInstance::applyScreenShape(ObjectEntry *entry, ScreenShape *shape) {
@@ -302,4 +331,4 @@ bool ScreenEntityInstance::loadFromFile(const String& fileName) {
 		addChild(rootEntity);		
 	}
 	return true;
-}
+}

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

@@ -71,6 +71,16 @@ ScreenImage::~ScreenImage() {
 
 }
 
+Entity *ScreenImage::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenImage *newImage = new ScreenImage(getTexture()->getResourcePath());
+	applyClone(newImage, deepClone, ignoreEditorOnly);
+	return newImage;
+}
+
+void ScreenImage::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	ScreenShape::applyClone(clone, deepClone, ignoreEditorOnly);
+}
+
 void ScreenImage::setImageCoordinates(Number x, Number y, Number width, Number height) {
 	Vertex *vertex;
 	Number pixelSizeX = 1/imageWidth;

+ 12 - 0
Core/Contents/Source/PolyScreenLabel.cpp

@@ -53,6 +53,18 @@ Label *ScreenLabel::getLabel() const {
 	return label;
 }
 
+Entity *ScreenLabel::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenLabel *newLabel = new ScreenLabel(getText(), label->getSize(), label->getFont()->getFontName(), label->getAntialiasMode());
+	applyClone(newLabel, deepClone, ignoreEditorOnly);
+	return newLabel;
+}
+
+void ScreenLabel::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	ScreenShape::applyClone(clone, deepClone, ignoreEditorOnly);
+	ScreenLabel *_clone = (ScreenLabel*) clone;
+	_clone->positionAtBaseline = positionAtBaseline;
+}
+
 void ScreenLabel::addDropShadow(Color color, Number size, Number offsetX, Number offsetY) {
 	delete dropShadowImage;
 	Image *labelImage = new Image(label);

+ 13 - 0
Core/Contents/Source/PolyScreenShape.cpp

@@ -71,6 +71,19 @@ void ScreenShape::operator=(const ScreenShape& copy) {
 
 }
 
+Entity *ScreenShape::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenShape *newEntity = new ScreenShape(ScreenShape::SHAPE_RECT, 1,1);
+	applyClone(newEntity, deepClone, ignoreEditorOnly);
+	return newEntity;
+
+}
+
+void ScreenShape::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	ScreenEntity::applyClone(clone, deepClone, ignoreEditorOnly);
+	ScreenShape *_clone = (ScreenShape*) clone;
+	*_clone = *this;
+}
+
 void ScreenShape::buildShapeMesh() {
 
 	mesh->clearMesh();

+ 9 - 0
Core/Contents/Source/PolyScreenSound.cpp

@@ -50,6 +50,15 @@ void ScreenSoundListener::Update() {
 
 }
 
+Entity *ScreenSound::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenSound *newSound = new ScreenSound(sound->getFileName(), sound->getReferenceDistance(), sound->getMaxDistance());
+	applyClone(newSound, deepClone, ignoreEditorOnly);
+	return newSound;
+}
+
+void ScreenSound::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	ScreenEntity::applyClone(clone, deepClone, ignoreEditorOnly);
+}
 
 ScreenSound::ScreenSound(const String& fileName, Number referenceDistance, Number maxDistance) : ScreenEntity() {
 	sound = new Sound(fileName);

+ 17 - 0
Core/Contents/Source/PolyScreenSprite.cpp

@@ -39,6 +39,23 @@ ScreenSprite::ScreenSprite(const String& fileName) : ScreenShape(ScreenShape::SH
 	loadFromFile(fileName);
 }
 
+Entity *ScreenSprite::Clone(bool deepClone, bool ignoreEditorOnly) {
+	ScreenSprite *newSprite = new ScreenSprite(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);
+	}
+	applyClone(newSprite, deepClone, ignoreEditorOnly);
+	return newSprite;
+}
+
+void ScreenSprite::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) {
+	ScreenShape::applyClone(clone, deepClone, ignoreEditorOnly);
+	
+}
+
 bool ScreenSprite::loadFromFile(const String& fileName) {
 	Object loadObject;
 	

+ 38 - 1
Core/Contents/Source/PolyWinCore.cpp

@@ -627,6 +627,41 @@ void Win32Core::handleMouseUp(int mouseCode,LPARAM lParam, WPARAM wParam) {
 	unlockMutex(eventMutex);
 }
 
+bool Win32Core::checkSpecialKeyEvents(PolyKEY key) {
+	
+	if(key == KEY_a && (input->getKeyState(KEY_LCTRL) || input->getKeyState(KEY_RCTRL))) {
+		dispatchEvent(new Event(), Core::EVENT_SELECT_ALL);
+		return true;
+	}
+	
+	if(key == KEY_c && (input->getKeyState(KEY_LCTRL) || input->getKeyState(KEY_RCTRL))) {
+		dispatchEvent(new Event(), Core::EVENT_COPY);
+		return true;
+	}
+	
+	if(key == KEY_x && (input->getKeyState(KEY_LCTRL) || input->getKeyState(KEY_RCTRL))) {
+		dispatchEvent(new Event(), Core::EVENT_CUT);
+		return true;
+	}
+	
+	
+	if(key == KEY_y && (input->getKeyState(KEY_LCTRL) || input->getKeyState(KEY_RCTRL))) {
+		dispatchEvent(new Event(), Core::EVENT_REDO);
+		return true;
+	}
+		
+	if(key == KEY_z  && (input->getKeyState(KEY_LCTRL) || input->getKeyState(KEY_RCTRL))) {
+		dispatchEvent(new Event(), Core::EVENT_UNDO);
+		return true;
+	}
+	
+	if(key == KEY_v && (input->getKeyState(KEY_LCTRL) || input->getKeyState(KEY_RCTRL))) {
+		dispatchEvent(new Event(), Core::EVENT_PASTE);
+		return true;
+	}
+	return false;
+}
+
 void Win32Core::checkEvents() {
 	lockMutex(eventMutex);
 	Win32Event event;
@@ -657,7 +692,9 @@ void Win32Core::checkEvents() {
 							input->setMouseButtonState(event.mouseButton, false, getTicks());
 					break;
 					case InputEvent::EVENT_KEYDOWN:
-						input->setKeyState(event.keyCode, (char)event.unicodeChar, true, getTicks());
+						if(!checkSpecialKeyEvents((event.keyCode))) {
+							input->setKeyState(event.keyCode, (char)event.unicodeChar, true, getTicks());
+						}
 					break;
 					case InputEvent::EVENT_KEYUP:
 						input->setKeyState(event.keyCode, (char)event.unicodeChar, false, getTicks());

+ 1 - 1
IDE/Build/Linux/Makefile

@@ -2,7 +2,7 @@ CC=g++
 CFLAGS=-I../../Contents/Include -I../../../Release/Linux/Framework/Core/Dependencies/include -I../../../Release/Linux/Framework/Core/Dependencies/include/AL -I../../../Release/Linux/Framework/Core/include -I../../../Release/Linux/Framework/Modules/include -I../../../Release/Linux/Framework/Modules/Dependencies/include -I../../../Release/Linux/Framework/Modules/Dependencies/include/bullet -DUSE_POLYCODEUI_FILE_DIALOGS -DUSE_POLYCODEUI_MENUBAR
 LDFLAGS=-lrt -ldl -lpthread ../../../Release/Linux/Framework/Core/lib/libPolycore.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libfreetype.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisfile.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbis.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibogg.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libopenal.so ../../../Release/Linux/Framework/Core/Dependencies/lib/libphysfs.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libpng15.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../../Release/Linux/Framework/Modules/lib/libPolycode2DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBox2D.a ../../../Release/Linux/Framework/Modules/lib/libPolycode3DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletDynamics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletCollision.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libLinearMath.a ../../../Release/Linux/Framework/Modules/lib/libPolycodeUI.a
 LDFLAGS_DEBUG=-lrt -ldl -lpthread ../../../Release/Linux/Framework/Core/lib/libPolycore_d.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libfreetype_d.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisfiled.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisd.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libliboggd.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libopenal.so ../../../Release/Linux/Framework/Core/Dependencies/lib/libphysfsd.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libpng15d.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../../Release/Linux/Framework/Modules/lib/libPolycode2DPhysics_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBox2D_d.a ../../../Release/Linux/Framework/Modules/lib/libPolycode3DPhysics_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletDynamics_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletCollision_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libLinearMath_d.a ../../../Release/Linux/Framework/Modules/lib/libPolycodeUI_d.a
-SRCS=../../Contents/Source/ExampleBrowserWindow.cpp ../../Contents/Source/PolycodeEditorManager.cpp  ../../Contents/Source/PolycodeProject.cpp        ../../Contents/Source/PolycodeScreenEditor.cpp ../../Contents/Source/ExportProjectWindow.cpp  ../../Contents/Source/PolycodeFontEditor.cpp     ../../Contents/Source/PolycodeProjectBrowser.cpp ../../Contents/Source/PolycodeSpriteEditor.cpp ../../Contents/Source/NewFileWindow.cpp        ../../Contents/Source/PolycodeFrame.cpp          ../../Contents/Source/PolycodeProjectEditor.cpp  ../../Contents/Source/PolycodeTextEditor.cpp ../../Contents/Source/NewProjectWindow.cpp     ../../Contents/Source/PolycodeIDEApp.cpp         ../../Contents/Source/PolycodeProjectManager.cpp ../../Contents/Source/PolycodeToolLauncher.cpp ../../Contents/Source/PolycodeConsole.cpp      ../../Contents/Source/PolycodeImageEditor.cpp    ../../Contents/Source/PolycodeProps.cpp          ../../Contents/Source/TextureBrowser.cpp ../../Contents/Source/PolycodeEditor.cpp       ../../Contents/Source/PolycodeMaterialEditor.cpp ../../Contents/Source/PolycodeRemoteDebugger.cpp ../../Contents/Source/ToolWindows.cpp
+SRCS=../../Contents/Source/ExampleBrowserWindow.cpp ../../Contents/Source/PolycodeEditorManager.cpp  ../../Contents/Source/PolycodeProject.cpp        ../../Contents/Source/PolycodeScreenEditor.cpp ../../Contents/Source/ExportProjectWindow.cpp  ../../Contents/Source/PolycodeFontEditor.cpp     ../../Contents/Source/PolycodeProjectBrowser.cpp ../../Contents/Source/PolycodeSpriteEditor.cpp ../../Contents/Source/NewFileWindow.cpp        ../../Contents/Source/PolycodeFrame.cpp          ../../Contents/Source/PolycodeProjectEditor.cpp  ../../Contents/Source/PolycodeTextEditor.cpp ../../Contents/Source/NewProjectWindow.cpp     ../../Contents/Source/PolycodeIDEApp.cpp         ../../Contents/Source/PolycodeProjectManager.cpp ../../Contents/Source/PolycodeToolLauncher.cpp ../../Contents/Source/PolycodeConsole.cpp      ../../Contents/Source/PolycodeImageEditor.cpp    ../../Contents/Source/PolycodeProps.cpp          ../../Contents/Source/TextureBrowser.cpp ../../Contents/Source/PolycodeEditor.cpp       ../../Contents/Source/PolycodeMaterialEditor.cpp ../../Contents/Source/PolycodeRemoteDebugger.cpp ../../Contents/Source/ToolWindows.cpp ../../Contents/Source/PolycodeClipboard.cpp
 
 default:
 	$(CC) $(CFLAGS) -O2 main.cpp $(SRCS) -o ./Build/Polycode $(LDFLAGS)

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

@@ -30,6 +30,7 @@
 		6D80EB1612AB7C6D0037A708 /* NewProjectWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D80EB1512AB7C6D0037A708 /* NewProjectWindow.cpp */; };
 		6D8A55B914B3EABB005F6411 /* main_icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 6D8A55B814B3EABB005F6411 /* main_icon.icns */; };
 		6D8A55BC14B3EACB005F6411 /* PolycodeView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D8A55BB14B3EACB005F6411 /* PolycodeView.mm */; };
+		6D8A845D16F593D000F3BA08 /* PolycodeClipboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D8A845C16F593D000F3BA08 /* PolycodeClipboard.cpp */; };
 		6D91B3B512AF2B1D00261ED4 /* PolycodeTextEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D91B3B412AF2B1D00261ED4 /* PolycodeTextEditor.cpp */; };
 		6DC67A541656F693004FD1EF /* TextureBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DC67A531656F693004FD1EF /* TextureBrowser.cpp */; };
 		6DC825791648571E006AFC03 /* ExportProjectWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DC825781648571E006AFC03 /* ExportProjectWindow.cpp */; };
@@ -116,6 +117,8 @@
 		6D8A55B814B3EABB005F6411 /* main_icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = main_icon.icns; path = ../../../Assets/Icons/main_icon.icns; sourceTree = "<group>"; };
 		6D8A55BA14B3EACB005F6411 /* PolycodeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PolycodeView.h; path = ../../../Release/Darwin/Framework/Core/PolycodeView/PolycodeView.h; sourceTree = "<group>"; };
 		6D8A55BB14B3EACB005F6411 /* PolycodeView.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = PolycodeView.mm; path = ../../../Release/Darwin/Framework/Core/PolycodeView/PolycodeView.mm; sourceTree = "<group>"; };
+		6D8A845A16F593C800F3BA08 /* PolycodeClipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeClipboard.h; sourceTree = "<group>"; };
+		6D8A845C16F593D000F3BA08 /* PolycodeClipboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeClipboard.cpp; sourceTree = "<group>"; };
 		6D91B3B312AF2B1600261ED4 /* PolycodeTextEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeTextEditor.h; sourceTree = "<group>"; };
 		6D91B3B412AF2B1D00261ED4 /* PolycodeTextEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeTextEditor.cpp; sourceTree = "<group>"; };
 		6DC67A531656F693004FD1EF /* TextureBrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureBrowser.cpp; sourceTree = "<group>"; };
@@ -271,6 +274,7 @@
 		6D80E91212AB53FB0037A708 /* Include */ = {
 			isa = PBXGroup;
 			children = (
+				6D8A845A16F593C800F3BA08 /* PolycodeClipboard.h */,
 				6DC67A561656F699004FD1EF /* TextureBrowser.h */,
 				6DC8257B16485726006AFC03 /* ExportProjectWindow.h */,
 				6D80B0D0163B14D100EF3C04 /* PolycodeMaterialEditor.h */,
@@ -304,6 +308,7 @@
 		6D80E91812AB53FB0037A708 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				6D8A845C16F593D000F3BA08 /* PolycodeClipboard.cpp */,
 				6DC67A531656F693004FD1EF /* TextureBrowser.cpp */,
 				6D79732D167F0D4600646407 /* PolycodeSpriteEditor.cpp */,
 				6DC825781648571E006AFC03 /* ExportProjectWindow.cpp */,
@@ -444,6 +449,7 @@
 				6DC67A541656F693004FD1EF /* TextureBrowser.cpp in Sources */,
 				6D79732E167F0D4600646407 /* PolycodeSpriteEditor.cpp in Sources */,
 				6D797333167F0EB100646407 /* PolycodeProps.cpp in Sources */,
+				6D8A845D16F593D000F3BA08 /* PolycodeClipboard.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 2 - 0
IDE/Build/Windows/Polycode.vcxproj

@@ -15,6 +15,7 @@
     <ClCompile Include="..\..\Contents\Source\ExportProjectWindow.cpp" />
     <ClCompile Include="..\..\Contents\Source\NewFileWindow.cpp" />
     <ClCompile Include="..\..\Contents\Source\NewProjectWindow.cpp" />
+    <ClCompile Include="..\..\Contents\Source\PolycodeClipboard.cpp" />
     <ClCompile Include="..\..\Contents\Source\PolycodeConsole.cpp" />
     <ClCompile Include="..\..\Contents\Source\PolycodeEditor.cpp" />
     <ClCompile Include="..\..\Contents\Source\PolycodeEditorManager.cpp" />
@@ -42,6 +43,7 @@
     <ClInclude Include="..\..\Contents\Include\ExportProjectWindow.h" />
     <ClInclude Include="..\..\Contents\Include\NewFileWindow.h" />
     <ClInclude Include="..\..\Contents\Include\NewProjectWindow.h" />
+    <ClInclude Include="..\..\Contents\Include\PolycodeClipboard.h" />
     <ClInclude Include="..\..\Contents\Include\PolycodeConsole.h" />
     <ClInclude Include="..\..\Contents\Include\PolycodeEditor.h" />
     <ClInclude Include="..\..\Contents\Include\PolycodeEditorManager.h" />

+ 6 - 0
IDE/Build/Windows/Polycode.vcxproj.filters

@@ -84,6 +84,9 @@
     <ClCompile Include="main.cpp">
       <Filter>Source</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\Contents\Source\PolycodeClipboard.cpp">
+      <Filter>Source</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\Contents\Include\ExampleBrowserWindow.h">
@@ -161,5 +164,8 @@
     <ClInclude Include="..\..\Contents\Include\ToolWindows.h">
       <Filter>Include</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\Contents\Include\PolycodeClipboard.h">
+      <Filter>Include</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>

+ 50 - 0
IDE/Contents/Include/PolycodeClipboard.h

@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once 
+
+#include <Polycode.h>
+
+using namespace Polycode;
+
+class ClipboardProvider {
+	public:
+		ClipboardProvider(){}
+
+		virtual void destroyClipboardData(void *data, String type) {}
+};
+
+class PolycodeClipboard {
+	public:
+		PolycodeClipboard();
+
+		void setData(void *data, String type, ClipboardProvider *provider);
+		void *getData();
+		String getType();
+
+	protected:
+
+		ClipboardProvider *currentProvider;
+		String type;
+		void *data;
+};
+

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

@@ -25,11 +25,12 @@
 #include "Polycode.h"
 #include "OSBasics.h"
 #include "PolycodeProject.h"
+#include "PolycodeClipboard.h"
 
 using namespace Polycode;
 
 
-class PolycodeEditor : public ScreenEntity { 
+class PolycodeEditor : public ScreenEntity, public ClipboardProvider { 
 public:
 	PolycodeEditor(bool _isReadOnly);
 	virtual ~PolycodeEditor();
@@ -37,10 +38,15 @@ public:
 	virtual bool openFile(OSFileEntry filePath){ this->filePath = filePath.fullPath; return true;}
 	virtual void Resize(int x, int y);
 	
+	virtual void handleEvent(Event *event);
+
 	virtual void Activate() {};
 	
 	virtual void saveFile(){};
 	
+	virtual String Copy(void **data) { return ""; }
+	virtual void Paste(void *data, String clipboardType) {}
+
 	virtual void handleDroppedFile(OSFileEntry file, Number x, Number y) {};
 	
 	void setFilePath(String newPath);
@@ -53,6 +59,9 @@ public:
 	PolycodeProject *parentProject;
 		
 protected:
+
+	
+
 	String filePath;
 	bool _isReadOnly;
 	
@@ -75,4 +84,4 @@ public:
 protected:
 	std::vector<std::string> extensions;
 	
-};
+};

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

@@ -45,6 +45,7 @@
 #include "PolycodeToolLauncher.h"
 
 #include "PolycodeRemoteDebugger.h"
+#include "PolycodeClipboard.h"
 
 using namespace Polycode;
 

+ 30 - 2
IDE/Contents/Include/PolycodeScreenEditor.h

@@ -27,6 +27,17 @@
 #include <PolycodeUI.h>
 #include "PolycodeProps.h"
 
+#if defined(__APPLE__) && defined(__MACH__)
+	#define COPYMOD_1 KEY_RALT
+	#define COPYMOD_2 KEY_LALT
+#elif defined _WINDOWS
+	#define COPYMOD_1 KEY_RCTRL
+	#define COPYMOD_2 KEY_LCTRL
+#else
+	#define COPYMOD_1 KEY_RCTRL
+	#define COPYMOD_2 KEY_LCTRL
+#endif
+
 using namespace Polycode;
 
 #ifdef _WINDOWS
@@ -126,7 +137,11 @@ class PolycodeScreenEditorMain : public UIElement {
 		void handleMouseUp(Vector2 position);
 		
 		void setGrid(int gridSize);
-				
+		
+		String Copy(void **data);
+		void Paste(void *data, String clipboardType);
+		void destroyClipboardData(void *data, String type);
+		
 		static const int MODE_SELECT = 0;
 		static const int MODE_SHAPE = 1;
 		static const int MODE_ZOOM = 2;
@@ -165,9 +180,9 @@ class PolycodeScreenEditorMain : public UIElement {
 		
 		ScreenEntity *objectBaseEntity;		
 		ScreenEntity *placingPreviewEntity;												
+		bool multiSelect;
 	protected:
 	
-		bool multiSelect;
 	
 		int gridSize;
 		bool gridSnap;
@@ -186,6 +201,8 @@ class PolycodeScreenEditorMain : public UIElement {
 
 		bool firstResize;
 		
+		bool firstMove;
+
 		int placementCount;
 	
 		
@@ -298,6 +315,13 @@ class PolycodeScreenEditorMain : public UIElement {
 		int mode;	
 };
 
+class ScreenEntityClipboardData {
+	public:
+		ScreenEntityClipboardData(){}
+		
+		std::vector<ScreenEntity*> entities;
+};
+
 class PolycodeScreenEditor : public PolycodeEditor {
 	public:
 		PolycodeScreenEditor();
@@ -306,6 +330,10 @@ class PolycodeScreenEditor : public PolycodeEditor {
 		bool openFile(OSFileEntry filePath);
 		void Resize(int x, int y);
 		
+		String Copy(void **data);
+		void Paste(void *data, String clipboardType);
+		void destroyClipboardData(void *data, String type);
+
 		void Activate();		
 		
 		void saveCurveToObject(ObjectEntry *entry, BezierCurve *curve);

+ 51 - 0
IDE/Contents/Source/PolycodeClipboard.cpp

@@ -0,0 +1,51 @@
+
+/*
+ Copyright (C) 2012 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#include "PolycodeClipboard.h"
+
+PolycodeClipboard::PolycodeClipboard() {
+	data = NULL;
+}
+
+void PolycodeClipboard::setData(void *data, String type, ClipboardProvider *provider) {
+	if(!data)
+		return;
+
+	if(this->data) {
+		currentProvider->destroyClipboardData(this->data, this->type);
+		this->data = NULL;
+		currentProvider = NULL;
+	}
+	
+	this->data = data;
+	this->type = type;
+	currentProvider = provider;
+}
+
+void *PolycodeClipboard::getData() {
+	return data;
+}
+
+String PolycodeClipboard::getType() {
+	return type;
+}

+ 31 - 1
IDE/Contents/Source/PolycodeEditor.cpp

@@ -22,6 +22,8 @@
 
 #include "PolycodeEditor.h"
 
+extern PolycodeClipboard *globalClipboard;
+
 PolycodeEditorFactory::PolycodeEditorFactory() {
 	
 }
@@ -42,10 +44,38 @@ void PolycodeEditor::setFilePath(String newPath) {
 	filePath = newPath;
 }
 
-PolycodeEditor::PolycodeEditor(bool _isReadOnly) : ScreenEntity() {
+PolycodeEditor::PolycodeEditor(bool _isReadOnly) : ScreenEntity(), ClipboardProvider() {
 	this->_isReadOnly = _isReadOnly;
 	enableScissor = true;	
 	processInputEvents = true;
+
+	Core *core = CoreServices::getInstance()->getCore();
+	
+	core->addEventListener(this, Core::EVENT_COPY);
+	core->addEventListener(this, Core::EVENT_PASTE);
+}
+
+void PolycodeEditor::handleEvent(Event *event) {
+	if(event->getDispatcher() == CoreServices::getInstance()->getCore()) {
+		switch(event->getEventCode()) {
+			case Core::EVENT_COPY:
+			{
+				void *data = NULL;
+				String dataType = Copy(&data);
+				if(data) {
+					globalClipboard->setData(data, dataType, this);
+				}
+			}
+			break;
+			case Core::EVENT_PASTE:
+			{
+				if(globalClipboard->getData()) {
+					Paste(globalClipboard->getData(), globalClipboard->getType());
+				}
+			}
+			break;
+		}
+	}
 }
 
 void PolycodeEditor::Resize(int x, int y) {

+ 14 - 9
IDE/Contents/Source/PolycodeIDEApp.cpp

@@ -27,11 +27,14 @@ using namespace Polycode;
 
 UIGlobalMenu *globalMenu;
 SyntaxHighlightTheme *globalSyntaxTheme;
+PolycodeClipboard *globalClipboard;
+
 
 PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	core = new POLYCODE_CORE(view, 900,700,false,true, 0, 0,30, -1);	
 	core->addEventListener(this, Core::EVENT_CORE_RESIZE);
 	
+	globalClipboard = new PolycodeClipboard();
 	
 	CoreServices::getInstance()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_NEAREST);
 				
@@ -120,15 +123,15 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	menuBar = new UIMenuBar(100, globalMenu);
 
 	UIMenuBarEntry *fileEntry = menuBar->addMenuBarEntry("File");
-	fileEntry->addItem("New File", "new_file");
-	fileEntry->addItem("New Project", "new_project");
-	fileEntry->addItem("New Folder", "new_folder");
-	fileEntry->addItem("Open Project", "open_project");
-	fileEntry->addItem("Close Project", "close_project");
+	fileEntry->addItem("New File", "new_file", KEY_n);
+	fileEntry->addItem("New Project", "new_project", KEY_LSHIFT, KEY_n);
+	fileEntry->addItem("New Folder", "new_folder", KEY_LSHIFT, KEY_f);
+	fileEntry->addItem("Open Project", "open_project", KEY_LSHIFT, KEY_o);
+	fileEntry->addItem("Close Project", "close_project", KEY_LSHIFT, KEY_w);
 	fileEntry->addItem("Remove File", "remove_file");
 	fileEntry->addItem("Refresh Project", "refresh_project");
-	fileEntry->addItem("Save File", "save_file");
-	fileEntry->addItem("Browse Examples", "browse_examples");
+	fileEntry->addItem("Save File", "save_file", KEY_s);
+	fileEntry->addItem("Browse Examples", "browse_examples", KEY_LSHIFT, KEY_e);
 	fileEntry->addItem("Quit", "quit");
 
 	UIMenuBarEntry *editEntry = menuBar->addMenuBarEntry("Edit");
@@ -138,7 +141,7 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	editEntry->addItem("Copy", "copy");
 
 	UIMenuBarEntry *projectEntry = menuBar->addMenuBarEntry("Project");
-	projectEntry->addItem("Run Project", "run_project");
+	projectEntry->addItem("Run Project", "run_project", KEY_r);
 	projectEntry->addItem("Publish Project", "export_project");
 
 	UIMenuBarEntry *helpEntry = menuBar->addMenuBarEntry("Help");
@@ -446,9 +449,11 @@ void PolycodeIDEApp::handleEvent(Event *event) {
 	if(event->getDispatcher() == core) {
 		switch(event->getEventCode()) {
 			case Core::EVENT_CORE_RESIZE:
-				frame->Resize(core->getXRes(), core->getYRes());
 				if(menuBar) {
+					frame->Resize(core->getXRes(), core->getYRes()-25);
 					menuBar->Resize(core->getXRes(), 25);
+				} else {
+					frame->Resize(core->getXRes(), core->getYRes());
 				}
 			break;
 		}

+ 17 - 1
IDE/Contents/Source/PolycodeProjectManager.cpp

@@ -136,7 +136,7 @@ void PolycodeProjectManager::createNewProject(String templateFolder, String proj
 	openProject(projectLocation+"/"+projectName+"/"+projectName+".polyproject");	
 }
 
-void PolycodeProjectManager::exportProject(PolycodeProject *project, String exportPath, bool macOS, bool windows, bool _linux) {
+void PolycodeProjectManager::exportProject(PolycodeProject *project, String exportPath, bool macOS, bool windows, bool linux) {
 
 	String polycodeBasePath = CoreServices::getInstance()->getCore()->getDefaultWorkingDirectory();
 
@@ -162,5 +162,21 @@ void PolycodeProjectManager::exportProject(PolycodeProject *project, String expo
 		CoreServices::getInstance()->getCore()->copyDiskItem(polyappPath, appPath+"/Contents/Resources/main.polyapp");
 		
 	}
+
+	if(windows) {
+		PolycodeConsole::print("Exporting Windows version to "+exportPath+"/Win \n");
+		CoreServices::getInstance()->getCore()->copyDiskItem(publishPath+"/Win", exportPath+"/Win");
+		CoreServices::getInstance()->getCore()->moveDiskItem(exportPath+"/Win/StandalonePlayer.exe", exportPath+"/Win/"+project->getProjectName()+".exe");
+		CoreServices::getInstance()->getCore()->removeDiskItem(exportPath+"/Win/main.polyapp");
+		CoreServices::getInstance()->getCore()->copyDiskItem(polyappPath, exportPath+"/Win/main.polyapp");
+	}
+
+	if(linux) {
+		PolycodeConsole::print("Exporting Linux version to "+exportPath+"/Linux \n");
+		CoreServices::getInstance()->getCore()->copyDiskItem(publishPath+"/Linux", exportPath+"/Linux");
+		CoreServices::getInstance()->getCore()->moveDiskItem(exportPath+"/Linux/StandalonePlayer", exportPath+"/Linux/"+project->getProjectName());
+		CoreServices::getInstance()->getCore()->removeDiskItem(exportPath+"/Linux/main.polyapp");
+		CoreServices::getInstance()->getCore()->copyDiskItem(polyappPath, exportPath+"/Linux/main.polyapp");
+	}
 }
 

+ 81 - 1
IDE/Contents/Source/PolycodeScreenEditor.cpp

@@ -257,6 +257,8 @@ void EntityTreeView::Resize(Number width, Number height) {
 
 PolycodeScreenEditorMain::PolycodeScreenEditorMain() {
 
+	firstMove = false;
+
 	multiSelect = false;
 	currentLayer = NULL;
 	treeView = NULL;
@@ -1662,6 +1664,7 @@ void PolycodeScreenEditorMain::handleEvent(Event *event) {
 	
 	if(event->getDispatcher() == CoreServices::getInstance()->getCore()->getInput()) {
 		if(event->getEventCode() == InputEvent::EVENT_KEYDOWN) {
+			printf("KEY: %d\n", inputEvent->key);
 			switch(inputEvent->key) {
 				case Polycode::KEY_ESCAPE:
 					if(selectedEntity) {
@@ -1893,11 +1896,13 @@ void PolycodeScreenEditorMain::handleEvent(Event *event) {
 	if(event->getDispatcher() == baseEntity) {
 		switch (event->getEventCode()) {
 			case InputEvent::EVENT_MOUSEDOWN:
+				firstMove = true;
 				handleMouseDown(inputEvent->mousePosition);
 				focusChild(baseEntity);
 			break;		
 			case InputEvent::EVENT_MOUSEUP:
 			case InputEvent::EVENT_MOUSEUP_OUTSIDE:			
+				firstMove = false;
 				handleMouseUp(inputEvent->mousePosition);
 			break;
 			case InputEvent::EVENT_MOUSEOUT:
@@ -1905,6 +1910,18 @@ void PolycodeScreenEditorMain::handleEvent(Event *event) {
 			break;
 			case InputEvent::EVENT_MOUSEMOVE:
 			{
+				if(firstMove) {
+					Core *core = CoreServices::getInstance()->getCore();
+					if(core->getInput()->getKeyState(COPYMOD_1) || core->getInput()->getKeyState(COPYMOD_2)) {
+						void *data;
+						String type = Copy(&data);
+						if(data) {
+							Paste(data, type);
+							destroyClipboardData(data, type);
+						}
+					}
+					firstMove = false;
+				}
 				updateCursor();
 				handleMouseMove(inputEvent->mousePosition);
 			}
@@ -2110,6 +2127,68 @@ PolycodeScreenEditor::PolycodeScreenEditor() : PolycodeEditor(true){
 	treeView->Refresh();
 }
 
+String PolycodeScreenEditor::Copy(void **data) {
+	return editorMain->Copy(data);
+}
+
+void PolycodeScreenEditor::Paste(void *data, String clipboardType) {
+	editorMain->Paste(data, clipboardType);
+}
+
+void PolycodeScreenEditor::destroyClipboardData(void *data, String type) {
+	editorMain->destroyClipboardData(data, type);
+}
+
+String PolycodeScreenEditorMain::Copy(void **data) {
+	if(selectedEntities.size() > 0) {
+		ScreenEntityClipboardData *newData = new ScreenEntityClipboardData();
+		for(int i=0; i < selectedEntities.size(); i++) {
+			ScreenEntity *clone = (ScreenEntity*)selectedEntities[i]->Clone(true, true);
+			newData->entities.push_back(clone);
+		}
+		*data = (void*) newData;
+	}
+	return "ScreenEntity";
+}
+
+void PolycodeScreenEditorMain::Paste(void *data, String clipboardType) {
+	if(!data)
+		return;
+	if(clipboardType == "ScreenEntity") {
+		selectEntity(NULL);
+		multiSelect = true;
+		ScreenEntityClipboardData *newData = (ScreenEntityClipboardData*) data;
+		if(currentLayer) {
+			for(int i=0; i < newData->entities.size(); i++) {
+				ScreenEntity *entity = (ScreenEntity*) newData->entities[i]->Clone(true, true);
+				entity->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+				entity->addEventListener(this, InputEvent::EVENT_MOUSEUP);
+				if(selectedEntity && selectedEntity != currentLayer) {
+					selectedEntity->getParentEntity()->addChild(entity);
+				} else {
+					currentLayer->addChild(entity);
+				}
+				applyEditorProperties(entity);
+				selectEntity(entity);
+			}
+		}
+		multiSelect = false;
+	}
+	if(treeView) {
+		treeView->Refresh();		
+	}											
+}
+
+void PolycodeScreenEditorMain::destroyClipboardData(void *data, String type) {
+	if(type == "ScreenEntity") {
+		ScreenEntityClipboardData *oldData = (ScreenEntityClipboardData*) data;
+		for(int i=0; i < oldData->entities.size(); i++) {
+			delete oldData->entities[i];
+		}
+		delete oldData;
+	}
+}
+
 void PolycodeScreenEditor::Activate() {
 	editorMain->labelSheet->refreshFonts();
 }
@@ -2361,7 +2440,7 @@ void PolycodeScreenEditor::handleEvent(Event *event) {
 		}
 
 	}
-
+	PolycodeEditor::handleEvent(event);
 }
 
 PolycodeScreenEditor::~PolycodeScreenEditor() {
@@ -2375,6 +2454,7 @@ void PolycodeScreenEditorMain::applyEditorProperties(ScreenEntity *entity) {
 	}
 
 	if(dynamic_cast<ScreenEntityInstance*>(entity)) {
+		(((ScreenEntityInstance*)entity))->cloneUsingReload = true;
 		applyEditorOnly(((ScreenEntityInstance*)entity)->getRootEntity());
 		entity->setWidth(50);
 		entity->setHeight(50);		

+ 8 - 2
Modules/Contents/UI/Include/PolyUIMenuBar.h

@@ -35,16 +35,22 @@ namespace Polycode {
 
 	class UIMenuBarEntryItem {
 		public:
-			UIMenuBarEntryItem(String name, String code) { this->name = name; this->code = code; }
+			UIMenuBarEntryItem(String name, String code, PolyKEY shortCut1, PolyKEY shortCut2);
 			String name;	
 			String code;
+
+			bool checkShortCut(PolyKEY shortCut);
+
+			PolyKEY shortCut1;
+			PolyKEY shortCut2;
+
 	};
 
 	class _PolyExport UIMenuBarEntry : public UIElement {
 		public:
 			UIMenuBarEntry(String name);
 			~UIMenuBarEntry();		
-			void addItem(String name, String code);
+			void addItem(String name, String code, PolyKEY shortCut1 = KEY_UNKNOWN, PolyKEY shortCut2 = KEY_UNKNOWN);
 
 			void Select();
 			void Deselect();

+ 2 - 2
Modules/Contents/UI/Include/PolyUITree.h

@@ -70,7 +70,7 @@ namespace Polycode {
 			Number handleRotation;
 		
 		private:
-		
+
 			bool willDrag;
 			bool isDragging;
 		
@@ -99,4 +99,4 @@ namespace Polycode {
 			Number cellHeight;
 			Number cellPadding;
 	};
-}
+}

+ 52 - 2
Modules/Contents/UI/Source/PolyUIMenuBar.cpp

@@ -1,9 +1,40 @@
 
 #include "PolyUIMenuBar.h"
 #include "PolyLabel.h"
+#include <PolyCoreServices.h>
+#include <PolyCore.h>
 
 using namespace Polycode;
 
+UIMenuBarEntryItem::UIMenuBarEntryItem(String name, String code, PolyKEY shortCut1, PolyKEY shortCut2) {
+	this->name = name;
+	this->code = code;
+	this->shortCut1 = shortCut1;
+	this->shortCut2 = shortCut2;
+}
+
+bool UIMenuBarEntryItem::checkShortCut(PolyKEY shortCut) {
+	if(shortCut1 == KEY_UNKNOWN && shortCut2 == KEY_UNKNOWN)
+		return false;
+
+	if(CoreServices::getInstance()->getCore()->getInput()->getKeyState(KEY_RCTRL) || CoreServices::getInstance()->getCore()->getInput()->getKeyState(KEY_LCTRL)) {
+		if(shortCut1 != KEY_UNKNOWN && shortCut2 != KEY_UNKNOWN) {
+			if(shortCut == shortCut1 && CoreServices::getInstance()->getCore()->getInput()->getKeyState(shortCut2)) {
+				return true;
+			}
+			if(shortCut == shortCut2 && CoreServices::getInstance()->getCore()->getInput()->getKeyState(shortCut1)) {
+				return true;
+			}
+		} else {
+			if(shortCut == shortCut1) {
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
 UIMenuBarEntry::UIMenuBarEntry(String name): UIElement() {
 	
 	label = new ScreenLabel(name, 14, "sans");
@@ -25,8 +56,8 @@ void UIMenuBarEntry::Deselect() {
 	bg->color.setColorHex(0xce5a1600);
 }
 
-void UIMenuBarEntry::addItem(String name, String code) {
-	items.push_back(UIMenuBarEntryItem(name,code));
+void UIMenuBarEntry::addItem(String name, String code, PolyKEY shortCut1, PolyKEY shortCut2) {
+	items.push_back(UIMenuBarEntryItem(name,code, shortCut1, shortCut2));
 }
 
 UIMenuBarEntry::~UIMenuBarEntry() {
@@ -48,6 +79,8 @@ UIMenuBar::UIMenuBar(int width, UIGlobalMenu *globalMenu) : UIElement() {
 	dropMenu = NULL;
 
 	holdingMouse = false;
+
+	CoreServices::getInstance()->getCore()->getInput()->addEventListener(this, InputEvent::EVENT_KEYDOWN);
 }
 
 UIMenuBarEntry *UIMenuBar::addMenuBarEntry(String name) {
@@ -87,6 +120,23 @@ String UIMenuBar::getSelectedItem() {
 }
 
 void UIMenuBar::handleEvent(Event *event) {
+
+	if(event->getDispatcher() == CoreServices::getInstance()->getCore()->getInput()) {
+		InputEvent *inputEvent = (InputEvent*) event;
+		if(event->getEventCode() == InputEvent::EVENT_KEYDOWN) {
+			for(int i=0; i < entries.size(); i++) {
+				UIMenuBarEntry *entry = entries[i];
+				for(int j=0; j < entry->items.size(); j++) {
+					if(entry->items[j].checkShortCut(inputEvent->key)) {
+						selectedItem = entry->items[j].code;
+						dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
+						break;
+					}
+				}
+			}
+		}
+	}
+
 	if(event->getDispatcher() == dropMenu) {
 		if(event->getEventCode() == UIEvent::OK_EVENT) {
 			selectedItem = dropMenu->getSelectedItem()->_id;

+ 2 - 2
Modules/Contents/UI/Source/PolyUITree.cpp

@@ -248,14 +248,14 @@ void UITree::clearSelection(UITree *selectedNode) {
 
 void UITree::refreshTree() {
 	if(collapsed) {
-		new Tween(&handleRotation, Tween::EASE_IN_QUAD, handleRotation, 0, 0.2f, false, true);
+		handleRotation = 0;
 		for(int i=0; i < treeChildren.size(); i++) {
 			treeChildren[i]->visible = false;
 			treeChildren[i]->enabled = false;			
 		}
 		treeHeight = 0;
 	} else {
-		new Tween(&handleRotation, Tween::EASE_IN_QUAD, handleRotation, 90, 0.2f, false, true);
+		handleRotation = 90;
 		int offset = cellHeight;
 		for(int i=0; i < treeChildren.size(); i++) {
 			treeChildren[i]->visible = true;

+ 8 - 1
Tools/Contents/polybuild/Source/polybuild.cpp

@@ -5,6 +5,7 @@
 
 #ifdef _WINDOWS
 	#include <windows.h>
+	#include <direct.h>
 #else
 	#include <dirent.h>
 	#include <sys/types.h>
@@ -425,7 +426,13 @@ int main(int argc, char **argv) {
 	
 	zipClose(z, "");	
 
+#ifdef _WINDOWS
+	char *buffer = _getcwd(NULL, 0);
+	String workingDir = String(buffer);
+	free(buffer);
+	OSBasics::removeItem(workingDir+"/runinfo_tmp_zzzz.polyrun");
+#else
 	OSBasics::removeItem("runinfo_tmp_zzzz.polyrun");
-
+#endif
 	return 0;
 }