Parcourir la source

Fixed mouse picking in virtual 2D scenes, added 2D mode to entity editor

Ivan Safrin il y a 12 ans
Parent
commit
b60472479c

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

@@ -117,6 +117,8 @@ namespace Polycode {
 		* @param endDepth Ending depth of the fog.							
 		*/				
 		void setFogProperties(int fogMode, Color color, Number density, Number startDepth, Number endDepth);
+        
+        void setSceneType(int newType);
 	
 		virtual void Update();
 		void setVirtual(bool val);
@@ -184,12 +186,13 @@ namespace Polycode {
 						
 		Entity rootEntity;
 		
-		Vector2 sceneMouseAdjust;
+        Polycode::Rectangle sceneMouseRect;
+        bool remapMouse;
 		
 	protected:
 		
 		void initScene(int sceneType, bool virtualScene);
-		
+
 		bool hasLightmaps;
 		
 		Renderer *renderer;

+ 38 - 18
Core/Contents/Source/PolyScene.cpp

@@ -62,34 +62,40 @@ void Scene::initScene(int sceneType, bool virtualScene) {
 	ambientColor.setColor(0.0,0.0,0.0,1.0);	
 	useClearColor = false;
 	ownsChildren = false;
+    remapMouse = false;
 	renderer = CoreServices::getInstance()->getRenderer();
 	rootEntity.setRenderer(renderer);
 	if (!isSceneVirtual) {
 		CoreServices::getInstance()->getSceneManager()->addScene(this);
 	}
 	
+    setSceneType(sceneType);
+	
+	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEUP);
+	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
+	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_UP);
+	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_DOWN);	
+}
+
+void Scene::setSceneType(int newType) {
+    sceneType = newType;
 	switch(sceneType) {
 		case SCENE_2D:
-			printf("WHAT\n");
 			defaultCamera->setClippingPlanes(-100.0, 100.0);
-			defaultCamera->setOrthoMode(true, CoreServices::getInstance()->getCore()->getXRes(),CoreServices::getInstance()->getCore()->getYRes());	
-		break;
+			defaultCamera->setOrthoMode(true, CoreServices::getInstance()->getCore()->getXRes(),CoreServices::getInstance()->getCore()->getYRes());
+            break;
 		case SCENE_2D_TOPLEFT:
 			defaultCamera->setClippingPlanes(-100.0, 100.0);
 			defaultCamera->setOrthoMode(true, 0,0);
 			defaultCamera->topLeftOrtho = true;
 			rootEntity.setInverseY(true);
-		break;
+            break;
 		case SCENE_3D:
 			defaultCamera->setClippingPlanes(1.0, 1000.0);
-		break;		
+            break;		
 	}
-	
-	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
-	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEUP);
-	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
-	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_UP);
-	core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_DOWN);	
+    
 }
 
 void Scene::setActiveCamera(Camera *camera) {
@@ -268,19 +274,33 @@ void Scene::RenderDepthOnly(Camera *targetCamera) {
 Ray Scene::projectRayFromCameraAndViewportCoordinate(Camera *camera, Vector2 coordinate) {
 
 	Polycode::Rectangle viewport = camera->getViewport();
-	viewport.x = sceneMouseAdjust.x * renderer->getBackingResolutionScaleX();
-	viewport.y = sceneMouseAdjust.y * renderer->getBackingResolutionScaleY();
-        
+    
+    if(remapMouse) {
+        viewport.x = sceneMouseRect.x * renderer->getBackingResolutionScaleX();
+        viewport.y = (core->getYRes() - (sceneMouseRect.y + sceneMouseRect.h)) * renderer->getBackingResolutionScaleY();
+    }
+    
 	Vector3 dir =  renderer->projectRayFrom2DCoordinate(coordinate.x *  renderer->getBackingResolutionScaleX(), coordinate.y  * renderer->getBackingResolutionScaleY(), camera->getConcatenatedMatrix(), camera->getProjectionMatrix(), viewport);
 	Vector3 pos;
-
+    
 	switch(sceneType) {
 		case SCENE_2D:
 		{
 			Number orthoSizeX = camera->getOrthoSizeX();
-			Number orthoSizeY = camera->getOrthoSizeY();			
-			pos = Vector3(((coordinate.x/(Number)core->getXRes())*orthoSizeX) - (orthoSizeX*0.5), (((core->getYRes()-coordinate.y)/(Number)core->getYRes())*orthoSizeY) - (orthoSizeY*0.5), 0.0);
-			pos = camera->getConcatenatedMatrix() * pos;	
+			Number orthoSizeY = camera->getOrthoSizeY();
+            
+            Vector2 remappedMouse = Vector2(coordinate.x, coordinate.y);
+            Vector2 screenSize = Vector2(core->getXRes(), core->getYRes());
+            if(remapMouse) {
+                remappedMouse.x = coordinate.x - sceneMouseRect.x;
+                remappedMouse.y = coordinate.y - sceneMouseRect.y;
+                screenSize = Vector2(sceneMouseRect.w, sceneMouseRect.h);
+            }
+            
+			pos = Vector3(((remappedMouse.x/screenSize.x)*orthoSizeX) - (orthoSizeX*0.5), (((screenSize.y-remappedMouse.y)/screenSize.y)*orthoSizeY) - (orthoSizeY*0.5), 0.0);
+            
+			pos = camera->getConcatenatedMatrix() * pos;
+            
 		}
 		break;
 		case SCENE_2D_TOPLEFT:

+ 5 - 0
IDE/Contents/Include/EditorGrid.h

@@ -33,7 +33,12 @@ class EditorGrid : public Entity {
 		~EditorGrid();
 		
 		void setGrid(int gridSize);
+        void setGridMode(int mode);
 		
+        static const int GRID_MODE_3D = 0;
+        static const int GRID_MODE_2D = 1;
+    
 	private:
+        int gridMode;
 		SceneMesh *grid;
 };

+ 7 - 3
IDE/Contents/Include/PolycodeEntityEditor.h

@@ -48,14 +48,18 @@ class EntityEditorMainView : public UIElement {
 			void handleEvent(Event *event);
 			void Resize(Number width, Number height);
 			void Update();
-    
             void addEntityFromMenu(String command);
 			
+            void setEditorMode(int newMode);
             Entity *getSelectedEntity();
     
+            static const int EDITOR_MODE_3D = 0;
+            static const int EDITOR_MODE_2D = 1;
+    
 		protected:
 			
-			Entity *sideBar;
+            int editorMode;
+			Entity *topBar;
 			UIRect *headerBg;
 				
 			std::vector<Entity*> selectedEntities;
@@ -72,12 +76,12 @@ class EntityEditorMainView : public UIElement {
 			EditorGrid *grid;
     
             UIImageButton *addEntityButton;
+            UIComboBox *modeSwitchDropdown;
             UIMenu *addEntityMenu;
     
             std::vector<ScenePrimitive*> icons;
     
             Vector3 cursorPosition;
-    
             String assetSelectType;
     
 };

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

@@ -36,11 +36,18 @@ class TrackballCamera : public EventHandler {
 		void setOrbitingCenter(const Vector3 &newCenter);
 		void setCameraDistance(Number cameraDistance);
 		Camera *getTargetCamera();
-		
+    
+        void setCameraPosition(Vector3 cameraPosition);
+    
+        bool disableRotation(bool val);
+    
 		static const int MOUSE_MODE_IDLE = 0;
 		static const int MOUSE_MODE_ORBITING = 1;
 		static const int MOUSE_MODE_PANNING = 2;
-		static const int MOUSE_MODE_ZOOMING = 3;				
+		static const int MOUSE_MODE_ZOOMING = 3;
+    
+        Number getCameraDistance();
+        Vector3 getOribitingCenter();
 		
 		Number trackballPanSpeed;
 		Number trackballZoomSpeed;	
@@ -56,6 +63,8 @@ class TrackballCamera : public EventHandler {
 		
 		Camera *targetCamera;
 		Entity *trackballShape;
+    
+        bool rotationDisabled;
 		
 		Vector2 trackBallMouseStart;
 		Vector2 trackBallMouseEnd;			

+ 32 - 5
IDE/Contents/Include/TransformGizmo.h

@@ -33,10 +33,10 @@ class TransformGizmo : public Entity {
 		TransformGizmo(Scene *targetScene, Camera *targetCamera);
 		~TransformGizmo();
 		
-		void handleEvent(Event *event);		
-		
+		void handleEvent(Event *event);
 		void setTransformMode(int newMode);
-		
+        void setGizmoMode(int newMode);
+    
 		void Update();
 		
 		void setTransformSelection(std::vector<Entity*> selectedEntities);
@@ -49,8 +49,13 @@ class TransformGizmo : public Entity {
 		static const int TRANSFORM_MOVE = 0;		
 		static const int TRANSFORM_SCALE = 1;
 		static const int TRANSFORM_ROTATE = 2;
-								
+    
+        static const int GIZMO_MODE_3D = 0;
+		static const int GIZMO_MODE_2D = 1;
+    
 	private:
+        int transformMode;
+        int gizmoMode;
 	
 		std::vector<Entity*> selectedEntities;
 	
@@ -78,7 +83,29 @@ class TransformGizmo : public Entity {
 		
 		ScenePrimitive *pitchGrip;
 		ScenePrimitive *rollGrip;
-		ScenePrimitive *yawGrip;				
+		ScenePrimitive *yawGrip;
+
+        ScenePrimitive *viewportRotateGrip;
+        Entity *viewportRotateGripBase;
+    
+        SceneMesh *xLine;
+        SceneMesh *yLine;
+        SceneMesh *zLine;
+    
+        ScenePrimitive *xArrow;
+        ScenePrimitive *yArrow;
+        ScenePrimitive *zArrow;
+    
+        ScenePrimitive *xBox;
+        ScenePrimitive *yBox;
+        ScenePrimitive *zBox;
+    
+        ScenePrimitive *outerCircle;
+        ScenePrimitive *bgCircle;
+    
+        ScenePrimitive *pitchCircle;
+        ScenePrimitive *yawCircle;
+        ScenePrimitive *rollCircle;
 };
 
 class TransformGizmoMenu : public UIElement {

+ 18 - 7
IDE/Contents/Source/EditorGrid.cpp

@@ -24,6 +24,8 @@
 
 EditorGrid::EditorGrid() : Entity() {
 	grid = NULL;
+    gridMode = GRID_MODE_3D;
+    
 	setGrid(1.0);
 	setPitch(90);
 }
@@ -31,15 +33,15 @@ EditorGrid::EditorGrid() : Entity() {
 void EditorGrid::setGrid(int gridSize) {
 	Polycode::Polygon *gridPoly = new Polycode::Polygon();
 	int gridLen = 16;
-	
+    
 	for(int x=0; x < gridLen+1; x++) {
-			gridPoly->addVertex(x * gridSize,0, 0);
-			gridPoly->addVertex(x * gridSize,gridSize * gridLen, 0);
+			gridPoly->addVertex((-gridSize * gridLen * 0.5) + (x * gridSize), (-gridSize * gridLen * 0.5), 0);
+			gridPoly->addVertex((-gridSize * gridLen * 0.5) + (x * gridSize) , (-gridSize * gridLen * 0.5) + (gridSize * gridLen), 0);
 	}
 
 	for(int y=0; y < gridLen+1; y++) {
-			gridPoly->addVertex(0, y * gridSize, 0);
-			gridPoly->addVertex(gridSize * gridLen, y * gridSize, 0);                
+			gridPoly->addVertex((-gridSize * gridLen * 0.5), (-gridSize * gridLen * 0.5) + (y * gridSize), 0);
+			gridPoly->addVertex((-gridSize * gridLen * 0.5) + (gridSize * gridLen), (-gridSize * gridLen * 0.5) + (y * gridSize), 0);
 	}        
 
 	if(grid) {
@@ -52,11 +54,20 @@ void EditorGrid::setGrid(int gridSize) {
 			grid = new SceneMesh(gridMesh);
 			grid->setColor(0.3, 0.3, 0.3, 1.0);
             grid->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
-			addChild(grid);                
-			grid->setPosition(-gridSize * gridLen * 0.5, -gridSize * gridLen * 0.5);
+			addChild(grid);
+            grid->cacheToVertexBuffer(true);
+            
 	}
 }
 
+void EditorGrid::setGridMode(int mode) {
+    gridMode = mode;
+    if(gridMode == GRID_MODE_3D) {
+        grid->setPitch(0);
+    } else {
+        grid->setPitch(90);
+    }
+}
 
 EditorGrid::~EditorGrid() {
 

+ 57 - 13
IDE/Contents/Source/PolycodeEntityEditor.cpp

@@ -29,7 +29,7 @@ extern PolycodeFrame *globalFrame;
 EntityEditorMainView::EntityEditorMainView() {
 	processInputEvents = true;
 
-	mainScene = new Scene(Scene::SCENE_3D, true);		
+	mainScene = new Scene(Scene::SCENE_3D, true);
 	renderTexture = new SceneRenderTexture(mainScene, mainScene->getDefaultCamera(), 512, 512);
 	mainScene->clearColor.setColor(0.2, 0.2, 0.2, 1.0);	
 	mainScene->useClearColor = true;
@@ -47,10 +47,10 @@ EntityEditorMainView::EntityEditorMainView() {
 	headerBg->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiHeaderBgColor"));
     
 	
-	sideBar = new Entity();
-	addChild(sideBar);
-	sideBar->setPosition(0, 0);
-	sideBar->processInputEvents = true;
+	topBar = new Entity();
+	addChild(topBar);
+	topBar->setPosition(0, 0);
+	topBar->processInputEvents = true;
     
 	
 	mainScene->getDefaultCamera()->setPosition(10, 10, 10);
@@ -68,14 +68,44 @@ EntityEditorMainView::EntityEditorMainView() {
 	trackballCamera = new TrackballCamera(mainScene->getDefaultCamera(), renderTextureShape);
 	
     addEntityButton = new UIImageButton("entityEditor/add_entity.png", 1.0, 24, 24);
-	sideBar->addChild(addEntityButton);
+	topBar->addChild(addEntityButton);
     addEntityButton->setPosition(4, 2);
     addEntityButton->addEventListener(this, UIEvent::CLICK_EVENT);
     
 	transformGizmoMenu = new TransformGizmoMenu(transformGizmo);
-	sideBar->addChild(transformGizmoMenu);
+	topBar->addChild(transformGizmoMenu);
     transformGizmoMenu->setPositionX(40);
     
+    modeSwitchDropdown = new UIComboBox(globalMenu, 100);
+    topBar->addChild(modeSwitchDropdown);
+    
+    modeSwitchDropdown->addComboItem("3D MODE");
+    modeSwitchDropdown->addComboItem("2D MODE");
+    modeSwitchDropdown->setSelectedIndex(0);
+    modeSwitchDropdown->addEventListener(this, UIEvent::CHANGE_EVENT);
+    
+    editorMode = EDITOR_MODE_3D;
+}
+
+void EntityEditorMainView::setEditorMode(int newMode) {
+    editorMode = newMode;
+    if(editorMode == EDITOR_MODE_3D) {
+        mainScene->setSceneType(Scene::SCENE_3D);
+        grid->setGridMode(EditorGrid::GRID_MODE_3D);
+        transformGizmo->setGizmoMode(TransformGizmo::GIZMO_MODE_3D);
+        mainScene->getDefaultCamera()->setOrthoMode(false);
+        mainScene->getDefaultCamera()->setClippingPlanes(1, 1000);
+        trackballCamera->disableRotation(false);
+    } else {
+        mainScene->setSceneType(Scene::SCENE_2D);
+        mainScene->getDefaultCamera()->setOrthoMode(true);
+        mainScene->getDefaultCamera()->setClippingPlanes(-1, 10000);
+        trackballCamera->setCameraPosition(trackballCamera->getOribitingCenter()+Vector3(0.0, 0.0, trackballCamera->getCameraDistance()));
+        grid->setGridMode(EditorGrid::GRID_MODE_2D);
+        transformGizmo->setGizmoMode(TransformGizmo::GIZMO_MODE_2D);
+        trackballCamera->disableRotation(true);
+        Update();
+    }
 }
 
 Entity *EntityEditorMainView::getSelectedEntity() {
@@ -87,6 +117,12 @@ Entity *EntityEditorMainView::getSelectedEntity() {
 }
 
 void EntityEditorMainView::Update() {
+    
+    if(editorMode == EDITOR_MODE_2D) {
+        Number aspect = renderTextureShape->getWidth() / renderTextureShape->getHeight();
+        mainScene->getDefaultCamera()->setOrthoSize(trackballCamera->getCameraDistance() * aspect, trackballCamera->getCameraDistance());
+    }
+    
     for(int i=0; i < icons.size(); i++) {
         Number scale = mainScene->getDefaultCamera()->getPosition().distance(icons[i]->getConcatenatedMatrix().getPosition()) * 0.1;
         icons[i]->setScale(scale, scale, scale);
@@ -118,7 +154,7 @@ void EntityEditorMainView::setEditorProps(Entity *entity) {
     SceneMesh *sceneMesh = dynamic_cast<SceneMesh*>(entity);
     if(sceneMesh) {
         sceneMesh->wireFrameColor = Color(1.0, 0.8, 0.3, 1.0);
-        sceneMesh->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
+//        sceneMesh->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
         sceneMesh->useGeometryHitDetection = true;
     }
     
@@ -165,10 +201,13 @@ void EntityEditorMainView::addEntityFromMenu(String command) {
 
 void EntityEditorMainView::handleEvent(Event *event) {
 
-    if(event->getDispatcher() == globalFrame->assetBrowser) {
+    if(event->getDispatcher() == modeSwitchDropdown) {
+        setEditorMode(modeSwitchDropdown->getSelectedIndex());
+    } else if(event->getDispatcher() == globalFrame->assetBrowser) {
         if(event->getEventCode() == UIEvent::OK_EVENT) {
             if(assetSelectType == "mesh") {
                 SceneMesh *newMesh = new SceneMesh(globalFrame->assetBrowser->getFullSelectedAssetPath());
+                newMesh->cacheToVertexBuffer(true);
                 sceneObjectRoot->addChild(newMesh);
                 setEditorProps(newMesh);
                 newMesh->setPosition(cursorPosition);
@@ -237,13 +276,18 @@ EntityEditorMainView::~EntityEditorMainView() {
 
 void EntityEditorMainView::Resize(Number width, Number height) {
 	headerBg->Resize(width, 30);
-	
-	mainScene->sceneMouseAdjust.x = renderTextureShape->getScreenPositionForMainCamera().x;
-	mainScene->sceneMouseAdjust.y = CoreServices::getInstance()->getCore()->getYRes() - (renderTextureShape->getScreenPositionForMainCamera().y + renderTextureShape->getHeight());
-	
+	modeSwitchDropdown->setPosition(width-110, 4);
+    
+	mainScene->sceneMouseRect.x = renderTextureShape->getScreenPositionForMainCamera().x;
+	mainScene->sceneMouseRect.y = renderTextureShape->getScreenPositionForMainCamera().y;
+	mainScene->sceneMouseRect.w = renderTextureShape->getWidth();
+	mainScene->sceneMouseRect.h = renderTextureShape->getHeight();
+    mainScene->remapMouse = true;
+    
 	renderTexture->resizeRenderTexture(width, height-30);
 	renderTextureShape->setTexture(renderTexture->getTargetTexture());		
 	renderTextureShape->Resize(width, height-30);
+    Update();
 }
 
 PolycodeEntityEditor::PolycodeEntityEditor() : PolycodeEditor(true){

+ 19 - 3
IDE/Contents/Source/TrackballCamera.cpp

@@ -49,6 +49,10 @@ TrackballCamera::TrackballCamera(Camera *targetCamera, Entity *trackballShape) :
 	updateCamera();	
 }
 
+Number TrackballCamera::getCameraDistance() {
+    return cameraDistance;
+}
+
 TrackballCamera::~TrackballCamera() {
 	trackballShape->removeAllHandlersForListener(this);
 }
@@ -84,8 +88,10 @@ void TrackballCamera::handleEvent(Event *event) {
 						);
 						trackBallMouseEnd = trackBallMouseStart;												
 					} else {
-						mouseMode = MOUSE_MODE_ORBITING;
-						trackballRotateStart = trackballRotateEnd = getMouseProjectionOnBall(inputEvent->getMousePosition());
+                        if(!rotationDisabled) {
+                            mouseMode = MOUSE_MODE_ORBITING;
+                            trackballRotateStart = trackballRotateEnd = getMouseProjectionOnBall(inputEvent->getMousePosition());
+                        }
 					}
 				}
 			break;
@@ -157,7 +163,14 @@ void TrackballCamera::processMouseMovement(const Vector2 &newPosition) {
 	}
 }
 
+void TrackballCamera::setCameraPosition(Vector3 cameraPosition) {
+    targetCamera->setPosition(cameraPosition);
+    updateCamera();
+}
 
+Vector3 TrackballCamera::getOribitingCenter() {
+    return orbitingCenter;
+}
 
 void TrackballCamera::updateCamera() {
 
@@ -183,7 +196,10 @@ void TrackballCamera::updateCamera() {
 		
 	targetCamera->setPosition(orbitingCenter + trackballEye);	
 	targetCamera->lookAt(orbitingCenter);
-	
+}
+
+bool TrackballCamera::disableRotation(bool val) {
+    rotationDisabled = val;
 }
 
 Vector3 TrackballCamera::getMouseProjectionOnBall(const Vector2 &mousePosition) {

+ 107 - 25
IDE/Contents/Source/TransformGizmo.cpp

@@ -84,8 +84,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	rotateDectorators = new Entity();
 	addChild(rotateDectorators);	
 		
-			
-	SceneMesh *yLine = new SceneMesh(Mesh::LINE_MESH);	
+	yLine = new SceneMesh(Mesh::LINE_MESH);
 	Polycode::Polygon *poly = new Polycode::Polygon();
 	poly->addVertex(0.0, 0.0, 0.0);
 	poly->addVertex(0.0, 1.0, 0.0);	
@@ -96,7 +95,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     yLine->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
 	transformAndScaleLines->addChild(yLine);
 
-	SceneMesh *xLine = new SceneMesh(Mesh::LINE_MESH);	
+	xLine = new SceneMesh(Mesh::LINE_MESH);
 	poly = new Polycode::Polygon();
 	poly->addVertex(0.0, 0.0, 0.0);
 	poly->addVertex(1.0, 0.0, 0.0);	
@@ -107,7 +106,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     xLine->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
 	transformAndScaleLines->addChild(xLine);
 
-	SceneMesh *zLine = new SceneMesh(Mesh::LINE_MESH);	
+	zLine = new SceneMesh(Mesh::LINE_MESH);
 	poly = new Polycode::Polygon();
 	poly->addVertex(0.0, 0.0, 0.0);
 	poly->addVertex(0.0, 0.0, 1.0);	
@@ -120,20 +119,20 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	
 	// MOVE
 	
-	ScenePrimitive *yArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
+	yArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	yArrow->setColor(0.0, 1.0, 0.0, 1.0);
 	yArrow->setPosition(0.0, 1.0, 0.0);
 	yArrow->depthTest = false;
 	trasnformDecorators->addChild(yArrow);
 	
-	ScenePrimitive *xArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
+	xArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	xArrow->setColor(1.0, 0.0, 0.0, 1.0);
 	xArrow->setPosition(1.0, 0.0, 0.0);
 	xArrow->Roll(-90);
 	xArrow->depthTest = false;
 	trasnformDecorators->addChild(xArrow);
 
-	ScenePrimitive *zArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
+	zArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	zArrow->setColor(0.0, 0.0, 1.0, 1.0);
 	zArrow->setPosition(0.0, 0.0, 1.0);
 	zArrow->Pitch(90);
@@ -142,20 +141,20 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 
 	// SCALE
 
-	ScenePrimitive *yBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
+	yBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
 	yBox->setColor(0.0, 1.0, 0.0, 1.0);
 	yBox->setPosition(0.0, 1.0, 0.0);
 	yBox->depthTest = false;
 	scaleDecorators->addChild(yBox);
 	
-	ScenePrimitive *xBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
+	xBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
 	xBox->setColor(1.0, 0.0, 0.0, 1.0);
 	xBox->setPosition(1.0, 0.0, 0.0);
 	xBox->Roll(-90);
 	xBox->depthTest = false;
 	scaleDecorators->addChild(xBox);
 
-	ScenePrimitive *zBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
+	zBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.1, 0.1, 0.1);
 	zBox->setColor(0.0, 0.0, 1.0, 1.0);
 	zBox->setPosition(0.0, 0.0, 1.0);
 	zBox->Pitch(90);
@@ -164,7 +163,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 
 	// ROTATE
 
-	ScenePrimitive *bgCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.6, 1.6, 32);
+	bgCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.6, 1.6, 32);
 	bgCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	bgCircle->setColor(0.0, 0.0, 0.0, 1.0);
 	bgCircle->depthTest = false;
@@ -172,7 +171,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	rotateDectorators->addChild(bgCircle);
     bgCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
 
-	ScenePrimitive *outerCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 2.0, 2.0, 32);
+	outerCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 2.0, 2.0, 32);
 	outerCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	outerCircle->setColor(1.0, 1.0, 1.0, 1.0);
 	outerCircle->depthTest = false;
@@ -180,7 +179,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	rotateDectorators->addChild(outerCircle);
     outerCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
     
-	ScenePrimitive *pitchCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.55, 1.55, 32);
+	pitchCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.55, 1.55, 32);
 	pitchCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	pitchCircle->setColor(1.0, 0.0, 0.0, 1.0);
 	pitchCircle->depthTest = false;
@@ -189,7 +188,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	pitchCircle->setMaterialByName("OneSidedLine");
     pitchCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
     
-	ScenePrimitive *yawCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.65, 1.65, 32);
+	yawCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.65, 1.65, 32);
 	yawCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	yawCircle->setColor(0.0, 1.0, 0.0, 1.0);
 	yawCircle->depthTest = false;
@@ -198,7 +197,7 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	yawCircle->setMaterialByName("OneSidedLine");
     yawCircle->setLineWidth(CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX());
     
-	ScenePrimitive *rollCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.6, 1.6, 32);
+	rollCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.6, 1.6, 32);
 	rollCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	rollCircle->setColor(0.0, 0.0, 1.0, 1.0);
 	rollCircle->depthTest = false;
@@ -243,10 +242,25 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	yawGrip->useGeometryHitDetection = true;
 	yawGrip->blockMouseInput = true;
 	
-	pitchGrip->visible = false;		
+    viewportRotateGripBase = new Entity();
+    viewportRotateGripBase->processInputEvents = true;
+	rotateDectorators->addChild(viewportRotateGripBase);
+    
+	viewportRotateGrip = new ScenePrimitive(ScenePrimitive::TYPE_TORUS, 2.0 * 0.5, 0.1, 10, 3);
+    viewportRotateGrip->Pitch(90);
+	viewportRotateGrip->setColor(0.0, 1.0, 0.0, 0.2);
+	viewportRotateGrip->depthTest = false;
+	viewportRotateGripBase->addChild(viewportRotateGrip);
+	viewportRotateGrip->processInputEvents = true;
+	viewportRotateGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+	viewportRotateGrip->useGeometryHitDetection = true;
+	viewportRotateGrip->blockMouseInput = true;
+    
+    pitchGrip->visible = false;
 	yawGrip->visible = false;
 	rollGrip->visible = false;
-
+    viewportRotateGrip->visible = false;
+    
 	xTransformGrip = new Entity();
 	xTransformGrip->bBox.set(1.3, 0.1, 0.1);
 	addChild(xTransformGrip);
@@ -277,7 +291,8 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	coreInput = CoreServices::getInstance()->getCore()->getInput();
 	coreInput->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
 	coreInput->addEventListener(this, InputEvent::EVENT_MOUSEUP);	
-	
+
+	gizmoMode = GIZMO_MODE_3D;
 	setTransformMode(TRANSFORM_MOVE);
 }
 
@@ -296,6 +311,8 @@ Vector3 TransformGizmo::getTransformPlanePosition() {
 }
 
 void TransformGizmo::setTransformMode(int newMode) {
+    
+    transformMode = newMode;
 	trasnformDecorators->visible = false;
 	scaleDecorators->visible = false;
 	transformAndScaleLines->visible = false;
@@ -307,6 +324,7 @@ void TransformGizmo::setTransformMode(int newMode) {
 	pitchGrip->enabled = false;
 	rollGrip->enabled = false;
 	yawGrip->enabled = false;
+    viewportRotateGrip->enabled = false;
 	
 			
 	mode = newMode;
@@ -316,20 +334,48 @@ void TransformGizmo::setTransformMode(int newMode) {
 			transformAndScaleLines->visible = true;
 			xTransformGrip->enabled = true;
 			yTransformGrip->enabled = true;
-			zTransformGrip->enabled = true;						
+            if(gizmoMode == GIZMO_MODE_3D) {
+                zTransformGrip->enabled = true;
+                zArrow->visible = true;
+                zLine->visible = true;
+            } else {
+                zArrow->visible = false;
+                zLine->visible = false;
+            }
+            
 		break;
 		case TRANSFORM_SCALE:
 			scaleDecorators->visible = true;
 			transformAndScaleLines->visible = true;					
 			xTransformGrip->enabled = true;
 			yTransformGrip->enabled = true;
-			zTransformGrip->enabled = true;				
+            if(gizmoMode == GIZMO_MODE_3D) {
+                zTransformGrip->enabled = true;
+                zBox->visible = true;
+                zLine->visible = true;
+            } else {
+                zBox->visible = false;
+                zLine->visible = false;
+            }
+
 		break;	
 		case TRANSFORM_ROTATE:
 			rotateDectorators->visible = true;
 			pitchGrip->enabled = true;
-			rollGrip->enabled = true;
-			yawGrip->enabled = true;			
+			yawGrip->enabled = true;
+            viewportRotateGrip->enabled = true;
+            
+            if(gizmoMode == GIZMO_MODE_3D) {
+                rollGrip->enabled = true;
+                rollCircle->visible = true;
+                rollCircle->visible = true;
+                outerCircle->setColor(1.0, 1.0, 1.0, 1.0);
+            } else {
+                rollCircle->visible = false;
+                rollCircle->visible = false;
+                outerCircle->setColor(0.0, 0.0, 1.0, 1.0);
+            }
+            
 		break;
 		default:
 			assert(false); // invalid mode
@@ -412,6 +458,11 @@ Number TransformGizmo::getTransformPlaneAngle() {
 	return atan2(planePosition.x, planePosition.y);
 }
 
+void TransformGizmo::setGizmoMode(int newMode) {
+    gizmoMode = newMode;
+    setTransformMode(transformMode);
+}
+
 void TransformGizmo::handleEvent(Event *event) {
 
 	if(!coreInput->getKeyState(KEY_LALT) && !coreInput->getKeyState(KEY_RALT)) {
@@ -419,14 +470,26 @@ void TransformGizmo::handleEvent(Event *event) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
 				transforming = true;
 				transformConstraint = Vector3(1.0, 0.0, 0.0);
-				transformPlane = Vector3(1.0, 0.0, 0.0);
+                
+                if(gizmoMode == GIZMO_MODE_3D) {
+                    transformPlane = Vector3(1.0, 0.0, 0.0);
+                } else {
+                    transformPlane = Vector3(0.0, 0.0, 1.0);
+                }
+                
 				startingAngle = getTransformPlaneAngle();
 			}
 		} else 	if(event->getDispatcher() == yawGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
 				transforming = true;
 				transformConstraint = Vector3(0.0, 1.0, 0.0);
-				transformPlane = Vector3(0.0, 1.0, 0.0);
+                
+                if(gizmoMode == GIZMO_MODE_3D) {
+                    transformPlane = Vector3(0.0, 1.0, 0.0);
+                } else {
+                    transformPlane = Vector3(0.0, 0.0, 1.0);
+                }
+                
 				startingAngle = getTransformPlaneAngle();
 			}
 		} else 	if(event->getDispatcher() == rollGrip) {
@@ -436,13 +499,28 @@ void TransformGizmo::handleEvent(Event *event) {
 				transformPlane = Vector3(0.0, 0.0, 1.0);
 				startingAngle = getTransformPlaneAngle();
 			}
+		} else 	if(event->getDispatcher() == viewportRotateGrip) {
+			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
+                if(gizmoMode == GIZMO_MODE_2D) {
+                    transforming = true;
+                    transformConstraint = Vector3(0.0, 0.0, -1.0);
+                    transformPlane = Vector3(0.0, 0.0, 1.0);
+                    startingAngle = getTransformPlaneAngle();
+                }
+			}
 		}
 
+
 		if(event->getDispatcher() == xTransformGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
 				transforming = true;
 				transformConstraint = Vector3(1.0, 0.0, 0.0);
-				transformPlane = Vector3(0.0, 1.0, 0.0);
+                
+                if(gizmoMode == GIZMO_MODE_3D) {
+                    transformPlane = Vector3(0.0, 1.0, 0.0);
+                } else {
+                    transformPlane = Vector3(0.0, 0.0, 1.0);
+                }
 				startingPoint = getTransformPlanePosition();
 			}
 		} else 	if(event->getDispatcher() == yTransformGrip) {
@@ -505,7 +583,11 @@ TransformGizmo::~TransformGizmo() {
 }
 
 void TransformGizmo::Update() {
+    viewportRotateGripBase->lookAt(targetCamera->getPosition());
 	Number scale = getPosition().distance(targetCamera->getPosition()) * 0.1;
+    if(scale < 0.0) {
+        scale = 0.0;
+    }
 	setScale(scale, scale, scale);
 }