Menu

example_03

Benedict Jäggi

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.
**/

Related

Wiki: Home