Code: Select all
#include <iostream>
#include <irrlicht.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")
#endif
IrrlichtDevice* device;
IVideoDriver* driver;
ISceneManager* smgr;
IGUIEnvironment* env;
namespace irr
{
namespace scene
{
enum ESCENE_NODE_TYPE_EXTRA
{
ESNT_GROUP = MAKE_IRR_ID('g','r','u','p')
};
}
}
enum RXKeyStates { KSTATE_UP, KSTATE_DOWN, KSTATE_HELD, KSTATE_RELEASED };
// GROUP NODE (based on CEmptySceneNode)
class CMyGroupSceneNode : public scene::ISceneNode
{
public:
//! constructor
CMyGroupSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
// : ISceneNode(parent, mgr, id)
: ISceneNode((parent ? parent : mgr->getRootSceneNode()), mgr, id) // Else a NULL parent crashes it
{
#ifdef _DEBUG
setDebugName("CMyGroupSceneNode");
#endif
setAutomaticCulling(scene::EAC_OFF);
Box.reset(getPosition()); // Reset size to a single point, a better way?
}
//! returns the axis aligned bounding box of this node
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return Box;
}
//! This method is called just before the rendering process of the whole scene.
virtual void OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
//! does nothing.
virtual void render()
{
// do nothing
}
//! Returns type of the scene node
//virtual ESCENE_NODE_TYPE getType() const { return ESNT_EMPTY; }
virtual ESCENE_NODE_TYPE getType() const { return (ESCENE_NODE_TYPE)ESNT_GROUP; }
//! Creates a clone of this scene node and its children.
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CMyGroupSceneNode* nb = new CMyGroupSceneNode(newParent, newManager, ID);
nb->cloneMembers(this, newManager);
nb->Box = Box;
if ( newParent )
nb->drop();
return nb;
}
private:
core::aabbox3d<f32> Box;
};
// EVENT RECEIVER
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(scene::ISceneManager* smgr)
: SceneManager(smgr)
, SelectedNode(0), LastSelectedNode(0)
{
// GET SCENE MANAGER
SceneManager->grab();
// INIT KEY ARRAY
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
KeyIsDown[i] = KSTATE_UP;
}
virtual ~MyEventReceiver()
{
SceneManager->drop();
}
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
{
// MOUSE LEFT BUTTON
const core::position2di pos(event.MouseInput.X, event.MouseInput.Y);
SelectedNode = SceneManager->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(pos);
std::cout << "Object ID: " << SelectedNode->getID() << std::endl;
ISceneNode *p = SelectedNode->getParent();
if(p != NULL)
{
if(p->getType() == (ESCENE_NODE_TYPE)ESNT_GROUP)
{
std::cout << "Found GROUP CHILD object" << std::endl;
}
}
if(LastSelectedNode == SelectedNode){
std::cout << "Clicked current object" << std::endl;
}
LastSelectedNode = SelectedNode;
return false;
}
else if (event.EventType == irr::EET_KEY_INPUT_EVENT){
// KEYS... 0=up,1=down,2=hold,3=release
if(event.KeyInput.PressedDown){ // PRESSED DOWN
if(KeyIsDown[event.KeyInput.Key]==KSTATE_UP){ KeyIsDown[event.KeyInput.Key]=KSTATE_DOWN; } // INITIAL DOWN
}else{ // PRESSED UP
KeyIsDown[event.KeyInput.Key]=KSTATE_RELEASED; // RELEASED
}
}
return false;
}
virtual void cycle_end(){
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i){
//KeyIsDown[i] = false;
if(KeyIsDown[i]==KSTATE_DOWN){ KeyIsDown[i]=KSTATE_HELD; }
else if(KeyIsDown[i]==KSTATE_RELEASED){ KeyIsDown[i]=KSTATE_UP; }
}
}
// This is used to check whether a key is being held down
virtual s32 getKey(EKEY_CODE keyCode) const{
return KeyIsDown[keyCode]; // KEYS... 0=up,1=down,2=hold,3=release
}
private:
scene::ISceneManager* SceneManager;
s32 KeyIsDown[KEY_KEY_CODES_COUNT];
public:
scene::ISceneNode* SelectedNode;
scene::ISceneNode* LastSelectedNode;
};
void node_anim(ISceneNode *node, core::vector3df offset=core::vector3df(0,0.5f,0), u32 t=250, bool loop=true, bool ping=true)
{
if(node)
{
scene::ISceneNodeAnimator* anim = NULL;
anim = smgr->createFlyStraightAnimator(node->getPosition(), node->getPosition()+offset, t, loop, ping);
if(anim)
{
node->addAnimator(anim);
anim->drop();
}
}
}
scene::ISceneNode *add_node(io::path s_mesh, io::path s_tex, scene::ISceneNode *parent, vector3df pos=vector3df(0.0f), vector3df scale=vector3df(1.0f), vector3df rot=vector3df(0.0f), s32 id=-1)
{
scene::IAnimatedMesh* mesh = smgr->getMesh(s_mesh);
//scene::ISceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
scene::IAnimatedMeshSceneNode *node = smgr->addAnimatedMeshSceneNode(mesh, NULL, id);
node->setMaterialTexture(0, driver->getTexture(s_tex));
if(parent)
{
node->setParent(parent);
}
node->setScale(scale);
node->setPosition(pos);
node->setRotation(rot);
node->getMaterial(0).Shininess = 2.0f;
//node->getMaterial(0).SpecularColor.set(0,0,0,0);
node->getMaterial(0).Lighting = true;
// SET SHADOWS
bool cast_shadows= true;
if(cast_shadows){
((scene::IAnimatedMeshSceneNode*)node)->addShadowVolumeSceneNode();
((scene::IAnimatedMeshSceneNode*)node)->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); // TODO: only required if scale not 1,1,1
}
return node;
}
void test_00()
{
ISceneNode *node0 = new CMyGroupSceneNode(NULL, smgr, 303);
node0->drop();
node0->setPosition(vector3df(0.0f));
node0->setScale(vector3df(1.0f));
node0->setRotation(vector3df(0.0f));
scene::ISceneNode *node1 = add_node("media/box_a_chamfer2.dae", "media/textures.png", NULL, vector3df(4.0f, 0.0f, 0.0f), vector3df(1.0f), vector3df(0.0f), 304);
scene::ISceneNode *node2 = add_node("media/box_a_chamfer2.dae", "media/textures.png", NULL, vector3df(4.0f, 0.0f, -4.0f), vector3df(1.0f), vector3df(0.0f), 305);
node0->addChild(node1);
node0->addChild(node2);
// BOUNCERS
node_anim(node0);
//node_anim(node1);
}
int main()
{
bool shadows = true;
bool fullscreen = false;
device = createDevice(video::EDT_OPENGL, dimension2d<u32>(800, 480), 24, fullscreen, shadows, false);
if (device == 0)
return 1; // could not create selected driver.
driver = device->getVideoDriver();
smgr = device->getSceneManager();
env = device->getGUIEnvironment();
MyEventReceiver receiver(smgr);
device->setEventReceiver(&receiver);
IGUISkin* skin = env->getSkin();
IGUIFont* font = env->getFont("media/fonthaettenschweiler.bmp");
if (font)
skin->setFont(font);
skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
// LIGHTS
smgr->setShadowColor(video::SColor(150,0,0,0));
smgr->setAmbientLight(video::SColorf(0.8f,0.8f,0.8f,1)); // r,g,b,a
smgr->addLightSceneNode(0, core::vector3df(-20,10,-20), video::SColorf(0.3f,0.3f,0.3f), 100.0f, 1);
ILightSceneNode* light1 = smgr->addLightSceneNode(0, core::vector3df(-20,1,20), video::SColorf(1.0f,0.3f,0.3f), 100.0f, 1);
light1->enableCastShadow(false);
// GROUND
//scene::ISceneNode *node0 =
add_node("media/box_a_chamfer.dae", "media/textures.png", NULL, vector3df(0.0f, -0.5f, 0.0f), vector3df(20.0f, 0.1f, 20.0f), vector3df(0.0f), 111);
// CAM
ICameraSceneNode* cam = smgr->addCameraSceneNode();
cam->setTarget(vector3df(0,0,0)); // cube->getPosition());
cam->setPosition(vector3df(5,5,5));
//cam->setPosition(vector3df(50,50,50));
// GUI
//env->addStaticText(L"Hello", core::rect<s32>(10,10,790,50), false, false, NULL, -1, true);
// TEST
test_00();
bool run = true;
while(device && device->run() && run)
{
if(device->isWindowActive())
{
if(receiver.getKey(irr::KEY_ESCAPE)==KSTATE_RELEASED)
run = false;
driver->beginScene(true, true, video::SColor(0,55,55,55));
smgr->drawAll();
env->drawAll();
driver->endScene();
receiver.cycle_end();
}else{
device->yield();
}
}
device->drop();
}