Page 1 of 1

saveScene question

Posted: Wed Feb 02, 2011 8:44 am
by wsw1231
If I call

Code: Select all

smgr->saveScene(..)
, the .irr file will be generated at the project directory.

How can I get the path of that directory?

I have used

Code: Select all

Device->getFileSystem()->getWorkingDirectory().c_str()
but this seems to return an empty string...

Posted: Wed Feb 02, 2011 11:03 am
by Fury.
not know. if you save the file as "hello.irr" what about search it with your operative system searching utilities?

if you are using codeblocks you can specify the work directory and also if you are using visual studio..

my suggestion is to put all binary files in a "bin" folder and keep there all dlls and set that folder as working directory (this is how irrlicht solution is configured by default)

Posted: Wed Feb 02, 2011 12:10 pm
by serengeor
Maybe it returns an empty string because it returns relative directory to executable?

I think most of the IDE's do that, I always compile and launch the executable myself.

Posted: Wed Feb 02, 2011 12:17 pm
by hybrid
The call should return the full path to the current working directory, hence it should never be empty. Are you sure you use the correct assignment there. If you use unicode paths and convert the path to stringc, there can be a bad mapping which would lead to truncated strings.

Posted: Wed Feb 02, 2011 12:46 pm
by wsw1231
hybrid wrote:The call should return the full path to the current working directory, hence it should never be empty. Are you sure you use the correct assignment there. If you use unicode paths and convert the path to stringc, there can be a bad mapping which would lead to truncated strings.

Code: Select all

core::stringc lastFilePath("");
core::stringc filePath("");
filePath = Device->getFileSystem()->getWorkingDirectory().c_str();	//bug

//some code...

if (lastFilePath != filePath)
{....}
I know filePath is still empty because the thing in the if statement cannot be executed.....

Posted: Wed Feb 02, 2011 1:38 pm
by hybrid
IIRC, the call does not return a stringc. So just use the correct type and see what happens.

Posted: Wed Feb 02, 2011 2:55 pm
by wsw1231
hybrid wrote:IIRC, the call does not return a stringc. So just use the correct type and see what happens.
I think the type is fine....
because I use

Code: Select all

filePath = core::stringc(Device->getFileSystem()->getWorkingDirectory().c_str());	//bug
The bug still exists

filePath is stringc ( i.e. c8 ) and c_str() returns c8 too.
The problem should result from another aspect.

Posted: Thu Feb 03, 2011 7:22 am
by wsw1231
Arghhhhhhhh
I still cannot figure out why the filePath is empty...Here is my full code, just copy &paste it to your IDE and run it please......

After running the program, click "File"-->"Save 3D Floor Plan", then type the file name in the editbox (e.g. abc.irr or C:/abc.irr)

If you type C:/abc.irr, you should be able to see a static text showing "C:/" representing the filePath.

The bug is that when you type abc.irr, the static text shows nothing :x :evil:

Code: Select all

#include <irrlicht.h>
#include <stdlib.h>

using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

IrrlichtDevice *Device = 0;
IVideoDriver *driver = 0; 
ISceneManager *smgr  = 0; 
IGUIEnvironment *env = 0;
ICameraSceneNode  *camera = 0;
ISceneCollisionManager  *CollMan = 0; 
IMetaTriangleSelector * meta = 0;
core::stringw fileName("");
core::stringc filePath("");
core::stringc lastFilePath("");
IGUIWindow *window =0;

#define ID_TRANSLATE   102 
#define ID_ROTATE      103 
#define ID_SCALE      104 
#define ID_ADDBOX      105 

enum
{
	// I use this ISceneNode ID to indicate a scene node that is
	// not pickable by getSceneNodeAndCollisionPointFromRay()
	ID_IsNotPickable = 0,

	// I use this flag in ISceneNode IDs to indicate that the
	// scene node can be picked by ray selection.
	IDFlag_IsPickable = 1 << 0,

	// I use this flag in ISceneNode IDs to indicate that the
	// scene node can be highlighted.  In this example, the
	// homonids can be highlighted, but the level mesh can't.
	IDFlag_IsHighlightable = 1 << 1
};

enum
{
	GUI_ID_DIALOG_ROOT_WINDOW  = 0x10000,

	GUI_ID_X_SCALE,
	GUI_ID_Y_SCALE,
	GUI_ID_Z_SCALE,

	GUI_ID_NEW_MODEL,
	GUI_ID_LOAD_FLOOR_PLAN,
	GUI_ID_SAVE_FLOOR_PLAN,
	GUI_ID_SAVEAS_FLOOR_PLAN,
	GUI_ID_SAVE_BUTTON,
	GUI_ID_SAVE_DIR,
	GUI_ID_SAVE_WINDOW,

	GUI_ID_SKY_BOX_VISIBLE,
	GUI_ID_TOGGLE_DEBUG_INFO,

