Просмотр исходного кода

Merge pull request #584 from randomteddybear/IDEImprovements

Gizmo and camera improvements.
Ivan Safrin 11 лет назад
Родитель
Сommit
2c1afa0294

+ 11 - 0
Core/Contents/Include/PolyRay.h

@@ -38,7 +38,18 @@ namespace Polycode {
 			Number boxIntersect(const Vector3 &box, const Matrix4 &transformMatrix, float near = 0.0, float far = 9999.0) const;
 			
 			Vector3 planeIntersectPoint(const Vector3 &planeNormal, Number planeDistance) const;
+			Vector3 planeIntersectPoint(const Vector3 &planeNormal, const Vector3 &planePosition) const;
 			Ray tranformByMatrix(const Matrix4& matrix) const;
+
+			/**
+			* finds the two closest point on the ray to an arbitrary point space.
+			*/
+			Vector3 closestPointOnRay(const Vector3 &point) const;
+
+			/**
+			* finds the two closest points between two rays, returns false if they're parallel.
+			*/
+			bool closestPointsBetween(const Ray &ray2, Vector3 *point1, Vector3 *point2);
 			
 			bool polygonIntersect(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) const;
 		

+ 39 - 0
Core/Contents/Source/PolyRay.cpp

@@ -55,6 +55,11 @@ Vector3 Ray::planeIntersectPoint(const Vector3 &planeNormal, Number planeDistanc
 	 return origin + direction * (-distanceToOrigin / direction.dot(planeNormal));
 }
 
+Vector3 Ray::planeIntersectPoint(const Vector3 &planeNormal, const Vector3 &planePosition) const {
+	Number d = (planePosition - origin).dot(planeNormal) / direction.dot(planeNormal);
+	return origin + direction * d;
+}
+
 bool Ray::polygonIntersect(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) const {
 
     Number t,u,v;
@@ -94,6 +99,40 @@ bool Ray::polygonIntersect(const Vector3 &v1, const Vector3 &v2, const Vector3 &
 	return true;
 }
 
+Vector3 Ray::closestPointOnRay(const Vector3 &point) const {
+	Number b = (point - origin).dot(direction)/ direction.dot(direction);
+	return origin + direction*b;
+}
+
+bool Ray::closestPointsBetween(const Ray &ray2, Vector3 *point1, Vector3 *point2) {
+	Vector3 wOrigin = origin - ray2.origin;
+
+	Number a = direction.dot(direction);
+	Number b = direction.dot(ray2.direction);
+	Number c = ray2.direction.dot(ray2.direction);
+	Number d = direction.dot(wOrigin);
+	Number e = ray2.direction.dot(wOrigin);
+	Number denom = a*c - b*b;
+
+	if(denom < 0.00001) {
+		if(point1)
+			*point1 = Vector3(0); 
+		if(point2)
+			*point2 = Vector3(0); 
+		return false;
+	}
+
+	Number s = (b*e - c*d)/denom;
+	Number t = (a*e - b*d)/denom;
+
+	
+	if(point1)
+		*point1 = origin + direction*s; 
+	if(point2)
+		*point2 = ray2.origin + ray2.direction*t; 
+	return true;
+}
+
 Number Ray::boxIntersect(const Vector3 &box, const Matrix4 &transformMatrix, float near, float far) const {
 
 	if(box.x == 0 || box.y == 0 || box.z == 0)

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

@@ -60,7 +60,6 @@ class TrackballCamera : public EventDispatcher {
 
 		int mouseMode;
 	
-		Vector3 getMouseProjectionOnBall(const Vector2 &mousePosition);
 		void updateCamera();	
 		void processMouseMovement(const Vector2 &newPosition);
 		
@@ -72,8 +71,6 @@ class TrackballCamera : public EventDispatcher {
 		Vector2 trackBallMouseStart;
 		Vector2 trackBallMouseEnd;			
 		Vector3 orbitingCenter;
-		Vector3 trackballRotateStart;
-		Vector3 trackballRotateEnd;	
 		Vector3 trackballEye;		
 		Number cameraDistance;
 		CoreInput *coreInput;		

+ 17 - 1
IDE/Contents/Include/TransformGizmo.h

@@ -94,17 +94,26 @@ class TransformGizmo : public Entity {
 		
 		void transformSelectedEntities(const Vector3 &move, const Vector3 &scale, Number rotate);
 		Vector3 getTransformPlanePosition();
-		
+		Vector3 getPositionAlongAxis();
+		bool isConstrainedToSingleAxis();
+
 		Number getTransformPlaneAngle();
+		Number get2dAngle();
+		Vector2 getCorrectedMousePosition();
+
+		void resetTransform();
     
         void setTransformOrientation(int orientation);
     
         void updateOrientationForEntity(Entity *entity);
     
         void setTransformPlane(Number x, Number y, Number z, bool forceGlobal = false);
+		void setTransformPlane(bool useX, bool useY, bool useZ);
         void setTransformPlaneFromView();
     
         void setCenterMode(int centerMode);
+
+		void toggleOrientation();
 		
 		static const int TRANSFORM_MOVE = 0;
 		static const int TRANSFORM_SCALE = 1;
@@ -136,11 +145,16 @@ class TransformGizmo : public Entity {
         int transformMode;
         int gizmoMode;
         int orientation;
+		int startingOrientation;
     
         int centerMode;
 	
 		std::vector<Entity*> selectedEntities;
 		std::vector<Vector3> entityPositions;
+
+		std::vector<Vector3> oldPosition;
+		std::vector<Vector3> oldScale;
+		std::vector<Quaternion> oldRotation;
     
 		Scene *targetScene;
 		Camera *targetCamera;
@@ -164,6 +178,8 @@ class TransformGizmo : public Entity {
         Vector3 gizmoPoint;
 		Vector3 startingPoint;
 		Number startingAngle;
+
+		Vector2 mouseStart2d;
     
         Number scaleAmount;
 				

+ 29 - 48
IDE/Contents/Source/TrackballCamera.cpp

@@ -46,11 +46,8 @@ TrackballCamera::TrackballCamera(Camera *targetCamera, Entity *trackballShape) :
 	
 	coreInput = CoreServices::getInstance()->getCore()->getInput();
 	
-	targetCamera->setPosition(cameraDistance, cameraDistance, cameraDistance);
-	trackballRotateEnd = getMouseProjectionOnBall(Vector2(trackballShape->getWidth()/2.0, trackballShape->getHeight()/2.0));
-	trackballRotateStart = trackballRotateEnd;
-	
-	updateCamera();	
+	targetCamera->lookAt(orbitingCenter);
+	updateCamera();
 }
 
 Number TrackballCamera::getCameraDistance() {
@@ -98,7 +95,10 @@ void TrackballCamera::handleEvent(Event *event) {
 					} else {
                         if(!rotationDisabled) {
                             mouseMode = MOUSE_MODE_ORBITING;
-                            trackballRotateStart = trackballRotateEnd = getMouseProjectionOnBall(inputEvent->getMousePosition());
+							trackBallMouseStart = trackBallMouseEnd = Vector2(
+								inputEvent->getMousePosition().x / trackballShape->getWidth(),
+								inputEvent->getMousePosition().y / trackballShape->getHeight()
+							);
                         }
 					}
 				}
@@ -125,15 +125,18 @@ void TrackballCamera::handleEvent(Event *event) {
 
 void TrackballCamera::setOrbitingCenter(const Vector3 &newCenter) {
 	orbitingCenter = newCenter;
-	updateCamera();	
 }
 
 void TrackballCamera::processMouseMovement(const Vector2 &newPosition) {
 	switch(mouseMode) {
 		case MOUSE_MODE_ORBITING:
 		{
-			trackballRotateEnd = getMouseProjectionOnBall(newPosition);
+			trackBallMouseEnd  = Vector2(
+							newPosition.x / trackballShape->getWidth(),
+							newPosition.y / trackballShape->getHeight()
+						);
 			updateCamera();
+			trackBallMouseStart = trackBallMouseEnd;
 		}	
 		break;
 		case MOUSE_MODE_PANNING:
@@ -183,6 +186,7 @@ void TrackballCamera::processMouseMovement(const Vector2 &newPosition) {
 
 void TrackballCamera::setCameraPosition(Vector3 cameraPosition) {
     targetCamera->setPosition(cameraPosition);
+	targetCamera->lookAt(orbitingCenter);
     updateCamera();
 }
 
@@ -192,28 +196,30 @@ Vector3 TrackballCamera::getOribitingCenter() {
 
 void TrackballCamera::updateCamera() {
 
+	Quaternion currentCamQuat = targetCamera->getRotationQuat();
 	trackballEye = targetCamera->getPosition() - orbitingCenter;
 	trackballEye.setLength(cameraDistance);
-	
-	
-	Number angle = acos(trackballRotateStart.dot(trackballRotateEnd) / trackballRotateStart.length() / trackballRotateEnd.length());
-	
-	if(angle == angle) {
-		Vector3 axis = trackballRotateStart.crossProduct(trackballRotateEnd);
-		axis.Normalize();
+
+	if(mouseMode == MOUSE_MODE_ORBITING) {
+		Vector2 localMouse =  trackBallMouseEnd - trackBallMouseStart;
+
 		Quaternion q;
-		
-		angle *= trackballRotateSpeed;	
-		q.fromAngleAxis(angle, axis);
-		
+		// yaw
+		if(Vector3(0.0, 1.0, 0.0).dot(currentCamQuat.applyTo(Vector3(0.0, 0.0, -1.0))) > 0.0)
+			q.fromAngleAxis(localMouse.x*2.0, Vector3(0.0, 1.0, 0.0));
+		else
+			q.fromAngleAxis(localMouse.x*-2.0, Vector3(0.0, 1.0, 0.0));
+		currentCamQuat = q * currentCamQuat;
+		trackballEye = q.applyTo(trackballEye);
+
+		// local pitch
+		q.fromAngleAxis(localMouse.y*-2.0, currentCamQuat.applyTo(Vector3(1.0, 0.0, 0.0)));
+		currentCamQuat = q * currentCamQuat;
 		trackballEye = q.applyTo(trackballEye);
-		trackballRotateEnd = q.applyTo(trackballRotateEnd);
-		
-		trackballRotateStart = trackballRotateEnd;
 	}
 		
 	targetCamera->setPosition(orbitingCenter + trackballEye);	
-	targetCamera->lookAt(orbitingCenter);
+	targetCamera->setRotationByQuaternion(currentCamQuat);
     dispatchEvent(new Event(), Event::CHANGE_EVENT);
 }
 
@@ -221,31 +227,6 @@ void TrackballCamera::disableRotation(bool val) {
     rotationDisabled = val;
 }
 
-Vector3 TrackballCamera::getMouseProjectionOnBall(const Vector2 &mousePosition) {
-
-	Vector3 mouseOnBall = Vector3((mousePosition.x - (trackballShape->getWidth() * 0.5)) / (trackballShape->getWidth() * 0.5),(mousePosition.y - (trackballShape->getHeight() * 0.5)) / (trackballShape->getHeight() * 0.5), 0.0);
-	mouseOnBall.x *= -1;	
-	
-	Number length = mouseOnBall.length();
-	
-
-	if (length < sqrt(0.5)) {
-		mouseOnBall.z = sqrt(1.0 - length*length);
-	} else {
-		mouseOnBall.z = 0.5 / length;
-	}
-
-	trackballEye = targetCamera->getPosition() - orbitingCenter;
-	
-	Vector3 projection = Vector3(0.0, 1.0, 0.0).setLength(mouseOnBall.y);		
-	
-	projection = projection + (Vector3(0.0, 1.0, 0.0).crossProduct(trackballEye).setLength(mouseOnBall.x));				
-	
-	trackballEye.setLength(mouseOnBall.z);
-	projection = projection + (trackballEye);
-	
-	return projection;	
-}
 /*
 void TrackballCamera::setCameraPosition(Vector3 cameraPosition) {
 

+ 363 - 89
IDE/Contents/Source/TransformGizmo.cpp

@@ -228,10 +228,20 @@ void TransformGizmo::setCenterMode(int centerMode) {
     this->centerMode = centerMode;
 }
 
+void TransformGizmo::toggleOrientation() {
+	if(startingOrientation == -1)
+		startingOrientation = orientation; 
+	
+	if(orientation == ORIENTATION_GLOBAL)
+		orientation = ORIENTATION_LOCAL;
+	else if(orientation == ORIENTATION_LOCAL)
+		orientation = ORIENTATION_GLOBAL;
+}
 
 TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entity() {
 	processInputEvents = true;
     orientation = ORIENTATION_GLOBAL;
+	startingOrientation = -1;
     centerMode = CENTER_MODE_MEDIAN;
     enableGizmo = true;
     firstMove = true;
@@ -487,15 +497,15 @@ void TransformGizmo::setTransformPlaneFromView() {
     switch(gizmoMode) {
         case GIZMO_MODE_2D_X:
             setTransformPlane(1.0, 0.0, 0.0, true);
-            transformConstraint = Vector3(1.0, 0.0, 0.0);
+            transformConstraint = Vector3(0.0, 1.0, 1.0);
         break;
         case GIZMO_MODE_2D_Y:
             setTransformPlane(0.0, 1.0, 0.0, true);
-            transformConstraint = Vector3(0.0, 1.0, 0.0);
+            transformConstraint = Vector3(1.0, 0.0, 1.0);
         break;
         case GIZMO_MODE_2D_Z:
             setTransformPlane(0.0, 0.0, 1.0, true);
-            transformConstraint = Vector3(0.0, 0.0, -1.0);
+            transformConstraint = Vector3(1.0, 1.0, 0.0);
         break;
         default:
             Vector3 camVec =  targetCamera->getConcatenatedMatrix().getPosition() - getConcatenatedMatrix().getPosition();
@@ -532,18 +542,75 @@ void TransformGizmo::setTransformPlane(Number x, Number y, Number z, bool forceG
     
 }
 
+void TransformGizmo::setTransformPlane(bool useX, bool useY, bool useZ) {
+	Vector3 xDir = getAnchorAdjustedMatrix().rotateVector(Vector3(1.0, 0.0, 0.0));
+	Vector3 yDir = getAnchorAdjustedMatrix().rotateVector(Vector3(0.0, 1.0, 0.0));
+	Vector3 zDir = getAnchorAdjustedMatrix().rotateVector(Vector3(0.0, 0.0, 1.0));
+	
+	Number xDot = abs(targetCamera->getRotationQuat().applyTo(Vector3(0.0, 0.0, -1.0)).dot(xDir));
+	Number yDot = abs(targetCamera->getRotationQuat().applyTo(Vector3(0.0, 0.0, -1.0)).dot(yDir));
+	Number zDot = abs(targetCamera->getRotationQuat().applyTo(Vector3(0.0, 0.0, -1.0)).dot(zDir));
+
+	if(useX && !useY && !useZ) {
+		if(yDot > zDot)
+			setTransformPlane(0.0, 1.0, 0.0);
+		else
+			setTransformPlane(0.0, 0.0, 1.0);
+	} else if(!useX && useY && !useZ) {
+		if(xDot > zDot)
+			setTransformPlane(1.0, 0.0, 0.0);
+		else
+			setTransformPlane(0.0, 0.0, 1.0);
+	} else if(!useX && !useY && useZ) {
+		if(xDot > yDot)
+			setTransformPlane(1.0, 0.0, 0.0);
+		else
+			setTransformPlane(0.0, 1.0, 0.0);
+	} else if(!useX) {
+		setTransformPlane(1.0, 0.0, 0.0);
+	} else if(!useY) {
+		setTransformPlane(0.0, 1.0, 0.0);
+	} else if(!useZ) {
+		setTransformPlane(0.0, 0.0, 1.0);
+	}
+}
+
 Vector3 TransformGizmo::getTransformPlanePosition() {
 
 	Ray ray = targetScene->projectRayFromCameraAndViewportCoordinate(targetCamera, coreInput->getMousePosition());
     
     // hack to fix NaN's in the plane intersect math (sorry)
     ray.direction += Vector3(0.00001, 0.00001, 0.00001);
-    
-    
+
     Vector3 ret = ray.planeIntersectPoint(transformPlane, transformPlaneDistance);
     return ret;
 }
 
+Vector3 TransformGizmo::getPositionAlongAxis() {
+	Ray ray = Ray(position, rotationQuat.applyTo(transformConstraint));
+	Ray ray2 = targetScene->projectRayFromCameraAndViewportCoordinate(targetCamera, coreInput->getMousePosition());
+	Vector3 ret;
+	ray.closestPointsBetween(ray2, &ret, NULL);
+
+	return ret;
+}
+
+bool TransformGizmo::isConstrainedToSingleAxis() {
+	if(transformConstraint.x == 1.0) {
+		if(transformConstraint.y == 0.0 && transformConstraint.z == 0.0)
+			return true;
+	}
+	if(transformConstraint.y == 1.0) {
+		if(transformConstraint.x == 0.0 && transformConstraint.z == 0.0)
+			return true;
+	}
+	if(transformConstraint.z == 1.0) {
+		if(transformConstraint.x == 0.0 && transformConstraint.y == 0.0)
+			return true;
+	}
+	return false;
+}
+
 void TransformGizmo::setTransformMode(int newMode) {
     
     transformMode = newMode;
@@ -754,18 +821,42 @@ void TransformGizmo::setTransformSelection(std::vector<Entity*> selectedEntities
     
 }
 
+void TransformGizmo::resetTransform() {
+	if(firstMove) return;
+	
+	for(int i=0; i < selectedEntities.size(); i++) {
+		selectedEntities[i]->setPosition(oldPosition[i]);
+		entityPositions[i] = oldPosition[i];
+		selectedEntities[i]->setScale(oldScale[i]);
+		selectedEntities[i]->setRotationByQuaternion(oldRotation[i]);
+	}
+	if(isConstrainedToSingleAxis())
+		startingPoint = getPositionAlongAxis();
+	else
+		startingPoint = getTransformPlanePosition();
+}
+
 void TransformGizmo::transformSelectedEntities(const Vector3 &move, const Vector3 &scale, Number rotate) {
     
     if(firstMove) {
         firstMove = false;
         dispatchEvent(new TrasnformGizmoEvent(mode), Event::SELECT_EVENT);
+		
+		oldPosition.clear();
+		oldScale.clear();
+		oldRotation.clear();
+		for(int i=0; i < selectedEntities.size(); i++) {
+			oldPosition.push_back(selectedEntities[i]->getPosition());
+			oldScale.push_back(selectedEntities[i]->getScale());
+			oldRotation.push_back(selectedEntities[i]->getRotationQuat());
+		}
     }
     
     Vector3 globalCenter = getConcatenatedMatrix().getPosition();
 	for(int i=0; i < selectedEntities.size(); i++) {
         
         
-        if((orientation == ORIENTATION_GLOBAL && mode != TRANSFORM_SCALE_VIEW) || (ORIENTATION_LOCAL && mode == TRANSFORM_MOVE_VIEW)) {
+        if((orientation == ORIENTATION_GLOBAL && mode != TRANSFORM_SCALE_VIEW)) {//|| (ORIENTATION_LOCAL && mode == TRANSFORM_MOVE_VIEW)) {
             entityPositions[i] += move;
             
             Quaternion q;
@@ -797,8 +888,8 @@ void TransformGizmo::transformSelectedEntities(const Vector3 &move, const Vector
                 if(move.length() == 0.0) {
                     entityPositions[i] = selectedEntities[i]->getPosition();
                 }
-                
-                selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+newScale));
+
+				selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+newScale));
                 
                 if(newScale.length() > 0.0) {
                     Vector3 scalePosition;
@@ -814,7 +905,10 @@ void TransformGizmo::transformSelectedEntities(const Vector3 &move, const Vector
                 
             } else {
                 selectedEntities[i]->setRotationByQuaternion(currentRotation * q);
-                selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+newScale));
+				if(mode == TRANSFORM_SCALE_VIEW)
+					selectedEntities[i]->setScale(oldScale[i] * scale);
+				else
+					selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+newScale));
             }
         } else {
             
@@ -825,7 +919,7 @@ void TransformGizmo::transformSelectedEntities(const Vector3 &move, const Vector
             Vector3 axisVector = transformConstraint;
             
             // always global in the 2d view
-            if(gizmoMode != GIZMO_MODE_3D || mode == TRANSFORM_ROTATE_VIEW) {
+            if(gizmoMode != GIZMO_MODE_3D) {
                 axisVector = currentRotation.Inverse().applyTo(axisVector);
             }
             axisVector.Normalize();
@@ -845,8 +939,11 @@ void TransformGizmo::transformSelectedEntities(const Vector3 &move, const Vector
                 if(move.length() == 0.0) {
                     entityPositions[i] = selectedEntities[i]->getPosition();
                 }
-                
-                selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+scale));
+                                
+                if(mode == TRANSFORM_SCALE_VIEW)
+					selectedEntities[i]->setScale(oldScale[i] * scale);
+				else
+					selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+scale));
                 
                 if(scale.length() > 0.0) {
                     Vector3 scalePosition;
@@ -862,7 +959,10 @@ void TransformGizmo::transformSelectedEntities(const Vector3 &move, const Vector
                 
             } else {
                 selectedEntities[i]->setRotationByQuaternion(currentRotation * q);
-                selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+scale));
+				if(mode == TRANSFORM_SCALE_VIEW)
+					selectedEntities[i]->setScale(oldScale[i] * scale);
+				else
+					selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+scale));
             }
 
             
@@ -916,6 +1016,34 @@ Number TransformGizmo::getTransformPlaneAngle() {
 	return atan2(planePosition.x, planePosition.y);
 }
 
+Vector2 TransformGizmo::getCorrectedMousePosition() {
+	Vector2 localMouse = CoreServices::getInstance()->getInput()->getMousePosition();
+	localMouse.x -= targetScene->sceneMouseRect.x;
+	localMouse.y -= targetScene->sceneMouseRect.y;
+	return localMouse;
+}
+
+Number TransformGizmo::get2dAngle() {
+	Polycode::Rectangle view = targetScene->sceneMouseRect;
+	Polycode::Rectangle camView = targetCamera->getViewport();
+	Vector2 origin = getScreenPosition(targetCamera->getProjectionMatrix(), targetCamera->getAnchorAdjustedMatrix(), camView);
+	Vector2 localStart = mouseStart2d - origin;
+	Vector2 localMouse = CoreServices::getInstance()->getInput()->getMousePosition();
+	localMouse.x -= view.x;
+	localMouse.y -= view.y;
+	localMouse -= origin;
+
+	Number ang = atan2(localStart.crossProduct(localMouse), localStart.dot(localMouse));
+	Number dot = targetCamera->getRotationQuat().applyTo(Vector3(0,0,-1)).dot(rotationQuat.applyTo(transformConstraint));
+	if(dot < 0.0)
+		ang *= -1.0;
+	else {
+		if(gizmoMode == GIZMO_MODE_2D_X || gizmoMode == GIZMO_MODE_2D_Y)
+			ang *= -1.0;
+	}
+	return ang;
+}
+
 void TransformGizmo::setGizmoMode(int newMode) {
     gizmoMode = newMode;
     setTransformMode(transformMode);
@@ -929,59 +1057,74 @@ void TransformGizmo::handleEvent(Event *event) {
 	if(!coreInput->getKeyState(KEY_LALT) && !coreInput->getKeyState(KEY_RALT)) {
 		if(event->getDispatcher() == pitchGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
-				transforming = true;
-				transformConstraint = Vector3(1.0, 0.0, 0.0);
-                setTransformPlane(1.0, 0.0, 0.0);
-				startingAngle = getTransformPlaneAngle();
+				if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
+					transforming = true;
+					transformConstraint = Vector3(1.0, 0.0, 0.0);
+					setTransformPlane(1.0, 0.0, 0.0);
+					mouseStart2d = getCorrectedMousePosition();
+					startingAngle = get2dAngle();
+				}
 			}
 		} else 	if(event->getDispatcher() == yawGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
-				transforming = true;
-				transformConstraint = Vector3(0.0, 1.0, 0.0);
-                setTransformPlane(0.0, 1.0, 0.0);
-				startingAngle = getTransformPlaneAngle();
+				if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
+					transforming = true;
+					transformConstraint = Vector3(0.0, 1.0, 0.0);
+					setTransformPlane(0.0, 1.0, 0.0);
+					mouseStart2d = getCorrectedMousePosition();
+					startingAngle = get2dAngle();
+				}
 			}
 		} else 	if(event->getDispatcher() == rollGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
-				transforming = true;
-				transformConstraint = Vector3(0.0, 0.0, -1.0);
-				setTransformPlane(0.0, 0.0, 1.0);
-				startingAngle = getTransformPlaneAngle();
+				if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
+					transforming = true;
+					transformConstraint = Vector3(0.0, 0.0, 1.0);
+					setTransformPlane(0.0, 0.0, -1.0);
+					mouseStart2d = getCorrectedMousePosition();
+					startingAngle = get2dAngle();
+				}
 			}
 		} else 	if(event->getDispatcher() == viewportRotateGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
-                if(gizmoMode != GIZMO_MODE_3D) {
-                    transforming = true;
-                    setTransformPlaneFromView();
-                    startingAngle = getTransformPlaneAngle();
-                }
+				if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
+					if(gizmoMode != GIZMO_MODE_3D) {
+						transforming = true;
+						setTransformPlaneFromView();
+						transformConstraint = transformPlane;
+						mouseStart2d = getCorrectedMousePosition();
+						startingAngle = get2dAngle();
+					}
+				}
 			}
 		}
 
 		if(event->getDispatcher() == xTransformGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
-				transforming = true;
-				transformConstraint = Vector3(1.0, 0.0, 0.0);
-                if(gizmoMode == GIZMO_MODE_3D) {
-                    setTransformPlane(0.0, 1.0, 0.0);
-                } else {
-                    setTransformPlane(0.0, 0.0, 1.0);
-                }
-				startingPoint = getTransformPlanePosition();
+				if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
+					transforming = true;
+					transformConstraint = Vector3(1.0, 0.0, 0.0);
+					setTransformPlane(true, false, false);
+					startingPoint = getTransformPlanePosition();
+				}
 			}
 		} else 	if(event->getDispatcher() == yTransformGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
-				transforming = true;
-				transformConstraint = Vector3(0.0, 1.0, 0.0);
-				setTransformPlane(0.0, 0.0, 1.0);
-				startingPoint = getTransformPlanePosition();
+				if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
+					transforming = true;
+					transformConstraint = Vector3(0.0, 1.0, 0.0);
+					setTransformPlane(false, true, false);
+					startingPoint = getTransformPlanePosition();
+				}
 			}
 		} else 	if(event->getDispatcher() == zTransformGrip) {
 			if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
-				transforming = true;
-				transformConstraint = Vector3(0.0, 0.0, 1.0);
-				setTransformPlane(0.0, 1.0, 0.0);
-				startingPoint = getTransformPlanePosition();
+				if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
+					transforming = true;
+					transformConstraint = Vector3(0.0, 0.0, 1.0);
+					setTransformPlane(false, false, true);
+					startingPoint = getTransformPlanePosition();
+				}
 			}		
 		}
 	}
@@ -994,34 +1137,144 @@ void TransformGizmo::handleEvent(Event *event) {
 				switch (inputEvent->key) {
 				case KEY_s:
 				{
-							  transforming = true;
-							  previousMode = mode;
-							  mode = TRANSFORM_SCALE_VIEW;
-							  setTransformPlaneFromView();
-							  startingPoint = getTransformPlanePosition();
-
+					transforming = true;
+					transformConstraint = Vector3(1.0, 1.0, 1.0);
+					previousMode = mode;
+					mode = TRANSFORM_SCALE_VIEW;
+					setTransformPlaneFromView();
+					startingPoint = getTransformPlanePosition();
+					mouseStart2d = getCorrectedMousePosition();
+					scaleAmount = 0.0;
+					resetTransform();
 				}
 					break;
 				case KEY_r:
 				{
-							  previousMode = mode;
-							  mode = TRANSFORM_ROTATE_VIEW;
-							  transforming = true;
-							  setTransformPlaneFromView();
-							  transformConstraint = transformPlane;
-							  if (gizmoMode == GIZMO_MODE_2D_Z) {
-								  transformConstraint = transformConstraint * -1.0;
-							  }
-							  startingAngle = getTransformPlaneAngle();
+					previousMode = mode;
+					mode = TRANSFORM_ROTATE_VIEW;
+					transforming = true;
+					transformConstraint = Vector3(1.0, 1.0, 1.0);
+					setTransformPlaneFromView();
+					transformConstraint = transformPlane;
+					mouseStart2d = getCorrectedMousePosition();
+					startingAngle = get2dAngle();
+					resetTransform();
 				}
 					break;
 				case KEY_g:
 				{
-							  previousMode = mode;
-							  mode = TRANSFORM_MOVE_VIEW;
-							  transforming = true;
-							  setTransformPlaneFromView();
-							  startingPoint = getTransformPlanePosition();
+					previousMode = mode;
+					mode = TRANSFORM_MOVE_VIEW;
+					transforming = true;
+					transformConstraint = Vector3(1.0, 1.0, 1.0);
+					setTransformPlaneFromView();
+					startingPoint = getTransformPlanePosition();
+					resetTransform();
+				}
+					break;
+				case KEY_x:
+				{
+					if(transforming && (mode == TRANSFORM_MOVE_VIEW || mode == TRANSFORM_SCALE_VIEW || ((mode == TRANSFORM_ROTATE_VIEW) && (gizmoMode == GIZMO_MODE_3D)))) {
+						if((coreInput->getKeyState(KEY_LSHIFT) || coreInput->getKeyState(KEY_RSHIFT)) && (mode != TRANSFORM_ROTATE_VIEW) && ((gizmoMode == GIZMO_MODE_2D_X) || (gizmoMode == GIZMO_MODE_3D))) {
+							if(transformConstraint != Vector3(0.0, 1.0, 1.0)) {
+								transformConstraint = Vector3(0.0, 1.0, 1.0);
+								setTransformPlane(false, true, true);
+								resetTransform();
+							} else {
+								toggleOrientation();
+								resetTransform();
+							}
+						} else if(gizmoMode != GIZMO_MODE_2D_X){
+							if(transformConstraint != Vector3(1.0, 0.0, 0.0)) {
+								transformConstraint = Vector3(1.0, 0.0, 0.0);
+								setTransformPlane(true, false, false);
+								resetTransform();
+							} else {
+								switch(gizmoMode) {
+									case GIZMO_MODE_3D:
+										toggleOrientation();
+										break;
+									case GIZMO_MODE_2D_Y:
+										transformConstraint = Vector3(1.0, 0.0, 1.0);
+										break;
+									case GIZMO_MODE_2D_Z:
+										transformConstraint = Vector3(1.0, 1.0, 0.0);
+										break;
+								}
+								resetTransform();
+							}
+						}
+					}	
+				}
+					break;
+				case KEY_y:
+				{
+					if(transforming && (mode == TRANSFORM_MOVE_VIEW || mode == TRANSFORM_SCALE_VIEW || ((mode == TRANSFORM_ROTATE_VIEW) && (gizmoMode == GIZMO_MODE_3D)))) {
+						if((coreInput->getKeyState(KEY_LSHIFT) || coreInput->getKeyState(KEY_RSHIFT)) && (mode != TRANSFORM_ROTATE_VIEW) && ((gizmoMode == GIZMO_MODE_2D_Y) || (gizmoMode == GIZMO_MODE_3D))) {
+							if(transformConstraint != Vector3(1.0, 0.0, 1.0)) {
+								transformConstraint = Vector3(1.0, 0.0, 1.0);
+								setTransformPlane(true, false, true);
+								resetTransform();
+							} else {
+								toggleOrientation();
+								resetTransform();
+							}
+						} else if(gizmoMode != GIZMO_MODE_2D_Y){
+							if(transformConstraint != Vector3(0.0, 1.0, 0.0)) {
+								transformConstraint = Vector3(0.0, 1.0, 0.0);
+								setTransformPlane(false, true, false);
+								resetTransform();
+							} else {
+								switch(gizmoMode) {
+									case GIZMO_MODE_3D:
+										toggleOrientation();
+										break;
+									case GIZMO_MODE_2D_X:
+										transformConstraint = Vector3(0.0, 1.0, 1.0);
+										break;
+									case GIZMO_MODE_2D_Z:
+										transformConstraint = Vector3(1.0, 1.0, 0.0);
+										break;
+								}
+								resetTransform();
+							}
+						}
+					}	
+				}
+					break;
+				case KEY_z:
+				{
+					if(transforming && (mode == TRANSFORM_MOVE_VIEW || mode == TRANSFORM_SCALE_VIEW || ((mode == TRANSFORM_ROTATE_VIEW) && (gizmoMode == GIZMO_MODE_3D)))) {
+						if((coreInput->getKeyState(KEY_LSHIFT) || coreInput->getKeyState(KEY_RSHIFT)) && (mode != TRANSFORM_ROTATE_VIEW) && ((gizmoMode == GIZMO_MODE_2D_Z) || (gizmoMode == GIZMO_MODE_3D))) {
+							if(transformConstraint != Vector3(1.0, 1.0, 0.0)) {
+								transformConstraint = Vector3(1.0, 1.0, 0.0);
+								setTransformPlane(true, true, false);
+								resetTransform();
+							} else {
+								toggleOrientation();
+								resetTransform();
+							}
+						} else if(gizmoMode != GIZMO_MODE_2D_Z){
+							if(transformConstraint != Vector3(0.0, 0.0, 1.0)) {
+								transformConstraint = Vector3(0.0, 0.0, 1.0);
+								setTransformPlane(false, false, true);
+								resetTransform();
+							} else {
+								switch(gizmoMode) {
+									case GIZMO_MODE_3D:
+										toggleOrientation();
+										break;
+									case GIZMO_MODE_2D_X:
+										transformConstraint = Vector3(0.0, 1.0, 1.0);
+										break;
+									case GIZMO_MODE_2D_Y:
+										transformConstraint = Vector3(1.0, 0.0, 1.0);
+										break;
+								}
+								resetTransform();
+							}
+						}
+					}	
 				}
 					break;
 				case KEY_ESCAPE:
@@ -1030,6 +1283,7 @@ void TransformGizmo::handleEvent(Event *event) {
 									   dispatchEndEvent();
 									   mode = previousMode;
 								   }
+								   resetTransform();
 								   transforming = false;
 								   firstMove = true;
 				}
@@ -1045,38 +1299,40 @@ void TransformGizmo::handleEvent(Event *event) {
                     switch(mode) {
                         case TRANSFORM_MOVE:
                         {
-                            Vector3 newPoint = getTransformPlanePosition();
+							Vector3 newPoint;
+							if(isConstrainedToSingleAxis())
+								newPoint = getPositionAlongAxis();
+							else
+								newPoint = getTransformPlanePosition();
+
                             Vector3 diff = (planeMatrix.Inverse() * newPoint) -(planeMatrix.Inverse() * startingPoint);
                             diff = diff * getCompoundScale();                                                        
                             transformSelectedEntities(transformConstraint * diff, Vector3(0.0, 0.0, 0.0), 0.0);
                             startingPoint = newPoint;
                         }
                         break;
-                        case TRANSFORM_MOVE_VIEW:
-                        {
-                            Vector3 newPoint = getTransformPlanePosition();
-                            Vector3 diff = newPoint - startingPoint;
-                            
-                            transformSelectedEntities(diff, Vector3(0.0, 0.0, 0.0), 0.0);
-                            startingPoint = newPoint;
-                        }
-                        break;
                         case TRANSFORM_SCALE_VIEW:
                         {
-                            Vector3 newPoint = getTransformPlanePosition();
-                            
-                            Number scaleMult = 1.0;
-                            if(newPoint.distance(gizmoPoint) < startingPoint.distance(gizmoPoint)) {
-                                scaleMult = -1.0;
-                            }
-                            
-                            transformSelectedEntities(Vector3(0.0, 0.0, 0.0), (Vector3(1.0, 1.0, 1.0) * (newPoint-startingPoint).length() * scaleMult) / getCompoundScale().x, 0.0);
-                            startingPoint = newPoint;
+							Vector2 pos2d = getScreenPosition(targetCamera->getProjectionMatrix(), targetCamera->getAnchorAdjustedMatrix(), targetCamera->getViewport());
+							Vector2 currentMouse = getCorrectedMousePosition();
+
+							Number scaleNew = currentMouse.distance(pos2d) / mouseStart2d.distance(pos2d);
+							
+							Vector3 scaleVec = transformConstraint * scaleNew;
+							scaleAmount = scaleNew;
+							if((mouseStart2d - pos2d).dot(currentMouse - pos2d) < 0.0)
+								scaleVec = -scaleVec;
+
+							scaleVec.x =  (transformConstraint.x == 0.0) ? 1.0 : scaleVec.x;
+							scaleVec.y =  (transformConstraint.y == 0.0) ? 1.0 : scaleVec.y;
+							scaleVec.z =  (transformConstraint.z == 0.0) ? 1.0 : scaleVec.z;
+
+                            transformSelectedEntities(Vector3(0.0, 0.0, 0.0), scaleVec, 0.0);
                         }
                         break;
                         case TRANSFORM_ROTATE_VIEW:
                         {
-                            Number newAngle = getTransformPlaneAngle();
+                            Number newAngle = get2dAngle();
                             
                             Vector3 newPoint = planeMatrix.Inverse() *getTransformPlanePosition();
                             
@@ -1084,6 +1340,19 @@ void TransformGizmo::handleEvent(Event *event) {
                             startingAngle = newAngle;
                         }
                         break;
+                        case TRANSFORM_MOVE_VIEW:
+                        {
+                            Vector3 newPoint;
+							if(isConstrainedToSingleAxis())
+								newPoint = getPositionAlongAxis();
+							else
+								newPoint = getTransformPlanePosition();
+
+							Vector3 diff = newPoint - startingPoint;
+                            transformSelectedEntities(transformConstraint * diff, Vector3(0.0, 0.0, 0.0), 0.0);
+                            startingPoint = newPoint;
+                        }
+                        break;
                         case TRANSFORM_SCALE:
                         {
                             Vector3 newPoint = getTransformPlanePosition();
@@ -1098,7 +1367,7 @@ void TransformGizmo::handleEvent(Event *event) {
                         break;
                         case TRANSFORM_ROTATE:
                         {
-                            Number newAngle = getTransformPlaneAngle();
+                            Number newAngle = get2dAngle();
                             transformSelectedEntities(Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), newAngle - startingAngle);
                             startingAngle = newAngle;						
                         }
@@ -1113,6 +1382,10 @@ void TransformGizmo::handleEvent(Event *event) {
                     if(mode == TRANSFORM_SCALE_VIEW || mode == TRANSFORM_ROTATE_VIEW || mode == TRANSFORM_MOVE_VIEW) {
                         mode = previousMode;
                     }
+					if( orientation != startingOrientation && startingOrientation != -1) {
+						orientation = startingOrientation;
+						startingOrientation = -1;
+					}
                     transforming = false;
                     firstMove = true;
                 }
@@ -1150,8 +1423,9 @@ void TransformGizmo::updateOrientationForEntity(Entity *entity) {
             setRotationByQuaternion(q);
         break;
         case ORIENTATION_LOCAL:
-            q = entity->getRotationQuat();
-            setRotationByQuaternion(q);
+			if(gizmoMode == GIZMO_MODE_3D || mode == TRANSFORM_SCALE)
+				q = entity->getRotationQuat();
+			setRotationByQuaternion(q);				
         break;
     }
 }