From 7028cbe09c688437910a25623098762bf0fa592d Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 28 Mar 2016 22:28:34 +1000 Subject: Move Irrlicht to src/others. --- .../examples/21.Quake3Explorer/Makefile | 38 + .../examples/21.Quake3Explorer/Quake3Explorer.cbp | 59 + .../examples/21.Quake3Explorer/Quake3Explorer.dev | 99 + .../21.Quake3Explorer/Quake3Explorer.vcproj | 132 ++ .../21.Quake3Explorer/Quake3Explorer_vc10.vcxproj | 196 ++ .../21.Quake3Explorer/Quake3Explorer_vc11.vcxproj | 200 ++ .../21.Quake3Explorer/Quake3Explorer_vc8.vcproj | 210 ++ .../21.Quake3Explorer/Quake3Explorer_vc9.vcproj | 204 ++ .../examples/21.Quake3Explorer/main.cpp | 2188 ++++++++++++++++++++ .../examples/21.Quake3Explorer/q3factory.cpp | 824 ++++++++ .../examples/21.Quake3Explorer/q3factory.h | 149 ++ .../examples/21.Quake3Explorer/sound.cpp | 98 + .../examples/21.Quake3Explorer/sound.h | 18 + 13 files changed, 4415 insertions(+) create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Makefile create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.cbp create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.dev create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.vcproj create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc10.vcxproj create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc11.vcxproj create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/main.cpp create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.h create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.cpp create mode 100644 src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.h (limited to 'src/others/irrlicht-1.8.1/examples/21.Quake3Explorer') diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Makefile b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Makefile new file mode 100644 index 0000000..b2c6927 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Makefile @@ -0,0 +1,38 @@ +# Makefile for Irrlicht Examples +# It's usually sufficient to change just the target name and source file list +# and be sure that CXX is set to a valid compiler +Target = 21.Quake3Explorer +Sources = main.cpp sound.cpp q3factory.cpp + +# general compiler settings +CPPFLAGS = -I../../include -I/usr/X11R6/include +#CXXFLAGS = -O3 -ffast-math +CXXFLAGS = -g -Wall + +#default target is Linux +all: all_linux + +ifeq ($(HOSTTYPE), x86_64) +LIBSELECT=64 +endif + +# target specific settings +all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor +all_linux clean_linux: SYSTEM=Linux +all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm +all_win32 clean_win32: SYSTEM=Win32-gcc +all_win32 clean_win32: SUF=.exe +# name of the binary - only valid for targets which set SYSTEM +DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) + +all_linux all_win32: + $(warning Building...) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) + +clean: clean_linux clean_win32 + $(warning Cleaning...) + +clean_linux clean_win32: + @$(RM) $(DESTPATH) + +.PHONY: all all_win32 clean clean_linux clean_win32 diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.cbp b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.cbp new file mode 100644 index 0000000..af962e2 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.cbp @@ -0,0 +1,59 @@ + + + + + + diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.dev b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.dev new file mode 100644 index 0000000..193c6bd --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.dev @@ -0,0 +1,99 @@ +[Project] +FileName=Quake3Explorer.dev +Name=Irrlicht Example 21 Quake3 Explorer +UnitCount=5 +Type=1 +Ver=1 +ObjFiles= +Includes=..\..\include +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ +IsCpp=1 +Icon= +ExeOutput=../../bin/Win32-gcc +ObjectOutput=obj +OverrideOutput=1 +OverrideOutputName=21.Quake3Explorer.exe +HostApplication= +Folders= +CommandLine= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder=Projekt1 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Irrlicht Engine example compiled using DevCpp and gcc +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit2] +FileName=q3factory.cpp +CompileCpp=1 +Folder=Irrlicht Example 21 Quake3 Explorer +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=q3factory.h +CompileCpp=1 +Folder=Irrlicht Example 21 Quake3 Explorer +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=sound.cpp +CompileCpp=1 +Folder=Irrlicht Example 21 Quake3 Explorer +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=sound.h +CompileCpp=1 +Folder=Irrlicht Example 21 Quake3 Explorer +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.vcproj b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.vcproj new file mode 100644 index 0000000..b869cc4 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer.vcproj @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc10.vcxproj b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc10.vcxproj new file mode 100644 index 0000000..8ba3e72 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc10.vcxproj @@ -0,0 +1,196 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + 21.Quake3Explorer + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD} + 21.Quake3Explorer + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ..\..\bin\Win32-VisualStudio\ + ..\..\bin\Win64-VisualStudio\ + true + true + ..\..\bin\Win32-VisualStudio\ + ..\..\bin\Win64-VisualStudio\ + false + false + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + EditAndContinue + + + ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) + true + $(OutDir)Quake3MapShader.pdb + Console + + + + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + + + ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) + true + $(OutDir)Quake3MapShader.pdb + Console + + + + + + + true + Speed + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + false + + + Level3 + + + FastCall + + + ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) + false + Console + true + true + + + + + + + true + Speed + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + false + + + Level3 + + + FastCall + + + ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) + false + Console + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc11.vcxproj b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc11.vcxproj new file mode 100644 index 0000000..d0c29b2 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc11.vcxproj @@ -0,0 +1,200 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + 21.Quake3Explorer + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD} + 21.Quake3Explorer + Win32Proj + + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ..\..\bin\Win32-VisualStudio\ + ..\..\bin\Win64-VisualStudio\ + true + true + ..\..\bin\Win32-VisualStudio\ + ..\..\bin\Win64-VisualStudio\ + false + false + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + EditAndContinue + + + ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) + true + $(OutDir)Quake3MapShader.pdb + Console + + + + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + + + ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) + true + $(OutDir)Quake3MapShader.pdb + Console + + + + + + + true + Speed + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + false + + + Level3 + + + FastCall + + + ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) + false + Console + true + true + + + + + + + true + Speed + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + false + + + Level3 + + + FastCall + + + ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe + ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) + false + Console + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj new file mode 100644 index 0000000..9045027 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj new file mode 100644 index 0000000..36aee41 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ +/** Example 021 Quake3 Explorer + +This Tutorial shows how to load different Quake 3 maps. + +Features: + - Load BSP Archives at Runtime from the menu + - Load a Map from the menu. Showing with Screenshot + - Set the VideoDriver at runtime from menu + - Adjust GammaLevel at runtime + - Create SceneNodes for the Shaders + - Load EntityList and create Entity SceneNodes + - Create Players with Weapons and with Collision Response + - Play music + +You can download the Quake III Arena demo ( copyright id software ) +at the following location: +ftp://ftp.idsoftware.com/idstuff/quake3/win32/q3ademo.exe + +Copyright 2006-2011 Burningwater, Thomas Alten +*/ + +#include "driverChoice.h" +#include +#include "q3factory.h" +#include "sound.h" + +/* + Game Data is used to hold Data which is needed to drive the game +*/ +struct GameData +{ + GameData ( const path &startupDir) : + retVal(0), StartupDir(startupDir), createExDevice(0), Device(0) + { + setDefault (); + } + + void setDefault (); + s32 save ( const path &filename ); + s32 load ( const path &filename ); + + s32 debugState; + s32 gravityState; + s32 flyTroughState; + s32 wireFrame; + s32 guiActive; + s32 guiInputActive; + f32 GammaValue; + s32 retVal; + s32 sound; + + path StartupDir; + stringw CurrentMapName; + array CurrentArchiveList; + + vector3df PlayerPosition; + vector3df PlayerRotation; + + tQ3EntityList Variable; + + Q3LevelLoadParameter loadParam; + SIrrlichtCreationParameters deviceParam; + funcptr_createDeviceEx createExDevice; + IrrlichtDevice *Device; +}; + +/* + set default settings +*/ +void GameData::setDefault () +{ + debugState = EDS_OFF; + gravityState = 1; + flyTroughState = 0; + wireFrame = 0; + guiActive = 1; + guiInputActive = 0; + GammaValue = 1.f; + + // default deviceParam; +#if defined ( _IRR_WINDOWS_ ) + deviceParam.DriverType = EDT_DIRECT3D9; +#else + deviceParam.DriverType = EDT_OPENGL; +#endif + deviceParam.WindowSize.Width = 800; + deviceParam.WindowSize.Height = 600; + deviceParam.Fullscreen = false; + deviceParam.Bits = 24; + deviceParam.ZBufferBits = 16; + deviceParam.Vsync = false; + deviceParam.AntiAlias = false; + + // default Quake3 loadParam + loadParam.defaultLightMapMaterial = EMT_LIGHTMAP; + loadParam.defaultModulate = EMFN_MODULATE_1X; + loadParam.defaultFilter = EMF_ANISOTROPIC_FILTER; + loadParam.verbose = 2; + loadParam.mergeShaderBuffer = 1; // merge meshbuffers with same material + loadParam.cleanUnResolvedMeshes = 1; // should unresolved meshes be cleaned. otherwise blue texture + loadParam.loadAllShaders = 1; // load all scripts in the script directory + loadParam.loadSkyShader = 0; // load sky Shader + loadParam.alpharef = 1; + + sound = 0; + + CurrentMapName = ""; + CurrentArchiveList.clear (); + + // Explorer Media directory + CurrentArchiveList.push_back ( StartupDir + "../../media/" ); + + // Add the original quake3 files before you load your custom map + // Most mods are using the original shaders, models&items&weapons + CurrentArchiveList.push_back("/q/baseq3/"); + + CurrentArchiveList.push_back(StartupDir + "../../media/map-20kdm2.pk3"); +} + +/* + Load the current game State from a typical quake3 cfg file +*/ +s32 GameData::load ( const path &filename ) +{ + if (!Device) + return 0; + + // the quake3 mesh loader can also handle *.shader and *.cfg file + IQ3LevelMesh* mesh = (IQ3LevelMesh*) Device->getSceneManager()->getMesh ( filename ); + if (!mesh) + return 0; + + tQ3EntityList &entityList = mesh->getEntityList (); + + stringc s; + u32 pos; + + for ( u32 e = 0; e != entityList.size (); ++e ) + { + //dumpShader ( s, &entityList[e], false ); + //printf ( s.c_str () ); + + for ( u32 g = 0; g != entityList[e].getGroupSize (); ++g ) + { + const SVarGroup *group = entityList[e].getGroup ( g ); + + for ( u32 index = 0; index < group->Variable.size (); ++index ) + { + const SVariable &v = group->Variable[index]; + pos = 0; + if ( v.name == "playerposition" ) + { + PlayerPosition = getAsVector3df ( v.content, pos ); + } + else + if ( v.name == "playerrotation" ) + { + PlayerRotation = getAsVector3df ( v.content, pos ); + } + } + } + } + + return 1; +} + +/* + Store the current game State in a quake3 configuration file +*/ +s32 GameData::save ( const path &filename ) +{ + return 0; + if (!Device) + return 0; + + c8 buf[128]; + u32 i; + + // Store current Archive for restart + CurrentArchiveList.clear(); + IFileSystem *fs = Device->getFileSystem(); + for ( i = 0; i != fs->getFileArchiveCount(); ++i ) + { + CurrentArchiveList.push_back ( fs->getFileArchive(i)->getFileList()->getPath() ); + } + + // Store Player Position and Rotation + ICameraSceneNode * camera = Device->getSceneManager()->getActiveCamera (); + if ( camera ) + { + PlayerPosition = camera->getPosition (); + PlayerRotation = camera->getRotation (); + } + + IWriteFile *file = fs->createAndWriteFile ( filename ); + if (!file) + return 0; + + snprintf ( buf, 128, "playerposition %.f %.f %.f\nplayerrotation %.f %.f %.f\n", + PlayerPosition.X, PlayerPosition.Z, PlayerPosition.Y, + PlayerRotation.X, PlayerRotation.Z, PlayerRotation.Y); + file->write ( buf, (s32) strlen ( buf ) ); + for ( i = 0; i != fs->getFileArchiveCount(); ++i ) + { + snprintf ( buf, 128, "archive %s\n",stringc ( fs->getFileArchive(i)->getFileList()->getPath() ).c_str () ); + file->write ( buf, (s32) strlen ( buf ) ); + } + + file->drop (); + return 1; +} + +/* + Representing a player +*/ +struct Q3Player : public IAnimationEndCallBack +{ + Q3Player () + : Device(0), MapParent(0), Mesh(0), WeaponNode(0), StartPositionCurrent(0) + { + animation[0] = 0; + memset(Anim, 0, sizeof(TimeFire)*4); + } + + virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node); + + void create ( IrrlichtDevice *device, + IQ3LevelMesh* mesh, + ISceneNode *mapNode, + IMetaTriangleSelector *meta + ); + void shutdown (); + void setAnim ( const c8 *name ); + void respawn (); + void setpos ( const vector3df &pos, const vector3df& rotation ); + + ISceneNodeAnimatorCollisionResponse * cam() { return camCollisionResponse ( Device ); } + + IrrlichtDevice *Device; + ISceneNode* MapParent; + IQ3LevelMesh* Mesh; + IAnimatedMeshSceneNode* WeaponNode; + s32 StartPositionCurrent; + TimeFire Anim[4]; + c8 animation[64]; + c8 buf[64]; +}; + + +/* End player +*/ +void Q3Player::shutdown () +{ + setAnim ( 0 ); + + dropElement (WeaponNode); + + if ( Device ) + { + ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); + dropElement ( camera ); + Device = 0; + } + + MapParent = 0; + Mesh = 0; +} + + +/* create a new player +*/ +void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode *mapNode, IMetaTriangleSelector *meta ) +{ + setTimeFire ( Anim + 0, 200, FIRED ); + setTimeFire ( Anim + 1, 5000 ); + + if (!device) + return; + // load FPS weapon to Camera + Device = device; + Mesh = mesh; + MapParent = mapNode; + + ISceneManager *smgr = device->getSceneManager (); + IVideoDriver * driver = device->getVideoDriver(); + + ICameraSceneNode* camera = 0; + + SKeyMap keyMap[10]; + keyMap[0].Action = EKA_MOVE_FORWARD; + keyMap[0].KeyCode = KEY_UP; + keyMap[1].Action = EKA_MOVE_FORWARD; + keyMap[1].KeyCode = KEY_KEY_W; + + keyMap[2].Action = EKA_MOVE_BACKWARD; + keyMap[2].KeyCode = KEY_DOWN; + keyMap[3].Action = EKA_MOVE_BACKWARD; + keyMap[3].KeyCode = KEY_KEY_S; + + keyMap[4].Action = EKA_STRAFE_LEFT; + keyMap[4].KeyCode = KEY_LEFT; + keyMap[5].Action = EKA_STRAFE_LEFT; + keyMap[5].KeyCode = KEY_KEY_A; + + keyMap[6].Action = EKA_STRAFE_RIGHT; + keyMap[6].KeyCode = KEY_RIGHT; + keyMap[7].Action = EKA_STRAFE_RIGHT; + keyMap[7].KeyCode = KEY_KEY_D; + + keyMap[8].Action = EKA_JUMP_UP; + keyMap[8].KeyCode = KEY_KEY_J; + + keyMap[9].Action = EKA_CROUCH; + keyMap[9].KeyCode = KEY_KEY_C; + + camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 0.6f, -1, keyMap, 10, false, 0.6f); + camera->setName ( "First Person Camera" ); + //camera->setFOV ( 100.f * core::DEGTORAD ); + camera->setFarValue( 20000.f ); + + IAnimatedMeshMD2* weaponMesh = (IAnimatedMeshMD2*) smgr->getMesh("gun.md2"); + if ( 0 == weaponMesh ) + return; + + if ( weaponMesh->getMeshType() == EAMT_MD2 ) + { + s32 count = weaponMesh->getAnimationCount(); + for ( s32 i = 0; i != count; ++i ) + { + snprintf ( buf, 64, "Animation: %s", weaponMesh->getAnimationName(i) ); + device->getLogger()->log(buf, ELL_INFORMATION); + } + } + + WeaponNode = smgr->addAnimatedMeshSceneNode( + weaponMesh, + smgr->getActiveCamera(), + 10, + vector3df( 0, 0, 0), + vector3df(-90,-90,90) + ); + WeaponNode->setMaterialFlag(EMF_LIGHTING, false); + WeaponNode->setMaterialTexture(0, driver->getTexture( "gun.jpg")); + WeaponNode->setLoopMode ( false ); + WeaponNode->setName ( "tommi the gun man" ); + + //create a collision auto response animator + ISceneNodeAnimator* anim = + smgr->createCollisionResponseAnimator( meta, camera, + vector3df(30,45,30), + getGravity ( "earth" ), + vector3df(0,40,0), + 0.0005f + ); + + camera->addAnimator( anim ); + anim->drop(); + + if ( meta ) + { + meta->drop (); + } + + respawn (); + setAnim ( "idle" ); +} + + +/* + so we need a good starting Position in the level. + we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" +*/ +void Q3Player::respawn () +{ + if (!Device) + return; + ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); + + Device->getLogger()->log( "respawn" ); + + if ( StartPositionCurrent >= Q3StartPosition ( + Mesh, camera,StartPositionCurrent++, + cam ()->getEllipsoidTranslation() ) + ) + { + StartPositionCurrent = 0; + } +} + +/* + set Player position from saved coordinates +*/ +void Q3Player::setpos ( const vector3df &pos, const vector3df &rotation ) +{ + if (!Device) + return; + Device->getLogger()->log( "setpos" ); + + ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); + if ( camera ) + { + camera->setPosition ( pos ); + camera->setRotation ( rotation ); + //! New. FPSCamera and animators catches reset on animate 0 + camera->OnAnimate ( 0 ); + } +} + +/* set the Animation of the player and weapon +*/ +void Q3Player::setAnim ( const c8 *name ) +{ + if ( name ) + { + snprintf ( animation, 64, "%s", name ); + if ( WeaponNode ) + { + WeaponNode->setAnimationEndCallback ( this ); + WeaponNode->setMD2Animation ( animation ); + } + } + else + { + animation[0] = 0; + if ( WeaponNode ) + { + WeaponNode->setAnimationEndCallback ( 0 ); + } + } +} + + +// Callback +void Q3Player::OnAnimationEnd(IAnimatedMeshSceneNode* node) +{ + setAnim ( 0 ); +} + + + +/* GUI Elements +*/ +struct GUI +{ + GUI () + { + memset ( this, 0, sizeof ( *this ) ); + } + + void drop() + { + dropElement ( Window ); + dropElement ( Logo ); + } + + IGUIComboBox* VideoDriver; + IGUIComboBox* VideoMode; + IGUICheckBox* FullScreen; + IGUICheckBox* Bit32; + IGUIScrollBar* MultiSample; + IGUIButton* SetVideoMode; + + IGUIScrollBar* Tesselation; + IGUIScrollBar* Gamma; + IGUICheckBox* Collision; + IGUICheckBox* Visible_Map; + IGUICheckBox* Visible_Shader; + IGUICheckBox* Visible_Fog; + IGUICheckBox* Visible_Unresolved; + IGUICheckBox* Visible_Skydome; + IGUIButton* Respawn; + + IGUITable* ArchiveList; + IGUIButton* ArchiveAdd; + IGUIButton* ArchiveRemove; + IGUIFileOpenDialog* ArchiveFileOpen; + IGUIButton* ArchiveUp; + IGUIButton* ArchiveDown; + + IGUIListBox* MapList; + IGUITreeView* SceneTree; + IGUIStaticText* StatusLine; + IGUIImage* Logo; + IGUIWindow* Window; +}; + + +/* + CQuake3EventHandler controls the game +*/ +class CQuake3EventHandler : public IEventReceiver +{ +public: + + CQuake3EventHandler( GameData *gameData ); + virtual ~CQuake3EventHandler (); + + void Animate(); + void Render(); + + void AddArchive ( const path& archiveName ); + void LoadMap ( const stringw& mapName, s32 collision ); + void CreatePlayers(); + void AddSky( u32 dome, const c8 *texture ); + Q3Player *GetPlayer ( u32 index ) { return &Player[index]; } + + void CreateGUI(); + void SetGUIActive( s32 command); + + bool OnEvent(const SEvent& eve); + + +private: + + GameData *Game; + + IQ3LevelMesh* Mesh; + ISceneNode* MapParent; + ISceneNode* ShaderParent; + ISceneNode* ItemParent; + ISceneNode* UnresolvedParent; + ISceneNode* BulletParent; + ISceneNode* FogParent; + ISceneNode * SkyNode; + IMetaTriangleSelector *Meta; + + c8 buf[256]; + + Q3Player Player[2]; + + struct SParticleImpact + { + u32 when; + vector3df pos; + vector3df outVector; + }; + array Impacts; + void useItem( Q3Player * player); + void createParticleImpacts( u32 now ); + + void createTextures (); + void addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent); + + GUI gui; + void dropMap (); +}; + +/* Constructor +*/ +CQuake3EventHandler::CQuake3EventHandler( GameData *game ) +: Game(game), Mesh(0), MapParent(0), ShaderParent(0), ItemParent(0), UnresolvedParent(0), + BulletParent(0), FogParent(0), SkyNode(0), Meta(0) +{ + buf[0]=0; + // Also use 16 Bit Textures for 16 Bit RenderDevice + if ( Game->deviceParam.Bits == 16 ) + { + game->Device->getVideoDriver()->setTextureCreationFlag(ETCF_ALWAYS_16_BIT, true); + } + + // Quake3 Shader controls Z-Writing + game->Device->getSceneManager()->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); + + // create internal textures + createTextures (); + + sound_init ( game->Device ); + + Game->Device->setEventReceiver ( this ); +} + + +// destructor +CQuake3EventHandler::~CQuake3EventHandler () +{ + Player[0].shutdown (); + sound_shutdown (); + + Game->save( "explorer.cfg" ); + + Game->Device->drop(); +} + + +// create runtime textures smog, fog +void CQuake3EventHandler::createTextures() +{ + IVideoDriver * driver = Game->Device->getVideoDriver(); + + dimension2du dim(64, 64); + + video::IImage* image; + u32 i; + u32 x; + u32 y; + u32 * data; + for ( i = 0; i != 8; ++i ) + { + image = driver->createImage ( video::ECF_A8R8G8B8, dim); + data = (u32*) image->lock (); + for ( y = 0; y != dim.Height; ++y ) + { + for ( x = 0; x != dim.Width; ++x ) + { + data [x] = 0xFFFFFFFF; + } + data = (u32*) ( (u8*) data + image->getPitch() ); + } + image->unlock(); + snprintf ( buf, 64, "smoke_%02d", i ); + driver->addTexture( buf, image ); + image->drop (); + } + + // fog + for ( i = 0; i != 1; ++i ) + { + image = driver->createImage ( video::ECF_A8R8G8B8, dim); + data = (u32*) image->lock (); + for ( y = 0; y != dim.Height; ++y ) + { + for ( x = 0; x != dim.Width; ++x ) + { + data [x] = 0xFFFFFFFF; + } + data = (u32*) ( (u8*) data + image->getPitch() ); + } + image->unlock(); + snprintf ( buf, 64, "fog_%02d", i ); + driver->addTexture( buf, image ); + image->drop (); + } +} + + +/* + create the GUI +*/ +void CQuake3EventHandler::CreateGUI() +{ + + IGUIEnvironment *env = Game->Device->getGUIEnvironment(); + IVideoDriver * driver = Game->Device->getVideoDriver(); + + gui.drop(); + + // set skin font + IGUIFont* font = env->getFont("fontlucida.png"); + if (font) + env->getSkin()->setFont(font); + env->getSkin()->setColor ( EGDC_BUTTON_TEXT, video::SColor(240,0xAA,0xAA,0xAA) ); + env->getSkin()->setColor ( EGDC_3D_HIGH_LIGHT, video::SColor(240,0x22,0x22,0x22) ); + env->getSkin()->setColor ( EGDC_3D_FACE, video::SColor(240,0x44,0x44,0x44) ); + env->getSkin()->setColor ( EGDC_EDITABLE, video::SColor(240,0x44,0x44,0x44) ); + env->getSkin()->setColor ( EGDC_FOCUSED_EDITABLE, video::SColor(240,0x54,0x54,0x54) ); + env->getSkin()->setColor ( EGDC_WINDOW, video::SColor(240,0x66,0x66,0x66) ); + + // minimal gui size 800x600 + dimension2d dim ( 800, 600 ); + dimension2d vdim ( Game->Device->getVideoDriver()->getScreenSize() ); + + if ( vdim.Height >= dim.Height && vdim.Width >= dim.Width ) + { + //dim = vdim; + } + else + { + } + + gui.Window = env->addWindow ( rect ( 0, 0, dim.Width, dim.Height ), false, L"Quake3 Explorer" ); + gui.Window->setToolTipText ( L"Quake3Explorer. Loads and show various BSP File Format and Shaders." ); + gui.Window->getCloseButton()->setToolTipText ( L"Quit Quake3 Explorer" ); + + // add a status line help text + gui.StatusLine = env->addStaticText( 0, rect( 5,dim.Height - 30,dim.Width - 5,dim.Height - 10), + false, false, gui.Window, -1, true + ); + + + env->addStaticText ( L"VideoDriver:", rect( dim.Width - 400, 24, dim.Width - 310, 40 ),false, false, gui.Window, -1, false ); + gui.VideoDriver = env->addComboBox(rect( dim.Width - 300, 24, dim.Width - 10, 40 ),gui.Window); + gui.VideoDriver->addItem(L"Direct3D 9.0c", EDT_DIRECT3D9 ); + gui.VideoDriver->addItem(L"Direct3D 8.1", EDT_DIRECT3D8 ); + gui.VideoDriver->addItem(L"OpenGL 1.5", EDT_OPENGL); + gui.VideoDriver->addItem(L"Software Renderer", EDT_SOFTWARE); + gui.VideoDriver->addItem(L"Burning's Video (TM) Thomas Alten", EDT_BURNINGSVIDEO); + gui.VideoDriver->setSelected ( gui.VideoDriver->getIndexForItemData ( Game->deviceParam.DriverType ) ); + gui.VideoDriver->setToolTipText ( L"Use a VideoDriver" ); + + env->addStaticText ( L"VideoMode:", rect( dim.Width - 400, 44, dim.Width - 310, 60 ),false, false, gui.Window, -1, false ); + gui.VideoMode = env->addComboBox(rect( dim.Width - 300, 44, dim.Width - 10, 60 ),gui.Window); + gui.VideoMode->setToolTipText ( L"Supported Screenmodes" ); + IVideoModeList *modeList = Game->Device->getVideoModeList(); + if ( modeList ) + { + s32 i; + for ( i = 0; i != modeList->getVideoModeCount (); ++i ) + { + u16 d = modeList->getVideoModeDepth ( i ); + if ( d < 16 ) + continue; + + u16 w = modeList->getVideoModeResolution ( i ).Width; + u16 h = modeList->getVideoModeResolution ( i ).Height; + u32 val = w << 16 | h; + + if ( gui.VideoMode->getIndexForItemData ( val ) >= 0 ) + continue; + + f32 aspect = (f32) w / (f32) h; + const c8 *a = ""; + if ( core::equals ( aspect, 1.3333333333f ) ) a = "4:3"; + else if ( core::equals ( aspect, 1.6666666f ) ) a = "15:9 widescreen"; + else if ( core::equals ( aspect, 1.7777777f ) ) a = "16:9 widescreen"; + else if ( core::equals ( aspect, 1.6f ) ) a = "16:10 widescreen"; + else if ( core::equals ( aspect, 2.133333f ) ) a = "20:9 widescreen"; + + snprintf ( buf, sizeof ( buf ), "%d x %d, %s",w, h, a ); + gui.VideoMode->addItem ( stringw ( buf ).c_str(), val ); + } + } + gui.VideoMode->setSelected ( gui.VideoMode->getIndexForItemData ( + Game->deviceParam.WindowSize.Width << 16 | + Game->deviceParam.WindowSize.Height ) ); + + gui.FullScreen = env->addCheckBox ( Game->deviceParam.Fullscreen, rect( dim.Width - 400, 64, dim.Width - 300, 80 ), gui.Window,-1, L"Fullscreen" ); + gui.FullScreen->setToolTipText ( L"Set Fullscreen or Window Mode" ); + + gui.Bit32 = env->addCheckBox ( Game->deviceParam.Bits == 32, rect( dim.Width - 300, 64, dim.Width - 240, 80 ), gui.Window,-1, L"32Bit" ); + gui.Bit32->setToolTipText ( L"Use 16 or 32 Bit" ); + + env->addStaticText ( L"MultiSample:", rect( dim.Width - 235, 64, dim.Width - 150, 80 ),false, false, gui.Window, -1, false ); + gui.MultiSample = env->addScrollBar( true, rect( dim.Width - 150, 64, dim.Width - 70, 80 ), gui.Window,-1 ); + gui.MultiSample->setMin ( 0 ); + gui.MultiSample->setMax ( 8 ); + gui.MultiSample->setSmallStep ( 1 ); + gui.MultiSample->setLargeStep ( 1 ); + gui.MultiSample->setPos ( Game->deviceParam.AntiAlias ); + gui.MultiSample->setToolTipText ( L"Set the MultiSample (disable, 1x, 2x, 4x, 8x )" ); + + gui.SetVideoMode = env->addButton (rect( dim.Width - 60, 64, dim.Width - 10, 80 ), gui.Window, -1,L"set" ); + gui.SetVideoMode->setToolTipText ( L"Set Video Mode with current values" ); + + env->addStaticText ( L"Gamma:", rect( dim.Width - 400, 104, dim.Width - 310, 120 ),false, false, gui.Window, -1, false ); + gui.Gamma = env->addScrollBar( true, rect( dim.Width - 300, 104, dim.Width - 10, 120 ), gui.Window,-1 ); + gui.Gamma->setMin ( 50 ); + gui.Gamma->setMax ( 350 ); + gui.Gamma->setSmallStep ( 1 ); + gui.Gamma->setLargeStep ( 10 ); + gui.Gamma->setPos ( core::floor32 ( Game->GammaValue * 100.f ) ); + gui.Gamma->setToolTipText ( L"Adjust Gamma Ramp ( 0.5 - 3.5)" ); + Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f ); + + + env->addStaticText ( L"Tesselation:", rect( dim.Width - 400, 124, dim.Width - 310, 140 ),false, false, gui.Window, -1, false ); + gui.Tesselation = env->addScrollBar( true, rect( dim.Width - 300, 124, dim.Width - 10, 140 ), gui.Window,-1 ); + gui.Tesselation->setMin ( 2 ); + gui.Tesselation->setMax ( 12 ); + gui.Tesselation->setSmallStep ( 1 ); + gui.Tesselation->setLargeStep ( 1 ); + gui.Tesselation->setPos ( Game->loadParam.patchTesselation ); + gui.Tesselation->setToolTipText ( L"How smooth should curved surfaces be rendered" ); + + gui.Collision = env->addCheckBox ( true, rect( dim.Width - 400, 150, dim.Width - 300, 166 ), gui.Window,-1, L"Collision" ); + gui.Collision->setToolTipText ( L"Set collision on or off ( flythrough ). \nPress F7 on your Keyboard" ); + gui.Visible_Map = env->addCheckBox ( true, rect( dim.Width - 300, 150, dim.Width - 240, 166 ), gui.Window,-1, L"Map" ); + gui.Visible_Map->setToolTipText ( L"Show or not show the static part the Level. \nPress F3 on your Keyboard" ); + gui.Visible_Shader = env->addCheckBox ( true, rect( dim.Width - 240, 150, dim.Width - 170, 166 ), gui.Window,-1, L"Shader" ); + gui.Visible_Shader->setToolTipText ( L"Show or not show the Shader Nodes. \nPress F4 on your Keyboard" ); + gui.Visible_Fog = env->addCheckBox ( true, rect( dim.Width - 170, 150, dim.Width - 110, 166 ), gui.Window,-1, L"Fog" ); + gui.Visible_Fog->setToolTipText ( L"Show or not show the Fog Nodes. \nPress F5 on your Keyboard" ); + gui.Visible_Unresolved = env->addCheckBox ( true, rect( dim.Width - 110, 150, dim.Width - 10, 166 ), gui.Window,-1, L"Unresolved" ); + gui.Visible_Unresolved->setToolTipText ( L"Show the or not show the Nodes the Engine can't handle. \nPress F6 on your Keyboard" ); + gui.Visible_Skydome = env->addCheckBox ( true, rect( dim.Width - 110, 180, dim.Width - 10, 196 ), gui.Window,-1, L"Skydome" ); + gui.Visible_Skydome->setToolTipText ( L"Show the or not show the Skydome." ); + + //Respawn = env->addButton ( rect( dim.Width - 260, 90, dim.Width - 10, 106 ), 0,-1, L"Respawn" ); + + env->addStaticText ( L"Archives:", rect( 5, dim.Height - 530, dim.Width - 600,dim.Height - 514 ),false, false, gui.Window, -1, false ); + + gui.ArchiveAdd = env->addButton ( rect( dim.Width - 725, dim.Height - 530, dim.Width - 665, dim.Height - 514 ), gui.Window,-1, L"add" ); + gui.ArchiveAdd->setToolTipText ( L"Add an archive, usually packed zip-archives (*.pk3) to the Filesystem" ); + gui.ArchiveRemove = env->addButton ( rect( dim.Width - 660, dim.Height - 530, dim.Width - 600, dim.Height - 514 ), gui.Window,-1, L"del" ); + gui.ArchiveRemove->setToolTipText ( L"Remove the selected archive from the FileSystem." ); + gui.ArchiveUp = env->addButton ( rect( dim.Width - 575, dim.Height - 530, dim.Width - 515, dim.Height - 514 ), gui.Window,-1, L"up" ); + gui.ArchiveUp->setToolTipText ( L"Arrange Archive Look-up Hirachy. Move the selected Archive up" ); + gui.ArchiveDown = env->addButton ( rect( dim.Width - 510, dim.Height - 530, dim.Width - 440, dim.Height - 514 ), gui.Window,-1, L"down" ); + gui.ArchiveDown->setToolTipText ( L"Arrange Archive Look-up Hirachy. Move the selected Archive down" ); + + + gui.ArchiveList = env->addTable ( rect( 5,dim.Height - 510, dim.Width - 450,dim.Height - 410 ), gui.Window ); + gui.ArchiveList->addColumn ( L"Type", 0 ); + gui.ArchiveList->addColumn ( L"Real File Path", 1 ); + gui.ArchiveList->setColumnWidth ( 0, 60 ); + gui.ArchiveList->setColumnWidth ( 1, 284 ); + gui.ArchiveList->setToolTipText ( L"Show the attached Archives" ); + + + env->addStaticText ( L"Maps:", rect( 5, dim.Height - 400, dim.Width - 450,dim.Height - 380 ),false, false, gui.Window, -1, false ); + gui.MapList = env->addListBox ( rect( 5,dim.Height - 380, dim.Width - 450,dim.Height - 40 ), gui.Window, -1, true ); + gui.MapList->setToolTipText ( L"Show the current Maps in all Archives.\n Double-Click the Map to start the level" ); + + + // create a visible Scene Tree + env->addStaticText ( L"Scenegraph:", rect( dim.Width - 400, dim.Height - 400, dim.Width - 5,dim.Height - 380 ),false, false, gui.Window, -1, false ); + gui.SceneTree = env->addTreeView( rect( dim.Width - 400, dim.Height - 380, dim.Width - 5, dim.Height - 40 ), + gui.Window, -1, true, true, false ); + gui.SceneTree->setToolTipText ( L"Show the current Scenegraph" ); + gui.SceneTree->getRoot()->clearChildren(); + addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() ); + + + IGUIImageList* imageList = env->createImageList( driver->getTexture ( "iconlist.png" ), + dimension2di( 32, 32 ), true ); + + if ( imageList ) + { + gui.SceneTree->setImageList( imageList ); + imageList->drop (); + } + + + // load the engine logo + gui.Logo = env->addImage( driver->getTexture("irrlichtlogo3.png"), position2d(5, 16 ), true, 0 ); + gui.Logo->setToolTipText ( L"The great Irrlicht Engine" ); + + AddArchive ( "" ); +} + + +/* + Add an Archive to the FileSystems and updates the GUI +*/ +void CQuake3EventHandler::AddArchive ( const path& archiveName ) +{ + IFileSystem *fs = Game->Device->getFileSystem(); + u32 i; + + if ( archiveName.size () ) + { + bool exists = false; + for ( i = 0; i != fs->getFileArchiveCount(); ++i ) + { + if ( fs->getFileArchive(i)->getFileList()->getPath() == archiveName ) + { + exists = true; + break; + } + } + + if (!exists) + { + fs->addFileArchive(archiveName, true, false); + } + } + + // store the current archives in game data + // show the attached Archive in proper order + if ( gui.ArchiveList ) + { + gui.ArchiveList->clearRows(); + + for ( i = 0; i != fs->getFileArchiveCount(); ++i ) + { + IFileArchive * archive = fs->getFileArchive ( i ); + + u32 index = gui.ArchiveList->addRow(i); + + core::stringw typeName; + switch(archive->getType()) + { + case io::EFAT_ZIP: + typeName = "ZIP"; + break; + case io::EFAT_GZIP: + typeName = "gzip"; + break; + case io::EFAT_FOLDER: + typeName = "Mount"; + break; + case io::EFAT_PAK: + typeName = "PAK"; + break; + case io::EFAT_TAR: + typeName = "TAR"; + break; + default: + typeName = "archive"; + } + + gui.ArchiveList->setCellText ( index, 0, typeName ); + gui.ArchiveList->setCellText ( index, 1, archive->getFileList()->getPath() ); + } + } + + + // browse the archives for maps + if ( gui.MapList ) + { + gui.MapList->clear(); + + IGUISpriteBank *bank = Game->Device->getGUIEnvironment()->getSpriteBank("sprite_q3map"); + if ( 0 == bank ) + bank = Game->Device->getGUIEnvironment()->addEmptySpriteBank("sprite_q3map"); + + SGUISprite sprite; + SGUISpriteFrame frame; + core::rect r; + + bank->getSprites().clear(); + bank->getPositions().clear (); + gui.MapList->setSpriteBank ( bank ); + + u32 g = 0; + core::stringw s; + + // browse the attached file system + fs->setFileListSystem ( FILESYSTEM_VIRTUAL ); + fs->changeWorkingDirectoryTo ( "/maps/" ); + IFileList *fileList = fs->createFileList (); + fs->setFileListSystem ( FILESYSTEM_NATIVE ); + + for ( i=0; i< fileList->getFileCount(); ++i) + { + s = fileList->getFullFileName(i); + if ( s.find ( ".bsp" ) >= 0 ) + { + // get level screenshot. reformat texture to 128x128 + path c ( s ); + deletePathFromFilename ( c ); + cutFilenameExtension ( c, c ); + c = path ( "levelshots/" ) + c; + + dimension2du dim ( 128, 128 ); + IVideoDriver * driver = Game->Device->getVideoDriver(); + IImage* image = 0; + ITexture *tex = 0; + path filename; + + filename = c + ".jpg"; + if ( fs->existFile ( filename ) ) + image = driver->createImageFromFile( filename ); + if ( 0 == image ) + { + filename = c + ".tga"; + if ( fs->existFile ( filename ) ) + image = driver->createImageFromFile( filename ); + } + + if ( image ) + { + IImage* filter = driver->createImage ( video::ECF_R8G8B8, dim ); + image->copyToScalingBoxFilter ( filter, 0 ); + image->drop (); + image = filter; + } + + if ( image ) + { + tex = driver->addTexture ( filename, image ); + image->drop (); + } + + + bank->setTexture ( g, tex ); + + r.LowerRightCorner.X = dim.Width; + r.LowerRightCorner.Y = dim.Height; + gui.MapList->setItemHeight ( r.LowerRightCorner.Y + 4 ); + frame.rectNumber = bank->getPositions().size(); + frame.textureNumber = g; + + bank->getPositions().push_back(r); + + sprite.Frames.set_used ( 0 ); + sprite.Frames.push_back(frame); + sprite.frameTime = 0; + bank->getSprites().push_back(sprite); + + gui.MapList->addItem ( s.c_str (), g ); + g += 1; + } + } + fileList->drop (); + + gui.MapList->setSelected ( -1 ); + IGUIScrollBar * bar = (IGUIScrollBar*)gui.MapList->getElementFromId( 0 ); + if ( bar ) + bar->setPos ( 0 ); + + } + +} + +/* + clears the Map in Memory +*/ +void CQuake3EventHandler::dropMap () +{ + IVideoDriver * driver = Game->Device->getVideoDriver(); + + driver->removeAllHardwareBuffers (); + driver->removeAllTextures (); + + Player[0].shutdown (); + + + dropElement ( ItemParent ); + dropElement ( ShaderParent ); + dropElement ( UnresolvedParent ); + dropElement ( FogParent ); + dropElement ( BulletParent ); + + + Impacts.clear(); + + if ( Meta ) + { + Meta = 0; + } + + dropElement ( MapParent ); + dropElement ( SkyNode ); + + // clean out meshes, because textures are invalid + // TODO: better texture handling;-) + IMeshCache *cache = Game->Device->getSceneManager ()->getMeshCache(); + cache->clear (); + Mesh = 0; +} + +/* Load new map +*/ +void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) +{ + if ( 0 == mapName.size() ) + return; + + dropMap (); + + IFileSystem *fs = Game->Device->getFileSystem(); + ISceneManager *smgr = Game->Device->getSceneManager (); + + IReadFile* file = fs->createMemoryReadFile(&Game->loadParam, + sizeof(Game->loadParam), L"levelparameter.cfg", false); + + // load cfg file + smgr->getMesh( file ); + file->drop (); + + // load the actual map + Mesh = (IQ3LevelMesh*) smgr->getMesh(mapName); + if ( 0 == Mesh ) + return; + + /* + add the geometry mesh to the Scene ( polygon & patches ) + The Geometry mesh is optimised for faster drawing + */ + + IMesh *geometry = Mesh->getMesh(E_Q3_MESH_GEOMETRY); + if ( 0 == geometry || geometry->getMeshBufferCount() == 0) + return; + + Game->CurrentMapName = mapName; + + //create a collision list + Meta = 0; + + ITriangleSelector * selector = 0; + if (collision) + Meta = smgr->createMetaTriangleSelector(); + + //IMeshBuffer *b0 = geometry->getMeshBuffer(0); + //s32 minimalNodes = b0 ? core::s32_max ( 2048, b0->getVertexCount() / 32 ) : 2048; + s32 minimalNodes = 2048; + + MapParent = smgr->addOctreeSceneNode(geometry, 0, -1, minimalNodes); + MapParent->setName ( mapName ); + if ( Meta ) + { + selector = smgr->createOctreeTriangleSelector( geometry,MapParent, minimalNodes); + //selector = smgr->createTriangleSelector ( geometry, MapParent ); + Meta->addTriangleSelector( selector); + selector->drop (); + } + + // logical parent for the items + ItemParent = smgr->addEmptySceneNode(); + if ( ItemParent ) + ItemParent->setName ( "Item Container" ); + + ShaderParent = smgr->addEmptySceneNode(); + if ( ShaderParent ) + ShaderParent->setName ( "Shader Container" ); + + UnresolvedParent = smgr->addEmptySceneNode(); + if ( UnresolvedParent ) + UnresolvedParent->setName ( "Unresolved Container" ); + + FogParent = smgr->addEmptySceneNode(); + if ( FogParent ) + FogParent->setName ( "Fog Container" ); + + // logical parent for the bullets + BulletParent = smgr->addEmptySceneNode(); + if ( BulletParent ) + BulletParent->setName ( "Bullet Container" ); + + /* + now construct SceneNodes for each Shader + The Objects are stored in the quake mesh E_Q3_MESH_ITEMS + and the Shader ID is stored in the MaterialParameters + mostly dark looking skulls and moving lava.. or green flashing tubes? + */ + Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_ITEMS,ShaderParent, Meta, false ); + Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_FOG,FogParent, 0, false ); + Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_UNRESOLVED,UnresolvedParent, Meta, true ); + + /* + Now construct Models from Entity List + */ + Q3ModelFactory ( Game->loadParam, Game->Device, Mesh, ItemParent, false ); +} + +/* + Adds a SceneNode with an icon to the Scene Tree +*/ +void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent) +{ + IGUITreeViewNode* node; + wchar_t msg[128]; + + s32 imageIndex; + list::ConstIterator it = parent->getChildren().begin(); + for (; it != parent->getChildren().end(); ++it) + { + switch ( (*it)->getType () ) + { + case ESNT_Q3SHADER_SCENE_NODE: imageIndex = 0; break; + case ESNT_CAMERA: imageIndex = 1; break; + case ESNT_EMPTY: imageIndex = 2; break; + case ESNT_MESH: imageIndex = 3; break; + case ESNT_OCTREE: imageIndex = 3; break; + case ESNT_ANIMATED_MESH: imageIndex = 4; break; + case ESNT_SKY_BOX: imageIndex = 5; break; + case ESNT_BILLBOARD: imageIndex = 6; break; + case ESNT_PARTICLE_SYSTEM: imageIndex = 7; break; + case ESNT_TEXT: imageIndex = 8; break; + default:imageIndex = -1; break; + } + + if ( imageIndex < 0 ) + { + swprintf ( msg, 128, L"%hs,%hs", + Game->Device->getSceneManager ()->getSceneNodeTypeName ( (*it)->getType () ), + (*it)->getName() + ); + } + else + { + swprintf ( msg, 128, L"%hs",(*it)->getName() ); + } + + node = nodeParent->addChildBack( msg, 0, imageIndex ); + + // Add all Animators + list::ConstIterator ait = (*it)->getAnimators().begin(); + for (; ait != (*it)->getAnimators().end(); ++ait) + { + imageIndex = -1; + swprintf ( msg, 128, L"%hs", + Game->Device->getSceneManager ()->getAnimatorTypeName ( (*ait)->getType () ) + ); + + switch ( (*ait)->getType () ) + { + case ESNAT_FLY_CIRCLE: + case ESNAT_FLY_STRAIGHT: + case ESNAT_FOLLOW_SPLINE: + case ESNAT_ROTATION: + case ESNAT_TEXTURE: + case ESNAT_DELETION: + case ESNAT_COLLISION_RESPONSE: + case ESNAT_CAMERA_FPS: + case ESNAT_CAMERA_MAYA: + default: + break; + } + node->addChildBack( msg, 0, imageIndex ); + } + + addSceneTreeItem ( *it, node ); + } +} + + +// Adds life! +void CQuake3EventHandler::CreatePlayers() +{ + Player[0].create ( Game->Device, Mesh, MapParent, Meta ); +} + + +// Adds a skydome to the scene +void CQuake3EventHandler::AddSky( u32 dome, const c8 *texture) +{ + ISceneManager *smgr = Game->Device->getSceneManager (); + IVideoDriver * driver = Game->Device->getVideoDriver(); + + bool oldMipMapState = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); + + if ( 0 == dome ) + { + // irrlicht order + //static const c8*p[] = { "ft", "lf", "bk", "rt", "up", "dn" }; + // quake3 order + static const c8*p[] = { "ft", "rt", "bk", "lf", "up", "dn" }; + + u32 i = 0; + snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] ); + SkyNode = smgr->addSkyBoxSceneNode( driver->getTexture ( buf ), 0, 0, 0, 0, 0 ); + + if (SkyNode) + { + for ( i = 0; i < 6; ++i ) + { + snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] ); + SkyNode->getMaterial(i).setTexture ( 0, driver->getTexture ( buf ) ); + } + } + } + else + if ( 1 == dome ) + { + snprintf ( buf, 64, "%s.jpg", texture ); + SkyNode = smgr->addSkyDomeSceneNode( + driver->getTexture( buf ), 32,32, + 1.f, 1.f, 1000.f, 0, 11); + } + else + if ( 2 == dome ) + { + snprintf ( buf, 64, "%s.jpg", texture ); + SkyNode = smgr->addSkyDomeSceneNode( + driver->getTexture( buf ), 16,8, + 0.95f, 2.f, 1000.f, 0, 11); + } + + if (SkyNode) + SkyNode->setName("Skydome"); + //SkyNode->getMaterial(0).ZBuffer = video::EMDF_DEPTH_LESS_EQUAL; + + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); +} + + +// enable GUI elements +void CQuake3EventHandler::SetGUIActive( s32 command) +{ + bool inputState = false; + + ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera (); + + switch ( command ) + { + case 0: Game->guiActive = 0; inputState = !Game->guiActive; break; + case 1: Game->guiActive = 1; inputState = !Game->guiActive;;break; + case 2: Game->guiActive ^= 1; inputState = !Game->guiActive;break; + case 3: + if ( camera ) + inputState = !camera->isInputReceiverEnabled(); + break; + } + + if ( camera ) + { + camera->setInputReceiverEnabled ( inputState ); + Game->Device->getCursorControl()->setVisible( !inputState ); + } + + if ( gui.Window ) + { + gui.Window->setVisible ( Game->guiActive != 0 ); + } + + if ( Game->guiActive && + gui.SceneTree && Game->Device->getGUIEnvironment()->getFocus() != gui.SceneTree + ) + { + gui.SceneTree->getRoot()->clearChildren(); + addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() ); + } + + Game->Device->getGUIEnvironment()->setFocus ( Game->guiActive ? gui.Window: 0 ); +} + + +/* + Handle game input +*/ +bool CQuake3EventHandler::OnEvent(const SEvent& eve) +{ + if ( eve.EventType == EET_LOG_TEXT_EVENT ) + { + return false; + } + + if ( Game->guiActive && eve.EventType == EET_GUI_EVENT ) + { + if ( eve.GUIEvent.Caller == gui.MapList && eve.GUIEvent.EventType == gui::EGET_LISTBOX_SELECTED_AGAIN ) + { + s32 selected = gui.MapList->getSelected(); + if ( selected >= 0 ) + { + stringw loadMap = gui.MapList->getListItem ( selected ); + if ( 0 == MapParent || loadMap != Game->CurrentMapName ) + { + printf ( "Loading map %ls\n", loadMap.c_str() ); + LoadMap ( loadMap , 1 ); + if ( 0 == Game->loadParam.loadSkyShader ) + { + AddSky ( 1, "skydome2" ); + } + CreatePlayers (); + CreateGUI (); + SetGUIActive ( 0 ); + return true; + } + } + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveRemove && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + Game->Device->getFileSystem()->removeFileArchive( gui.ArchiveList->getSelected() ); + Game->CurrentMapName = ""; + AddArchive ( "" ); + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveAdd && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + if ( 0 == gui.ArchiveFileOpen ) + { + Game->Device->getFileSystem()->setFileListSystem ( FILESYSTEM_NATIVE ); + gui.ArchiveFileOpen = Game->Device->getGUIEnvironment()->addFileOpenDialog ( L"Add Game Archive" , false,gui.Window ); + } + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_SELECTED ) + { + AddArchive ( gui.ArchiveFileOpen->getFileName() ); + gui.ArchiveFileOpen = 0; + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_DIRECTORY_SELECTED ) + { + AddArchive ( gui.ArchiveFileOpen->getDirectoryName() ); + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_CHOOSE_DIALOG_CANCELLED ) + { + gui.ArchiveFileOpen = 0; + } + else + if ( ( eve.GUIEvent.Caller == gui.ArchiveUp || eve.GUIEvent.Caller == gui.ArchiveDown ) && + eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + s32 rel = eve.GUIEvent.Caller == gui.ArchiveUp ? -1 : 1; + if ( Game->Device->getFileSystem()->moveFileArchive ( gui.ArchiveList->getSelected (), rel ) ) + { + s32 newIndex = core::s32_clamp ( gui.ArchiveList->getSelected() + rel, 0, gui.ArchiveList->getRowCount() - 1 ); + AddArchive ( "" ); + gui.ArchiveList->setSelected ( newIndex ); + Game->CurrentMapName = ""; + } + } + else + if ( eve.GUIEvent.Caller == gui.VideoDriver && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) + { + Game->deviceParam.DriverType = (E_DRIVER_TYPE) gui.VideoDriver->getItemData ( gui.VideoDriver->getSelected() ); + } + else + if ( eve.GUIEvent.Caller == gui.VideoMode && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) + { + u32 val = gui.VideoMode->getItemData ( gui.VideoMode->getSelected() ); + Game->deviceParam.WindowSize.Width = val >> 16; + Game->deviceParam.WindowSize.Height = val & 0xFFFF; + } + else + if ( eve.GUIEvent.Caller == gui.FullScreen && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + Game->deviceParam.Fullscreen = gui.FullScreen->isChecked(); + } + else + if ( eve.GUIEvent.Caller == gui.Bit32 && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + Game->deviceParam.Bits = gui.Bit32->isChecked() ? 32 : 16; + } + else + if ( eve.GUIEvent.Caller == gui.MultiSample && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) + { + Game->deviceParam.AntiAlias = gui.MultiSample->getPos(); + } + else + if ( eve.GUIEvent.Caller == gui.Tesselation && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) + { + Game->loadParam.patchTesselation = gui.Tesselation->getPos (); + } + else + if ( eve.GUIEvent.Caller == gui.Gamma && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) + { + Game->GammaValue = gui.Gamma->getPos () * 0.01f; + Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f ); + } + else + if ( eve.GUIEvent.Caller == gui.SetVideoMode && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + Game->retVal = 2; + Game->Device->closeDevice(); + } + else + if ( eve.GUIEvent.Caller == gui.Window && eve.GUIEvent.EventType == gui::EGET_ELEMENT_CLOSED ) + { + Game->Device->closeDevice(); + } + else + if ( eve.GUIEvent.Caller == gui.Collision && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + // set fly through active + Game->flyTroughState ^= 1; + Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 ); + + printf ( "collision %d\n", Game->flyTroughState == 0 ); + } + else + if ( eve.GUIEvent.Caller == gui.Visible_Map && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + bool v = gui.Visible_Map->isChecked(); + + if ( MapParent ) + { + printf ( "static node set visible %d\n",v ); + MapParent->setVisible ( v ); + } + } + else + if ( eve.GUIEvent.Caller == gui.Visible_Shader && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + bool v = gui.Visible_Shader->isChecked(); + + if ( ShaderParent ) + { + printf ( "shader node set visible %d\n",v ); + ShaderParent->setVisible ( v ); + } + } + else + if ( eve.GUIEvent.Caller == gui.Visible_Skydome && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + if ( SkyNode ) + { + bool v = !SkyNode->isVisible(); + printf ( "skynode set visible %d\n",v ); + SkyNode->setVisible ( v ); + } + } + else + if ( eve.GUIEvent.Caller == gui.Respawn && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + Player[0].respawn (); + } + + return false; + } + + // fire + if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_SPACE && + eve.KeyInput.PressedDown == false) || + (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) + ) + { + ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera (); + if ( camera && camera->isInputReceiverEnabled () ) + { + useItem( Player + 0 ); + } + } + + // gui active + if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_F1 && + eve.KeyInput.PressedDown == false) || + (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) + ) + { + SetGUIActive ( 2 ); + } + + // check if user presses the key + if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.PressedDown == false) + { + // Escape toggles camera Input + if ( eve.KeyInput.Key == irr::KEY_ESCAPE ) + { + SetGUIActive ( 3 ); + } + else + if (eve.KeyInput.Key == KEY_F11) + { + // screenshot are taken without gamma! + IImage* image = Game->Device->getVideoDriver()->createScreenShot(); + if (image) + { + core::vector3df pos; + core::vector3df rot; + ICameraSceneNode * cam = Game->Device->getSceneManager()->getActiveCamera (); + if ( cam ) + { + pos = cam->getPosition (); + rot = cam->getRotation (); + } + + static const c8 *dName[] = { "null", "software", "burning", + "d3d8", "d3d9", "opengl" }; + + snprintf(buf, 256, "%s_%ls_%.0f_%.0f_%.0f_%.0f_%.0f_%.0f.jpg", + dName[Game->Device->getVideoDriver()->getDriverType()], + Game->CurrentMapName.c_str(), + pos.X, pos.Y, pos.Z, + rot.X, rot.Y, rot.Z + ); + path filename ( buf ); + filename.replace ( '/', '_' ); + printf ( "screenshot : %s\n", filename.c_str() ); + Game->Device->getVideoDriver()->writeImageToFile(image, filename, 100 ); + image->drop(); + } + } + else + if (eve.KeyInput.Key == KEY_F9) + { + s32 value = EDS_OFF; + + Game->debugState = ( Game->debugState + 1 ) & 3; + + switch ( Game->debugState ) + { + case 1: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL; break; + case 2: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_SKELETON; break; + } +/* + // set debug map data on/off + debugState = debugState == EDS_OFF ? + EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL: + EDS_OFF; +*/ + if ( ItemParent ) + { + list::ConstIterator it = ItemParent->getChildren().begin(); + for (; it != ItemParent->getChildren().end(); ++it) + { + (*it)->setDebugDataVisible ( value ); + } + } + + if ( ShaderParent ) + { + list::ConstIterator it = ShaderParent->getChildren().begin(); + for (; it != ShaderParent->getChildren().end(); ++it) + { + (*it)->setDebugDataVisible ( value ); + } + } + + if ( UnresolvedParent ) + { + list::ConstIterator it = UnresolvedParent->getChildren().begin(); + for (; it != UnresolvedParent->getChildren().end(); ++it) + { + (*it)->setDebugDataVisible ( value ); + } + } + + if ( FogParent ) + { + list::ConstIterator it = FogParent->getChildren().begin(); + for (; it != FogParent->getChildren().end(); ++it) + { + (*it)->setDebugDataVisible ( value ); + } + } + + if ( SkyNode ) + { + SkyNode->setDebugDataVisible ( value ); + } + + } + else + if (eve.KeyInput.Key == KEY_F8) + { + // set gravity on/off + Game->gravityState ^= 1; + Player[0].cam()->setGravity ( getGravity ( Game->gravityState ? "earth" : "none" ) ); + printf ( "gravity %s\n", Game->gravityState ? "earth" : "none" ); + } + else + if (eve.KeyInput.Key == KEY_F7) + { + // set fly through active + Game->flyTroughState ^= 1; + Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 ); + if ( gui.Collision ) + gui.Collision->setChecked ( Game->flyTroughState == 0 ); + + printf ( "collision %d\n", Game->flyTroughState == 0 ); + } + else + if (eve.KeyInput.Key == KEY_F2) + { + Player[0].respawn (); + } + else + if (eve.KeyInput.Key == KEY_F3) + { + if ( MapParent ) + { + bool v = !MapParent->isVisible (); + printf ( "static node set visible %d\n",v ); + MapParent->setVisible ( v ); + if ( gui.Visible_Map ) + gui.Visible_Map->setChecked ( v ); + } + } + else + if (eve.KeyInput.Key == KEY_F4) + { + if ( ShaderParent ) + { + bool v = !ShaderParent->isVisible (); + printf ( "shader node set visible %d\n",v ); + ShaderParent->setVisible ( v ); + if ( gui.Visible_Shader ) + gui.Visible_Shader->setChecked ( v ); + } + } + else + if (eve.KeyInput.Key == KEY_F5) + { + if ( FogParent ) + { + bool v = !FogParent->isVisible (); + printf ( "fog node set visible %d\n",v ); + FogParent->setVisible ( v ); + if ( gui.Visible_Fog ) + gui.Visible_Fog->setChecked ( v ); + } + + } + else + if (eve.KeyInput.Key == KEY_F6) + { + if ( UnresolvedParent ) + { + bool v = !UnresolvedParent->isVisible (); + printf ( "unresolved node set visible %d\n",v ); + UnresolvedParent->setVisible ( v ); + if ( gui.Visible_Unresolved ) + gui.Visible_Unresolved->setChecked ( v ); + } + } + } + + // check if user presses the key C ( for crouch) + if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_KEY_C ) + { + // crouch + ISceneNodeAnimatorCollisionResponse *anim = Player[0].cam (); + if ( anim && 0 == Game->flyTroughState ) + { + if ( false == eve.KeyInput.PressedDown ) + { + // stand up + anim->setEllipsoidRadius ( vector3df(30,45,30) ); + anim->setEllipsoidTranslation ( vector3df(0,40,0)); + + } + else + { + // on your knees + anim->setEllipsoidRadius ( vector3df(30,20,30) ); + anim->setEllipsoidTranslation ( vector3df(0,20,0)); + } + return true; + } + } + return false; +} + + + +/* + useItem +*/ +void CQuake3EventHandler::useItem( Q3Player * player) +{ + ISceneManager* smgr = Game->Device->getSceneManager(); + ICameraSceneNode* camera = smgr->getActiveCamera(); + + if (!camera) + return; + + SParticleImpact imp; + imp.when = 0; + + // get line of camera + + vector3df start = camera->getPosition(); + + if ( player->WeaponNode ) + { + start.X += 0.f; + start.Y += 0.f; + start.Z += 0.f; + } + + vector3df end = (camera->getTarget() - start); + end.normalize(); + start += end*20.0f; + + end = start + (end * camera->getFarValue()); + + triangle3df triangle; + line3d line(start, end); + + // get intersection point with map + scene::ISceneNode* hitNode; + if (smgr->getSceneCollisionManager()->getCollisionPoint( + line, Meta, end, triangle,hitNode)) + { + // collides with wall + vector3df out = triangle.getNormal(); + out.setLength(0.03f); + + imp.when = 1; + imp.outVector = out; + imp.pos = end; + + player->setAnim ( "pow" ); + player->Anim[1].next += player->Anim[1].delta; + } + else + { + // doesnt collide with wall + vector3df start = camera->getPosition(); + if ( player->WeaponNode ) + { + //start.X += 10.f; + //start.Y += -5.f; + //start.Z += 1.f; + } + + vector3df end = (camera->getTarget() - start); + end.normalize(); + start += end*20.0f; + end = start + (end * camera->getFarValue()); + } + + // create fire ball + ISceneNode* node = 0; + node = smgr->addBillboardSceneNode( BulletParent,dimension2d(10,10), start); + + node->setMaterialFlag(EMF_LIGHTING, false); + node->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture("fireball.bmp")); + node->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); + node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR); + + f32 length = (f32)(end - start).getLength(); + const f32 speed = 5.8f; + u32 time = (u32)(length / speed); + + ISceneNodeAnimator* anim = 0; + + // set flight line + + anim = smgr->createFlyStraightAnimator(start, end, time); + node->addAnimator(anim); + anim->drop(); + + snprintf ( buf, 64, "bullet: %s on %.1f,%1.f,%1.f", + imp.when ? "hit" : "nohit", end.X, end.Y, end.Z ); + node->setName ( buf ); + + + anim = smgr->createDeleteAnimator(time); + node->addAnimator(anim); + anim->drop(); + + if (imp.when) + { + // create impact note + imp.when = Game->Device->getTimer()->getTime() + + (time + (s32) ( ( 1.f + Noiser::get() ) * 250.f )); + Impacts.push_back(imp); + } + + // play sound +} + +// rendered when bullets hit something +void CQuake3EventHandler::createParticleImpacts( u32 now ) +{ + ISceneManager* sm = Game->Device->getSceneManager(); + + struct smokeLayer + { + const c8 * texture; + f32 scale; + f32 minparticleSize; + f32 maxparticleSize; + f32 boxSize; + u32 minParticle; + u32 maxParticle; + u32 fadeout; + u32 lifetime; + }; + + smokeLayer smoke[] = + { + { "smoke2.jpg", 0.4f, 1.5f, 18.f, 20.f, 20, 50, 2000, 10000 }, + { "smoke3.jpg", 0.2f, 1.2f, 15.f, 20.f, 10, 30, 1000, 12000 } + }; + + + u32 i; + u32 g; + s32 factor = 1; + for ( g = 0; g != 2; ++g ) + { + smoke[g].minParticle *= factor; + smoke[g].maxParticle *= factor; + smoke[g].lifetime *= factor; + smoke[g].boxSize *= Noiser::get() * 0.5f; + } + + for ( i=0; i < Impacts.size(); ++i) + { + if (now < Impacts[i].when) + continue; + + // create smoke particle system + IParticleSystemSceneNode* pas = 0; + + for ( g = 0; g != 2; ++g ) + { + pas = sm->addParticleSystemSceneNode(false, BulletParent, -1, Impacts[i].pos); + + snprintf ( buf, 64, "bullet impact smoke at %.1f,%.1f,%1.f", + Impacts[i].pos.X,Impacts[i].pos.Y,Impacts[i].pos.Z); + pas->setName ( buf ); + + // create a flat smoke + vector3df direction = Impacts[i].outVector; + direction *= smoke[g].scale; + IParticleEmitter* em = pas->createBoxEmitter( + aabbox3d(-4.f,0.f,-4.f,20.f,smoke[g].minparticleSize,20.f), + direction,smoke[g].minParticle, smoke[g].maxParticle, + video::SColor(0,0,0,0),video::SColor(0,128,128,128), + 250,4000, 60); + + em->setMinStartSize (dimension2d( smoke[g].minparticleSize, smoke[g].minparticleSize)); + em->setMaxStartSize (dimension2d( smoke[g].maxparticleSize, smoke[g].maxparticleSize)); + + pas->setEmitter(em); + em->drop(); + + // particles get invisible + IParticleAffector* paf = pas->createFadeOutParticleAffector( + video::SColor ( 0, 0, 0, 0 ), smoke[g].fadeout); + pas->addAffector(paf); + paf->drop(); + + // particle system life time + ISceneNodeAnimator* anim = sm->createDeleteAnimator( smoke[g].lifetime); + pas->addAnimator(anim); + anim->drop(); + + pas->setMaterialFlag(video::EMF_LIGHTING, false); + pas->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); + pas->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); + pas->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture( smoke[g].texture )); + } + + + // play impact sound + #ifdef USE_IRRKLANG +/* + if (irrKlang) + { + audio::ISound* sound = + irrKlang->play3D(impactSound, Impacts[i].pos, false, false, true); + + if (sound) + { + // adjust max value a bit to make to sound of an impact louder + sound->setMinDistance(400); + sound->drop(); + } + } +*/ + #endif + + + // delete entry + Impacts.erase(i); + i--; + } +} + +/* + render +*/ +void CQuake3EventHandler::Render() +{ + IVideoDriver * driver = Game->Device->getVideoDriver(); + if ( 0 == driver ) + return; + + // TODO: This does not work, yet. + const bool anaglyph=false; + if (anaglyph) + { + scene::ICameraSceneNode* cameraOld = Game->Device->getSceneManager()->getActiveCamera(); + driver->beginScene(true, true, SColor(0,0,0,0)); + driver->getOverrideMaterial().Material.ColorMask = ECP_NONE; + driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK; + driver->getOverrideMaterial().EnablePasses = ESNRP_SKY_BOX + + ESNRP_SOLID + + ESNRP_TRANSPARENT + + ESNRP_TRANSPARENT_EFFECT + + ESNRP_SHADOW; + Game->Device->getSceneManager()->drawAll(); + driver->clearZBuffer(); + + const vector3df oldPosition = cameraOld->getPosition(); + const vector3df oldTarget = cameraOld->getTarget(); + const matrix4 startMatrix = cameraOld->getAbsoluteTransformation(); + const vector3df focusPoint = (oldTarget - + cameraOld->getAbsolutePosition()).setLength(10000) + + cameraOld->getAbsolutePosition() ; + + scene::ICameraSceneNode* camera = cameraOld;//Game->Device->getSceneManager()->addCameraSceneNode(); + + //Left eye... + vector3df pos; + matrix4 move; + + move.setTranslation( vector3df(-1.5f,0.0f,0.0f) ); + pos=(startMatrix*move).getTranslation(); + + driver->getOverrideMaterial().Material.ColorMask = ECP_RED; + driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK; + driver->getOverrideMaterial().EnablePasses = + ESNRP_SKY_BOX|ESNRP_SOLID|ESNRP_TRANSPARENT| + ESNRP_TRANSPARENT_EFFECT|ESNRP_SHADOW; + + camera->setPosition(pos); + camera->setTarget(focusPoint); + + Game->Device->getSceneManager()->drawAll(); + driver->clearZBuffer(); + + //Right eye... + move.setTranslation( vector3df(1.5f,0.0f,0.0f) ); + pos=(startMatrix*move).getTranslation(); + + driver->getOverrideMaterial().Material.ColorMask = ECP_GREEN + ECP_BLUE; + driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK; + driver->getOverrideMaterial().EnablePasses = + ESNRP_SKY_BOX|ESNRP_SOLID|ESNRP_TRANSPARENT| + ESNRP_TRANSPARENT_EFFECT|ESNRP_SHADOW; + + camera->setPosition(pos); + camera->setTarget(focusPoint); + + Game->Device->getSceneManager()->drawAll(); + + driver->getOverrideMaterial().Material.ColorMask=ECP_ALL; + driver->getOverrideMaterial().EnableFlags=0; + driver->getOverrideMaterial().EnablePasses=0; + + if (camera != cameraOld) + { + Game->Device->getSceneManager()->setActiveCamera(cameraOld); + camera->remove(); + } + else + { + camera->setPosition(oldPosition); + camera->setTarget(oldTarget); + } + } + else + { + driver->beginScene(true, true, SColor(0,0,0,0)); + Game->Device->getSceneManager()->drawAll(); + } + Game->Device->getGUIEnvironment()->drawAll(); + driver->endScene(); +} + +/* + update the generic scene node +*/ +void CQuake3EventHandler::Animate() +{ + u32 now = Game->Device->getTimer()->getTime(); + + Q3Player * player = Player + 0; + + checkTimeFire ( player->Anim, 4, now ); + + // Query Scene Manager attributes + if ( player->Anim[0].flags & FIRED ) + { + ISceneManager *smgr = Game->Device->getSceneManager (); + wchar_t msg[128]; + IVideoDriver * driver = Game->Device->getVideoDriver(); + + IAttributes * attr = smgr->getParameters(); +#ifdef _IRR_SCENEMANAGER_DEBUG + swprintf ( msg, 128, + L"Q3 %s [%ls], FPS:%03d Tri:%.03fm Cull %d/%d nodes (%d,%d,%d)", + Game->CurrentMapName.c_str(), + driver->getName(), + driver->getFPS (), + (f32) driver->getPrimitiveCountDrawn( 0 ) * ( 1.f / 1000000.f ), + attr->getAttributeAsInt ( "culled" ), + attr->getAttributeAsInt ( "calls" ), + attr->getAttributeAsInt ( "drawn_solid" ), + attr->getAttributeAsInt ( "drawn_transparent" ), + attr->getAttributeAsInt ( "drawn_transparent_effect" ) + ); +#else +swprintf ( msg, 128, + L"Q3 %s [%ls], FPS:%03d Tri:%.03fm", + Game->CurrentMapName.c_str(), + driver->getName(), + driver->getFPS (), + (f32) driver->getPrimitiveCountDrawn( 0 ) * ( 1.f / 1000000.f ) + ); +#endif + Game->Device->setWindowCaption( msg ); + + swprintf ( msg, 128, + L"%03d fps, F1 GUI on/off, F2 respawn, F3-F6 toggle Nodes, F7 Collision on/off" + L", F8 Gravity on/off, Right Mouse Toggle GUI", + Game->Device->getVideoDriver()->getFPS () + ); + if ( gui.StatusLine ) + gui.StatusLine->setText ( msg ); + player->Anim[0].flags &= ~FIRED; + } + + // idle.. + if ( player->Anim[1].flags & FIRED ) + { + if ( strcmp ( player->animation, "idle" ) ) + player->setAnim ( "idle" ); + + player->Anim[1].flags &= ~FIRED; + } + + createParticleImpacts ( now ); + +} + + +/* The main game states +*/ +void runGame ( GameData *game ) +{ + if ( game->retVal >= 3 ) + return; + + game->Device = (*game->createExDevice) ( game->deviceParam ); + if ( 0 == game->Device) + { + // could not create selected driver. + game->retVal = 0; + return; + } + + // create an event receiver based on current game data + CQuake3EventHandler *eventHandler = new CQuake3EventHandler( game ); + + // load stored config + game->load ( "explorer.cfg" ); + + // add our media directory and archive to the file system + for ( u32 i = 0; i < game->CurrentArchiveList.size(); ++i ) + { + eventHandler->AddArchive ( game->CurrentArchiveList[i] ); + } + + // Load a Map or startup to the GUI + if ( game->CurrentMapName.size () ) + { + eventHandler->LoadMap ( game->CurrentMapName, 1 ); + if ( 0 == game->loadParam.loadSkyShader ) + eventHandler->AddSky ( 1, "skydome2" ); + eventHandler->CreatePlayers (); + eventHandler->CreateGUI (); + eventHandler->SetGUIActive ( 0 ); + + // set player to last position on restart + if ( game->retVal == 2 ) + { + eventHandler->GetPlayer( 0 )->setpos ( game->PlayerPosition, game->PlayerRotation ); + } + } + else + { + // start up empty + eventHandler->AddSky ( 1, "skydome2" ); + eventHandler->CreatePlayers (); + eventHandler->CreateGUI (); + eventHandler->SetGUIActive ( 1 ); + background_music ( "IrrlichtTheme.ogg" ); + } + + + game->retVal = 3; + while( game->Device->run() ) + { + eventHandler->Animate (); + eventHandler->Render (); + //if ( !game->Device->isWindowActive() ) + game->Device->yield(); + } + + game->Device->setGammaRamp ( 1.f, 1.f, 1.f, 0.f, 0.f ); + delete eventHandler; +} + +#if defined (_IRR_WINDOWS_) && 0 + #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") +#endif + + +/* The main routine, doing all setup +*/ +int IRRCALLCONV main(int argc, char* argv[]) +{ + path prgname(argv[0]); + GameData game ( deletePathFromPath ( prgname, 1 ) ); + + // dynamically load irrlicht + const c8 * dllName = argc > 1 ? argv[1] : "irrlicht.dll"; + game.createExDevice = load_createDeviceEx ( dllName ); + if ( 0 == game.createExDevice ) + { + game.retVal = 3; + printf ( "Could not load %s.\n", dllName ); + return game.retVal; // could not load dll + } + + // start without asking for driver + game.retVal = 1; + do + { + // if driver could not created, ask for another driver + if ( game.retVal == 0 ) + { + game.setDefault (); + // ask user for driver + game.deviceParam.DriverType=driverChoiceConsole(); + if (game.deviceParam.DriverType==video::EDT_COUNT) + game.retVal = 3; + } + runGame ( &game ); + } while ( game.retVal < 3 ); + + return game.retVal; +} + +/* +**/ diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp new file mode 100644 index 0000000..d0f09b2 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp @@ -0,0 +1,824 @@ +/*! + Model Factory. + create the additional scenenodes for ( bullets, health... ) + + Defines the Entities for Quake3 +*/ + +#include +#include "q3factory.h" +#include "sound.h" + +using namespace irr; +using namespace scene; +using namespace gui; +using namespace video; +using namespace core; +using namespace quake3; + +//! This list is based on the original quake3. +static const SItemElement Quake3ItemElement [] = { +{ "item_health", + {"models/powerups/health/medium_cross.md3", + "models/powerups/health/medium_sphere.md3"}, + "sound/items/n_health.wav", + "icons/iconh_yellow", + "25 Health", + 25, + HEALTH, + SUB_NONE, + SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 +}, +{ "item_health_large", + "models/powerups/health/large_cross.md3", + "models/powerups/health/large_sphere.md3", + "sound/items/l_health.wav", + "icons/iconh_red", + "50 Health", + 50, + HEALTH, + SUB_NONE, + SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 +}, +{ + "item_health_mega", + "models/powerups/health/mega_cross.md3", + "models/powerups/health/mega_sphere.md3", + "sound/items/m_health.wav", + "icons/iconh_mega", + "Mega Health", + 100, + HEALTH, + SUB_NONE, + SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 +}, +{ + "item_health_small", + "models/powerups/health/small_cross.md3", + "models/powerups/health/small_sphere.md3", + "sound/items/s_health.wav", + "icons/iconh_green", + "5 Health", + 5, + HEALTH, + SUB_NONE, + SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 +}, +{ "ammo_bullets", + "models/powerups/ammo/machinegunam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_machinegun", + "Bullets", + 50, + AMMO, + MACHINEGUN, + SPECIAL_SFX_BOUNCE, +}, +{ + "ammo_cells", + "models/powerups/ammo/plasmaam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_plasma", + "Cells", + 30, + AMMO, + PLASMAGUN, + SPECIAL_SFX_BOUNCE +}, +{ "ammo_rockets", + "models/powerups/ammo/rocketam.md3", + "", + "", + "icons/icona_rocket", + "Rockets", + 5, + AMMO, + ROCKET_LAUNCHER, + SPECIAL_SFX_ROTATE +}, +{ + "ammo_shells", + "models/powerups/ammo/shotgunam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_shotgun", + "Shells", + 10, + AMMO, + SHOTGUN, + SPECIAL_SFX_ROTATE +}, +{ + "ammo_slugs", + "models/powerups/ammo/railgunam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_railgun", + "Slugs", + 10, + AMMO, + RAILGUN, + SPECIAL_SFX_ROTATE +}, +{ + "item_armor_body", + "models/powerups/armor/armor_red.md3", + "", + "sound/misc/ar2_pkup.wav", + "icons/iconr_red", + "Heavy Armor", + 100, + ARMOR, + SUB_NONE, + SPECIAL_SFX_ROTATE +}, +{ + "item_armor_combat", + "models/powerups/armor/armor_yel.md3", + "", + "sound/misc/ar2_pkup.wav", + "icons/iconr_yellow", + "Armor", + 50, + ARMOR, + SUB_NONE, + SPECIAL_SFX_ROTATE +}, +{ + "item_armor_shard", + "models/powerups/armor/shard.md3", + "", + "sound/misc/ar1_pkup.wav", + "icons/iconr_shard", + "Armor Shared", + 5, + ARMOR, + SUB_NONE, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_gauntlet", + "models/weapons2/gauntlet/gauntlet.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_gauntlet", + "Gauntlet", + 0, + WEAPON, + GAUNTLET, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_shotgun", + "models/weapons2/shotgun/shotgun.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_shotgun", + "Shotgun", + 10, + WEAPON, + SHOTGUN, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_machinegun", + "models/weapons2/machinegun/machinegun.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_machinegun", + "Machinegun", + 40, + WEAPON, + MACHINEGUN, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_grenadelauncher", + "models/weapons2/grenadel/grenadel.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_grenade", + "Grenade Launcher", + 10, + WEAPON, + GRENADE_LAUNCHER, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_rocketlauncher", + "models/weapons2/rocketl/rocketl.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_rocket", + "Rocket Launcher", + 10, + WEAPON, + ROCKET_LAUNCHER, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_lightning", + "models/weapons2/lightning/lightning.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_lightning", + "Lightning Gun", + 100, + WEAPON, + LIGHTNING, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_railgun", + "models/weapons2/railgun/railgun.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_railgun", + "Railgun", + 10, + WEAPON, + RAILGUN, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_plasmagun", + "models/weapons2/plasma/plasma.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_plasma", + "Plasma Gun", + 50, + WEAPON, + PLASMAGUN, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_bfg", + "models/weapons2/bfg/bfg.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_bfg", + "BFG10K", + 20, + WEAPON, + BFG, + SPECIAL_SFX_ROTATE +}, +{ + "weapon_grapplinghook", + "models/weapons2/grapple/grapple.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_grapple", + "Grappling Hook", + 0, + WEAPON, + GRAPPLING_HOOK, + SPECIAL_SFX_ROTATE +}, +{ + 0 +} + +}; + + +/*! +*/ +const SItemElement * getItemElement ( const stringc& key ) +{ + const SItemElement *item = Quake3ItemElement; + + while ( item->key ) + { + if ( 0 == strcmp ( key.c_str(), item->key ) ) + return item; + item += 1; + } + return 0; +} + +/*! + Quake3 Model Factory. + Takes the mesh buffers and creates scenenodes for their associated shaders +*/ +void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* mesh, + eQ3MeshIndex meshIndex, + ISceneNode *parent, + IMetaTriangleSelector *meta, + bool showShaderName ) +{ + if ( 0 == mesh || 0 == device ) + return; + + IMeshSceneNode* node = 0; + ISceneManager* smgr = device->getSceneManager(); + ITriangleSelector * selector = 0; + + // the additional mesh can be quite huge and is unoptimized + // Save to cast to SMesh + SMesh * additional_mesh = (SMesh*) mesh->getMesh ( meshIndex ); + if ( 0 == additional_mesh || additional_mesh->getMeshBufferCount() == 0) + return; + + char buf[128]; + if ( loadParam.verbose > 0 ) + { + loadParam.startTime = device->getTimer()->getRealTime(); + if ( loadParam.verbose > 1 ) + { + snprintf(buf, 128, "q3shaderfactory start" ); + device->getLogger()->log( buf, ELL_INFORMATION); + } + } + + IGUIFont *font = 0; + if ( showShaderName ) + font = device->getGUIEnvironment()->getFont("fontlucida.png"); + + IVideoDriver *driver = device->getVideoDriver(); + + // create helper textures + if ( 1 ) + { + tTexArray tex; + u32 pos = 0; + getTextures ( tex, "$redimage $blueimage $whiteimage $checkerimage", pos, + device->getFileSystem(), driver ); + } + + s32 sceneNodeID = 0; + for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount (); ++i ) + { + IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i ); + const SMaterial &material = meshBuffer->getMaterial(); + + //! The ShaderIndex is stored in the second material parameter + s32 shaderIndex = (s32) material.MaterialTypeParam2; + + // the meshbuffer can be rendered without additional support, or it has no shader + IShader *shader = (IShader *) mesh->getShader ( shaderIndex ); + + // no shader, or mapped to existing material + if ( 0 == shader ) + { + +#if 1 + // clone mesh + SMesh * m = new SMesh (); + m->addMeshBuffer ( meshBuffer ); + SMaterial &mat = m->getMeshBuffer( 0 )->getMaterial(); + if ( mat.getTexture( 0 ) == 0 ) + mat.setTexture ( 0, driver->getTexture ( "$blueimage" ) ); + if ( mat.getTexture( 1 ) == 0 ) + mat.setTexture ( 1, driver->getTexture ( "$redimage" ) ); + + IMesh * store = smgr->getMeshManipulator ()->createMeshWith2TCoords ( m ); + m->drop(); + + node = smgr->addMeshSceneNode ( store, parent, sceneNodeID ); + node->setAutomaticCulling ( scene::EAC_OFF ); + store->drop (); + sceneNodeID += 1; +#endif + } + else if ( 1 ) + { +/* + stringc s; + dumpShader ( s, shader ); + printf ( s.c_str () ); +*/ + // create sceneNode + node = smgr->addQuake3SceneNode ( meshBuffer, shader, parent, sceneNodeID ); + node->setAutomaticCulling ( scene::EAC_FRUSTUM_BOX ); + sceneNodeID += 1; + } + + // show Debug Shader Name + if ( showShaderName && node ) + { + swprintf ( (wchar_t*) buf, 64, L"%hs:%d", node->getName(),node->getID() ); + smgr->addBillboardTextSceneNode( + font, + (wchar_t*) buf, + node, + dimension2d(80.0f, 8.0f), + vector3df(0, 10, 0), + sceneNodeID); + sceneNodeID += 1; + } + + // create Portal Rendertargets + if ( shader ) + { + const SVarGroup *group = shader->getGroup(1); + if ( group->isDefined( "surfaceparm", "portal" ) ) + { + } + + } + + + // add collision + // find out if shader is marked as nonsolid + u8 doCreate = meta !=0 ; + + if ( shader ) + { + const SVarGroup *group = shader->getGroup(1); + if ( group->isDefined( "surfaceparm", "trans" ) + // || group->isDefined( "surfaceparm", "sky" ) + // || group->isDefined( "surfaceparm", "nonsolid" ) + ) + { + if ( !group->isDefined( "surfaceparm", "metalsteps" ) ) + { + doCreate = 0; + } + } + } + + if ( doCreate ) + { + IMesh *m = 0; + + //! controls if triangles are modified by the scenenode during runtime + bool takeOriginal = true; + + if ( takeOriginal ) + { + m = new SMesh (); + ((SMesh*) m )->addMeshBuffer (meshBuffer); + } + else + { + m = node->getMesh(); + } + + //selector = smgr->createOctreeTriangleSelector ( m, 0, 128 ); + selector = smgr->createTriangleSelector ( m, 0 ); + meta->addTriangleSelector ( selector ); + selector->drop (); + + if ( takeOriginal ) + { + delete m; + } + } + + } + +#if 0 + if ( meta ) + { + selector = smgr->createOctreeTriangleSelector ( additional_mesh, 0 ); + meta->addTriangleSelector ( selector ); + selector->drop (); + } +#endif + + if ( loadParam.verbose > 0 ) + { + loadParam.endTime = device->getTimer()->getRealTime (); + snprintf(buf, 128, "q3shaderfactory needed %04d ms to create %d shader nodes", + loadParam.endTime - loadParam.startTime, + sceneNodeID + ); + device->getLogger()->log(buf, ELL_INFORMATION); + } + +} + + +/*! + create Items from Entity +*/ +void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* masterMesh, + ISceneNode *parent, + bool showShaderName + ) +{ + if ( 0 == masterMesh ) + return; + + tQ3EntityList &entity = masterMesh->getEntityList (); + ISceneManager* smgr = device->getSceneManager(); + + + char buf[128]; + const SVarGroup *group; + IEntity search; + s32 index; + s32 lastIndex; + +/* + stringc s; + FILE *f = 0; + f = fopen ( "entity.txt", "wb" ); + for ( index = 0; (u32) index < entityList.size (); ++index ) + { + const IEntity *entity = &entityList[ index ]; + s = entity->name; + dumpShader ( s, entity ); + fwrite ( s.c_str(), 1, s.size(), f ); + } + fclose ( f ); +*/ + IAnimatedMeshMD3* model; + SMD3Mesh * mesh; + const SMD3MeshBuffer *meshBuffer; + IMeshSceneNode* node; + ISceneNodeAnimator* anim; + const IShader *shader; + u32 pos; + vector3df p; + u32 nodeCount = 0; + tTexArray textureArray; + + IGUIFont *font = 0; + if ( showShaderName ) + font = device->getGUIEnvironment()->getFont("fontlucida.png"); + + const SItemElement *itemElement; + + // walk list + for ( index = 0; (u32) index < entity.size(); ++index ) + { + itemElement = getItemElement ( entity[index].name ); + if ( 0 == itemElement ) + continue; + + pos = 0; + p = getAsVector3df ( entity[index].getGroup(1)->get ( "origin" ), pos ); + + nodeCount += 1; + for ( u32 g = 0; g < 2; ++g ) + { + if ( 0 == itemElement->model[g] || itemElement->model[g][0] == 0 ) + continue; + model = (IAnimatedMeshMD3*) smgr->getMesh( itemElement->model[g] ); + if ( 0 == model ) + continue; + + mesh = model->getOriginalMesh(); + for ( u32 j = 0; j != mesh->Buffer.size (); ++j ) + { + meshBuffer = mesh->Buffer[j]; + if ( 0 == meshBuffer ) + continue; + + shader = masterMesh->getShader ( meshBuffer->Shader.c_str(), false ); + IMeshBuffer *final = model->getMesh(0)->getMeshBuffer(j); + if ( shader ) + { + //!TODO: Hack don't modify the vertexbuffer. make it better;-) + final->getMaterial().ColorMask = 0; + node = smgr->addQuake3SceneNode ( final, shader, parent ); + final->getMaterial().ColorMask = 15; + } + else + { + // clone mesh + SMesh * m = new SMesh (); + m->addMeshBuffer ( final ); + node = smgr->addMeshSceneNode ( m, parent ); + m->drop(); + } + + if ( 0 == node ) + { + snprintf ( buf, 128, "q3ModelFactory shader %s failed", meshBuffer->Shader.c_str() ); + device->getLogger()->log ( buf ); + continue; + } + + // node was maybe centered by shaderscenenode + node->setPosition ( p ); + node->setName ( meshBuffer->Shader ); + node->setAutomaticCulling ( scene::EAC_BOX ); + + // add special effects to node + if ( itemElement->special & SPECIAL_SFX_ROTATE || + (g == 0 && itemElement->special & SPECIAL_SFX_ROTATE_1) + ) + { + anim = smgr->createRotationAnimator ( vector3df ( 0.f, + 2.f, 0.f ) ); + node->addAnimator ( anim ); + anim->drop (); + } + + if ( itemElement->special & SPECIAL_SFX_BOUNCE ) + { + //anim = smgr->createFlyStraightAnimator ( + // p, p + vector3df ( 0.f, 60.f, 0.f ), 1000, true, true ); + anim = smgr->createFlyCircleAnimator ( + p + vector3df( 0.f, 20.f, 0.f ), + 20.f, + 0.005f, + vector3df ( 1.f, 0.f, 0.f ), + core::fract ( nodeCount * 0.05f ), + 1.f + ); + node->addAnimator ( anim ); + anim->drop (); + } + } + } + // show name + if ( showShaderName ) + { + swprintf ( (wchar_t*) buf, sizeof(buf) / 2, L"%hs", itemElement->key ); + smgr->addBillboardTextSceneNode( + font, + (wchar_t*) buf, + parent, + dimension2d(80.0f, 8.0f), + p + vector3df(0, 30, 0), + 0); + } + } + + // music + search.name = "worldspawn"; + index = entity.binary_search_multi ( search, lastIndex ); + + if ( index >= 0 ) + { + group = entity[ index ].getGroup(1); + background_music ( group->get ( "music" ).c_str () ); + } + + // music + search.name = "worldspawn"; + index = entity.binary_search_multi ( search, lastIndex ); + + if ( index >= 0 ) + { + group = entity[ index ].getGroup(1); + background_music ( group->get ( "music" ).c_str () ); + } + + //IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); + //IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); + +} + +/*! + so we need a good starting Position in the level. + we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" +*/ +s32 Q3StartPosition ( IQ3LevelMesh* mesh, + ICameraSceneNode* camera, + s32 startposIndex, + const vector3df &translation + ) +{ + if ( 0 == mesh ) + return 0; + + tQ3EntityList &entityList = mesh->getEntityList (); + + IEntity search; + search.name = "info_player_start"; // "info_player_deathmatch"; + + // find all entities in the multi-list + s32 lastIndex; + s32 index = entityList.binary_search_multi ( search, lastIndex ); + + if ( index < 0 ) + { + search.name = "info_player_deathmatch"; + index = entityList.binary_search_multi ( search, lastIndex ); + } + + if ( index < 0 ) + return 0; + + index += core::clamp ( startposIndex, 0, lastIndex - index ); + + u32 parsepos; + + const SVarGroup *group; + group = entityList[ index ].getGroup(1); + + parsepos = 0; + vector3df pos = getAsVector3df ( group->get ( "origin" ), parsepos ); + pos += translation; + + parsepos = 0; + f32 angle = getAsFloat ( group->get ( "angle"), parsepos ); + + vector3df target ( 0.f, 0.f, 1.f ); + target.rotateXZBy ( angle - 90.f, vector3df () ); + + if ( camera ) + { + camera->setPosition ( pos ); + camera->setTarget ( pos + target ); + //! New. FPSCamera and animators catches reset on animate 0 + camera->OnAnimate ( 0 ); + } + return lastIndex - index + 1; +} + + +/*! + gets a accumulated force on a given surface +*/ +vector3df getGravity ( const c8 * surface ) +{ + if ( 0 == strcmp ( surface, "earth" ) ) return vector3df ( 0.f, -90.f, 0.f ); + if ( 0 == strcmp ( surface, "moon" ) ) return vector3df ( 0.f, -6.f / 100.f, 0.f ); + if ( 0 == strcmp ( surface, "water" ) ) return vector3df ( 0.1f / 100.f, -2.f / 100.f, 0.f ); + if ( 0 == strcmp ( surface, "ice" ) ) return vector3df ( 0.2f / 100.f, -9.f / 100.f, 0.3f / 100.f ); + + return vector3df ( 0.f, 0.f, 0.f ); +} + + + +/* + Dynamically load the Irrlicht Library +*/ + +#if defined(_IRR_WINDOWS_API_) +#ifdef _MSC_VER +#pragma comment(lib, "Irrlicht.lib") +#endif + +#include + +funcptr_createDevice load_createDevice ( const c8 * filename) +{ + return (funcptr_createDevice) GetProcAddress ( LoadLibrary ( filename ), "createDevice" ); +} + +funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) +{ + return (funcptr_createDeviceEx) GetProcAddress ( LoadLibrary ( filename ), "createDeviceEx" ); +} + +#else + +// TODO: Dynamic Loading for other os +funcptr_createDevice load_createDevice ( const c8 * filename) +{ + return createDevice; +} + +funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) +{ + return createDeviceEx; +} + +#endif + +/* + get the current collision response camera animator +*/ +ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ) +{ + ICameraSceneNode *camera = device->getSceneManager()->getActiveCamera(); + ISceneNodeAnimatorCollisionResponse *a = 0; + + list::ConstIterator it = camera->getAnimators().begin(); + for (; it != camera->getAnimators().end(); ++it) + { + a = (ISceneNodeAnimatorCollisionResponse*) (*it); + if ( a->getType() == ESNAT_COLLISION_RESPONSE ) + return a; + } + + return 0; +} + + +//! internal Animation +void setTimeFire ( TimeFire *t, u32 delta, u32 flags ) +{ + t->flags = flags; + t->next = 0; + t->delta = delta; +} + + +void checkTimeFire ( TimeFire *t, u32 listSize, u32 now ) +{ + u32 i; + for ( i = 0; i < listSize; ++i ) + { + if ( now < t[i].next ) + continue; + + t[i].next = core::max_ ( now + t[i].delta, t[i].next + t[i].delta ); + t[i].flags |= FIRED; + } +} diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.h b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.h new file mode 100644 index 0000000..d9606ed --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.h @@ -0,0 +1,149 @@ +/*! + Model Factory. + create the additional scenenodes for ( bullets, health... ) + + Defines the Entities for Quake3 +*/ +#ifndef __QUAKE3_FACTORY__H_INCLUDED__ +#define __QUAKE3_FACTORY__H_INCLUDED__ + +using namespace irr; +using namespace scene; +using namespace gui; +using namespace video; +using namespace core; +using namespace quake3; +using namespace io; + + + +//! Defines to which group the entities belong +enum eItemGroup +{ + WEAPON, + AMMO, + ARMOR, + HEALTH, + POWERUP +}; + +//! define a supgroup for the item. for e.q the Weapons +enum eItemSubGroup +{ + SUB_NONE = 0, + GAUNTLET, + MACHINEGUN, + SHOTGUN, + GRENADE_LAUNCHER, + ROCKET_LAUNCHER, + LIGHTNING, + RAILGUN, + PLASMAGUN, + BFG, + GRAPPLING_HOOK, + NAILGUN, + PROX_LAUNCHER, + CHAINGUN, +}; + +//! aplly a special effect to the shader +enum eItemSpecialEffect +{ + SPECIAL_SFX_NONE = 0, + SPECIAL_SFX_ROTATE = 1, + SPECIAL_SFX_BOUNCE = 2, + SPECIAL_SFX_ROTATE_1 = 4, +}; + +// a List for defining a model +struct SItemElement +{ + const c8 *key; + const c8 *model[2]; + const c8 *sound; + const c8 *icon; + const c8 *pickup; + s32 value; + eItemGroup group; + eItemSubGroup sub; + u32 special; +}; + + +//! Get's an entity based on it's key +const SItemElement * getItemElement ( const stringc& key ); + +/*! + Quake3 Model Factory. + Takes the mesh buffers and creates scenenodes for their associated shaders +*/ +void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* mesh, + eQ3MeshIndex meshIndex, + ISceneNode *parent, + IMetaTriangleSelector *meta, + bool showShaderName + ); + + +/*! + Creates Model based on the entity list +*/ +void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* masterMesh, + ISceneNode *parent, + bool showShaderName + ); + +/*! + so we need a good starting Position in the level. + we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" +*/ +s32 Q3StartPosition ( IQ3LevelMesh* mesh, + ICameraSceneNode* camera, + s32 startposIndex, + const vector3df &translation + ); +/*! + gets a accumulated force on a given surface +*/ +vector3df getGravity ( const c8 * surface ); + + +/* + Dynamically load the Irrlicht Library +*/ +funcptr_createDevice load_createDevice ( const c8 * filename); +funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename); + + +//! Macro for save Dropping an Element +#define dropElement(x) if (x) { x->remove(); x = 0; } + + +/* + get the current collision respone camera animator +*/ +ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ); + +//! internal Animation +enum eTimeFireFlag +{ + FIRED = 1, +}; + +struct TimeFire +{ + u32 flags; + u32 next; + u32 delta; +}; + +void setTimeFire ( TimeFire *t, u32 delta, u32 flags = 0 ); +void checkTimeFire ( TimeFire *t, u32 listSize, u32 now ); + +#endif // __QUAKE3_FACTORY__H_INCLUDED__ + + diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.cpp b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.cpp new file mode 100644 index 0000000..75615c1 --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.cpp @@ -0,0 +1,98 @@ +/*! + Sound Factory. + provides a sound interface + +*/ + +#include "sound.h" + + +//#define USE_IRRKLANG + +#ifdef USE_IRRKLANG + +#include +#ifdef _IRR_WINDOWS_ + #pragma comment (lib, "irrKlang.lib") +#endif + +using namespace irrklang; + +struct soundfile: public IFileReader +{ + soundfile ( io::IReadFile* f ): file (f ) {} + virtual ~soundfile () { file->drop (); } + + virtual ik_s32 read(void* buffer, ik_u32 sizeToRead) { return file->read ( buffer, sizeToRead ); } + virtual bool seek(ik_s32 finalPos, bool relativeMovement = false) { return file->seek ( finalPos, relativeMovement ); } + virtual ik_s32 getSize(){ return file->getSize (); } + virtual ik_s32 getPos() {return file->getPos (); } + virtual const ik_c8* getFileName() { return file->getFileName (); } + io::IReadFile* file; +}; + +struct klangFactory : public irrklang::IFileFactory +{ + klangFactory ( IrrlichtDevice *device ) { Device = device; } + + virtual irrklang::IFileReader* createFileReader(const ik_c8* filename) + { + io::IReadFile* file = Device->getFileSystem()->createAndOpenFile(filename); + if ( 0 == file ) + return 0; + + return new soundfile ( file ); + } + + IrrlichtDevice *Device; +}; + +ISoundEngine *engine = 0; +ISound *backMusic = 0; + +void sound_init ( IrrlichtDevice *device ) +{ + engine = createIrrKlangDevice (); + if ( 0 == engine ) + return; + + klangFactory *f = new klangFactory ( device ); + engine->addFileFactory ( f ); +} + +void sound_shutdown () +{ + if ( backMusic ) + backMusic->drop (); + + if ( engine ) + engine->drop (); +} + +void background_music ( const c8 * file ) +{ + if ( 0 == engine ) + return; + + if ( backMusic ) + { + backMusic->stop (); + backMusic->drop (); + } + + backMusic = engine->play2D ( file, true, false, true ); + + if ( backMusic ) + { + backMusic->setVolume ( 0.5f ); + } +} + +#else + +void sound_init ( IrrlichtDevice *device ) {} +void sound_shutdown () {} +void background_music ( const c8 * file ) {} + +#endif + diff --git a/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.h b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.h new file mode 100644 index 0000000..033e9bb --- /dev/null +++ b/src/others/irrlicht-1.8.1/examples/21.Quake3Explorer/sound.h @@ -0,0 +1,18 @@ +/*! + Sound Factory. + provides a sound interface + +*/ +#ifndef __QUAKE3_SOUND__H_INCLUDED__ +#define __QUAKE3_SOUND__H_INCLUDED__ + +#include + +using namespace irr; + +void sound_init ( IrrlichtDevice *device ); +void sound_shutdown (); +void background_music ( const c8 * file ); + + +#endif // __QUAKE3_SOUND__H_INCLUDED__ -- cgit v1.1