	GUI_ID_DEBUG_OFF,
	GUI_ID_DEBUG_BOUNDING_BOX,
	GUI_ID_DEBUG_NORMALS,
	GUI_ID_DEBUG_SKELETON,
	GUI_ID_DEBUG_WIRE_OVERLAY,
	GUI_ID_DEBUG_HALF_TRANSPARENT,
	GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES,
	GUI_ID_DEBUG_ALL,

	GUI_ID_MODEL_MATERIAL_SOLID,
	GUI_ID_MODEL_MATERIAL_TRANSPARENT,
	GUI_ID_MODEL_MATERIAL_REFLECTION,

	GUI_ID_CAMERA_MAYA,
	GUI_ID_CAMERA_FIRST_PERSON,

	GUI_ID_POSITION_TEXT,

	GUI_ID_ABOUT,
	GUI_ID_QUIT,

	GUI_ID_TEXTUREFILTER,
	GUI_ID_SKIN_TRANSPARENCY,
	GUI_ID_SKIN_ANIMATION_FPS,

	GUI_ID_BUTTON_GEN_ROOM,
	GUI_ID_BUTTON_LU,
	GUI_ID_BUTTON_LB,
	GUI_ID_BUTTON_RU,
	GUI_ID_BUTTON_RB,
	GUI_ID_BUTTON_OPEN_MODEL,
	GUI_ID_BUTTON_SHOW_ABOUT,
	GUI_ID_BUTTON_SHOW_TOOLBOX,
	GUI_ID_BUTTON_SELECT_ARCHIVE,
};


enum EditorMode 
{ 
   MODE_NONE, 
   MODE_QUIT, 
   MODE_TRANSLATE, 
   MODE_ROTATE, 
   MODE_SCALE, 
};

position2di        initialCursorPosition;      // where mouse cursor started 
position2di        initialObjectPosition;      // where ray from camera to object intersected screen 
ISceneNode*        SelectedNode         = 0;   // the selected node 
bool               ShiftIsPressed      = 0;   // is the shift key pressed? 
bool               LMouseButtonDown      = 0;   // is the left mouse button down? 
EditorMode         Mode               = MODE_TRANSLATE; 
float              RotateSpeed         = 0.01f; 
float              ScaleSpeed         = 0.01f; 
f32 camFOV = 1.0f;
ISceneNode* flat =0;
core::vector3df flatEdges[8];

void clearBoundingBox()
{
	core::array<scene::ISceneNode *> nodes;
	smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes); // Find all nodes

	for (u32 i=0; i < nodes.size(); ++i)
	{
		ISceneNode * node = nodes[i];
		node->setDebugDataVisible(scene::EDS_OFF);
	}
}

void saveAs()
{
	window = env->addWindow(core::rect<s32>(100,100,500,230), true, L"Save to...", 0, GUI_ID_SAVE_WINDOW);
	if (filePath.size()==0)
		env->addEditBox(L"", core::rect<s32>(20, 30, 380, 60), true, window, GUI_ID_SAVE_DIR);
	else
		env->addEditBox(fileName.c_str(), core::rect<s32>(20, 30, 380, 60), true, window, GUI_ID_SAVE_DIR);
	env->addButton(core::rect<s32>(100, 80, 300, 110), window, GUI_ID_SAVE_BUTTON, L"Save");
}

//f32 minX(ISceneNode* node)
//{
//	core::vector3df edges[8];
//	node->getTransformedBoundingBox().getEdges(edges);
//	f32 minX = edges[0].X;
//
//	for (int i=1; i<=7; i++)
//	{
//		if (minX > edges[i].X)
//			minX = edges[i].X;
//	}
//	return minX;
//}
//
//f32 maxX(ISceneNode* node)
//{
//	core::vector3df edges[8];
//	node->getTransformedBoundingBox().getEdges(edges);
//	f32 maxX = edges[0].X;
//
//	for (int i=1; i<=7; i++)
//	{
//		if (maxX < edges[i].X)
//			maxX = edges[i].X;
//	}
//	return maxX;
//}
//
//f32 minY(ISceneNode* node)
//{
//	core::vector3df edges[8];
//	node->getTransformedBoundingBox().getEdges(edges);
//	f32 minY = edges[0].Y;
//
//	for (int i=1; i<=7; i++)
//	{
//		if (minY > edges[i].Y)
//			minY = edges[i].Y;
//	}
//	return minY;
//}
//
//f32 maxY(ISceneNode* node)
//{
//	core::vector3df edges[8];
//	node->getTransformedBoundingBox().getEdges(edges);
//	f32 maxY = edges[0].Y;
//
//	for (int i=1; i<=7; i++)
//	{
//		if (maxY < edges[i].Y)
//			maxY = edges[i].Y;
//	}
//	return maxY;
//}
//
//f32 minZ(ISceneNode* node)
//{
//	core::vector3df edges[8];
//	node->getTransformedBoundingBox().getEdges(edges);
//	f32 minZ = edges[0].Z;
//
//	for (int i=1; i<=7; i++)
//	{
//		if (minZ > edges[i].Z)
//			minZ = edges[i].Z;
//	}
//	return minZ;
//}
//
//f32 maxZ(ISceneNode* node)
//{
//	core::vector3df edges[8];
//	node->getTransformedBoundingBox().getEdges(edges);
//	f32 maxZ = edges[0].Z;
//
//	for (int i=1; i<=7; i++)
//	{
//		if (maxZ < edges[i].Z)
//			maxZ = edges[i].Z;
//	}
//	return maxZ;
//}
//
//
//vector3df getIntersectionPoint(ISceneNode* wall, ISceneNode* flat)
//{
//	vector3df point;
//	
//
//	//X
//	if (maxX(wall) < maxX(flat))
//		point.X = maxX(wall);
//	else
//		point.X = maxX(flat);
//
//	//Y
//	if (maxY(wall) < maxY(flat))
//		point.Y = maxY(wall);
//	else
//		point.Y = maxY(flat);
//	//Z
//	if (minZ(wall) > minZ(flat))
//		point.Z = minZ(wall);
//	else
//		point.Z = minZ(flat);
//
//	return point;
//	
//}

