#include <irrlicht.h>
#include "driverChoice.h"
using namespace irr;
using namespace gui;
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
IrrlichtDevice *Device = 0;
core::stringc StartUpModelFile;
core::stringw MessageText;
core::stringw Caption;
scene::ISceneNode* Model = 0;
scene::ISceneNode* SkyBox = 0;
bool Octree=false;
bool UseLight=false;
scene::ICameraSceneNode* Camera[2] = {0, 0};
enum
{
GUI_ID_DIALOG_ROOT_WINDOW = 0x10000,
GUI_ID_X_SCALE,
GUI_ID_Y_SCALE,
GUI_ID_Z_SCALE,
GUI_ID_OPEN_MODEL,
GUI_ID_SET_MODEL_ARCHIVE,
GUI_ID_LOAD_AS_OCTREE,
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_SET_SCALE,
GUI_ID_BUTTON_SCALE_MUL10,
GUI_ID_BUTTON_SCALE_DIV10,
GUI_ID_BUTTON_OPEN_MODEL,
GUI_ID_BUTTON_SHOW_ABOUT,
GUI_ID_BUTTON_SHOW_TOOLBOX,
GUI_ID_BUTTON_SELECT_ARCHIVE,
MAX_FRAMERATE = 1000,
DEFAULT_FRAMERATE = 30
};
void setActiveCamera(scene::ICameraSceneNode* newActive)
{
if (0 == Device)
return;
scene::ICameraSceneNode * active = Device->getSceneManager()->getActiveCamera();
active->setInputReceiverEnabled(false);
newActive->setInputReceiverEnabled(true);
Device->getSceneManager()->setActiveCamera(newActive);
}
void SetSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin)
{
for (s32 i=0; i<irr::gui::EGDC_COUNT ; ++i)
{
video::SColor col = skin->getColor((EGUI_DEFAULT_COLOR)i);
col.setAlpha(alpha);
skin->setColor((EGUI_DEFAULT_COLOR)i, col);
}
}
void UpdateScaleInfo(scene::ISceneNode* model)
{
IGUIElement* toolboxWnd = Device->getGUIEnvironment()->getRootGUIElement()->
getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true);
if (!toolboxWnd)
return;
if (!model)
{
toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( L"-" );
toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( L"-" );
toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( L"-" );
}
else
{
core::vector3df scale = model->getScale();
toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( core::stringw(scale.X).c_str() );
toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( core::stringw(scale.Y).c_str() );
toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( core::stringw(scale.Z).c_str() );
}
}
void showAboutText()
{
Device->getGUIEnvironment()->addMessageBox(
Caption.c_str(), MessageText.c_str());
}
void loadModel(const c8* fn)
{
core::stringc filename(fn);
core::stringc extension;
core::getFileNameExtension(extension, filename);
extension.make_lower();
if (extension == ".jpg" || extension == ".pcx" ||
extension == ".png" || extension == ".ppm" ||
extension == ".pgm" || extension == ".pbm" ||
extension == ".psd" || extension == ".tga" ||
extension == ".bmp" || extension == ".wal" ||
extension == ".rgb" || extension == ".rgba")
{
video::ITexture * texture =
Device->getVideoDriver()->getTexture( filename );
if ( texture && Model )
{
Device->getVideoDriver()->removeTexture(texture);
texture = Device->getVideoDriver()->getTexture( filename );
Model->setMaterialTexture(0, texture);
}
return;
}
else if (extension == ".pk3" || extension == ".zip" || extension == ".pak" || extension == ".npk")
{
Device->getFileSystem()->addFileArchive(filename.c_str());
return;
}
if (Model)
Model->remove();
Model = 0;
if (extension==".irr")
{
core::array<scene::ISceneNode*> outNodes;
Device->getSceneManager()->loadScene(filename);
Device->getSceneManager()->getSceneNodesFromType(scene::ESNT_ANIMATED_MESH, outNodes);
if (outNodes.size())
Model = outNodes[0];
return;
}
scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() );
if (!m)
{
if (StartUpModelFile != filename)
Device->getGUIEnvironment()->addMessageBox(
Caption.c_str(), L"The model could not be loaded. " \
L"Maybe it is not a supported file format.");
return;
}
if (Octree)
Model = Device->getSceneManager()->addOctreeSceneNode(m->getMesh(0));
else
{
scene::IAnimatedMeshSceneNode* animModel =
Device->getSceneManager()->addAnimatedMeshSceneNode(m);
animModel->setAnimationSpeed(30);
Model = animModel;
}
Model->setMaterialFlag(video::EMF_LIGHTING, UseLight);
Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight);
Model->setDebugDataVisible(scene::EDS_OFF);
gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)Device->
getGUIEnvironment()->getRootGUIElement()->
getElementFromId(GUI_ID_TOGGLE_DEBUG_INFO, true);
if (menu)
for(int item = 1; item < 6; ++item)
menu->setItemChecked(item, false);
UpdateScaleInfo(Model);
}
void createToolBox()
{
IGUIEnvironment* env = Device->getGUIEnvironment();
IGUIElement* root = env->getRootGUIElement();
IGUIElement* e = root->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true);
if (e)
e->remove();
IGUIWindow* wnd = env->addWindow(core::rect<s32>(600,45,800,480),
false, L"Toolset", 0, GUI_ID_DIALOG_ROOT_WINDOW);
IGUITabControl* tab = env->addTabControl(
core::rect<s32>(2,20,800-602,480-7), wnd, true, true);
IGUITab* t1 = tab->addTab(L"Config");
env->addStaticText(L"Scale:",
core::rect<s32>(10,20,60,45), false, false, t1);
env->addStaticText(L"X:", core::rect<s32>(22,48,40,66), false, false, t1);
env->addEditBox(L"1.0", core::rect<s32>(40,46,130,66), true, t1, GUI_ID_X_SCALE);
env->addStaticText(L"Y:", core::rect<s32>(22,82,40,GUI_ID_OPEN_MODEL), false, false, t1);
env->addEditBox(L"1.0", core::rect<s32>(40,76,130,96), true, t1, GUI_ID_Y_SCALE);
env->addStaticText(L"Z:", core::rect<s32>(22,108,40,126), false, false, t1);
env->addEditBox(L"1.0", core::rect<s32>(40,106,130,126), true, t1, GUI_ID_Z_SCALE);
env->addButton(core::rect<s32>(10,134,85,165), t1, GUI_ID_BUTTON_SET_SCALE, L"Set");
env->addButton(core::rect<s32>(65,20,95,40), t1, GUI_ID_BUTTON_SCALE_MUL10, L"* 10");
env->addButton(core::rect<s32>(100,20,130,40), t1, GUI_ID_BUTTON_SCALE_DIV10, L"* 0.1");
UpdateScaleInfo(Model);
env->addStaticText(L"GUI Transparency Control:",
core::rect<s32>(10,200,150,225), true, false, t1);
IGUIScrollBar* scrollbar = env->addScrollBar(true,
core::rect<s32>(10,225,150,240), t1, GUI_ID_SKIN_TRANSPARENCY);
scrollbar->setMax(255);
scrollbar->setPos(255);
env->addStaticText(L"Framerate:",
core::rect<s32>(10,240,150,265), true, false, t1);
scrollbar = env->addScrollBar(true,
core::rect<s32>(10,265,150,280), t1, GUI_ID_SKIN_ANIMATION_FPS);
scrollbar->setMax(MAX_FRAMERATE);
scrollbar->setMin(-MAX_FRAMERATE);
scrollbar->setPos(DEFAULT_FRAMERATE);
root->bringToFront(root->getElementFromId(666, true));
}
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.PressedDown == false)
{
if ( OnKeyUp(event.KeyInput.Key) )
return true;
}
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = Device->getGUIEnvironment();
switch(event.GUIEvent.EventType)
{
case EGET_MENU_ITEM_SELECTED:
OnMenuItemSelected( (IGUIContextMenu*)event.GUIEvent.Caller );
break;
case EGET_FILE_SELECTED:
{
IGUIFileOpenDialog* dialog =
(IGUIFileOpenDialog*)event.GUIEvent.Caller;
loadModel(core::stringc(dialog->getFileName()).c_str());
}
break;
case EGET_SCROLL_BAR_CHANGED:
if (id == GUI_ID_SKIN_TRANSPARENCY)
{
const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
SetSkinTransparency(pos, env->getSkin());
}
else if (id == GUI_ID_SKIN_ANIMATION_FPS)
{
const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
if (scene::ESNT_ANIMATED_MESH == Model->getType())
((scene::IAnimatedMeshSceneNode*)Model)->setAnimationSpeed((f32)pos);
}
break;
case EGET_COMBO_BOX_CHANGED:
if (id == GUI_ID_TEXTUREFILTER)
{
OnTextureFilterSelected( (IGUIComboBox*)event.GUIEvent.Caller );
}
break;
case EGET_BUTTON_CLICKED:
switch(id)
{
case GUI_ID_BUTTON_SET_SCALE:
{
gui::IGUIElement* root = env->getRootGUIElement();
core::vector3df scale;
core::stringc s;
s = root->getElementFromId(GUI_ID_X_SCALE, true)->getText();
scale.X = (f32)atof(s.c_str());
s = root->getElementFromId(GUI_ID_Y_SCALE, true)->getText();
scale.Y = (f32)atof(s.c_str());
s = root->getElementFromId(GUI_ID_Z_SCALE, true)->getText();
scale.Z = (f32)atof(s.c_str());
if (Model)
Model->setScale(scale);
UpdateScaleInfo(Model);
}
break;
case GUI_ID_BUTTON_SCALE_MUL10:
if (Model)
Model->setScale(Model->getScale()*10.f);
UpdateScaleInfo(Model);
break;
case GUI_ID_BUTTON_SCALE_DIV10:
if (Model)
Model->setScale(Model->getScale()*0.1f);
UpdateScaleInfo(Model);
break;
case GUI_ID_BUTTON_OPEN_MODEL:
env->addFileOpenDialog(L"Please select a model file to open");
break;
case GUI_ID_BUTTON_SHOW_ABOUT:
showAboutText();
break;
case GUI_ID_BUTTON_SHOW_TOOLBOX:
createToolBox();
break;
case GUI_ID_BUTTON_SELECT_ARCHIVE:
env->addFileOpenDialog(L"Please select your game archive/directory");
break;
}
break;
default:
break;
}
}
return false;
}
bool OnKeyUp(irr::EKEY_CODE keyCode)
{
if (keyCode == irr::KEY_ESCAPE)
{
if (Device)
{
scene::ICameraSceneNode * camera =
Device->getSceneManager()->getActiveCamera();
if (camera)
{
camera->setInputReceiverEnabled( !camera->isInputReceiverEnabled() );
}
return true;
}
}
else if (keyCode == irr::KEY_F1)
{
if (Device)
{
IGUIElement* elem = Device->getGUIEnvironment()->
getRootGUIElement()->getElementFromId(GUI_ID_POSITION_TEXT);
if (elem)
elem->setVisible(!elem->isVisible());
}
}
else if (keyCode == irr::KEY_KEY_M)
{
if (Device)
Device->minimizeWindow();
}
else if (keyCode == irr::KEY_KEY_L)
{
UseLight=!UseLight;
if (Model)
{
Model->setMaterialFlag(video::EMF_LIGHTING, UseLight);
Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight);
}
}
return false;
}
void OnMenuItemSelected( IGUIContextMenu* menu )
{
s32 id = menu->getItemCommandId(menu->getSelectedItem());
IGUIEnvironment* env = Device->getGUIEnvironment();
switch(id)
{
case GUI_ID_OPEN_MODEL:
env->addFileOpenDialog(L"Please select a model file to open");
break;
case GUI_ID_SET_MODEL_ARCHIVE:
env->addFileOpenDialog(L"Please select your game archive/directory");
break;
case GUI_ID_LOAD_AS_OCTREE:
Octree = !Octree;
menu->setItemChecked(menu->getSelectedItem(), Octree);
break;
case GUI_ID_QUIT:
Device->closeDevice();
break;
case GUI_ID_SKY_BOX_VISIBLE:
menu->setItemChecked(menu->getSelectedItem(),
!menu->isItemChecked(menu->getSelectedItem()));
SkyBox->setVisible(!SkyBox->isVisible());
break;
case GUI_ID_DEBUG_OFF:
menu->setItemChecked(menu->getSelectedItem()+1, false);
menu->setItemChecked(menu->getSelectedItem()+2, false);
menu->setItemChecked(menu->getSelectedItem()+3, false);
menu->setItemChecked(menu->getSelectedItem()+4, false);
menu->setItemChecked(menu->getSelectedItem()+5, false);
menu->setItemChecked(menu->getSelectedItem()+6, false);
if (Model)
Model->setDebugDataVisible(scene::EDS_OFF);
break;
case GUI_ID_DEBUG_BOUNDING_BOX:
menu->setItemChecked(menu->getSelectedItem(),
!menu->isItemChecked(menu->getSelectedItem()));
if (Model)
Model->setDebugDataVisible
(
(scene::E_DEBUG_SCENE_TYPE)(Model->
isDebugDataVisible()^scene::EDS_BBOX)
);
break;
case GUI_ID_DEBUG_NORMALS:
menu->setItemChecked(menu->getSelectedItem(),
!menu->isItemChecked(menu->getSelectedItem()));
if (Model)
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)
(Model->isDebugDataVisible()^scene::EDS_NORMALS));
break;
case GUI_ID_DEBUG_SKELETON:
menu->setItemChecked(menu->getSelectedItem(),
!menu->isItemChecked(menu->getSelectedItem()));
if (Model)
Model->setDebugDataVisible
(
(scene::E_DEBUG_SCENE_TYPE)(Model->
isDebugDataVisible()^scene::EDS_SKELETON)
);
break;
case GUI_ID_DEBUG_WIRE_OVERLAY:
menu->setItemChecked(menu->getSelectedItem(),
!menu->isItemChecked(menu->getSelectedItem()));
if (Model)
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY));
break;
case GUI_ID_DEBUG_HALF_TRANSPARENT:
menu->setItemChecked(menu->getSelectedItem(),
!menu->isItemChecked(menu->getSelectedItem()));
if (Model)
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY));
break;
case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES:
menu->setItemChecked(menu->getSelectedItem(),
!menu->isItemChecked(menu->getSelectedItem()));
if (Model)
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)
(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS));
break;
case GUI_ID_DEBUG_ALL:
menu->setItemChecked(menu->getSelectedItem()-1, true);
menu->setItemChecked(menu->getSelectedItem()-2, true);
menu->setItemChecked(menu->getSelectedItem()-3, true);
menu->setItemChecked(menu->getSelectedItem()-4, true);
menu->setItemChecked(menu->getSelectedItem()-5, true);
menu->setItemChecked(menu->getSelectedItem()-6, true);
if (Model)
Model->setDebugDataVisible(scene::EDS_FULL);
break;
case GUI_ID_ABOUT:
showAboutText();
break;
case GUI_ID_MODEL_MATERIAL_SOLID:
if (Model)
Model->setMaterialType(video::EMT_SOLID);
break;
case GUI_ID_MODEL_MATERIAL_TRANSPARENT:
if (Model)
Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
break;
case GUI_ID_MODEL_MATERIAL_REFLECTION:
if (Model)
Model->setMaterialType(video::EMT_SPHERE_MAP);
break;
case GUI_ID_CAMERA_MAYA:
setActiveCamera(Camera[0]);
break;
case GUI_ID_CAMERA_FIRST_PERSON:
setActiveCamera(Camera[1]);
break;
}
}
void OnTextureFilterSelected( IGUIComboBox* combo )
{
s32 pos = combo->getSelected();
switch (pos)
{
case 0:
if (Model)
{
Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false);
Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false);
}
break;
case 1:
if (Model)
{
Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, true);
Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false);
}
break;
case 2:
if (Model)
{
Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, true);
}
break;
case 3:
if (Model)
{
Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, true);
}
break;
case 4:
if (Model)
{
Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false);
}
break;
}
}
};