aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/main.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/main.cpp2188
1 files changed, 2188 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/main.cpp b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/main.cpp
new file mode 100644
index 0000000..b2277e6
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/main.cpp
@@ -0,0 +1,2188 @@
1/** Example 021 Quake3 Explorer
2
3This Tutorial shows how to load different Quake 3 maps.
4
5Features:
6 - Load BSP Archives at Runtime from the menu
7 - Load a Map from the menu. Showing with Screenshot
8 - Set the VideoDriver at runtime from menu
9 - Adjust GammaLevel at runtime
10 - Create SceneNodes for the Shaders
11 - Load EntityList and create Entity SceneNodes
12 - Create Players with Weapons and with Collision Response
13 - Play music
14
15You can download the Quake III Arena demo ( copyright id software )
16at the following location:
17ftp://ftp.idsoftware.com/idstuff/quake3/win32/q3ademo.exe
18
19Copyright 2006-2011 Burningwater, Thomas Alten
20*/
21
22#include "driverChoice.h"
23#include <irrlicht.h>
24#include "q3factory.h"
25#include "sound.h"
26
27/*
28 Game Data is used to hold Data which is needed to drive the game
29*/
30struct GameData
31{
32 GameData ( const path &startupDir) :
33 retVal(0), StartupDir(startupDir), createExDevice(0), Device(0)
34 {
35 setDefault ();
36 }
37
38 void setDefault ();
39 s32 save ( const path &filename );
40 s32 load ( const path &filename );
41
42 s32 debugState;
43 s32 gravityState;
44 s32 flyTroughState;
45 s32 wireFrame;
46 s32 guiActive;
47 s32 guiInputActive;
48 f32 GammaValue;
49 s32 retVal;
50 s32 sound;
51
52 path StartupDir;
53 stringw CurrentMapName;
54 array<path> CurrentArchiveList;
55
56 vector3df PlayerPosition;
57 vector3df PlayerRotation;
58
59 tQ3EntityList Variable;
60
61 Q3LevelLoadParameter loadParam;
62 SIrrlichtCreationParameters deviceParam;
63 funcptr_createDeviceEx createExDevice;
64 IrrlichtDevice *Device;
65};
66
67/*
68 set default settings
69*/
70void GameData::setDefault ()
71{
72 debugState = EDS_OFF;
73 gravityState = 1;
74 flyTroughState = 0;
75 wireFrame = 0;
76 guiActive = 1;
77 guiInputActive = 0;
78 GammaValue = 1.f;
79
80 // default deviceParam;
81#if defined ( _IRR_WINDOWS_ )
82 deviceParam.DriverType = EDT_DIRECT3D9;
83#else
84 deviceParam.DriverType = EDT_OPENGL;
85#endif
86 deviceParam.WindowSize.Width = 800;
87 deviceParam.WindowSize.Height = 600;
88 deviceParam.Fullscreen = false;
89 deviceParam.Bits = 24;
90 deviceParam.ZBufferBits = 16;
91 deviceParam.Vsync = false;
92 deviceParam.AntiAlias = false;
93
94 // default Quake3 loadParam
95 loadParam.defaultLightMapMaterial = EMT_LIGHTMAP;
96 loadParam.defaultModulate = EMFN_MODULATE_1X;
97 loadParam.defaultFilter = EMF_ANISOTROPIC_FILTER;
98 loadParam.verbose = 2;
99 loadParam.mergeShaderBuffer = 1; // merge meshbuffers with same material
100 loadParam.cleanUnResolvedMeshes = 1; // should unresolved meshes be cleaned. otherwise blue texture
101 loadParam.loadAllShaders = 1; // load all scripts in the script directory
102 loadParam.loadSkyShader = 0; // load sky Shader
103 loadParam.alpharef = 1;
104
105 sound = 0;
106
107 CurrentMapName = "";
108 CurrentArchiveList.clear ();
109
110 // Explorer Media directory
111 CurrentArchiveList.push_back ( StartupDir + "../../media/" );
112
113 // Add the original quake3 files before you load your custom map
114 // Most mods are using the original shaders, models&items&weapons
115 CurrentArchiveList.push_back("/q/baseq3/");
116
117 CurrentArchiveList.push_back(StartupDir + "../../media/map-20kdm2.pk3");
118}
119
120/*
121 Load the current game State from a typical quake3 cfg file
122*/
123s32 GameData::load ( const path &filename )
124{
125 if (!Device)
126 return 0;
127
128 // the quake3 mesh loader can also handle *.shader and *.cfg file
129 IQ3LevelMesh* mesh = (IQ3LevelMesh*) Device->getSceneManager()->getMesh ( filename );
130 if (!mesh)
131 return 0;
132
133 tQ3EntityList &entityList = mesh->getEntityList ();
134
135 stringc s;
136 u32 pos;
137
138 for ( u32 e = 0; e != entityList.size (); ++e )
139 {
140 //dumpShader ( s, &entityList[e], false );
141 //printf ( s.c_str () );
142
143 for ( u32 g = 0; g != entityList[e].getGroupSize (); ++g )
144 {
145 const SVarGroup *group = entityList[e].getGroup ( g );
146
147 for ( u32 index = 0; index < group->Variable.size (); ++index )
148 {
149 const SVariable &v = group->Variable[index];
150 pos = 0;
151 if ( v.name == "playerposition" )
152 {
153 PlayerPosition = getAsVector3df ( v.content, pos );
154 }
155 else
156 if ( v.name == "playerrotation" )
157 {
158 PlayerRotation = getAsVector3df ( v.content, pos );
159 }
160 }
161 }
162 }
163
164 return 1;
165}
166
167/*
168 Store the current game State in a quake3 configuration file
169*/
170s32 GameData::save ( const path &filename )
171{
172 return 0;
173 if (!Device)
174 return 0;
175
176 c8 buf[128];
177 u32 i;
178
179 // Store current Archive for restart
180 CurrentArchiveList.clear();
181 IFileSystem *fs = Device->getFileSystem();
182 for ( i = 0; i != fs->getFileArchiveCount(); ++i )
183 {
184 CurrentArchiveList.push_back ( fs->getFileArchive(i)->getFileList()->getPath() );
185 }
186
187 // Store Player Position and Rotation
188 ICameraSceneNode * camera = Device->getSceneManager()->getActiveCamera ();
189 if ( camera )
190 {
191 PlayerPosition = camera->getPosition ();
192 PlayerRotation = camera->getRotation ();
193 }
194
195 IWriteFile *file = fs->createAndWriteFile ( filename );
196 if (!file)
197 return 0;
198
199 snprintf ( buf, 128, "playerposition %.f %.f %.f\nplayerrotation %.f %.f %.f\n",
200 PlayerPosition.X, PlayerPosition.Z, PlayerPosition.Y,
201 PlayerRotation.X, PlayerRotation.Z, PlayerRotation.Y);
202 file->write ( buf, (s32) strlen ( buf ) );
203 for ( i = 0; i != fs->getFileArchiveCount(); ++i )
204 {
205 snprintf ( buf, 128, "archive %s\n",stringc ( fs->getFileArchive(i)->getFileList()->getPath() ).c_str () );
206 file->write ( buf, (s32) strlen ( buf ) );
207 }
208
209 file->drop ();
210 return 1;
211}
212
213/*
214 Representing a player
215*/
216struct Q3Player : public IAnimationEndCallBack
217{
218 Q3Player ()
219 : Device(0), MapParent(0), Mesh(0), WeaponNode(0), StartPositionCurrent(0)
220 {
221 animation[0] = 0;
222 memset(Anim, 0, sizeof(TimeFire)*4);
223 }
224
225 virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node);
226
227 void create ( IrrlichtDevice *device,
228 IQ3LevelMesh* mesh,
229 ISceneNode *mapNode,
230 IMetaTriangleSelector *meta
231 );
232 void shutdown ();
233 void setAnim ( const c8 *name );
234 void respawn ();
235 void setpos ( const vector3df &pos, const vector3df& rotation );
236
237 ISceneNodeAnimatorCollisionResponse * cam() { return camCollisionResponse ( Device ); }
238
239 IrrlichtDevice *Device;
240 ISceneNode* MapParent;
241 IQ3LevelMesh* Mesh;
242 IAnimatedMeshSceneNode* WeaponNode;
243 s32 StartPositionCurrent;
244 TimeFire Anim[4];
245 c8 animation[64];
246 c8 buf[64];
247};
248
249
250/* End player
251*/
252void Q3Player::shutdown ()
253{
254 setAnim ( 0 );
255
256 dropElement (WeaponNode);
257
258 if ( Device )
259 {
260 ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera();
261 dropElement ( camera );
262 Device = 0;
263 }
264
265 MapParent = 0;
266 Mesh = 0;
267}
268
269
270/* create a new player
271*/
272void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode *mapNode, IMetaTriangleSelector *meta )
273{
274 setTimeFire ( Anim + 0, 200, FIRED );
275 setTimeFire ( Anim + 1, 5000 );
276
277 if (!device)
278 return;
279 // load FPS weapon to Camera
280 Device = device;
281 Mesh = mesh;
282 MapParent = mapNode;
283
284 ISceneManager *smgr = device->getSceneManager ();
285 IVideoDriver * driver = device->getVideoDriver();
286
287 ICameraSceneNode* camera = 0;
288
289 SKeyMap keyMap[10];
290 keyMap[0].Action = EKA_MOVE_FORWARD;
291 keyMap[0].KeyCode = KEY_UP;
292 keyMap[1].Action = EKA_MOVE_FORWARD;
293 keyMap[1].KeyCode = KEY_KEY_W;
294
295 keyMap[2].Action = EKA_MOVE_BACKWARD;
296 keyMap[2].KeyCode = KEY_DOWN;
297 keyMap[3].Action = EKA_MOVE_BACKWARD;
298 keyMap[3].KeyCode = KEY_KEY_S;
299
300 keyMap[4].Action = EKA_STRAFE_LEFT;
301 keyMap[4].KeyCode = KEY_LEFT;
302 keyMap[5].Action = EKA_STRAFE_LEFT;
303 keyMap[5].KeyCode = KEY_KEY_A;
304
305 keyMap[6].Action = EKA_STRAFE_RIGHT;
306 keyMap[6].KeyCode = KEY_RIGHT;
307 keyMap[7].Action = EKA_STRAFE_RIGHT;
308 keyMap[7].KeyCode = KEY_KEY_D;
309
310 keyMap[8].Action = EKA_JUMP_UP;
311 keyMap[8].KeyCode = KEY_KEY_J;
312
313 keyMap[9].Action = EKA_CROUCH;
314 keyMap[9].KeyCode = KEY_KEY_C;
315
316 camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 0.6f, -1, keyMap, 10, false, 0.6f);
317 camera->setName ( "First Person Camera" );
318 //camera->setFOV ( 100.f * core::DEGTORAD );
319 camera->setFarValue( 20000.f );
320
321 IAnimatedMeshMD2* weaponMesh = (IAnimatedMeshMD2*) smgr->getMesh("gun.md2");
322 if ( 0 == weaponMesh )
323 return;
324
325 if ( weaponMesh->getMeshType() == EAMT_MD2 )
326 {
327 s32 count = weaponMesh->getAnimationCount();
328 for ( s32 i = 0; i != count; ++i )
329 {
330 snprintf ( buf, 64, "Animation: %s", weaponMesh->getAnimationName(i) );
331 device->getLogger()->log(buf, ELL_INFORMATION);
332 }
333 }
334
335 WeaponNode = smgr->addAnimatedMeshSceneNode(
336 weaponMesh,
337 smgr->getActiveCamera(),
338 10,
339 vector3df( 0, 0, 0),
340 vector3df(-90,-90,90)
341 );
342 WeaponNode->setMaterialFlag(EMF_LIGHTING, false);
343 WeaponNode->setMaterialTexture(0, driver->getTexture( "gun.jpg"));
344 WeaponNode->setLoopMode ( false );
345 WeaponNode->setName ( "tommi the gun man" );
346
347 //create a collision auto response animator
348 ISceneNodeAnimator* anim =
349 smgr->createCollisionResponseAnimator( meta, camera,
350 vector3df(30,45,30),
351 getGravity ( "earth" ),
352 vector3df(0,40,0),
353 0.0005f
354 );
355
356 camera->addAnimator( anim );
357 anim->drop();
358
359 if ( meta )
360 {
361 meta->drop ();
362 }
363
364 respawn ();
365 setAnim ( "idle" );
366}
367
368
369/*
370 so we need a good starting Position in the level.
371 we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch"
372*/
373void Q3Player::respawn ()
374{
375 if (!Device)
376 return;
377 ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera();
378
379 Device->getLogger()->log( "respawn" );
380
381 if ( StartPositionCurrent >= Q3StartPosition (
382 Mesh, camera,StartPositionCurrent++,
383 cam ()->getEllipsoidTranslation() )
384 )
385 {
386 StartPositionCurrent = 0;
387 }
388}
389
390/*
391 set Player position from saved coordinates
392*/
393void Q3Player::setpos ( const vector3df &pos, const vector3df &rotation )
394{
395 if (!Device)
396 return;
397 Device->getLogger()->log( "setpos" );
398
399 ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera();
400 if ( camera )
401 {
402 camera->setPosition ( pos );
403 camera->setRotation ( rotation );
404 //! New. FPSCamera and animators catches reset on animate 0
405 camera->OnAnimate ( 0 );
406 }
407}
408
409/* set the Animation of the player and weapon
410*/
411void Q3Player::setAnim ( const c8 *name )
412{
413 if ( name )
414 {
415 snprintf ( animation, 64, "%s", name );
416 if ( WeaponNode )
417 {
418 WeaponNode->setAnimationEndCallback ( this );
419 WeaponNode->setMD2Animation ( animation );
420 }
421 }
422 else
423 {
424 animation[0] = 0;
425 if ( WeaponNode )
426 {
427 WeaponNode->setAnimationEndCallback ( 0 );
428 }
429 }
430}
431
432
433// Callback
434void Q3Player::OnAnimationEnd(IAnimatedMeshSceneNode* node)
435{
436 setAnim ( 0 );
437}
438
439
440
441/* GUI Elements
442*/
443struct GUI
444{
445 GUI ()
446 {
447 memset ( this, 0, sizeof ( *this ) );
448 }
449
450 void drop()
451 {
452 dropElement ( Window );
453 dropElement ( Logo );
454 }
455
456 IGUIComboBox* VideoDriver;
457 IGUIComboBox* VideoMode;
458 IGUICheckBox* FullScreen;
459 IGUICheckBox* Bit32;
460 IGUIScrollBar* MultiSample;
461 IGUIButton* SetVideoMode;
462
463 IGUIScrollBar* Tesselation;
464 IGUIScrollBar* Gamma;
465 IGUICheckBox* Collision;
466 IGUICheckBox* Visible_Map;
467 IGUICheckBox* Visible_Shader;
468 IGUICheckBox* Visible_Fog;
469 IGUICheckBox* Visible_Unresolved;
470 IGUICheckBox* Visible_Skydome;
471 IGUIButton* Respawn;
472
473 IGUITable* ArchiveList;
474 IGUIButton* ArchiveAdd;
475 IGUIButton* ArchiveRemove;
476 IGUIFileOpenDialog* ArchiveFileOpen;
477 IGUIButton* ArchiveUp;
478 IGUIButton* ArchiveDown;
479
480 IGUIListBox* MapList;
481 IGUITreeView* SceneTree;
482 IGUIStaticText* StatusLine;
483 IGUIImage* Logo;
484 IGUIWindow* Window;
485};
486
487
488/*
489 CQuake3EventHandler controls the game
490*/
491class CQuake3EventHandler : public IEventReceiver
492{
493public:
494
495 CQuake3EventHandler( GameData *gameData );
496 virtual ~CQuake3EventHandler ();
497
498 void Animate();
499 void Render();
500
501 void AddArchive ( const path& archiveName );
502 void LoadMap ( const stringw& mapName, s32 collision );
503 void CreatePlayers();
504 void AddSky( u32 dome, const c8 *texture );
505 Q3Player *GetPlayer ( u32 index ) { return &Player[index]; }
506
507 void CreateGUI();
508 void SetGUIActive( s32 command);
509
510 bool OnEvent(const SEvent& eve);
511
512
513private:
514
515 GameData *Game;
516
517 IQ3LevelMesh* Mesh;
518 ISceneNode* MapParent;
519 ISceneNode* ShaderParent;
520 ISceneNode* ItemParent;
521 ISceneNode* UnresolvedParent;
522 ISceneNode* BulletParent;
523 ISceneNode* FogParent;
524 ISceneNode * SkyNode;
525 IMetaTriangleSelector *Meta;
526
527 c8 buf[256];
528
529 Q3Player Player[2];
530
531 struct SParticleImpact
532 {
533 u32 when;
534 vector3df pos;
535 vector3df outVector;
536 };
537 array<SParticleImpact> Impacts;
538 void useItem( Q3Player * player);
539 void createParticleImpacts( u32 now );
540
541 void createTextures ();
542 void addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent);
543
544 GUI gui;
545 void dropMap ();
546};
547
548/* Constructor
549*/
550CQuake3EventHandler::CQuake3EventHandler( GameData *game )
551: Game(game), Mesh(0), MapParent(0), ShaderParent(0), ItemParent(0), UnresolvedParent(0),
552 BulletParent(0), FogParent(0), SkyNode(0), Meta(0)
553{
554 buf[0]=0;
555 // Also use 16 Bit Textures for 16 Bit RenderDevice
556 if ( Game->deviceParam.Bits == 16 )
557 {
558 game->Device->getVideoDriver()->setTextureCreationFlag(ETCF_ALWAYS_16_BIT, true);
559 }
560
561 // Quake3 Shader controls Z-Writing
562 game->Device->getSceneManager()->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
563
564 // create internal textures
565 createTextures ();
566
567 sound_init ( game->Device );
568
569 Game->Device->setEventReceiver ( this );
570}
571
572
573// destructor
574CQuake3EventHandler::~CQuake3EventHandler ()
575{
576 Player[0].shutdown ();
577 sound_shutdown ();
578
579 Game->save( "explorer.cfg" );
580
581 Game->Device->drop();
582}
583
584
585// create runtime textures smog, fog
586void CQuake3EventHandler::createTextures()
587{
588 IVideoDriver * driver = Game->Device->getVideoDriver();
589
590 dimension2du dim(64, 64);
591
592 video::IImage* image;
593 u32 i;
594 u32 x;
595 u32 y;
596 u32 * data;
597 for ( i = 0; i != 8; ++i )
598 {
599 image = driver->createImage ( video::ECF_A8R8G8B8, dim);
600 data = (u32*) image->lock ();
601 for ( y = 0; y != dim.Height; ++y )
602 {
603 for ( x = 0; x != dim.Width; ++x )
604 {
605 data [x] = 0xFFFFFFFF;
606 }
607 data = (u32*) ( (u8*) data + image->getPitch() );
608 }
609 image->unlock();
610 snprintf ( buf, 64, "smoke_%02d", i );
611 driver->addTexture( buf, image );
612 image->drop ();
613 }
614
615 // fog
616 for ( i = 0; i != 1; ++i )
617 {
618 image = driver->createImage ( video::ECF_A8R8G8B8, dim);
619 data = (u32*) image->lock ();
620 for ( y = 0; y != dim.Height; ++y )
621 {
622 for ( x = 0; x != dim.Width; ++x )
623 {
624 data [x] = 0xFFFFFFFF;
625 }
626 data = (u32*) ( (u8*) data + image->getPitch() );
627 }
628 image->unlock();
629 snprintf ( buf, 64, "fog_%02d", i );
630 driver->addTexture( buf, image );
631 image->drop ();
632 }
633}
634
635
636/*
637 create the GUI
638*/
639void CQuake3EventHandler::CreateGUI()
640{
641
642 IGUIEnvironment *env = Game->Device->getGUIEnvironment();
643 IVideoDriver * driver = Game->Device->getVideoDriver();
644
645 gui.drop();
646
647 // set skin font
648 IGUIFont* font = env->getFont("fontlucida.png");
649 if (font)
650 env->getSkin()->setFont(font);
651 env->getSkin()->setColor ( EGDC_BUTTON_TEXT, video::SColor(240,0xAA,0xAA,0xAA) );
652 env->getSkin()->setColor ( EGDC_3D_HIGH_LIGHT, video::SColor(240,0x22,0x22,0x22) );
653 env->getSkin()->setColor ( EGDC_3D_FACE, video::SColor(240,0x44,0x44,0x44) );
654 env->getSkin()->setColor ( EGDC_EDITABLE, video::SColor(240,0x44,0x44,0x44) );
655 env->getSkin()->setColor ( EGDC_FOCUSED_EDITABLE, video::SColor(240,0x54,0x54,0x54) );
656 env->getSkin()->setColor ( EGDC_WINDOW, video::SColor(240,0x66,0x66,0x66) );
657
658 // minimal gui size 800x600
659 dimension2d<u32> dim ( 800, 600 );
660 dimension2d<u32> vdim ( Game->Device->getVideoDriver()->getScreenSize() );
661
662 if ( vdim.Height >= dim.Height && vdim.Width >= dim.Width )
663 {
664 //dim = vdim;
665 }
666 else
667 {
668 }
669
670 gui.Window = env->addWindow ( rect<s32> ( 0, 0, dim.Width, dim.Height ), false, L"Quake3 Explorer" );
671 gui.Window->setToolTipText ( L"Quake3Explorer. Loads and show various BSP File Format and Shaders." );
672 gui.Window->getCloseButton()->setToolTipText ( L"Quit Quake3 Explorer" );
673
674 // add a status line help text
675 gui.StatusLine = env->addStaticText( 0, rect<s32>( 5,dim.Height - 30,dim.Width - 5,dim.Height - 10),
676 false, false, gui.Window, -1, true
677 );
678
679
680 env->addStaticText ( L"VideoDriver:", rect<s32>( dim.Width - 400, 24, dim.Width - 310, 40 ),false, false, gui.Window, -1, false );
681 gui.VideoDriver = env->addComboBox(rect<s32>( dim.Width - 300, 24, dim.Width - 10, 40 ),gui.Window);
682 gui.VideoDriver->addItem(L"Direct3D 9.0c", EDT_DIRECT3D9 );
683 gui.VideoDriver->addItem(L"Direct3D 8.1", EDT_DIRECT3D8 );
684 gui.VideoDriver->addItem(L"OpenGL 1.5", EDT_OPENGL);
685 gui.VideoDriver->addItem(L"Software Renderer", EDT_SOFTWARE);
686 gui.VideoDriver->addItem(L"Burning's Video (TM) Thomas Alten", EDT_BURNINGSVIDEO);
687 gui.VideoDriver->setSelected ( gui.VideoDriver->getIndexForItemData ( Game->deviceParam.DriverType ) );
688 gui.VideoDriver->setToolTipText ( L"Use a VideoDriver" );
689
690 env->addStaticText ( L"VideoMode:", rect<s32>( dim.Width - 400, 44, dim.Width - 310, 60 ),false, false, gui.Window, -1, false );
691 gui.VideoMode = env->addComboBox(rect<s32>( dim.Width - 300, 44, dim.Width - 10, 60 ),gui.Window);
692 gui.VideoMode->setToolTipText ( L"Supported Screenmodes" );
693 IVideoModeList *modeList = Game->Device->getVideoModeList();
694 if ( modeList )
695 {
696 s32 i;
697 for ( i = 0; i != modeList->getVideoModeCount (); ++i )
698 {
699 u16 d = modeList->getVideoModeDepth ( i );
700 if ( d < 16 )
701 continue;
702
703 u16 w = modeList->getVideoModeResolution ( i ).Width;
704 u16 h = modeList->getVideoModeResolution ( i ).Height;
705 u32 val = w << 16 | h;
706
707 if ( gui.VideoMode->getIndexForItemData ( val ) >= 0 )
708 continue;
709
710 f32 aspect = (f32) w / (f32) h;
711 const c8 *a = "";
712 if ( core::equals ( aspect, 1.3333333333f ) ) a = "4:3";
713 else if ( core::equals ( aspect, 1.6666666f ) ) a = "15:9 widescreen";
714 else if ( core::equals ( aspect, 1.7777777f ) ) a = "16:9 widescreen";
715 else if ( core::equals ( aspect, 1.6f ) ) a = "16:10 widescreen";
716 else if ( core::equals ( aspect, 2.133333f ) ) a = "20:9 widescreen";
717
718 snprintf ( buf, sizeof ( buf ), "%d x %d, %s",w, h, a );
719 gui.VideoMode->addItem ( stringw ( buf ).c_str(), val );
720 }
721 }
722 gui.VideoMode->setSelected ( gui.VideoMode->getIndexForItemData (
723 Game->deviceParam.WindowSize.Width << 16 |
724 Game->deviceParam.WindowSize.Height ) );
725
726 gui.FullScreen = env->addCheckBox ( Game->deviceParam.Fullscreen, rect<s32>( dim.Width - 400, 64, dim.Width - 300, 80 ), gui.Window,-1, L"Fullscreen" );
727 gui.FullScreen->setToolTipText ( L"Set Fullscreen or Window Mode" );
728
729 gui.Bit32 = env->addCheckBox ( Game->deviceParam.Bits == 32, rect<s32>( dim.Width - 300, 64, dim.Width - 240, 80 ), gui.Window,-1, L"32Bit" );
730 gui.Bit32->setToolTipText ( L"Use 16 or 32 Bit" );
731
732 env->addStaticText ( L"MultiSample:", rect<s32>( dim.Width - 235, 64, dim.Width - 150, 80 ),false, false, gui.Window, -1, false );
733 gui.MultiSample = env->addScrollBar( true, rect<s32>( dim.Width - 150, 64, dim.Width - 70, 80 ), gui.Window,-1 );
734 gui.MultiSample->setMin ( 0 );
735 gui.MultiSample->setMax ( 8 );
736 gui.MultiSample->setSmallStep ( 1 );
737 gui.MultiSample->setLargeStep ( 1 );
738 gui.MultiSample->setPos ( Game->deviceParam.AntiAlias );
739 gui.MultiSample->setToolTipText ( L"Set the MultiSample (disable, 1x, 2x, 4x, 8x )" );
740
741 gui.SetVideoMode = env->addButton (rect<s32>( dim.Width - 60, 64, dim.Width - 10, 80 ), gui.Window, -1,L"set" );
742 gui.SetVideoMode->setToolTipText ( L"Set Video Mode with current values" );
743
744 env->addStaticText ( L"Gamma:", rect<s32>( dim.Width - 400, 104, dim.Width - 310, 120 ),false, false, gui.Window, -1, false );
745 gui.Gamma = env->addScrollBar( true, rect<s32>( dim.Width - 300, 104, dim.Width - 10, 120 ), gui.Window,-1 );
746 gui.Gamma->setMin ( 50 );
747 gui.Gamma->setMax ( 350 );
748 gui.Gamma->setSmallStep ( 1 );
749 gui.Gamma->setLargeStep ( 10 );
750 gui.Gamma->setPos ( core::floor32 ( Game->GammaValue * 100.f ) );
751 gui.Gamma->setToolTipText ( L"Adjust Gamma Ramp ( 0.5 - 3.5)" );
752 Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f );
753
754
755 env->addStaticText ( L"Tesselation:", rect<s32>( dim.Width - 400, 124, dim.Width - 310, 140 ),false, false, gui.Window, -1, false );
756 gui.Tesselation = env->addScrollBar( true, rect<s32>( dim.Width - 300, 124, dim.Width - 10, 140 ), gui.Window,-1 );
757 gui.Tesselation->setMin ( 2 );
758 gui.Tesselation->setMax ( 12 );
759 gui.Tesselation->setSmallStep ( 1 );
760 gui.Tesselation->setLargeStep ( 1 );
761 gui.Tesselation->setPos ( Game->loadParam.patchTesselation );
762 gui.Tesselation->setToolTipText ( L"How smooth should curved surfaces be rendered" );
763
764 gui.Collision = env->addCheckBox ( true, rect<s32>( dim.Width - 400, 150, dim.Width - 300, 166 ), gui.Window,-1, L"Collision" );
765 gui.Collision->setToolTipText ( L"Set collision on or off ( flythrough ). \nPress F7 on your Keyboard" );
766 gui.Visible_Map = env->addCheckBox ( true, rect<s32>( dim.Width - 300, 150, dim.Width - 240, 166 ), gui.Window,-1, L"Map" );
767 gui.Visible_Map->setToolTipText ( L"Show or not show the static part the Level. \nPress F3 on your Keyboard" );
768 gui.Visible_Shader = env->addCheckBox ( true, rect<s32>( dim.Width - 240, 150, dim.Width - 170, 166 ), gui.Window,-1, L"Shader" );
769 gui.Visible_Shader->setToolTipText ( L"Show or not show the Shader Nodes. \nPress F4 on your Keyboard" );
770 gui.Visible_Fog = env->addCheckBox ( true, rect<s32>( dim.Width - 170, 150, dim.Width - 110, 166 ), gui.Window,-1, L"Fog" );
771 gui.Visible_Fog->setToolTipText ( L"Show or not show the Fog Nodes. \nPress F5 on your Keyboard" );
772 gui.Visible_Unresolved = env->addCheckBox ( true, rect<s32>( dim.Width - 110, 150, dim.Width - 10, 166 ), gui.Window,-1, L"Unresolved" );
773 gui.Visible_Unresolved->setToolTipText ( L"Show the or not show the Nodes the Engine can't handle. \nPress F6 on your Keyboard" );
774 gui.Visible_Skydome = env->addCheckBox ( true, rect<s32>( dim.Width - 110, 180, dim.Width - 10, 196 ), gui.Window,-1, L"Skydome" );
775 gui.Visible_Skydome->setToolTipText ( L"Show the or not show the Skydome." );
776
777 //Respawn = env->addButton ( rect<s32>( dim.Width - 260, 90, dim.Width - 10, 106 ), 0,-1, L"Respawn" );
778
779 env->addStaticText ( L"Archives:", rect<s32>( 5, dim.Height - 530, dim.Width - 600,dim.Height - 514 ),false, false, gui.Window, -1, false );
780
781 gui.ArchiveAdd = env->addButton ( rect<s32>( dim.Width - 725, dim.Height - 530, dim.Width - 665, dim.Height - 514 ), gui.Window,-1, L"add" );
782 gui.ArchiveAdd->setToolTipText ( L"Add an archive, usually packed zip-archives (*.pk3) to the Filesystem" );
783 gui.ArchiveRemove = env->addButton ( rect<s32>( dim.Width - 660, dim.Height - 530, dim.Width - 600, dim.Height - 514 ), gui.Window,-1, L"del" );
784 gui.ArchiveRemove->setToolTipText ( L"Remove the selected archive from the FileSystem." );
785 gui.ArchiveUp = env->addButton ( rect<s32>( dim.Width - 575, dim.Height - 530, dim.Width - 515, dim.Height - 514 ), gui.Window,-1, L"up" );
786 gui.ArchiveUp->setToolTipText ( L"Arrange Archive Look-up Hirachy. Move the selected Archive up" );
787 gui.ArchiveDown = env->addButton ( rect<s32>( dim.Width - 510, dim.Height - 530, dim.Width - 440, dim.Height - 514 ), gui.Window,-1, L"down" );
788 gui.ArchiveDown->setToolTipText ( L"Arrange Archive Look-up Hirachy. Move the selected Archive down" );
789
790
791 gui.ArchiveList = env->addTable ( rect<s32>( 5,dim.Height - 510, dim.Width - 450,dim.Height - 410 ), gui.Window );
792 gui.ArchiveList->addColumn ( L"Type", 0 );
793 gui.ArchiveList->addColumn ( L"Real File Path", 1 );
794 gui.ArchiveList->setColumnWidth ( 0, 60 );
795 gui.ArchiveList->setColumnWidth ( 1, 284 );
796 gui.ArchiveList->setToolTipText ( L"Show the attached Archives" );
797
798
799 env->addStaticText ( L"Maps:", rect<s32>( 5, dim.Height - 400, dim.Width - 450,dim.Height - 380 ),false, false, gui.Window, -1, false );
800 gui.MapList = env->addListBox ( rect<s32>( 5,dim.Height - 380, dim.Width - 450,dim.Height - 40 ), gui.Window, -1, true );
801 gui.MapList->setToolTipText ( L"Show the current Maps in all Archives.\n Double-Click the Map to start the level" );
802
803
804 // create a visible Scene Tree
805 env->addStaticText ( L"Scenegraph:", rect<s32>( dim.Width - 400, dim.Height - 400, dim.Width - 5,dim.Height - 380 ),false, false, gui.Window, -1, false );
806 gui.SceneTree = env->addTreeView( rect<s32>( dim.Width - 400, dim.Height - 380, dim.Width - 5, dim.Height - 40 ),
807 gui.Window, -1, true, true, false );
808 gui.SceneTree->setToolTipText ( L"Show the current Scenegraph" );
809 gui.SceneTree->getRoot()->clearChildren();
810 addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() );
811
812
813 IGUIImageList* imageList = env->createImageList( driver->getTexture ( "iconlist.png" ),
814 dimension2di( 32, 32 ), true );
815
816 if ( imageList )
817 {
818 gui.SceneTree->setImageList( imageList );
819 imageList->drop ();
820 }
821
822
823 // load the engine logo
824 gui.Logo = env->addImage( driver->getTexture("irrlichtlogo3.png"), position2d<s32>(5, 16 ), true, 0 );
825 gui.Logo->setToolTipText ( L"The great Irrlicht Engine" );
826
827 AddArchive ( "" );
828}
829
830
831/*
832 Add an Archive to the FileSystems and updates the GUI
833*/
834void CQuake3EventHandler::AddArchive ( const path& archiveName )
835{
836 IFileSystem *fs = Game->Device->getFileSystem();
837 u32 i;
838
839 if ( archiveName.size () )
840 {
841 bool exists = false;
842 for ( i = 0; i != fs->getFileArchiveCount(); ++i )
843 {
844 if ( fs->getFileArchive(i)->getFileList()->getPath() == archiveName )
845 {
846 exists = true;
847 break;
848 }
849 }
850
851 if (!exists)
852 {
853 fs->addFileArchive(archiveName, true, false);
854 }
855 }
856
857 // store the current archives in game data
858 // show the attached Archive in proper order
859 if ( gui.ArchiveList )
860 {
861 gui.ArchiveList->clearRows();
862
863 for ( i = 0; i != fs->getFileArchiveCount(); ++i )
864 {
865 IFileArchive * archive = fs->getFileArchive ( i );
866
867 u32 index = gui.ArchiveList->addRow(i);
868
869 core::stringw typeName;
870 switch(archive->getType())
871 {
872 case io::EFAT_ZIP:
873 typeName = "ZIP";
874 break;
875 case io::EFAT_GZIP:
876 typeName = "gzip";
877 break;
878 case io::EFAT_FOLDER:
879 typeName = "Mount";
880 break;
881 case io::EFAT_PAK:
882 typeName = "PAK";
883 break;
884 case io::EFAT_TAR:
885 typeName = "TAR";
886 break;
887 default:
888 typeName = "archive";
889 }
890
891 gui.ArchiveList->setCellText ( index, 0, typeName );
892 gui.ArchiveList->setCellText ( index, 1, archive->getFileList()->getPath() );
893 }
894 }
895
896
897 // browse the archives for maps
898 if ( gui.MapList )
899 {
900 gui.MapList->clear();
901
902 IGUISpriteBank *bank = Game->Device->getGUIEnvironment()->getSpriteBank("sprite_q3map");
903 if ( 0 == bank )
904 bank = Game->Device->getGUIEnvironment()->addEmptySpriteBank("sprite_q3map");
905
906 SGUISprite sprite;
907 SGUISpriteFrame frame;
908 core::rect<s32> r;
909
910 bank->getSprites().clear();
911 bank->getPositions().clear ();
912 gui.MapList->setSpriteBank ( bank );
913
914 u32 g = 0;
915 core::stringw s;
916
917 // browse the attached file system
918 fs->setFileListSystem ( FILESYSTEM_VIRTUAL );
919 fs->changeWorkingDirectoryTo ( "/maps/" );
920 IFileList *fileList = fs->createFileList ();
921 fs->setFileListSystem ( FILESYSTEM_NATIVE );
922
923 for ( i=0; i< fileList->getFileCount(); ++i)
924 {
925 s = fileList->getFullFileName(i);
926 if ( s.find ( ".bsp" ) >= 0 )
927 {
928 // get level screenshot. reformat texture to 128x128
929 path c ( s );
930 deletePathFromFilename ( c );
931 cutFilenameExtension ( c, c );
932 c = path ( "levelshots/" ) + c;
933
934 dimension2du dim ( 128, 128 );
935 IVideoDriver * driver = Game->Device->getVideoDriver();
936 IImage* image = 0;
937 ITexture *tex = 0;
938 path filename;
939
940 filename = c + ".jpg";
941 if ( fs->existFile ( filename ) )
942 image = driver->createImageFromFile( filename );
943 if ( 0 == image )
944 {
945 filename = c + ".tga";
946 if ( fs->existFile ( filename ) )
947 image = driver->createImageFromFile( filename );
948 }
949
950 if ( image )
951 {
952 IImage* filter = driver->createImage ( video::ECF_R8G8B8, dim );
953 image->copyToScalingBoxFilter ( filter, 0 );
954 image->drop ();
955 image = filter;
956 }
957
958 if ( image )
959 {
960 tex = driver->addTexture ( filename, image );
961 image->drop ();
962 }
963
964
965 bank->setTexture ( g, tex );
966
967 r.LowerRightCorner.X = dim.Width;
968 r.LowerRightCorner.Y = dim.Height;
969 gui.MapList->setItemHeight ( r.LowerRightCorner.Y + 4 );
970 frame.rectNumber = bank->getPositions().size();
971 frame.textureNumber = g;
972
973 bank->getPositions().push_back(r);
974
975 sprite.Frames.set_used ( 0 );
976 sprite.Frames.push_back(frame);
977 sprite.frameTime = 0;
978 bank->getSprites().push_back(sprite);
979
980 gui.MapList->addItem ( s.c_str (), g );
981 g += 1;
982 }
983 }
984 fileList->drop ();
985
986 gui.MapList->setSelected ( -1 );
987 IGUIScrollBar * bar = (IGUIScrollBar*)gui.MapList->getElementFromId( 0 );
988 if ( bar )
989 bar->setPos ( 0 );
990
991 }
992
993}
994
995/*
996 clears the Map in Memory
997*/
998void CQuake3EventHandler::dropMap ()
999{
1000 IVideoDriver * driver = Game->Device->getVideoDriver();
1001
1002 driver->removeAllHardwareBuffers ();
1003 driver->removeAllTextures ();
1004
1005 Player[0].shutdown ();
1006
1007
1008 dropElement ( ItemParent );
1009 dropElement ( ShaderParent );
1010 dropElement ( UnresolvedParent );
1011 dropElement ( FogParent );
1012 dropElement ( BulletParent );
1013
1014
1015 Impacts.clear();
1016
1017 if ( Meta )
1018 {
1019 Meta = 0;
1020 }
1021
1022 dropElement ( MapParent );
1023 dropElement ( SkyNode );
1024
1025 // clean out meshes, because textures are invalid
1026 // TODO: better texture handling;-)
1027 IMeshCache *cache = Game->Device->getSceneManager ()->getMeshCache();
1028 cache->clear ();
1029 Mesh = 0;
1030}
1031
1032/* Load new map
1033*/
1034void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision )
1035{
1036 if ( 0 == mapName.size() )
1037 return;
1038
1039 dropMap ();
1040
1041 IFileSystem *fs = Game->Device->getFileSystem();
1042 ISceneManager *smgr = Game->Device->getSceneManager ();
1043
1044 IReadFile* file = fs->createMemoryReadFile(&Game->loadParam,
1045 sizeof(Game->loadParam), L"levelparameter.cfg", false);
1046
1047 // load cfg file
1048 smgr->getMesh( file );
1049 file->drop ();
1050
1051 // load the actual map
1052 Mesh = (IQ3LevelMesh*) smgr->getMesh(mapName);
1053 if ( 0 == Mesh )
1054 return;
1055
1056 /*
1057 add the geometry mesh to the Scene ( polygon & patches )
1058 The Geometry mesh is optimised for faster drawing
1059 */
1060
1061 IMesh *geometry = Mesh->getMesh(E_Q3_MESH_GEOMETRY);
1062 if ( 0 == geometry || geometry->getMeshBufferCount() == 0)
1063 return;
1064
1065 Game->CurrentMapName = mapName;
1066
1067 //create a collision list
1068 Meta = 0;
1069
1070 ITriangleSelector * selector = 0;
1071 if (collision)
1072 Meta = smgr->createMetaTriangleSelector();
1073
1074 //IMeshBuffer *b0 = geometry->getMeshBuffer(0);
1075 //s32 minimalNodes = b0 ? core::s32_max ( 2048, b0->getVertexCount() / 32 ) : 2048;
1076 s32 minimalNodes = 2048;
1077
1078 MapParent = smgr->addOctreeSceneNode(geometry, 0, -1, minimalNodes);
1079 MapParent->setName ( mapName );
1080 if ( Meta )
1081 {
1082 selector = smgr->createOctreeTriangleSelector( geometry,MapParent, minimalNodes);
1083 //selector = smgr->createTriangleSelector ( geometry, MapParent );
1084 Meta->addTriangleSelector( selector);
1085 selector->drop ();
1086 }
1087
1088 // logical parent for the items
1089 ItemParent = smgr->addEmptySceneNode();
1090 if ( ItemParent )
1091 ItemParent->setName ( "Item Container" );
1092
1093 ShaderParent = smgr->addEmptySceneNode();
1094 if ( ShaderParent )
1095 ShaderParent->setName ( "Shader Container" );
1096
1097 UnresolvedParent = smgr->addEmptySceneNode();
1098 if ( UnresolvedParent )
1099 UnresolvedParent->setName ( "Unresolved Container" );
1100
1101 FogParent = smgr->addEmptySceneNode();
1102 if ( FogParent )
1103 FogParent->setName ( "Fog Container" );
1104
1105 // logical parent for the bullets
1106 BulletParent = smgr->addEmptySceneNode();
1107 if ( BulletParent )
1108 BulletParent->setName ( "Bullet Container" );
1109
1110 /*
1111 now construct SceneNodes for each Shader
1112 The Objects are stored in the quake mesh E_Q3_MESH_ITEMS
1113 and the Shader ID is stored in the MaterialParameters
1114 mostly dark looking skulls and moving lava.. or green flashing tubes?
1115 */
1116 Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_ITEMS,ShaderParent, Meta, false );
1117 Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_FOG,FogParent, 0, false );
1118 Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_UNRESOLVED,UnresolvedParent, Meta, true );
1119
1120 /*
1121 Now construct Models from Entity List
1122 */
1123 Q3ModelFactory ( Game->loadParam, Game->Device, Mesh, ItemParent, false );
1124}
1125
1126/*
1127 Adds a SceneNode with an icon to the Scene Tree
1128*/
1129void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent)
1130{
1131 IGUITreeViewNode* node;
1132 wchar_t msg[128];
1133
1134 s32 imageIndex;
1135 list<ISceneNode*>::ConstIterator it = parent->getChildren().begin();
1136 for (; it != parent->getChildren().end(); ++it)
1137 {
1138 switch ( (*it)->getType () )
1139 {
1140 case ESNT_Q3SHADER_SCENE_NODE: imageIndex = 0; break;
1141 case ESNT_CAMERA: imageIndex = 1; break;
1142 case ESNT_EMPTY: imageIndex = 2; break;
1143 case ESNT_MESH: imageIndex = 3; break;
1144 case ESNT_OCTREE: imageIndex = 3; break;
1145 case ESNT_ANIMATED_MESH: imageIndex = 4; break;
1146 case ESNT_SKY_BOX: imageIndex = 5; break;
1147 case ESNT_BILLBOARD: imageIndex = 6; break;
1148 case ESNT_PARTICLE_SYSTEM: imageIndex = 7; break;
1149 case ESNT_TEXT: imageIndex = 8; break;
1150 default:imageIndex = -1; break;
1151 }
1152
1153 if ( imageIndex < 0 )
1154 {
1155 swprintf ( msg, 128, L"%hs,%hs",
1156 Game->Device->getSceneManager ()->getSceneNodeTypeName ( (*it)->getType () ),
1157 (*it)->getName()
1158 );
1159 }
1160 else
1161 {
1162 swprintf ( msg, 128, L"%hs",(*it)->getName() );
1163 }
1164
1165 node = nodeParent->addChildBack( msg, 0, imageIndex );
1166
1167 // Add all Animators
1168 list<ISceneNodeAnimator*>::ConstIterator ait = (*it)->getAnimators().begin();
1169 for (; ait != (*it)->getAnimators().end(); ++ait)
1170 {
1171 imageIndex = -1;
1172 swprintf ( msg, 128, L"%hs",
1173 Game->Device->getSceneManager ()->getAnimatorTypeName ( (*ait)->getType () )
1174 );
1175
1176 switch ( (*ait)->getType () )
1177 {
1178 case ESNAT_FLY_CIRCLE:
1179 case ESNAT_FLY_STRAIGHT:
1180 case ESNAT_FOLLOW_SPLINE:
1181 case ESNAT_ROTATION:
1182 case ESNAT_TEXTURE:
1183 case ESNAT_DELETION:
1184 case ESNAT_COLLISION_RESPONSE:
1185 case ESNAT_CAMERA_FPS:
1186 case ESNAT_CAMERA_MAYA:
1187 default:
1188 break;
1189 }
1190 node->addChildBack( msg, 0, imageIndex );
1191 }
1192
1193 addSceneTreeItem ( *it, node );
1194 }
1195}
1196
1197
1198// Adds life!
1199void CQuake3EventHandler::CreatePlayers()
1200{
1201 Player[0].create ( Game->Device, Mesh, MapParent, Meta );
1202}
1203
1204
1205// Adds a skydome to the scene
1206void CQuake3EventHandler::AddSky( u32 dome, const c8 *texture)
1207{
1208 ISceneManager *smgr = Game->Device->getSceneManager ();
1209 IVideoDriver * driver = Game->Device->getVideoDriver();
1210
1211 bool oldMipMapState = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
1212 driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
1213
1214 if ( 0 == dome )
1215 {
1216 // irrlicht order
1217 //static const c8*p[] = { "ft", "lf", "bk", "rt", "up", "dn" };
1218 // quake3 order
1219 static const c8*p[] = { "ft", "rt", "bk", "lf", "up", "dn" };
1220
1221 u32 i = 0;
1222 snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] );
1223 SkyNode = smgr->addSkyBoxSceneNode( driver->getTexture ( buf ), 0, 0, 0, 0, 0 );
1224
1225 if (SkyNode)
1226 {
1227 for ( i = 0; i < 6; ++i )
1228 {
1229 snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] );
1230 SkyNode->getMaterial(i).setTexture ( 0, driver->getTexture ( buf ) );
1231 }
1232 }
1233 }
1234 else
1235 if ( 1 == dome )
1236 {
1237 snprintf ( buf, 64, "%s.jpg", texture );
1238 SkyNode = smgr->addSkyDomeSceneNode(
1239 driver->getTexture( buf ), 32,32,
1240 1.f, 1.f, 1000.f, 0, 11);
1241 }
1242 else
1243 if ( 2 == dome )
1244 {
1245 snprintf ( buf, 64, "%s.jpg", texture );
1246 SkyNode = smgr->addSkyDomeSceneNode(
1247 driver->getTexture( buf ), 16,8,
1248 0.95f, 2.f, 1000.f, 0, 11);
1249 }
1250
1251 if (SkyNode)
1252 SkyNode->setName("Skydome");
1253 //SkyNode->getMaterial(0).ZBuffer = video::EMDF_DEPTH_LESS_EQUAL;
1254
1255 driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState);
1256}
1257
1258
1259// enable GUI elements
1260void CQuake3EventHandler::SetGUIActive( s32 command)
1261{
1262 bool inputState = false;
1263
1264 ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera ();
1265
1266 switch ( command )
1267 {
1268 case 0: Game->guiActive = 0; inputState = !Game->guiActive; break;
1269 case 1: Game->guiActive = 1; inputState = !Game->guiActive;;break;
1270 case 2: Game->guiActive ^= 1; inputState = !Game->guiActive;break;
1271 case 3:
1272 if ( camera )
1273 inputState = !camera->isInputReceiverEnabled();
1274 break;
1275 }
1276
1277 if ( camera )
1278 {
1279 camera->setInputReceiverEnabled ( inputState );
1280 Game->Device->getCursorControl()->setVisible( !inputState );
1281 }
1282
1283 if ( gui.Window )
1284 {
1285 gui.Window->setVisible ( Game->guiActive != 0 );
1286 }
1287
1288 if ( Game->guiActive &&
1289 gui.SceneTree && Game->Device->getGUIEnvironment()->getFocus() != gui.SceneTree
1290 )
1291 {
1292 gui.SceneTree->getRoot()->clearChildren();
1293 addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() );
1294 }
1295
1296 Game->Device->getGUIEnvironment()->setFocus ( Game->guiActive ? gui.Window: 0 );
1297}
1298
1299
1300/*
1301 Handle game input
1302*/
1303bool CQuake3EventHandler::OnEvent(const SEvent& eve)
1304{
1305 if ( eve.EventType == EET_LOG_TEXT_EVENT )
1306 {
1307 return false;
1308 }
1309
1310 if ( Game->guiActive && eve.EventType == EET_GUI_EVENT )
1311 {
1312 if ( eve.GUIEvent.Caller == gui.MapList && eve.GUIEvent.EventType == gui::EGET_LISTBOX_SELECTED_AGAIN )
1313 {
1314 s32 selected = gui.MapList->getSelected();
1315 if ( selected >= 0 )
1316 {
1317 stringw loadMap = gui.MapList->getListItem ( selected );
1318 if ( 0 == MapParent || loadMap != Game->CurrentMapName )
1319 {
1320 printf ( "Loading map %ls\n", loadMap.c_str() );
1321 LoadMap ( loadMap , 1 );
1322 if ( 0 == Game->loadParam.loadSkyShader )
1323 {
1324 AddSky ( 1, "skydome2" );
1325 }
1326 CreatePlayers ();
1327 CreateGUI ();
1328 SetGUIActive ( 0 );
1329 return true;
1330 }
1331 }
1332 }
1333 else
1334 if ( eve.GUIEvent.Caller == gui.ArchiveRemove && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
1335 {
1336 Game->Device->getFileSystem()->removeFileArchive( gui.ArchiveList->getSelected() );
1337 Game->CurrentMapName = "";
1338 AddArchive ( "" );
1339 }
1340 else
1341 if ( eve.GUIEvent.Caller == gui.ArchiveAdd && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
1342 {
1343 if ( 0 == gui.ArchiveFileOpen )
1344 {
1345 Game->Device->getFileSystem()->setFileListSystem ( FILESYSTEM_NATIVE );
1346 gui.ArchiveFileOpen = Game->Device->getGUIEnvironment()->addFileOpenDialog ( L"Add Game Archive" , false,gui.Window );
1347 }
1348 }
1349 else
1350 if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_SELECTED )
1351 {
1352 AddArchive ( gui.ArchiveFileOpen->getFileName() );
1353 gui.ArchiveFileOpen = 0;
1354 }
1355 else
1356 if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_DIRECTORY_SELECTED )
1357 {
1358 AddArchive ( gui.ArchiveFileOpen->getDirectoryName() );
1359 }
1360 else
1361 if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_CHOOSE_DIALOG_CANCELLED )
1362 {
1363 gui.ArchiveFileOpen = 0;
1364 }
1365 else
1366 if ( ( eve.GUIEvent.Caller == gui.ArchiveUp || eve.GUIEvent.Caller == gui.ArchiveDown ) &&
1367 eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
1368 {
1369 s32 rel = eve.GUIEvent.Caller == gui.ArchiveUp ? -1 : 1;
1370 if ( Game->Device->getFileSystem()->moveFileArchive ( gui.ArchiveList->getSelected (), rel ) )
1371 {
1372 s32 newIndex = core::s32_clamp ( gui.ArchiveList->getSelected() + rel, 0, gui.ArchiveList->getRowCount() - 1 );
1373 AddArchive ( "" );
1374 gui.ArchiveList->setSelected ( newIndex );
1375 Game->CurrentMapName = "";
1376 }
1377 }
1378 else
1379 if ( eve.GUIEvent.Caller == gui.VideoDriver && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
1380 {
1381 Game->deviceParam.DriverType = (E_DRIVER_TYPE) gui.VideoDriver->getItemData ( gui.VideoDriver->getSelected() );
1382 }
1383 else
1384 if ( eve.GUIEvent.Caller == gui.VideoMode && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
1385 {
1386 u32 val = gui.VideoMode->getItemData ( gui.VideoMode->getSelected() );
1387 Game->deviceParam.WindowSize.Width = val >> 16;
1388 Game->deviceParam.WindowSize.Height = val & 0xFFFF;
1389 }
1390 else
1391 if ( eve.GUIEvent.Caller == gui.FullScreen && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
1392 {
1393 Game->deviceParam.Fullscreen = gui.FullScreen->isChecked();
1394 }
1395 else
1396 if ( eve.GUIEvent.Caller == gui.Bit32 && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
1397 {
1398 Game->deviceParam.Bits = gui.Bit32->isChecked() ? 32 : 16;
1399 }
1400 else
1401 if ( eve.GUIEvent.Caller == gui.MultiSample && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED )
1402 {
1403 Game->deviceParam.AntiAlias = gui.MultiSample->getPos();
1404 }
1405 else
1406 if ( eve.GUIEvent.Caller == gui.Tesselation && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED )
1407 {
1408 Game->loadParam.patchTesselation = gui.Tesselation->getPos ();
1409 }
1410 else
1411 if ( eve.GUIEvent.Caller == gui.Gamma && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED )
1412 {
1413 Game->GammaValue = gui.Gamma->getPos () * 0.01f;
1414 Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f );
1415 }
1416 else
1417 if ( eve.GUIEvent.Caller == gui.SetVideoMode && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
1418 {
1419 Game->retVal = 2;
1420 Game->Device->closeDevice();
1421 }
1422 else
1423 if ( eve.GUIEvent.Caller == gui.Window && eve.GUIEvent.EventType == gui::EGET_ELEMENT_CLOSED )
1424 {
1425 Game->Device->closeDevice();
1426 }
1427 else
1428 if ( eve.GUIEvent.Caller == gui.Collision && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
1429 {
1430 // set fly through active
1431 Game->flyTroughState ^= 1;
1432 Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 );
1433
1434 printf ( "collision %d\n", Game->flyTroughState == 0 );
1435 }
1436 else
1437 if ( eve.GUIEvent.Caller == gui.Visible_Map && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
1438 {
1439 bool v = gui.Visible_Map->isChecked();
1440
1441 if ( MapParent )
1442 {
1443 printf ( "static node set visible %d\n",v );
1444 MapParent->setVisible ( v );
1445 }
1446 }
1447 else
1448 if ( eve.GUIEvent.Caller == gui.Visible_Shader && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
1449 {
1450 bool v = gui.Visible_Shader->isChecked();
1451
1452 if ( ShaderParent )
1453 {
1454 printf ( "shader node set visible %d\n",v );
1455 ShaderParent->setVisible ( v );
1456 }
1457 }
1458 else
1459 if ( eve.GUIEvent.Caller == gui.Visible_Skydome && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
1460 {
1461 if ( SkyNode )
1462 {
1463 bool v = !SkyNode->isVisible();
1464 printf ( "skynode set visible %d\n",v );
1465 SkyNode->setVisible ( v );
1466 }
1467 }
1468 else
1469 if ( eve.GUIEvent.Caller == gui.Respawn && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
1470 {
1471 Player[0].respawn ();
1472 }
1473
1474 return false;
1475 }
1476
1477 // fire
1478 if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_SPACE &&
1479 eve.KeyInput.PressedDown == false) ||
1480 (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
1481 )
1482 {
1483 ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera ();
1484 if ( camera && camera->isInputReceiverEnabled () )
1485 {
1486 useItem( Player + 0 );
1487 }
1488 }
1489
1490 // gui active
1491 if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_F1 &&
1492 eve.KeyInput.PressedDown == false) ||
1493 (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_RMOUSE_LEFT_UP)
1494 )
1495 {
1496 SetGUIActive ( 2 );
1497 }
1498
1499 // check if user presses the key
1500 if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.PressedDown == false)
1501 {
1502 // Escape toggles camera Input
1503 if ( eve.KeyInput.Key == irr::KEY_ESCAPE )
1504 {
1505 SetGUIActive ( 3 );
1506 }
1507 else
1508 if (eve.KeyInput.Key == KEY_F11)
1509 {
1510 // screenshot are taken without gamma!
1511 IImage* image = Game->Device->getVideoDriver()->createScreenShot();
1512 if (image)
1513 {
1514 core::vector3df pos;
1515 core::vector3df rot;
1516 ICameraSceneNode * cam = Game->Device->getSceneManager()->getActiveCamera ();
1517 if ( cam )
1518 {
1519 pos = cam->getPosition ();
1520 rot = cam->getRotation ();
1521 }
1522
1523 static const c8 *dName[] = { "null", "software", "burning",
1524 "d3d8", "d3d9", "opengl" };
1525
1526 snprintf(buf, 256, "%s_%ls_%.0f_%.0f_%.0f_%.0f_%.0f_%.0f.jpg",
1527 dName[Game->Device->getVideoDriver()->getDriverType()],
1528 Game->CurrentMapName.c_str(),
1529 pos.X, pos.Y, pos.Z,
1530 rot.X, rot.Y, rot.Z
1531 );
1532 path filename ( buf );
1533 filename.replace ( '/', '_' );
1534 printf ( "screenshot : %s\n", filename.c_str() );
1535 Game->Device->getVideoDriver()->writeImageToFile(image, filename, 100 );
1536 image->drop();
1537 }
1538 }
1539 else
1540 if (eve.KeyInput.Key == KEY_F9)
1541 {
1542 s32 value = EDS_OFF;
1543
1544 Game->debugState = ( Game->debugState + 1 ) & 3;
1545
1546 switch ( Game->debugState )
1547 {
1548 case 1: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL; break;
1549 case 2: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_SKELETON; break;
1550 }
1551/*
1552 // set debug map data on/off
1553 debugState = debugState == EDS_OFF ?
1554 EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL:
1555 EDS_OFF;
1556*/
1557 if ( ItemParent )
1558 {
1559 list<ISceneNode*>::ConstIterator it = ItemParent->getChildren().begin();
1560 for (; it != ItemParent->getChildren().end(); ++it)
1561 {
1562 (*it)->setDebugDataVisible ( value );
1563 }
1564 }
1565
1566 if ( ShaderParent )
1567 {
1568 list<ISceneNode*>::ConstIterator it = ShaderParent->getChildren().begin();
1569 for (; it != ShaderParent->getChildren().end(); ++it)
1570 {
1571 (*it)->setDebugDataVisible ( value );
1572 }
1573 }
1574
1575 if ( UnresolvedParent )
1576 {
1577 list<ISceneNode*>::ConstIterator it = UnresolvedParent->getChildren().begin();
1578 for (; it != UnresolvedParent->getChildren().end(); ++it)
1579 {
1580 (*it)->setDebugDataVisible ( value );
1581 }
1582 }
1583
1584 if ( FogParent )
1585 {
1586 list<ISceneNode*>::ConstIterator it = FogParent->getChildren().begin();
1587 for (; it != FogParent->getChildren().end(); ++it)
1588 {
1589 (*it)->setDebugDataVisible ( value );
1590 }
1591 }
1592
1593 if ( SkyNode )
1594 {
1595 SkyNode->setDebugDataVisible ( value );
1596 }
1597
1598 }
1599 else
1600 if (eve.KeyInput.Key == KEY_F8)
1601 {
1602 // set gravity on/off
1603 Game->gravityState ^= 1;
1604 Player[0].cam()->setGravity ( getGravity ( Game->gravityState ? "earth" : "none" ) );
1605 printf ( "gravity %s\n", Game->gravityState ? "earth" : "none" );
1606 }
1607 else
1608 if (eve.KeyInput.Key == KEY_F7)
1609 {
1610 // set fly through active
1611 Game->flyTroughState ^= 1;
1612 Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 );
1613 if ( gui.Collision )
1614 gui.Collision->setChecked ( Game->flyTroughState == 0 );
1615
1616 printf ( "collision %d\n", Game->flyTroughState == 0 );
1617 }
1618 else
1619 if (eve.KeyInput.Key == KEY_F2)
1620 {
1621 Player[0].respawn ();
1622 }
1623 else
1624 if (eve.KeyInput.Key == KEY_F3)
1625 {
1626 if ( MapParent )
1627 {
1628 bool v = !MapParent->isVisible ();
1629 printf ( "static node set visible %d\n",v );
1630 MapParent->setVisible ( v );
1631 if ( gui.Visible_Map )
1632 gui.Visible_Map->setChecked ( v );
1633 }
1634 }
1635 else
1636 if (eve.KeyInput.Key == KEY_F4)
1637 {
1638 if ( ShaderParent )
1639 {
1640 bool v = !ShaderParent->isVisible ();
1641 printf ( "shader node set visible %d\n",v );
1642 ShaderParent->setVisible ( v );
1643 if ( gui.Visible_Shader )
1644 gui.Visible_Shader->setChecked ( v );
1645 }
1646 }
1647 else
1648 if (eve.KeyInput.Key == KEY_F5)
1649 {
1650 if ( FogParent )
1651 {
1652 bool v = !FogParent->isVisible ();
1653 printf ( "fog node set visible %d\n",v );
1654 FogParent->setVisible ( v );
1655 if ( gui.Visible_Fog )
1656 gui.Visible_Fog->setChecked ( v );
1657 }
1658
1659 }
1660 else
1661 if (eve.KeyInput.Key == KEY_F6)
1662 {
1663 if ( UnresolvedParent )
1664 {
1665 bool v = !UnresolvedParent->isVisible ();
1666 printf ( "unresolved node set visible %d\n",v );
1667 UnresolvedParent->setVisible ( v );
1668 if ( gui.Visible_Unresolved )
1669 gui.Visible_Unresolved->setChecked ( v );
1670 }
1671 }
1672 }
1673
1674 // check if user presses the key C ( for crouch)
1675 if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_KEY_C )
1676 {
1677 // crouch
1678 ISceneNodeAnimatorCollisionResponse *anim = Player[0].cam ();
1679 if ( anim && 0 == Game->flyTroughState )
1680 {
1681 if ( false == eve.KeyInput.PressedDown )
1682 {
1683 // stand up
1684 anim->setEllipsoidRadius ( vector3df(30,45,30) );
1685 anim->setEllipsoidTranslation ( vector3df(0,40,0));
1686
1687 }
1688 else
1689 {
1690 // on your knees
1691 anim->setEllipsoidRadius ( vector3df(30,20,30) );
1692 anim->setEllipsoidTranslation ( vector3df(0,20,0));
1693 }
1694 return true;
1695 }
1696 }
1697 return false;
1698}
1699
1700
1701
1702/*
1703 useItem
1704*/
1705void CQuake3EventHandler::useItem( Q3Player * player)
1706{
1707 ISceneManager* smgr = Game->Device->getSceneManager();
1708 ICameraSceneNode* camera = smgr->getActiveCamera();
1709
1710 if (!camera)
1711 return;
1712
1713 SParticleImpact imp;
1714 imp.when = 0;
1715
1716 // get line of camera
1717
1718 vector3df start = camera->getPosition();
1719
1720 if ( player->WeaponNode )
1721 {
1722 start.X += 0.f;
1723 start.Y += 0.f;
1724 start.Z += 0.f;
1725 }
1726
1727 vector3df end = (camera->getTarget() - start);
1728 end.normalize();
1729 start += end*20.0f;
1730
1731 end = start + (end * camera->getFarValue());
1732
1733 triangle3df triangle;
1734 line3d<f32> line(start, end);
1735
1736 // get intersection point with map
1737 scene::ISceneNode* hitNode;
1738 if (smgr->getSceneCollisionManager()->getCollisionPoint(
1739 line, Meta, end, triangle,hitNode))
1740 {
1741 // collides with wall
1742 vector3df out = triangle.getNormal();
1743 out.setLength(0.03f);
1744
1745 imp.when = 1;
1746 imp.outVector = out;
1747 imp.pos = end;
1748
1749 player->setAnim ( "pow" );
1750 player->Anim[1].next += player->Anim[1].delta;
1751 }
1752 else
1753 {
1754 // doesnt collide with wall
1755 vector3df start = camera->getPosition();
1756 if ( player->WeaponNode )
1757 {
1758 //start.X += 10.f;
1759 //start.Y += -5.f;
1760 //start.Z += 1.f;
1761 }
1762
1763 vector3df end = (camera->getTarget() - start);
1764 end.normalize();
1765 start += end*20.0f;
1766 end = start + (end * camera->getFarValue());
1767 }
1768
1769 // create fire ball
1770 ISceneNode* node = 0;
1771 node = smgr->addBillboardSceneNode( BulletParent,dimension2d<f32>(10,10), start);
1772
1773 node->setMaterialFlag(EMF_LIGHTING, false);
1774 node->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture("fireball.bmp"));
1775 node->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
1776 node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);
1777
1778 f32 length = (f32)(end - start).getLength();
1779 const f32 speed = 5.8f;
1780 u32 time = (u32)(length / speed);
1781
1782 ISceneNodeAnimator* anim = 0;
1783
1784 // set flight line
1785
1786 anim = smgr->createFlyStraightAnimator(start, end, time);
1787 node->addAnimator(anim);
1788 anim->drop();
1789
1790 snprintf ( buf, 64, "bullet: %s on %.1f,%1.f,%1.f",
1791 imp.when ? "hit" : "nohit", end.X, end.Y, end.Z );
1792 node->setName ( buf );
1793
1794
1795 anim = smgr->createDeleteAnimator(time);
1796 node->addAnimator(anim);
1797 anim->drop();
1798
1799 if (imp.when)
1800 {
1801 // create impact note
1802 imp.when = Game->Device->getTimer()->getTime() +
1803 (time + (s32) ( ( 1.f + Noiser::get() ) * 250.f ));
1804 Impacts.push_back(imp);
1805 }
1806
1807 // play sound
1808}
1809
1810// rendered when bullets hit something
1811void CQuake3EventHandler::createParticleImpacts( u32 now )
1812{
1813 ISceneManager* sm = Game->Device->getSceneManager();
1814
1815 struct smokeLayer
1816 {
1817 const c8 * texture;
1818 f32 scale;
1819 f32 minparticleSize;
1820 f32 maxparticleSize;
1821 f32 boxSize;
1822 u32 minParticle;
1823 u32 maxParticle;
1824 u32 fadeout;
1825 u32 lifetime;
1826 };
1827
1828 smokeLayer smoke[] =
1829 {
1830 { "smoke2.jpg", 0.4f, 1.5f, 18.f, 20.f, 20, 50, 2000, 10000 },
1831 { "smoke3.jpg", 0.2f, 1.2f, 15.f, 20.f, 10, 30, 1000, 12000 }
1832 };
1833
1834
1835 u32 i;
1836 u32 g;
1837 s32 factor = 1;
1838 for ( g = 0; g != 2; ++g )
1839 {
1840 smoke[g].minParticle *= factor;
1841 smoke[g].maxParticle *= factor;
1842 smoke[g].lifetime *= factor;
1843 smoke[g].boxSize *= Noiser::get() * 0.5f;
1844 }
1845
1846 for ( i=0; i < Impacts.size(); ++i)
1847 {
1848 if (now < Impacts[i].when)
1849 continue;
1850
1851 // create smoke particle system
1852 IParticleSystemSceneNode* pas = 0;
1853
1854 for ( g = 0; g != 2; ++g )
1855 {
1856 pas = sm->addParticleSystemSceneNode(false, BulletParent, -1, Impacts[i].pos);
1857
1858 snprintf ( buf, 64, "bullet impact smoke at %.1f,%.1f,%1.f",
1859 Impacts[i].pos.X,Impacts[i].pos.Y,Impacts[i].pos.Z);
1860 pas->setName ( buf );
1861
1862 // create a flat smoke
1863 vector3df direction = Impacts[i].outVector;
1864 direction *= smoke[g].scale;
1865 IParticleEmitter* em = pas->createBoxEmitter(
1866 aabbox3d<f32>(-4.f,0.f,-4.f,20.f,smoke[g].minparticleSize,20.f),
1867 direction,smoke[g].minParticle, smoke[g].maxParticle,
1868 video::SColor(0,0,0,0),video::SColor(0,128,128,128),
1869 250,4000, 60);
1870
1871 em->setMinStartSize (dimension2d<f32>( smoke[g].minparticleSize, smoke[g].minparticleSize));
1872 em->setMaxStartSize (dimension2d<f32>( smoke[g].maxparticleSize, smoke[g].maxparticleSize));
1873
1874 pas->setEmitter(em);
1875 em->drop();
1876
1877 // particles get invisible
1878 IParticleAffector* paf = pas->createFadeOutParticleAffector(
1879 video::SColor ( 0, 0, 0, 0 ), smoke[g].fadeout);
1880 pas->addAffector(paf);
1881 paf->drop();
1882
1883 // particle system life time
1884 ISceneNodeAnimator* anim = sm->createDeleteAnimator( smoke[g].lifetime);
1885 pas->addAnimator(anim);
1886 anim->drop();
1887
1888 pas->setMaterialFlag(video::EMF_LIGHTING, false);
1889 pas->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
1890 pas->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
1891 pas->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture( smoke[g].texture ));
1892 }
1893
1894
1895 // play impact sound
1896 #ifdef USE_IRRKLANG
1897/*
1898 if (irrKlang)
1899 {
1900 audio::ISound* sound =
1901 irrKlang->play3D(impactSound, Impacts[i].pos, false, false, true);
1902
1903 if (sound)
1904 {
1905 // adjust max value a bit to make to sound of an impact louder
1906 sound->setMinDistance(400);
1907 sound->drop();
1908 }
1909 }
1910*/
1911 #endif
1912
1913
1914 // delete entry
1915 Impacts.erase(i);
1916 i--;
1917 }
1918}
1919
1920/*
1921 render
1922*/
1923void CQuake3EventHandler::Render()
1924{
1925 IVideoDriver * driver = Game->Device->getVideoDriver();
1926 if ( 0 == driver )
1927 return;
1928
1929 // TODO: This does not work, yet.
1930 const bool anaglyph=false;
1931 if (anaglyph)
1932 {
1933 scene::ICameraSceneNode* cameraOld = Game->Device->getSceneManager()->getActiveCamera();
1934 driver->beginScene(true, true, SColor(0,0,0,0));
1935 driver->getOverrideMaterial().Material.ColorMask = ECP_NONE;
1936 driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK;
1937 driver->getOverrideMaterial().EnablePasses = ESNRP_SKY_BOX +
1938 ESNRP_SOLID +
1939 ESNRP_TRANSPARENT +
1940 ESNRP_TRANSPARENT_EFFECT +
1941 ESNRP_SHADOW;
1942 Game->Device->getSceneManager()->drawAll();
1943 driver->clearZBuffer();
1944
1945 const vector3df oldPosition = cameraOld->getPosition();
1946 const vector3df oldTarget = cameraOld->getTarget();
1947 const matrix4 startMatrix = cameraOld->getAbsoluteTransformation();
1948 const vector3df focusPoint = (oldTarget -
1949 cameraOld->getAbsolutePosition()).setLength(10000) +
1950 cameraOld->getAbsolutePosition() ;
1951
1952 scene::ICameraSceneNode* camera = cameraOld;//Game->Device->getSceneManager()->addCameraSceneNode();
1953
1954 //Left eye...
1955 vector3df pos;
1956 matrix4 move;
1957
1958 move.setTranslation( vector3df(-1.5f,0.0f,0.0f) );
1959 pos=(startMatrix*move).getTranslation();
1960
1961 driver->getOverrideMaterial().Material.ColorMask = ECP_RED;
1962 driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK;
1963 driver->getOverrideMaterial().EnablePasses =
1964 ESNRP_SKY_BOX|ESNRP_SOLID|ESNRP_TRANSPARENT|
1965 ESNRP_TRANSPARENT_EFFECT|ESNRP_SHADOW;
1966
1967 camera->setPosition(pos);
1968 camera->setTarget(focusPoint);
1969
1970 Game->Device->getSceneManager()->drawAll();
1971 driver->clearZBuffer();
1972
1973 //Right eye...
1974 move.setTranslation( vector3df(1.5f,0.0f,0.0f) );
1975 pos=(startMatrix*move).getTranslation();
1976
1977 driver->getOverrideMaterial().Material.ColorMask = ECP_GREEN + ECP_BLUE;
1978 driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK;
1979 driver->getOverrideMaterial().EnablePasses =
1980 ESNRP_SKY_BOX|ESNRP_SOLID|ESNRP_TRANSPARENT|
1981 ESNRP_TRANSPARENT_EFFECT|ESNRP_SHADOW;
1982
1983 camera->setPosition(pos);
1984 camera->setTarget(focusPoint);
1985
1986 Game->Device->getSceneManager()->drawAll();
1987
1988 driver->getOverrideMaterial().Material.ColorMask=ECP_ALL;
1989 driver->getOverrideMaterial().EnableFlags=0;
1990 driver->getOverrideMaterial().EnablePasses=0;
1991
1992 if (camera != cameraOld)
1993 {
1994 Game->Device->getSceneManager()->setActiveCamera(cameraOld);
1995 camera->remove();
1996 }
1997 else
1998 {
1999 camera->setPosition(oldPosition);
2000 camera->setTarget(oldTarget);
2001 }
2002 }
2003 else
2004 {
2005 driver->beginScene(true, true, SColor(0,0,0,0));
2006 Game->Device->getSceneManager()->drawAll();
2007 }
2008 Game->Device->getGUIEnvironment()->drawAll();
2009 driver->endScene();
2010}
2011
2012/*
2013 update the generic scene node
2014*/
2015void CQuake3EventHandler::Animate()
2016{
2017 u32 now = Game->Device->getTimer()->getTime();
2018
2019 Q3Player * player = Player + 0;
2020
2021 checkTimeFire ( player->Anim, 4, now );
2022
2023 // Query Scene Manager attributes
2024 if ( player->Anim[0].flags & FIRED )
2025 {
2026 ISceneManager *smgr = Game->Device->getSceneManager ();
2027 wchar_t msg[128];
2028 IVideoDriver * driver = Game->Device->getVideoDriver();
2029
2030 IAttributes * attr = smgr->getParameters();
2031#ifdef _IRR_SCENEMANAGER_DEBUG
2032 swprintf ( msg, 128,
2033 L"Q3 %s [%ls], FPS:%03d Tri:%.03fm Cull %d/%d nodes (%d,%d,%d)",
2034 Game->CurrentMapName.c_str(),
2035 driver->getName(),
2036 driver->getFPS (),
2037 (f32) driver->getPrimitiveCountDrawn( 0 ) * ( 1.f / 1000000.f ),
2038 attr->getAttributeAsInt ( "culled" ),
2039 attr->getAttributeAsInt ( "calls" ),
2040 attr->getAttributeAsInt ( "drawn_solid" ),
2041 attr->getAttributeAsInt ( "drawn_transparent" ),
2042 attr->getAttributeAsInt ( "drawn_transparent_effect" )
2043 );
2044#else
2045swprintf ( msg, 128,
2046 L"Q3 %s [%ls], FPS:%03d Tri:%.03fm",
2047 Game->CurrentMapName.c_str(),
2048 driver->getName(),
2049 driver->getFPS (),
2050 (f32) driver->getPrimitiveCountDrawn( 0 ) * ( 1.f / 1000000.f )
2051 );
2052#endif
2053 Game->Device->setWindowCaption( msg );
2054
2055 swprintf ( msg, 128,
2056 L"%03d fps, F1 GUI on/off, F2 respawn, F3-F6 toggle Nodes, F7 Collision on/off"
2057 L", F8 Gravity on/off, Right Mouse Toggle GUI",
2058 Game->Device->getVideoDriver()->getFPS ()
2059 );
2060 if ( gui.StatusLine )
2061 gui.StatusLine->setText ( msg );
2062 player->Anim[0].flags &= ~FIRED;
2063 }
2064
2065 // idle..
2066 if ( player->Anim[1].flags & FIRED )
2067 {
2068 if ( strcmp ( player->animation, "idle" ) )
2069 player->setAnim ( "idle" );
2070
2071 player->Anim[1].flags &= ~FIRED;
2072 }
2073
2074 createParticleImpacts ( now );
2075
2076}
2077
2078
2079/* The main game states
2080*/
2081void runGame ( GameData *game )
2082{
2083 if ( game->retVal >= 3 )
2084 return;
2085
2086 game->Device = (*game->createExDevice) ( game->deviceParam );
2087 if ( 0 == game->Device)
2088 {
2089 // could not create selected driver.
2090 game->retVal = 0;
2091 return;
2092 }
2093
2094 // create an event receiver based on current game data
2095 CQuake3EventHandler *eventHandler = new CQuake3EventHandler( game );
2096
2097 // load stored config
2098 game->load ( "explorer.cfg" );
2099
2100 // add our media directory and archive to the file system
2101 for ( u32 i = 0; i < game->CurrentArchiveList.size(); ++i )
2102 {
2103 eventHandler->AddArchive ( game->CurrentArchiveList[i] );
2104 }
2105
2106 // Load a Map or startup to the GUI
2107 if ( game->CurrentMapName.size () )
2108 {
2109 eventHandler->LoadMap ( game->CurrentMapName, 1 );
2110 if ( 0 == game->loadParam.loadSkyShader )
2111 eventHandler->AddSky ( 1, "skydome2" );
2112 eventHandler->CreatePlayers ();
2113 eventHandler->CreateGUI ();
2114 eventHandler->SetGUIActive ( 0 );
2115
2116 // set player to last position on restart
2117 if ( game->retVal == 2 )
2118 {
2119 eventHandler->GetPlayer( 0 )->setpos ( game->PlayerPosition, game->PlayerRotation );
2120 }
2121 }
2122 else
2123 {
2124 // start up empty
2125 eventHandler->AddSky ( 1, "skydome2" );
2126 eventHandler->CreatePlayers ();
2127 eventHandler->CreateGUI ();
2128 eventHandler->SetGUIActive ( 1 );
2129 background_music ( "IrrlichtTheme.ogg" );
2130 }
2131
2132
2133 game->retVal = 3;
2134 while( game->Device->run() )
2135 {
2136 eventHandler->Animate ();
2137 eventHandler->Render ();
2138 //if ( !game->Device->isWindowActive() )
2139 game->Device->yield();
2140 }
2141
2142 game->Device->setGammaRamp ( 1.f, 1.f, 1.f, 0.f, 0.f );
2143 delete eventHandler;
2144}
2145
2146#if defined (_IRR_WINDOWS_) && 0
2147 #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
2148#endif
2149
2150
2151/* The main routine, doing all setup
2152*/
2153int IRRCALLCONV main(int argc, char* argv[])
2154{
2155 path prgname(argv[0]);
2156 GameData game ( deletePathFromPath ( prgname, 1 ) );
2157
2158 // dynamically load irrlicht
2159 const c8 * dllName = argc > 1 ? argv[1] : "irrlicht.dll";
2160 game.createExDevice = load_createDeviceEx ( dllName );
2161 if ( 0 == game.createExDevice )
2162 {
2163 game.retVal = 3;
2164 printf ( "Could not load %s.\n", dllName );
2165 return game.retVal; // could not load dll
2166 }
2167
2168 // start without asking for driver
2169 game.retVal = 1;
2170 do
2171 {
2172 // if driver could not created, ask for another driver
2173 if ( game.retVal == 0 )
2174 {
2175 game.setDefault ();
2176 // ask user for driver
2177 game.deviceParam.DriverType=driverChoiceConsole();
2178 if (game.deviceParam.DriverType==video::EDT_COUNT)
2179 game.retVal = 3;
2180 }
2181 runGame ( &game );
2182 } while ( game.retVal < 3 );
2183
2184 return game.retVal;
2185}
2186
2187/*
2188**/