void OnMenuItemSelected( IGUIContextMenu* menu )
	{
		s32 id = menu->getItemCommandId(menu->getSelectedItem());
		IGUIEnvironment* env = Device->getGUIEnvironment();

		switch(id)
		{
			case GUI_ID_SAVE_FLOOR_PLAN:
				if (filePath.size()==0)
					saveAs();
				else
					smgr->saveScene(fileName);
			break;

			case GUI_ID_SAVEAS_FLOOR_PLAN: 
				saveAs();
			break;

			case GUI_ID_LOAD_FLOOR_PLAN: 
				env->addFileOpenDialog(L"Please select a floor plan file (*.irr) to open");			
			break;

		}
}

void loadFloorPlan(const c8* fn, IGUIFileOpenDialog* dialog)
{	
	fileName = fn;

	core::stringc extension;
	core::getFileNameExtension(extension, fileName);
	extension.make_lower();

	if (extension==".irr")
	{
		Device->getSceneManager()->loadScene(fileName);
		filePath = core::stringc(dialog->getDirectoryName().c_str());		
		
		return;
	}

	Device->getGUIEnvironment()->addMessageBox(
			L"Warning!", L"The file could not be loaded. " \
			L"Maybe it is not a supported file format.");

}


void clearAxes()
{
	core::array<scene::ISceneNode *> nodes;
	smgr->getSceneNodesFromType(scene::ESNT_ANIMATED_MESH, nodes); // Find all nodes

	for (u32 i=0; i < nodes.size(); ++i)
	{
		ISceneNode * node = nodes[i];
		node->remove();
	}
}
void updateAxes(ISceneNode* node)
{ 
	//clear previous axes
	clearAxes();
	
	ISceneNode * arrowX = smgr->addAnimatedMeshSceneNode(smgr->addArrowMesh("arrowZ",
		SColor(255, 255, 0, 0), SColor(255, 255, 0, 0),4,8,1.0f,0.6f,0.05f,0.2f)); 
	arrowX->setMaterialFlag(video::EMF_LIGHTING, true); 
	arrowX->setScale(vector3df(10, 10, 10));
	arrowX->setRotation(vector3df(0,0,-90));

	ISceneNode * arrowY = smgr->addAnimatedMeshSceneNode(smgr->addArrowMesh("arrowY",
		SColor(255, 0, 255, 0), SColor(255, 0, 255, 0),4,8,1.0f,0.6f,0.05f,0.2f)); 
	arrowY->setMaterialFlag(video::EMF_LIGHTING, true); 
	arrowY->setRotation(vector3df(0,90,0));
	arrowY->setScale(vector3df(10, 10, 10));

	ISceneNode * arrowZ = smgr->addAnimatedMeshSceneNode(smgr->addArrowMesh("arrowX",
		SColor(255, 0, 0, 255), SColor(255, 0, 0, 255),4,8,1.0f,0.6f,0.05f,0.2f)); 
	arrowZ->setMaterialFlag(video::EMF_LIGHTING, true); 
	arrowZ->setScale(vector3df(10, 10, 10));
	arrowZ->setRotation(vector3df(90,0,0));

	vector3df pos = node->getPosition();
	arrowX->setPosition(pos);
	arrowY->setPosition(pos);
	arrowZ->setPosition(pos);


	//Move the arrows to the front
	

}

