Q Engine Wiki
Brought to you by:
benjaeggi
This is a primitive editor.
It can move, rotate and scale entities around X and Z (not Y yet)
It can set texture to entities.
And of course it can create entities from cubes, spheres and loaded meshes.
You can save and load the scene.
#include "engine.hpp"
// screen width and height
const int screenWidth=800;
const int screenHeight=600;
// what transformations can we do with an entity?
enum eTransformation
{
TRANS_POS=1,
TRANS_ROT,
TRANS_SCALE
};
// all the gui buttons, menu items and other stuff.
enum eGUIValues
{
GUIBUTTON_NEW_CUBE=101, // create a new cube
GUIBUTTON_NEW_SPHERE, // create a new sphere
GUIBUTTON_NEW_MESH, // open a file open dialog for loading a new mesh.
GUIBUTTON_NEW_FILE, // clear the scene
GUIBUTTON_SAVE_FILE, // save to scene.bsc in the current folder.
GUIBUTTON_LOAD_FILE, // open a file open dialog for loading a scene
GUIBUTTON_SELECT_TEXTURE,// open a file open dialog for loading a texture
GUIBUTTON_SET_POSITION, // set the transform variable to TRANS_POS
GUIBUTTON_SET_ROTATION, // set the transform variable to TRANS_ROT
GUIBUTTON_SET_SCALING, // set the transform variable to TRANS_SCALE
GUIBUTTON_SET_TEXTURE, // set the lastly loaded texture to the selected entity.
GUIBUTTON_VIEW_ENTITY_LIST, // show or hide the entity list.
GUIDIALOG_OPEN_MESH, // load the selected mesh from the file dialog.
GUIDIALOG_OPEN_TEXTURE, // load the selected texture from the file dialog.
GUIDIALOG_OPEN_SCENE, // load the selected scene from the file dialog.
GUILISTBOX_ENTITIES // the list box containing all entities.
};
qEntity *selectedEntity=NULL; // the selected entity
std::string selectedTextureFilePath="irrlicht-1.8.5/media/Faerie5.BMP"; // the selected texture
eTransformation selectedTransformation = TRANS_POS; // the selected transformation
// the window with the entity list.
qGUIWindow *entityWindow=NULL;
// the listbox with the entities in it.
irr::gui::IGUIListBox* guiEntityList=NULL;
// function to fill the entity list box.
void buildGUIEntityList()
{
// get all entities
qEntityList list=qEntity::getGlobalEntityList();
// clear the list box
guiEntityList->clear();
// add each entity to the listbox
for(qEntityList::iterator it=list.begin();it!=list.end();++it)
guiEntityList->addItem(_to_wstring((*it)->getName()).c_str());
}
// the event receiver class for this application.
class evtreceiver : public qEventReceiver
{
protected:
// we need the engine sometimes.
qEngine *engine;
public:
// set the engine singleton.
evtreceiver() {engine=qEngine::getInstance();}
// do something when a key is pressed ONCE.
virtual void OnKeyDown(qKeyCode key)
{
// we need the entity list.
qEntityList l=qEntity::getGlobalEntityList();
switch(key)
{
// delete the selected entity.
case qKeyCode::KEY_DELETE:
if(selectedEntity)
{
printf("Deleting entity %s (%d).\n",selectedEntity->getName().c_str(), selectedEntity->getID());
delete selectedEntity;
selectedEntity=NULL;
}
// rebuild the entity list
buildGUIEntityList();
break;
default:
break;
}
}
// get clicks on GUI buttons and menu items.
virtual void OnGUIButtonClick(int id)
{
// printf("BUTTON %d clicked!\n", id);
qMeshNodeEntity *entity=NULL; // maybe we create a new entity
// maybe we need the selected entity casted as qMeshNodeEntity
qMeshNodeEntity* selNode=dynamic_cast<qMeshNodeEntity*>(selectedEntity);
switch(id)
{
// create new entities.
case GUIBUTTON_NEW_CUBE:
entity=engine->createNodeEntity("#cube","@cube",selectedTextureFilePath,engine->getWorkingPath());
buildGUIEntityList();
break;
case GUIBUTTON_NEW_SPHERE:
entity=engine->createNodeEntity("#sphere","@sphere",selectedTextureFilePath,engine->getWorkingPath());
buildGUIEntityList();
break;
case GUIBUTTON_NEW_MESH:
engine->addGUIFileDialog(GUIDIALOG_OPEN_MESH, "Load mesh..");
break;
// other menu stuff
case GUIBUTTON_NEW_FILE:
engine->clearScene();
selectedEntity=NULL;
buildGUIEntityList();
break;
// mesh transform value
case GUIBUTTON_SET_POSITION:
selectedTransformation=TRANS_POS;
break;
case GUIBUTTON_SET_ROTATION:
selectedTransformation=TRANS_ROT;
break;
case GUIBUTTON_SET_SCALING:
selectedTransformation=TRANS_SCALE;
break;
// open a file dialog to select a texture.
case GUIBUTTON_SELECT_TEXTURE:
engine->addGUIFileDialog(GUIDIALOG_OPEN_TEXTURE, "Select texture..");
break;
// set the selected texture to the selected entity
case GUIBUTTON_SET_TEXTURE:
if(selNode)
{
selNode->setTexture(selectedTextureFilePath,engine->getWorkingPath());
//selectedEntity->setTextureFileName(selectedTextureFilePath);
}
break;
// show or hide the entity list
case GUIBUTTON_VIEW_ENTITY_LIST:
entityWindow->setVisible(!entityWindow->isVisible());
break;
// scene loading and saving
case GUIBUTTON_SAVE_FILE:
engine->saveScene("scene.bsc");
break;
case GUIBUTTON_LOAD_FILE:
engine->addGUIFileDialog(GUIDIALOG_OPEN_SCENE, "Open scene..");
break;
default:
break;
};
// if an entity was created, turn off lighting on the newly created entity.
if(entity)
entity->enableLighting(false);
}
// when the ok button on a file dialog is pressed,
// you get the file dialog id, the absolute path and the relative path corresponding to the application directory.
virtual void OnFileDialogOK(int id, std::string absolutePath, std::string relativePath)
{
// when file name is shorter than 4 chars, it has no ending.
if(relativePath.length()<=4)
return;
// get the file ending
qString fileend=relativePath.substr(relativePath.length()-4);
if(id==GUIDIALOG_OPEN_SCENE)
{
if(fileend==".bsc" || fileend==".BSC")
{
printf("Load scene from %s\n",relativePath.c_str());
selectedEntity=NULL;
engine->loadScene(engine->getWorkingPath()+relativePath);
// rebuild the entity list box.
buildGUIEntityList();
}else{
printf("Could not load scene %s: Wrong file format.\n",relativePath.c_str());
engine->addGUIMessageBox("Scene Load Error","Wrong file format.");
}
}
if(id==GUIDIALOG_OPEN_MESH)
{
if(fileend==".obj" || fileend==".OBJ")
{
printf("Create Mesh Entity from %s\n",relativePath.c_str());
qMeshNodeEntity *mesh = engine->createNodeEntity("#loadedMesh",relativePath,selectedTextureFilePath,engine->getWorkingPath());
if(mesh)
mesh->enableLighting(false);
buildGUIEntityList();
}else{
printf("Could not create entity with mesh %s: Wrong file format.\n",relativePath.c_str());
engine->addGUIMessageBox("Mesh Load Error","Wrong file format.");
}
}
// open a texture and set it to the selected entity
if(id==GUIDIALOG_OPEN_TEXTURE)
{
if(fileend==".bmp" || fileend==".BMP" ||
fileend==".jpg" || fileend==".JPG" ||
fileend==".png" || fileend==".PNG")
{
printf("Actual texture filename: %s\n",relativePath.c_str());
selectedTextureFilePath=relativePath;
if(!selectedEntity)
return;
// maybe set texture of selected entity
qMeshNodeEntity* selNode=dynamic_cast<qMeshNodeEntity*>(selectedEntity);
if(selNode)
{
selNode->setTexture(selectedTextureFilePath, engine->getWorkingPath());
}
}else{
printf("Could not load texture %s: Wrong file format.\n",relativePath.c_str());
engine->addGUIMessageBox("Texture Load Error","Wrong file format.");
}
}
}
// catch listbox entries
virtual void OnListboxEntryChanged(int id, int index)
{
if(id==GUILISTBOX_ENTITIES)
{
int idx=0;
selectedEntity=NULL;
qEntityList list=qEntity::getGlobalEntityList();
// select the entity clicked on the listbox.
for(qEntityList::iterator it=list.begin();it!=list.end();++it)
{
if(idx==index)
{
selectedEntity=(*it);
}
idx++;
}
}
}
virtual void OnMouseUp(qEMouseButton which, int x, int y)
{
// printf("BTN %d IS UP.\n",which);
// we catch the entity on mouseup, so you're really sure.
// there are no entities in this scene but if you have some,
// you can get the one under the mouse with that call.
qEntity *ent=engine->getEntityAtMousePos();
if(ent)
{
printf("Entity %s clicked.\n", ent->getName().c_str());
selectedEntity=ent;
// select the right entry in the entity list box
int idx=0;
qEntityList list=qEntity::getGlobalEntityList();
for(qEntityList::iterator it=list.begin();it!=list.end();++it)
{
if(selectedEntity==(*it))
{
// select the clicked entity (in 3d view) on the entity listbox.
guiEntityList->setSelected(idx);
}
idx++;
}
}else{
// go through all entities and try to catch the ones
// wich have no node.
// Dont know, how right now.
}
}
// draw some stuff in the update call.
virtual void OnDraw(qiVideoDriver *video)
{
// draw center gizmo.
video->draw3DLine(qVec3f(0,0,0),qVec3f(10,0,0));
video->draw3DLine(qVec3f(0,0,0),qVec3f(0,10,0));
video->draw3DLine(qVec3f(0,0,0),qVec3f(0,0,10));
}
};
// now for the main function.
int main()
{
// get the engine singleton.
qEngine* e = qEngine::getInstance();
// create the window
if(!e->createWindow("BeOS", screenWidth, screenHeight))
{
printf("Could not create the main Window. Aborting.\n");
return 1;
}
// set camera to maya style steering.
e->setCameraMayaStyle();
// create the event receiver and register it.
evtreceiver gcr;
e->setEventReceiver(&gcr);
e->setBackgroundColor(0,0,100,255);
);
// add some gui buttons
e->addGUIButton(GUIBUTTON_SET_POSITION, qRecti(10,25,13,13), "P", "Set position.");
e->addGUIButton(GUIBUTTON_SET_ROTATION, qRecti(25,25,13,13),"R","Set rotation.");
e->addGUIButton(GUIBUTTON_SET_SCALING, qRecti(40,25,13,13), "S", "Set scaling.");
e->addGUIButton(GUIBUTTON_SET_TEXTURE, qRecti(55,25,13,13),"T", "Set actual texture to selected entity.");
// add a menu in the top of the window.
qGUIMenu *menu=e->addGUIMenu();
// add the file menu
irr::u32 crmenu= menu->addItem(L"File",-1,true,true);
menu->getSubMenu(crmenu)->addItem(L"New",GUIBUTTON_NEW_FILE);
menu->getSubMenu(crmenu)->addItem(L"Load..",GUIBUTTON_LOAD_FILE);
menu->getSubMenu(crmenu)->addItem(L"Save..",GUIBUTTON_SAVE_FILE);
// add the create menu. Note that only mesh entities can be created right now.
crmenu= menu->addItem(L"Create",-1,true,true);
menu->getSubMenu(crmenu)->addItem(L"Cube", GUIBUTTON_NEW_CUBE);
menu->getSubMenu(crmenu)->addItem(L"Sphere",GUIBUTTON_NEW_SPHERE);
menu->getSubMenu(crmenu)->addItem(L"Mesh",GUIBUTTON_NEW_MESH);
// set some "global" stuff. Texture only right now.
crmenu= menu->addItem(L"Set",-1,true,true);
menu->getSubMenu(crmenu)->addItem(L"Texture", GUIBUTTON_SELECT_TEXTURE);
// show or hide the windows.(Entity list window.)
crmenu=menu->addItem(L"View",-1,true,true);
menu->getSubMenu(crmenu)->addItem(L"Entity List", GUIBUTTON_VIEW_ENTITY_LIST);
// create the entity window.
entityWindow = e->addGUIWindow(qRecti(520,10,100,400),"Entity List");
// remove the close button.
qGUIButton* b=entityWindow->getCloseButton();
b->setVisible(false);
// add the entity list box.
guiEntityList=e->getGUIEnvironment()->addListBox(qRecti(3,25,94,394), entityWindow, GUILISTBOX_ENTITIES);
///////////////////// ENDOF MENU AND BUTTON CREATION
// build the entity list for the first time.
buildGUIEntityList();
while(e->isRunning())
{
e->update();
float delta=e->getDeltaTime();
// move the selected entity with keys
if(selectedEntity!=NULL)
{
bool doit=false;
// maybe we need the selected entity as qMeshNodeEntity.
qMeshNodeEntity* selNode=dynamic_cast<qMeshNodeEntity*>(selectedEntity);
qVec3f trans=qVec3f(0.0,0.0,0.0);
// z
if(e->getKeyDown(qKeyCode::KEY_UP))
{
trans=qVec3f(0,0,10.0*delta);
doit=true;
}
if(e->getKeyDown(qKeyCode::KEY_DOWN))
{
trans=qVec3f(0,0,-10.0*delta);
doit=true;
}
// x
if(e->getKeyDown(qKeyCode::KEY_LEFT))
{
trans=qVec3f(-10.0*delta,0,0);
doit=true;
}
if(e->getKeyDown(qKeyCode::KEY_RIGHT))
{
trans=qVec3f(10.0*delta,0,0);
doit=true;
}
// no y right now.
// maybe move entity
if(selectedTransformation==TRANS_POS && doit==true)
selectedEntity->addPosition(trans);
if(selNode)
{
// maybe scale entity
if(selectedTransformation==TRANS_SCALE && doit==true)
selNode->addScale(trans);
// maybe rotate entity
if(selectedTransformation==TRANS_ROT && doit==true)
selNode->addRotation(trans);
}
doit=false;
}
}
e->quit();
return 0;
}
/*
That's it. Compile and run.
**/