فهرست منبع

Added a grid and transform gizmo to the 3d editor, added 2d circle primitive type to ScenePrimitive, added plane intersection test to Ray

Ivan Safrin 12 سال پیش
والد
کامیت
72f3e20460

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

@@ -320,6 +320,13 @@ namespace Polycode {
 			*/									
 			void Scale(Number x, Number y, Number z=0.0);
 			
+
+			/**
+			* Scales the entity relative to its current scale.
+			@param scale Scale vector.				
+			*/									
+			void Scale(const Vector3 &scale);			
+
 			/**
 			* Sets the entity's scale.
 			@param x X-axis value.

+ 8 - 0
Core/Contents/Include/PolyMesh.h

@@ -197,6 +197,14 @@ namespace Polycode {
 			*/ 
 			void createVPlane(Number w, Number h);
 
+			/**
+			* Creates a 2D circle.
+			* @param w Width of circle.
+			* @param h Height of plane.			
+			* @param numSegments Number of segments 			
+			*/ 
+			void createCircle(Number w, Number h, unsigned int numSegments);
+
 			/**
 			* Creates a torus.
 			* @param radius Radius of the torus.

+ 3 - 1
Core/Contents/Include/PolyRay.h

@@ -35,7 +35,9 @@ namespace Polycode {
 			Ray();
 			Ray(const Vector3 &origin, const Vector3 &direction);
 	
-			bool boxIntersect(const Vector3 &box, const Matrix4 &transformMatrix, float near = 0.0, float far = 9999.0) const;			
+			bool boxIntersect(const Vector3 &box, const Matrix4 &transformMatrix, float near = 0.0, float far = 9999.0) const;
+			
+			Vector3 planeIntersectPoint(const Vector3 &planeNormal, Number planeDistance) const;
 			Ray tranformByMatrix(const Matrix4& matrix) const;
 		
 			Vector3 origin;

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

@@ -130,6 +130,8 @@ namespace Polycode {
 		
 		void handleEvent(Event *event);
 		
+		Ray projectRayFromCameraAndViewportCoordinate(Camera *camera, Vector2 coordinate);
+		
 		/**
 		* Adds a light to the scene.
 		* @param light Light to add to the scene.

+ 9 - 0
Core/Contents/Include/PolyScenePrimitive.h

@@ -113,6 +113,15 @@ namespace Polycode {
 			* v3 - Number of segments.
 			*/			
 			static const int TYPE_UNCAPPED_CYLINDER = 7;
+
+			/**
+			* A 2D circle.
+			* v1 - X size
+			* v2 - Y size
+			* v3 - Number of segments
+			*/			
+			static const int TYPE_CIRCLE = 8;			
+
 							
 		
 		protected:

+ 5 - 0
Core/Contents/Include/PolyVector3.h

@@ -88,6 +88,11 @@ namespace Polycode {
 				return Vector3(x * val, y * val, z * val);
 			}
 
+			inline Vector3 operator * (const Vector3 &v2) const {
+				return Vector3(x * v2.x, y * v2.y, z * v2.z);
+			}
+
+
 			inline Vector3 operator / (const Number val) const {
 				assert( val != 0.0 );
 				return operator*(1/val);

+ 7 - 1
Core/Contents/Source/PolyEntity.cpp

@@ -620,7 +620,8 @@ Matrix4 Entity::getConcatenatedMatrixRelativeTo(Entity *relativeEntity) {
 Matrix4 Entity::getAnchorAdjustedMatrix() {
 	Matrix4 mat = getConcatenatedMatrix();
 	Matrix4 adjust;
-	adjust.setPosition(-anchorPoint.x * bBox.x * 0.5, -anchorPoint.y * bBox.y * 0.5 * yAdjust, -anchorPoint.z * bBox.z * 0.5);
+	Vector3 compoundScale = getCompoundScale();
+	adjust.setPosition(-anchorPoint.x * bBox.x * 0.5 * compoundScale.x, -anchorPoint.y * bBox.y * 0.5 * yAdjust * compoundScale.y, -anchorPoint.z * bBox.z * 0.5 * compoundScale.z);
 	return mat * adjust;
 }
 
@@ -816,6 +817,11 @@ void Entity::Translate(Number x, Number y, Number z) {
 	matrixDirty = true;
 }
 
+void Entity::Scale(const Vector3 &scale) {
+	this->scale = this->scale * scale;
+	matrixDirty = true;
+}
+
 void Entity::Scale(Number x, Number y, Number z) {
 	scale.x *= x;
 	scale.y *= y;

+ 29 - 0
Core/Contents/Source/PolyMesh.cpp

@@ -265,6 +265,35 @@ namespace Polycode {
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 	}
+
+	void Mesh::createCircle(Number w, Number h, unsigned int numSegments) {
+		setMeshType(Mesh::TRIFAN_MESH);
+		Polygon *poly = new Polygon();
+		int step;
+		if(numSegments > 0) {
+				step = ceil(360/numSegments);
+		} else {
+				step = 1;
+		}
+		
+  
+		poly->addVertex(cosf(0)*(w/2),sinf(0)*(h/2), 0, (cosf(0)*0.5) + 0.5,(sinf(0) * 0.5)+ 0.5);		
+		for (int i=0; i < 361; i+= step) {
+				Number degInRad = i*TORADIANS;
+				Vertex *v = poly->addVertex(cos(degInRad)*(w/2),sin(degInRad)*(h/2), 0, (cos(degInRad) * 0.5)+ 0.5 , 1.0- ((sin(degInRad) * 0.5)+ 0.5));
+				Vector3 normal = *v; 
+				normal.Normalize();
+				v->normal = normal;
+		}
+		
+		addPolygon(poly);
+		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
+		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
+		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
+		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;			
+	}
+	
 	
 	void Mesh::createVPlane(Number w, Number h) { 
 		Polygon *imagePolygon = new Polygon();

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

@@ -50,6 +50,10 @@ Ray Ray::tranformByMatrix(const Matrix4& matrix) const {
 	return Ray(pos, dir);
 }
 
+Vector3 Ray::planeIntersectPoint(const Vector3 &planeNormal, Number planeDistance) const {
+	Number distanceToOrigin = origin.dot(planeNormal) - planeDistance;
+	 return origin + direction * (-distanceToOrigin / direction.dot(planeNormal));
+}
 
 bool Ray::boxIntersect(const Vector3 &box, const Matrix4 &transformMatrix, float near, float far) const {	
 

+ 32 - 25
Core/Contents/Source/PolyScene.cpp

@@ -265,34 +265,41 @@ void Scene::RenderDepthOnly(Camera *targetCamera) {
 	CoreServices::getInstance()->getRenderer()->cullFrontFaces(false);	
 }
 
+Ray Scene::projectRayFromCameraAndViewportCoordinate(Camera *camera, Vector2 coordinate) {
+
+	Polycode::Rectangle viewport = camera->getViewport();
+	viewport.x = sceneMouseAdjust.x;
+	viewport.y = sceneMouseAdjust.y;
+	Vector3 dir =  renderer->projectRayFrom2DCoordinate(coordinate.x, coordinate.y, 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;	
+		}
+		break;
+		case SCENE_2D_TOPLEFT:
+			pos = Vector3(coordinate.x, core->getYRes()-coordinate.y, 0.0);
+			pos = camera->getConcatenatedMatrix() * pos;			
+		break;
+		case SCENE_3D:
+			pos = camera->getConcatenatedMatrix().getPosition();
+		break;		
+	}
+
+	return Ray(pos, dir);
+}
+
+
 void Scene::handleEvent(Event *event) {
 	if(event->getDispatcher() == core->getInput() && rootEntity.processInputEvents) {
 		InputEvent *inputEvent = (InputEvent*) event;
-		Polycode::Rectangle viewport = activeCamera->getViewport();
-		viewport.x = sceneMouseAdjust.x;
-		viewport.y = sceneMouseAdjust.y;
-		Vector3 dir =  renderer->projectRayFrom2DCoordinate(inputEvent->mousePosition.x, inputEvent->mousePosition.y, activeCamera->getConcatenatedMatrix(), activeCamera->getProjectionMatrix(), viewport);
-		Vector3 pos;
-		
-		switch(sceneType) {
-			case SCENE_2D:
-			{
-				Number orthoSizeX = activeCamera->getOrthoSizeX();
-				Number orthoSizeY = activeCamera->getOrthoSizeY();			
-				pos = Vector3(((inputEvent->mousePosition.x/(Number)core->getXRes())*orthoSizeX) - (orthoSizeX*0.5), (((core->getYRes()-inputEvent->mousePosition.y)/(Number)core->getYRes())*orthoSizeY) - (orthoSizeY*0.5), 0.0);
-				pos = activeCamera->getConcatenatedMatrix() * pos;	
-			}
-			break;
-			case SCENE_2D_TOPLEFT:
-				pos = Vector3(inputEvent->mousePosition.x, core->getYRes()-inputEvent->mousePosition.y, 0.0);
-				pos = activeCamera->getConcatenatedMatrix() * pos;			
-			break;
-			case SCENE_3D:
-				pos = activeCamera->getConcatenatedMatrix().getPosition();
-			break;		
-		}
-				
-		Ray ray(pos, dir);
+
+		Ray ray = projectRayFromCameraAndViewportCoordinate(activeCamera, inputEvent->mousePosition);
 		
 		switch(inputEvent->getEventCode()) {
 			case InputEvent::EVENT_MOUSEDOWN:

+ 6 - 0
Core/Contents/Source/PolyScenePrimitive.cpp

@@ -88,6 +88,12 @@ void ScenePrimitive::recreatePrimitive() {
 			bBox.y = v2;
 			bBox.z = v1*2;						
 		break;						
+		case TYPE_CIRCLE:
+			mesh->createCircle(v1, v2, v3);
+			bBox.x = v1;
+			bBox.y = v2;
+			bBox.z = 0.001;
+		break;
 	}
 }
 

+ 53 - 1
IDE/Contents/Include/PolycodeEntityEditor.h

@@ -32,10 +32,59 @@ using namespace Polycode;
 
 class TransformGizmo : public Entity {
 	public:
-		TransformGizmo();
+		TransformGizmo(Scene *targetScene, Camera *targetCamera);
 		~TransformGizmo();
 		
+		void handleEvent(Event *event);		
 		
+		void setTransformMode(int newMode);
+		
+		void Update();
+		
+		void setTransformSelection(std::vector<Entity*> selectedEntities);
+		
+		void transfromSelectedEntities(const Vector3 &move, const Vector3 &scale);	
+		Vector3 getTransformPlanePosition();
+		
+		static const int TRANSFORM_MOVE = 0;		
+		static const int TRANSFORM_SCALE = 1;
+		static const int TRANSFORM_ROTATE = 2;
+								
+	private:
+	
+		std::vector<Entity*> selectedEntities;
+	
+		Scene *targetScene;
+		Camera *targetCamera;
+	
+		CoreInput *coreInput;
+		int mode;
+		bool transforming;
+		
+		Vector3 transformConstraint;
+		Vector3 transformPlane;
+				
+		Vector3 startingPoint;
+					
+		Entity *trasnformDecorators;
+		Entity *scaleDecorators;
+		Entity *transformAndScaleLines;			
+		Entity *rotateDectorators;	
+							
+		Entity *xTransformGrip;
+		Entity *yTransformGrip;
+		Entity *zTransformGrip;				
+};
+
+class EditorGrid : public Entity {
+	public:
+		EditorGrid();
+		~EditorGrid();
+		
+		void setGrid(int gridSize);
+		
+	private:
+		SceneMesh *grid;
 };
 
 class EntityEditorMainView : public UIElement {
@@ -52,12 +101,15 @@ class EntityEditorMainView : public UIElement {
 			Entity *sideBar;
 			UIRect *headerBg;	
 			
+			std::vector<Entity*> selectedEntities;
+			
 			Scene *mainScene;
 			SceneRenderTexture *renderTexture;
 			UIRect *renderTextureShape;			
 
 			TransformGizmo *transformGizmo;
 			TrackballCamera *trackballCamera;
+			EditorGrid *grid;
 			
 };
 

+ 12 - 0
IDE/Contents/Resources/Materials/OneSidedLine.frag

@@ -0,0 +1,12 @@
+varying vec4 vertexColor;
+varying vec3 normal;
+varying vec4 pos;
+
+void main()
+{
+	if(dot(pos.xyz * -1.0, normal) < 0.0) {
+		discard;
+	}
+
+    gl_FragColor = vertexColor;
+}

+ 17 - 0
IDE/Contents/Resources/Materials/utils.mat

@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<polycode_material_library>
+    <shaders>
+        <shader type="glsl" name="OneSidedLine" numAreaLights="0" numSpotLights="0" screen="false">
+            <vp source="default/DefaultShader.vert" />
+            <fp source="Materials/OneSidedLine.frag" />
+        </shader>
+    </shaders>
+    <cubemaps />
+    <materials>
+        <material name="OneSidedLine" blendingMode="0">
+            <shader name="OneSidedLine">
+                <textures />
+            </shader>
+        </material>
+    </materials>
+</polycode_material_library>

+ 313 - 16
IDE/Contents/Source/PolycodeEntityEditor.cpp

@@ -22,8 +22,25 @@
  
 #include "PolycodeEntityEditor.h"
 
-TransformGizmo::TransformGizmo() : Entity() {
+TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entity() {
+	processInputEvents = true;
+	
+	this->targetScene = targetScene;
+	this->targetCamera = targetCamera;
+	
+	trasnformDecorators = new Entity();
+	addChild(trasnformDecorators);
+	
+	scaleDecorators = new Entity();
+	addChild(scaleDecorators);
+		
+	transformAndScaleLines = new Entity();
+	addChild(transformAndScaleLines);
 		
+	rotateDectorators = new Entity();
+	addChild(rotateDectorators);	
+	
+			
 	SceneMesh *yLine = new SceneMesh(Mesh::LINE_MESH);	
 	Polycode::Polygon *poly = new Polycode::Polygon();
 	poly->addVertex(0.0, 0.0, 0.0);
@@ -32,7 +49,7 @@ TransformGizmo::TransformGizmo() : Entity() {
 	yLine->getMesh()->dirtyArrays();
 	yLine->depthTest = false;
 	yLine->setColor(0.0, 1.0, 0.0, 1.0);
-	addChild(yLine);
+	transformAndScaleLines->addChild(yLine);
 
 	SceneMesh *xLine = new SceneMesh(Mesh::LINE_MESH);	
 	poly = new Polycode::Polygon();
@@ -42,7 +59,7 @@ TransformGizmo::TransformGizmo() : Entity() {
 	xLine->getMesh()->dirtyArrays();
 	xLine->depthTest = false;
 	xLine->setColor(1.0, 0.0, 0.0, 1.0);
-	addChild(xLine);
+	transformAndScaleLines->addChild(xLine);
 
 	SceneMesh *zLine = new SceneMesh(Mesh::LINE_MESH);	
 	poly = new Polycode::Polygon();
@@ -52,34 +69,311 @@ TransformGizmo::TransformGizmo() : Entity() {
 	zLine->getMesh()->dirtyArrays();
 	zLine->depthTest = false;
 	zLine->setColor(0.0, 0.0, 1.0, 1.0);
-	addChild(zLine);
+	transformAndScaleLines->addChild(zLine);
+	
+	// MOVE
 	
 	ScenePrimitive *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;
-	addChild(yArrow);
+	trasnformDecorators->addChild(yArrow);
 	
 	ScenePrimitive *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;
-	addChild(xArrow);
+	trasnformDecorators->addChild(xArrow);
 
 	ScenePrimitive *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);
 	zArrow->depthTest = false;	
-	addChild(zArrow);
+	trasnformDecorators->addChild(zArrow);
+
+	// SCALE
+
+	ScenePrimitive *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->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->setColor(0.0, 0.0, 1.0, 1.0);
+	zBox->setPosition(0.0, 0.0, 1.0);
+	zBox->Pitch(90);
+	zBox->depthTest = false;	
+	scaleDecorators->addChild(zBox);
+
+	// ROTATE
+
+	ScenePrimitive *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;
+	bgCircle->billboardMode = true;
+	rotateDectorators->addChild(bgCircle);
+
+	ScenePrimitive *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;
+	outerCircle->billboardMode = true;
+	rotateDectorators->addChild(outerCircle);
+	
+	ScenePrimitive *pitchCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.6, 1.6, 32);
+	pitchCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
+	pitchCircle->setColor(1.0, 0.0, 0.0, 1.0);
+	pitchCircle->depthTest = false;
+	pitchCircle->Yaw(90);	
+	rotateDectorators->addChild(pitchCircle);
+	pitchCircle->setMaterialByName("OneSidedLine");
+
+	ScenePrimitive *yawCircle = new ScenePrimitive(ScenePrimitive::TYPE_CIRCLE, 1.6, 1.6, 32);
+	yawCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
+	yawCircle->setColor(0.0, 1.0, 0.0, 1.0);
+	yawCircle->depthTest = false;
+	yawCircle->Pitch(90);
+	rotateDectorators->addChild(yawCircle);
+	yawCircle->setMaterialByName("OneSidedLine");
+	
+	ScenePrimitive *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;
+	rotateDectorators->addChild(rollCircle);
+	rollCircle->setMaterialByName("OneSidedLine");
+		
+	pitchCircle->lineWidth = 2.0;	
+	yawCircle->lineWidth = 2.0;
+	rollCircle->lineWidth = 2.0;		
+	
+	xTransformGrip = new Entity();
+	xTransformGrip->bBox.set(1.3, 0.1, 0.1);
+	addChild(xTransformGrip);
+	xTransformGrip->setAnchorPoint(Vector3(-1.0, 0.0, 0.0));
+	xTransformGrip->processInputEvents = true;
+	xTransformGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+
+	yTransformGrip = new Entity();
+	yTransformGrip->bBox.set(0.1, 1.3, 0.1);
+	addChild(yTransformGrip);
+	yTransformGrip->setAnchorPoint(Vector3(0.0, -1.0, 0.0));
+	yTransformGrip->processInputEvents = true;
+	yTransformGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+
+	zTransformGrip = new Entity();
+	zTransformGrip->bBox.set(0.1, 0.1, 1.3);
+	addChild(zTransformGrip);
+	zTransformGrip->setAnchorPoint(Vector3(0.0, 0.0, -1.0));
+	zTransformGrip->processInputEvents = true;
+	zTransformGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+
+
+		
+	transforming = false;
+	mode = TRANSFORM_MOVE;
+	
+	visible = false;
+	enabled = false;
+	
+	coreInput = CoreServices::getInstance()->getCore()->getInput();
+	coreInput->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
+	coreInput->addEventListener(this, InputEvent::EVENT_MOUSEUP);	
+	
+	setTransformMode(TRANSFORM_MOVE);
+}
+
+Vector3 TransformGizmo::getTransformPlanePosition() {
+
+	Number planeDistance = 0;
+	if(transformPlane.x > 0) {
+		planeDistance = getPosition().x;
+	} else if(transformPlane.y > 0.0) {
+		planeDistance = getPosition().y;	
+	} else if(transformPlane.z > 0.0) {
+		planeDistance = getPosition().z;	
+	}
+	Ray ray = targetScene->projectRayFromCameraAndViewportCoordinate(targetCamera, coreInput->getMousePosition());	
+	
+	return ray.planeIntersectPoint(transformPlane, planeDistance);
+}
+
+void TransformGizmo::setTransformMode(int newMode) {
+
+	trasnformDecorators->visible = false;
+	scaleDecorators->visible = false;
+	transformAndScaleLines->visible = false;
+	rotateDectorators->visible = false;
+	xTransformGrip->enabled = false;
+	yTransformGrip->enabled = false;
+	zTransformGrip->enabled = false;
+			
+	mode = newMode;
+	switch (mode) {
+		case TRANSFORM_MOVE:
+			trasnformDecorators->visible = true;
+			transformAndScaleLines->visible = true;
+			xTransformGrip->enabled = true;
+			yTransformGrip->enabled = true;
+			zTransformGrip->enabled = true;						
+		break;
+		case TRANSFORM_SCALE:
+			scaleDecorators->visible = true;
+			transformAndScaleLines->visible = true;					
+			xTransformGrip->enabled = true;
+			yTransformGrip->enabled = true;
+			zTransformGrip->enabled = true;				
+		break;	
+		case TRANSFORM_ROTATE:
+			rotateDectorators->visible = true;
+		break;
+		default:
+			assert(false); // invalid mode
+		break;
+	}
+}
+
+void TransformGizmo::setTransformSelection(std::vector<Entity*> selectedEntities) {
+	this->selectedEntities = selectedEntities;
+	if(selectedEntities.size() > 0) {
+		visible = true;
+		enabled = true;
+		
+		Vector3 centerPoint;
+		for(int i=0; i < selectedEntities.size(); i++) {
+			centerPoint += selectedEntities[i]->getConcatenatedMatrix().getPosition();			
+		}
+		centerPoint = centerPoint / selectedEntities.size();
+		setPosition(centerPoint);
+	} else {
+		visible = false;
+		enabled = false;
+	}
+	
+}
+
+void TransformGizmo::transfromSelectedEntities(const Vector3 &move, const Vector3 &scale) {
+	for(int i=0; i < selectedEntities.size(); i++) {
+		selectedEntities[i]->Translate(move);
+		selectedEntities[i]->setScale(selectedEntities[i]->getScale() + scale);
+	}
+	Translate(move);
+}
+
+void TransformGizmo::handleEvent(Event *event) {
+	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);
+			startingPoint = getTransformPlanePosition();
+		}
+	} else 	if(event->getDispatcher() == yTransformGrip) {
+		if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
+			transforming = true;
+			transformConstraint = Vector3(0.0, 1.0, 0.0);
+			transformPlane = Vector3(0.0, 0.0, 1.0);			
+			startingPoint = getTransformPlanePosition();
+		}
+	} else 	if(event->getDispatcher() == zTransformGrip) {
+		if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
+			transforming = true;
+			transformConstraint = Vector3(0.0, 0.0, 1.0);
+			transformPlane = Vector3(0.0, 1.0, 0.0);			
+			startingPoint = getTransformPlanePosition();
+		}		
+	} else if(event->getDispatcher() == coreInput && transforming) {
+		InputEvent *inputEvent = (InputEvent*) event;
+		switch(event->getEventCode()) {
+			case InputEvent::EVENT_MOUSEMOVE:
+			{
+				switch(mode) {
+					case TRANSFORM_MOVE:
+					{
+						Vector3 newPoint = getTransformPlanePosition();
+						transfromSelectedEntities((newPoint-startingPoint) * transformConstraint, Vector3(0.0, 0.0, 0.0));
+						startingPoint = newPoint;
+					}
+					break;
+					case TRANSFORM_SCALE:
+					{
+						Vector3 newPoint = getTransformPlanePosition();
+						transfromSelectedEntities(Vector3(0.0, 0.0, 0.0), ((newPoint-startingPoint) * transformConstraint));
+						startingPoint = newPoint;					
+					}
+					break;
+				}
+			}
+			break;
+			case InputEvent::EVENT_MOUSEUP:
+			{
+				transforming = false;
+			}
+			break;
+		}
+	}
 }
 
 TransformGizmo::~TransformGizmo() {
 
 }
 
+void TransformGizmo::Update() {
+	Number scale = getPosition().distance(targetCamera->getPosition()) * 0.1;
+	setScale(scale, scale, scale);
+}
+
+EditorGrid::EditorGrid() : Entity() {
+	grid = NULL;
+	setGrid(1.0);
+	setPitch(90);
+}
+
+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);
+	}
+
+	for(int y=0; y < gridLen+1; y++) {
+			gridPoly->addVertex(0, y * gridSize, 0);
+			gridPoly->addVertex(gridSize * gridLen, y * gridSize, 0);                
+	}        
+
+	if(grid) {
+			grid->getMesh()->clearMesh();
+			grid->getMesh()->addPolygon(gridPoly);
+	} else {
+			Mesh *gridMesh = new Mesh(Mesh::LINE_MESH);
+			gridMesh->addPolygon(gridPoly);
+				
+			grid = new SceneMesh(gridMesh);
+			grid->setColor(1.0, 1.0, 1.0, 0.1);
+			addChild(grid);                
+			grid->setPosition(-gridSize * gridLen * 0.5, -gridSize * gridLen * 0.5);
+	}
+}
+
+
+EditorGrid::~EditorGrid() {
+
+}
+
+
 EntityEditorMainView::EntityEditorMainView() {
 	processInputEvents = true;
 
@@ -110,6 +404,9 @@ EntityEditorMainView::EntityEditorMainView() {
 	
 	mainScene->getDefaultCamera()->setPosition(10, 10, 10);
 	mainScene->getDefaultCamera()->lookAt(Vector3());
+
+	grid = new EditorGrid();
+	mainScene->addChild(grid);
 			
 	// TEMPORARY!	
 	
@@ -121,16 +418,15 @@ EntityEditorMainView::EntityEditorMainView() {
 	testCube->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
 	testCube->wireFrameColor = Color(1.0, 0.8, 0.3, 1.0);
 	
-	transformGizmo = new TransformGizmo();
-	mainScene->addChild(transformGizmo);
-	transformGizmo->visible = false;
-	
+	transformGizmo = new TransformGizmo(mainScene, mainScene->getDefaultCamera());
+	mainScene->addChild(transformGizmo);		
 	trackballCamera = new TrackballCamera(mainScene->getDefaultCamera(), renderTextureShape);
+	
+	
+//	transformGizmo->setTransformMode(TransformGizmo::TRANSFORM_ROTATE);
 }
 
 void EntityEditorMainView::Update() {
-	Number scale = transformGizmo->getPosition().distance(mainScene->getDefaultCamera()->getPosition()) * 0.1;
-	transformGizmo->setScale(scale, scale, scale);
 }
 
 void EntityEditorMainView::handleEvent(Event *event) {
@@ -141,9 +437,10 @@ void EntityEditorMainView::handleEvent(Event *event) {
 		if(inputEvent->mouseButton == CoreInput::MOUSE_BUTTON2) {
 			Entity* targetEntity = (Entity*) event->getDispatcher();
 			
-			transformGizmo->setPosition(targetEntity->getConcatenatedMatrix().getPosition());
-			transformGizmo->visible = true;
-				
+			selectedEntities.clear();			
+			selectedEntities.push_back(targetEntity);
+			transformGizmo->setTransformSelection(selectedEntities);
+							
 			SceneMesh *sceneMesh = dynamic_cast<SceneMesh*>(targetEntity);
 			if(sceneMesh) {
 				sceneMesh->overlayWireframe = true;

+ 2 - 0
IDE/Contents/Source/PolycodeIDEApp.cpp

@@ -57,6 +57,8 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
 	CoreServices::getInstance()->getResourceManager()->addArchive("Physics2D.pak");
 	CoreServices::getInstance()->getResourceManager()->addArchive("Physics3D.pak");
 	CoreServices::getInstance()->getResourceManager()->addArchive("UI.pak");
+
+	CoreServices::getInstance()->getResourceManager()->addDirResource("Materials");	
 			
 	CoreServices::getInstance()->getFontManager()->registerFont("section", "Fonts/RobotoCondensed-Bold.ttf");