class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(const SEvent& event)
	{
		switch(event.EventType) 
		{
			case EET_GUI_EVENT:
			{
				switch (event.GUIEvent.EventType)
				{
					case EGET_MENU_ITEM_SELECTED:
						// a menu item was clicked
						OnMenuItemSelected( (IGUIContextMenu*)event.GUIEvent.Caller );
					break;
					case EGET_FILE_SELECTED:
					{
						// load the model file, selected in the file open dialog
						IGUIFileOpenDialog* dialog =
							(IGUIFileOpenDialog*)event.GUIEvent.Caller;
						loadFloorPlan(core::stringc(dialog->getFileName()).c_str(), dialog);
					}
					break;
					case EGET_BUTTON_CLICKED: 
                     { 
                        switch (event.GUIEvent.Caller->getID()) 
						{
							case ID_TRANSLATE  : { Mode = MODE_TRANSLATE;  } break; 
							case ID_ROTATE      : { Mode = MODE_ROTATE;      } break; 
							case ID_SCALE      : { Mode = MODE_SCALE;      } break; 
							case ID_ADDBOX      : 
							{
								ISceneNode* box = smgr->addCubeSceneNode(); 
								box->setMaterialTexture(0, driver->getTexture("fire.bmp")); 
								box->setMaterialFlag(video::EMF_LIGHTING, false); 
								box->setMaterialFlag(video::EMF_FOG_ENABLE,false);
								
								/*ITriangleSelector * selector = smgr->createTriangleSelectorFromBoundingBox(box);;
								meta->addTriangleSelector(selector);*/
							} break;
							case GUI_ID_SAVE_BUTTON:
							{
								IGUIElement* root = env->getRootGUIElement();								
								core::stringc s;

								s = root->getElementFromId(GUI_ID_SAVE_DIR, true)->getText();
								core::stringc extension;
								core::getFileNameExtension(extension, s);
								extension.make_lower();
								if (extension != ".irr")
									env->addMessageBox(L"Warning!", L"The file extension must be .irr!", true);
								else if (!smgr->saveScene(s,0))
									env->addMessageBox(L"Warning!", L"The file path you input is not valid!", true);
								else //when saving succeeds
								{
									if (s.findLast('/'))
									{
										filePath = s.subString(0,s.findLast('/')+1);
										fileName = s;
									}
									else 
									{
										filePath += Device->getFileSystem()->getWorkingDirectory();	//bug
										fileName = filePath + s;
									}
									
								}
								core::stringw str(filePath);
								IGUIStaticText *staticText = env->addStaticText(str.c_str(), rect<s32>(130,200,260,522), true); 
								window->remove();
							} break;
							case GUI_ID_BUTTON_GEN_ROOM:
							{	
								f32 flatHeight = flatEdges[3].Y-flatEdges[2].Y;

								//set the wall to one of the corner
								ISceneNode* wall_1 = smgr->addCubeSceneNode(flatHeight,0,-1,core::vector3df(flatEdges[0].X,flatHeight/2,flatEdges[0].Z),core::vector3df(0,0,0),core::vector3df(0.3f,1.0f,0.3f));
								wall_1->setPosition(core::vector3df(flatEdges[0].X+(wall_1->getTransformedBoundingBox().MaxEdge.X-wall_1->getTransformedBoundingBox().MinEdge.X)/2,
													flatHeight/2,
													flatEdges[0].Z+(wall_1->getTransformedBoundingBox().MaxEdge.Z-wall_1->getTransformedBoundingBox().MinEdge.Z)/2));

					
								
								//set the position and scale of the wall
								vector3df pos = wall_1->getPosition();
								vector3df scale = wall_1->getScale();
								core::vector3df wallEdges1[8];
								core::vector3df wallEdges2[8];
								wall_1->setPosition(core::vector3df(pos.X+50, pos.Y, pos.Z));
								wall_1->updateAbsolutePosition();
								wall_1->getTransformedBoundingBox().getEdges(wallEdges1);
								wall_1->setScale(core::vector3df(scale.X, scale.Y, 5*scale.Z));

								
								////reset the position of the wall to be inside the flat
								
								wall_1->updateAbsolutePosition();
								pos = wall_1->getPosition();
								wall_1->getTransformedBoundingBox().getEdges(wallEdges2);
								//wall_1->getTransformedBoundingBox().getEdges(wallEdges);
								
								
								wall_1->setPosition(core::vector3df(pos.X, pos.Y, pos.Z+wallEdges1[4].Z-wallEdges2[4].Z+1));
								
								//ITriangleSelector * selector = smgr->createTriangleSelectorFromBoundingBox(wall_1);;
								//meta->addTriangleSelector(selector);

								//set the wall to one of the corner
								ISceneNode* wall_2 = smgr->addCubeSceneNode(flatHeight,0,-1,core::vector3df(flatEdges[0].X,flatHeight/2,flatEdges[0].Z),core::vector3df(0,0,0),core::vector3df(0.3f,1.0f,0.3f));
								wall_2->setPosition(core::vector3df(flatEdges[0].X+(wall_2->getTransformedBoundingBox().MaxEdge.X-wall_2->getTransformedBoundingBox().MinEdge.X)/2,
													flatHeight/2,
													flatEdges[0].Z+(wall_2->getTransformedBoundingBox().MaxEdge.Z-wall_2->getTransformedBoundingBox().MinEdge.Z)/2));

					
								
								//set the position and scale of the wall
								pos = wall_2->getPosition();
								scale = wall_2->getScale();

								wall_2->setPosition(core::vector3df(pos.X, pos.Y, pos.Z+50));
								wall_2->updateAbsolutePosition();
								wall_2->getTransformedBoundingBox().getEdges(wallEdges1);
								wall_2->setScale(core::vector3df(6*scale.X, scale.Y, scale.Z));

								
								////reset the position of the wall to be inside the flat
								
								wall_2->updateAbsolutePosition();
								pos = wall_2->getPosition();
								wall_2->getTransformedBoundingBox().getEdges(wallEdges2);
												
								
								wall_2->setPosition(core::vector3df(pos.X+wallEdges1[0].X-wallEdges2[0].X+1, pos.Y, pos.Z));
								
							}
							break;
						}
					 } break;
				}
			} break;
			
			case EET_KEY_INPUT_EVENT :
			{ 
				//check if "Shift" key is pressed
				if (event.KeyInput.Shift)
					ShiftIsPressed = true; 
				else 
					ShiftIsPressed = false; 

				if (event.KeyInput.Key == KEY_DELETE)
				{
					if(SelectedNode && SelectedNode->getID() !=ID_IsNotPickable)
						SelectedNode->remove();
				}

				switch (event.KeyInput.Char)
				{ 
					case 'm':
						Mode = MODE_TRANSLATE;
						break;
					case 'r':
						Mode = MODE_ROTATE;
						break;
					case 's':
						Mode = MODE_SCALE;
						break;
				}

			} break; 

			// if it is a mouse event 
			case EET_MOUSE_INPUT_EVENT : 
			 { 
				// based upon the mouse event type 
				switch (event.MouseInput.Event) 
				{ 
				   case EMIE_LMOUSE_PRESSED_DOWN : 
					{
						LMouseButtonDown = true; 
												
						// check for a node being selected 
						SelectedNode = CollMan->getSceneNodeFromScreenCoordinatesBB(Device->getCursorControl()->getPosition(),0,true); 
						
						//!need to check the node type

						// If we selected a node 
						if(SelectedNode && SelectedNode->getID() !=ID_IsNotPickable) 
						{ 
							
							clearBoundingBox();
							//clearAxes();
							// Remember where the node and cursor were when it was clicked on 
							initialCursorPosition = Device->getCursorControl()->getPosition(); 
							initialObjectPosition = CollMan->getScreenCoordinatesFrom3DPosition(SelectedNode->getAbsolutePosition(), camera); 

							//Add a bounding box around the selected object
							SelectedNode->setDebugDataVisible(scene::EDS_BBOX); 

							//Add XYZ axes on the object
							//updateAxes(SelectedNode);

							/*if (Mode==MODE_ROTATE)
							{
							if (SelectedNode)
							{
							vector3df rot = SelectedNode->getRotation(); 
							rot.Y +=45;
							SelectedNode->setRotation(rot);										

							}
							}*/
						     
						}
						return false;
					} break; 

					case EMIE_LMOUSE_LEFT_UP : 
					{ 
						LMouseButtonDown = false; 
						//if (SelectedNode) SelectedNode->setDebugDataVisible(scene::EDS_OFF); 
						//SelectedNode = 0; 
						
						return false; 
					} break; 
					

					case EMIE_RMOUSE_LEFT_UP : 
					{ 
						if (camera) 
						{ 
							camera->setInputReceiverEnabled(!camera->isInputReceiverEnabled()); 
							Device->getCursorControl()->setVisible(!camera->isInputReceiverEnabled()); 	
							 //if (camera->isInputReceiverEnabled()) Mode = MODE_NONE; 
						}                
					} break; 

					case EMIE_MOUSE_WHEEL:
					{ 
						if (event.MouseInput.Wheel == -1.0f)  camFOV+=0.1f; 
						else if (event.MouseInput.Wheel == 1.0f) camFOV-=0.1f; 

						// clip the value 
						#define maxFOV 2.8f 
						#define minFOV 0.1f 
						if (camFOV < minFOV) camFOV = minFOV; 
						if (camFOV > maxFOV) camFOV = maxFOV; 

						camera->setFOV(camFOV); 
					} break;

					case EMIE_MOUSE_MOVED :
					{ 
						if (!LMouseButtonDown) return false; 

						if (Mode == MODE_TRANSLATE) 
						{ 
							if (SelectedNode && SelectedNode->getID() !=ID_IsNotPickable) 
							{ 
								vector3df p = SelectedNode->getPosition(); 

								if (ShiftIsPressed) 
								{ 
									plane3df const planeXY(SelectedNode->getAbsolutePosition(), vector3df(0.f, 0.f, 1.f)); 
									position2di currentCursorPosition(Device->getCursorControl()->getPosition()); 
									position2di effectiveObjectPosition = initialObjectPosition + currentCursorPosition - initialCursorPosition; 
									line3df ray(CollMan->getRayFromScreenCoordinates(effectiveObjectPosition, camera)); 
									vector3df intersectWithPlane; 
									vector3df oldPos = SelectedNode->getAbsolutePosition(); 

									if(planeXY.getIntersectionWithLine(ray.start, ray.getVector(), intersectWithPlane)) 
									{ 
										intersectWithPlane.X = oldPos.X; 
										intersectWithPlane.Z = oldPos.Z; 
										SelectedNode->setPosition(intersectWithPlane); 
									} 
								} 
								else 
								{ 
									plane3df const planeXZ(SelectedNode->getAbsolutePosition(), vector3df(0.f, 1.f, 0.f)); 
									position2di currentCursorPosition(Device->getCursorControl()->getPosition()); 
									position2di effectiveObjectPosition = initialObjectPosition + currentCursorPosition - initialCursorPosition; 
									line3df ray(CollMan->getRayFromScreenCoordinates(effectiveObjectPosition, camera)); 
									vector3df intersectWithPlane; 
									if(planeXZ.getIntersectionWithLine(ray.start, ray.getVector(), intersectWithPlane)) 
										SelectedNode->setPosition(intersectWithPlane);
								} 
								//SelectedNode->setMaterialFlag(video::EMF_ZBUFFER, false);
								updateAxes(SelectedNode);
							} 
						} // end mode translate 
					  
					  else 
					  if (Mode == MODE_ROTATE) 
					  { 
						 if (SelectedNode && SelectedNode->getID() !=ID_IsNotPickable) 
						 { 
							vector3df rot = SelectedNode->getRotation(); 
							position2di currentCursorPosition(Device->getCursorControl()->getPosition()); 
							if (ShiftIsPressed) 
							{ 
							   if (initialObjectPosition.X < currentCursorPosition.X) rot.X -= RotateSpeed; 
							   if (initialObjectPosition.X > currentCursorPosition.X) rot.X += RotateSpeed; 
							} 
							else 
							{ 
							  // if (initialObjectPosition.X < currentCursorPosition.X) rot.Y -= RotateSpeed; 
							   //if (initialObjectPosition.X > currentCursorPosition.X) rot.Y += RotateSpeed; 
							   if (initialObjectPosition.X < currentCursorPosition.X) rot.Y -= 1; 
							   if (initialObjectPosition.X > currentCursorPosition.X) rot.Y += 1; 
							   if (initialObjectPosition.Y < currentCursorPosition.Y) rot.X -= 1;
							   if (initialObjectPosition.Y > currentCursorPosition.Y) rot.X += 1;
							} 
							initialObjectPosition = currentCursorPosition; 
							SelectedNode->setRotation(rot); 
						 } 

					  } 
					  else 
					  if (Mode == MODE_SCALE) 
					  { 
						 if (SelectedNode && SelectedNode->getID() !=ID_IsNotPickable) 
						 { 
							vector3df scale = SelectedNode->getScale(); 
							position2di currentCursorPosition(Device->getCursorControl()->getPosition()); 
							if (initialObjectPosition.X > currentCursorPosition.X) 
							{ 
							   scale.X -= ScaleSpeed; 
							   scale.Y -= ScaleSpeed; 
							   scale.Z -= ScaleSpeed; 
							} 
							if (initialObjectPosition.X < currentCursorPosition.X) 
							{ 
							   scale.X += ScaleSpeed; 
							   scale.Y += ScaleSpeed; 
							   scale.Z += ScaleSpeed; 
							} 
							initialObjectPosition = currentCursorPosition; 
							SelectedNode->setScale(scale); 
						 } 
					  } 

					} break; 
				} 
			}
		 }
		 return false;	
	}
		
};


void createToolBox()
{
	// remove tool box if already there
	IGUIElement* root = env->getRootGUIElement();
	IGUIElement* e = root->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true);
	if (e)
		e->remove();

	// create the toolbox window
	IGUIWindow* wnd = env->addWindow(core::rect<s32>(700,95,1000,530),
		false, L"Toolset", 0, GUI_ID_DIALOG_ROOT_WINDOW);

	// create tab control and tabs
	IGUITabControl* tab = env->addTabControl(
		core::rect<s32>(2,20,800-502,480-7), wnd, true, true);

	IGUITab* t1 = tab->addTab(L"Config");

	// add some edit boxes and a button to tab one
	env->addStaticText(L"Wall:",
			core::rect<s32>(10,20,60,45), false, false, t1);
	

	env->addButton(core::rect<s32>(10,134,90,165), t1, GUI_ID_BUTTON_GEN_ROOM, L"Generate room");

	// quick scale buttons
	env->addButton(core::rect<s32>(40,20,115,40), t1, GUI_ID_BUTTON_LU, L"Left-up");
	env->addButton(core::rect<s32>(125,20,200,40), t1, GUI_ID_BUTTON_RU, L"Right-up");
	env->addButton(core::rect<s32>(40,50,115,70), t1, GUI_ID_BUTTON_LB, L"Left-bottom");
	env->addButton(core::rect<s32>(125,50,200,70), t1, GUI_ID_BUTTON_RB, L"Right-bottom");

//	UpdateScaleInfo(Model);

}

void GUI()
{
	// add my little plug 
	int x      = 10; 
	int y      = 60; 
	int width   = 100; 
	int height   = 20; 
	int space   = 5; 

	env->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_TRANSLATE,L"Translate"); 
	y += height + space; 
	env->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_ROTATE,L"Rotate"); 
	y += height + space; 
	env->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_SCALE,L"Scale"); 
	y += height + space; 
	env->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_ADDBOX,L"Add A Box"); 

	// set a nicer font

	
	IGUISkin* skin = env->getSkin();
	IGUIFont* font = env->getFont("fonthaettenschweiler.bmp");
	if (font)
		skin->setFont(font);

	// create menu
	gui::IGUIContextMenu* menu = env->addMenu();
	menu->addItem(L"File", -1, true, true);
	menu->addItem(L"Edit", -1, true, true);
	menu->addItem(L"View", -1, true, true);
	menu->addItem(L"Camera", -1, true, true);
	menu->addItem(L"Help", -1, true, true);

	gui::IGUIContextMenu* submenu;
	submenu = menu->getSubMenu(0);
	submenu->addItem(L"New project", GUI_ID_NEW_MODEL);
	submenu->addItem(L"Load 3D floor plan", GUI_ID_LOAD_FLOOR_PLAN);
	submenu->addItem(L"Save 3D floor plan", GUI_ID_SAVE_FLOOR_PLAN); 
	submenu->addItem(L"Save as...", GUI_ID_SAVEAS_FLOOR_PLAN);
	submenu->addSeparator();
	submenu->addItem(L"Quit", GUI_ID_QUIT);

	submenu = menu->getSubMenu(3);
	submenu->addItem(L"Maya Style", GUI_ID_CAMERA_MAYA);
	submenu->addItem(L"First Person", GUI_ID_CAMERA_FIRST_PERSON);

	submenu = menu->getSubMenu(4);
	submenu->addItem(L"About", GUI_ID_ABOUT);

	/*
	Below the menu we want a toolbar, onto which we can place colored
	buttons and important looking stuff like a senseless combobox.
	*/

	// create toolbar

	gui::IGUIToolBar* bar = env->addToolBar();

	IVideoDriver* driver = Device->getVideoDriver();
	video::ITexture* image = driver->getTexture("open.png");
	bar->addButton(GUI_ID_BUTTON_OPEN_MODEL, 0, L"Open a model",image, 0, true, true);

	image = driver->getTexture("tools.png");
	bar->addButton(GUI_ID_BUTTON_SHOW_TOOLBOX, 0, L"Open Toolset",image, 0, false, true);

	image = driver->getTexture("zip.png");
	bar->addButton(GUI_ID_BUTTON_SELECT_ARCHIVE, 0, L"Set Model Archive",image, 0, false, true);

	image = driver->getTexture("help.png");
	bar->addButton(GUI_ID_BUTTON_SHOW_ABOUT, 0, L"Open Help", image, 0, false, true);

	// create a combobox with some senseless text

	gui::IGUIComboBox* box = env->addComboBox(core::rect<s32>(250,4,350,23), bar, GUI_ID_TEXTUREFILTER);


	/*
	To make the editor look a little bit better, we disable transparent gui
	elements, and add an Irrlicht Engine logo. In addition, a text showing
	the current frames per second value is created and the window caption is
	changed.
	*/

	// disable alpha

	for (s32 i=0; i<gui::EGDC_COUNT ; ++i)
	{
		video::SColor col = env->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
		col.setAlpha(255);
		env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col);
	}

	// add a tabcontrol
	createToolBox();
}

int main(int argc, char* argv[])
{
	// create device and exit if creation failed
	MyEventReceiver receiver;
	Device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(1024, 768),
		16, false, false, false, &receiver);

	if (Device == 0)
		return 1; // could not create selected driver.

	Device->setResizable(true);

	Device->setWindowCaption(L"3D Floor Plan Creator - New floor plan");

	driver = Device->getVideoDriver();
	env = Device->getGUIEnvironment();
	smgr = Device->getSceneManager();
	smgr->getParameters()->setAttribute(scene::COLLADA_CREATE_SCENE_INSTANCES, true);
	CollMan = smgr->getSceneCollisionManager(); 

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

	smgr->addLightSceneNode(0, core::vector3df(200,200,200),
		video::SColorf(1.0f,1.0f,1.0f),2000,ID_IsNotPickable);
	smgr->setAmbientLight(video::SColorf(0.3f,0.3f,0.3f));
	// add media directory as "search path"
	Device->getFileSystem()->addFolderFileArchive("../../media/");
	GUI();

	 // add a camera 
	camera = smgr->addCameraSceneNodeFPS(0, 100.0f, .1f, ID_IsNotPickable, 0, 0, false, 3.f); 
	camera->setPosition(vector3df(80,100,-220)); 
	camera->setTarget(vector3df(80,-30,30)); 
	camera->setIsDebugObject(true); 
	camera->setInputReceiverEnabled(false); 

	/*IMesh* mesh = smgr->getMesh("../../media/flat2.irrmesh");
	if (!mesh)
	{
		Device->drop();
		return 1;
	}
	flat = smgr->addMeshSceneNode(mesh,0,ID_IsNotPickable);
	flat->setScale(flat->getScale() * 0.1f);*/
	
	
	
	//smgr->loadScene("zzz.irr");

		// Create a meta triangle selector to hold several triangle selectors.
	meta = smgr->createMetaTriangleSelector();

	/*
	Now we will find all the nodes in the scene and create triangle
	selectors for all suitable nodes.  Typically, you would want to make a
	more informed decision about which nodes to performs collision checks
	on; you could capture that information in the node name or Id.
	*/
	core::array<scene::ISceneNode *> nodes;
	smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes); // Find all nodes

	for (u32 i=0; i < nodes.size(); ++i)
	{
		ISceneNode * node = nodes[i];
		ITriangleSelector * selector = 0;

		switch(node->getType())
		{
		case ESNT_CUBE:
		case ESNT_ANIMATED_MESH:
			// Because the selector won't animate with the mesh,
			// and is only being used for camera collision, we'll just use an approximate
			// bounding box instead of ((scene::IAnimatedMeshSceneNode*)node)->getMesh(0)
			selector = smgr->createTriangleSelectorFromBoundingBox(node);
		break;

		case ESNT_MESH:
		case ESNT_SPHERE: // Derived from IMeshSceneNode
			selector = smgr->createTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
			break;

		case ESNT_TERRAIN:
			selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node);
			break;

		case ESNT_OCTREE:
			selector = smgr->createOctreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
			break;

		default:
			// Don't create a selector for this node type
			break;
		}

		if(selector)
		{
			// Add it to the meta selector, which will take a reference to it
			meta->addTriangleSelector(selector);
			// And drop my reference to it, so that the meta selector owns it.
			selector->drop();
		}
	}


	/*
	Now that the mesh scene nodes have had triangle selectors created and added
	to the meta selector, create a collision response animator from that meta selector.
	*/
	ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
		meta, camera, core::vector3df(5,5,5),
		core::vector3df(0,0,0));
	meta->drop();

	camera->addAnimator(anim);
	anim->drop(); 

	while(Device->run())
	{
		if (Device->isWindowActive())
		{
			driver->beginScene(true, true, SColor(255,100,101,140));

			//if (SelectedNode && Mode != MODE_SCALE)
			//{				
			//	/*SMaterial material; 
			//	material.Lighting=false; 
			//	material.Thickness = 10;
			//	driver->setMaterial(material); 
			//	driver->setTransform(video::ETS_WORLD, core::matrix4());	
			//	driver->draw3DLine(SelectedNode->getAbsolutePosition(), SelectedNode->getAbsolutePosition() + vector3df(abs(SelectedNode->getBoundingBox().MaxEdge.X - SelectedNode->getBoundingBox().getCenter().X)+10,0,0), SColor(255,255,0,0)); 
			//	driver->draw3DLine(SelectedNode->getAbsolutePosition(), SelectedNode->getAbsolutePosition() + vector3df(0,abs(SelectedNode->getBoundingBox().MaxEdge.Y - SelectedNode->getBoundingBox().getCenter().Y)+10,0), SColor(255,0,255,0)); 
			//	driver->draw3DLine(SelectedNode->getAbsolutePosition(), SelectedNode->getAbsolutePosition() + vector3df(0,0,abs(SelectedNode->getBoundingBox().MaxEdge.Z - SelectedNode->getBoundingBox().getCenter().Z)+10), SColor(255,0,0,255)); */

			//}

			
			smgr->drawAll();
			env->drawAll();

			//flat->getTransformedBoundingBox().getEdges(flatEdges);


			//core::stringw str = L"";
			//str += wallEdges1[4].Z;
			//str+= " ";
			//str+=wallEdges2[4].Z;
			//Device->setWindowCaption(str.c_str());

			driver->endScene();

			if (lastFilePath != filePath)
			{
				core::stringw str = L"3D Floor Plan Creator - ";
				str += Device->getFileSystem()->getFileBasename(fileName, false);
				Device->setWindowCaption(str.c_str());
				lastFilePath = filePath;
			}
		}
		else
			Device->yield();
	}


	Device->drop();


	return 0;
}