From d47de55ce9d017485934b08d354306a8041f1b19 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 15:19:39 +0200 Subject: [PATCH 01/22] read info records --- components/esm/records.hpp | 2 +- components/esm_store/store.cpp | 72 +++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/components/esm/records.hpp b/components/esm/records.hpp index 4ef8ce5642..fb5733c632 100644 --- a/components/esm/records.hpp +++ b/components/esm/records.hpp @@ -14,13 +14,13 @@ #include "loadcont.hpp" #include "loadcrea.hpp" #include "loadcrec.hpp" +#include "loadinfo.hpp" #include "loaddial.hpp" #include "loaddoor.hpp" #include "loadench.hpp" #include "loadfact.hpp" #include "loadglob.hpp" #include "loadgmst.hpp" -#include "loadinfo.hpp" #include "loadingr.hpp" #include "loadland.hpp" #include "loadlevlist.hpp" diff --git a/components/esm_store/store.cpp b/components/esm_store/store.cpp index 2016272e0e..6226766895 100644 --- a/components/esm_store/store.cpp +++ b/components/esm_store/store.cpp @@ -18,32 +18,68 @@ static string toStr(int i) void ESMStore::load(ESMReader &esm) { - set missing; + set missing; - // Loop through all records - while(esm.hasMoreRecs()) + ESM::Dialogue *dialogue = 0; + + // Loop through all records + while(esm.hasMoreRecs()) { - NAME n = esm.getRecName(); - esm.getRecHeader(); + NAME n = esm.getRecName(); + esm.getRecHeader(); - // Look up the record type. - RecListList::iterator it = recLists.find(n.val); + // Look up the record type. + RecListList::iterator it = recLists.find(n.val); - if(it == recLists.end()) + if(it == recLists.end()) { - // Not found (this would be an error later) - esm.skipRecord(); - missing.insert(n.toString()); - continue; + if (n.val==ESM::REC_INFO) + { + if (dialogue) + { + ESM::DialInfo info; + info.load (esm); + } + else + { + std::cerr << "error: info record without dialog" << std::endl; + esm.skipRecord(); + continue; + } + } + else + { + // Not found (this would be an error later) + esm.skipRecord(); + missing.insert(n.toString()); + continue; + } } + else + { + // Load it + std::string id = esm.getHNOString("NAME"); + it->second->load(esm, id); - // Load it - std::string id = esm.getHNOString("NAME"); - it->second->load(esm, id); + if (n.val==ESM::REC_DIAL) + { + RecListT& recList = static_cast& > (*it->second); - // Insert the reference into the global lookup - if(!id.empty()) - all[id] = n.val; + id = recList.toLower (id); + + RecListT::MapType::iterator iter = recList.list.find (id); + + assert (iter!=recList.list.end()); + + dialogue = &iter->second; + } + else + dialogue = 0; + + // Insert the reference into the global lookup + if(!id.empty()) + all[id] = n.val; + } } /* This information isn't needed on screen. But keep the code around From 6b1b3b20fda3b2286a2a0840347c0b1a907f5d88 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 15:23:13 +0200 Subject: [PATCH 02/22] store info records in dialogue records --- components/esm/loaddial.hpp | 4 ++++ components/esm_store/store.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index 4c80fc7833..c435eb2765 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -1,7 +1,10 @@ #ifndef _ESM_DIAL_H #define _ESM_DIAL_H +#include + #include "esm_reader.hpp" +#include "loadinfo.hpp" namespace ESM { @@ -23,6 +26,7 @@ struct Dialogue }; char type; + std::vector mInfo; void load(ESMReader &esm) { diff --git a/components/esm_store/store.cpp b/components/esm_store/store.cpp index 6226766895..c43855873a 100644 --- a/components/esm_store/store.cpp +++ b/components/esm_store/store.cpp @@ -39,6 +39,8 @@ void ESMStore::load(ESMReader &esm) { ESM::DialInfo info; info.load (esm); + + dialogue->mInfo.push_back (info); } else { From 761157206548a33a3aa84c2177e75b195138ca5e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 15:25:54 +0200 Subject: [PATCH 03/22] cleanup --- components/esm_store/store.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/esm_store/store.hpp b/components/esm_store/store.hpp index fd4a47d4b8..02b5264922 100644 --- a/components/esm_store/store.hpp +++ b/components/esm_store/store.hpp @@ -69,7 +69,6 @@ namespace ESMS // Lists that need special rules CellList cells; RecIDListT gameSettings; - //RecListT dialInfos; //RecListT lands; //RecListT landTexts; //RecListT magicEffects; @@ -92,7 +91,6 @@ namespace ESMS ESMStore() { - recLists[REC_ACTI] = &activators; recLists[REC_ACTI] = &activators; recLists[REC_ALCH] = &potions; recLists[REC_APPA] = &appas; @@ -113,7 +111,6 @@ namespace ESMS recLists[REC_FACT] = &factions; recLists[REC_GLOB] = &globals; recLists[REC_GMST] = &gameSettings; - //recLists[REC_INFO] = &dialInfos; recLists[REC_INGR] = &ingreds; //recLists[REC_LAND] = &lands; recLists[REC_LEVC] = &creatureLists; From 8045320ac94c507c805f511d599d2846b5afd1c9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 18:01:34 +0200 Subject: [PATCH 04/22] added dialog manager --- apps/openmw/CMakeLists.txt | 12 ++++++++++-- apps/openmw/engine.cpp | 6 ++++++ apps/openmw/mwdialog/dialogmanager.cpp | 17 +++++++++++++++++ apps/openmw/mwdialog/dialogmanager.hpp | 26 ++++++++++++++++++++++++++ apps/openmw/mwworld/environment.hpp | 11 ++++++++--- 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 apps/openmw/mwdialog/dialogmanager.cpp create mode 100644 apps/openmw/mwdialog/dialogmanager.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c9112b0ee8..f07143be5d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -41,6 +41,14 @@ set(GAMEGUI ) source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI}) +set(GAMEDIALOG_HEADER + mwdialog/dialogmanager.hpp +) +set(GAMEDIALOG + mwdialog/dialogmanager.cpp +) +source_group(apps\\openmw\\mwdialog FILES ${GAMEDIALOG_HEADER} ${GAMEDIALOG}) + set(GAMESCRIPT mwscript/scriptmanager.cpp mwscript/compilercontext.cpp @@ -154,11 +162,11 @@ set(GAMEMECHANICS_HEADER source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER}) set(OPENMW_CPP ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT} ${GAMESOUND} ${GAMEGUI} ${GAMEWORLD} - ${GAMECLASS} ${GAMEMECHANICS} + ${GAMECLASS} ${GAMEMECHANICS} ${GAMEDIALOG} ) set(OPENMW_HEADER ${GAME_HEADER} ${GAMEREND_HEADER} ${GAMEINPUT_HEADER} ${GAMESCRIPT_HEADER} ${GAMESOUND_HEADER} ${GAMEGUI_HEADER} ${GAMEWORLD_HEADER} ${GAMECLASS_HEADER} - ${GAMEMECHANICS_HEADER} + ${GAMEMECHANICS_HEADER} ${GAMEDIALOG_HEADER} ) # Main executable diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b67bcd0ac7..2cd7386230 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -28,6 +28,8 @@ #include "mwclass/classes.hpp" +#include "mwdialog/dialogmanager.hpp" + #include "mwmechanics/mechanicsmanager.hpp" #include @@ -117,6 +119,7 @@ OMW::Engine::~Engine() delete mEnvironment.mSoundManager; delete mEnvironment.mGlobalScripts; delete mEnvironment.mMechanicsManager; + delete mEnvironment.mDialogManager; delete mScriptManager; delete mScriptContext; } @@ -250,6 +253,9 @@ void OMW::Engine::go() mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager ( mEnvironment.mWorld->getStore(), *mEnvironment.mWindowManager); + // Create dialog system + mEnvironment.mDialogManager = new MWDialog::DialogManager (mEnvironment); + // load cell ESM::Position pos; pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; diff --git a/apps/openmw/mwdialog/dialogmanager.cpp b/apps/openmw/mwdialog/dialogmanager.cpp new file mode 100644 index 0000000000..2dfaebb768 --- /dev/null +++ b/apps/openmw/mwdialog/dialogmanager.cpp @@ -0,0 +1,17 @@ + +#include "dialogmanager.hpp" + +#include "../mwworld/class.hpp" + +#include + +namespace MWDialog +{ + DialogManager::DialogManager (MWWorld::Environment& environment) : mEnvironment (environment) {} + + void DialogManager::startDialog (const MWWorld::Ptr& actor) + { + std::cout << "talking with " << MWWorld::Class::get (actor).getName (actor) << std::endl; + } + +} diff --git a/apps/openmw/mwdialog/dialogmanager.hpp b/apps/openmw/mwdialog/dialogmanager.hpp new file mode 100644 index 0000000000..8f4067c9ab --- /dev/null +++ b/apps/openmw/mwdialog/dialogmanager.hpp @@ -0,0 +1,26 @@ +#ifndef GAME_MMDIALOG_DIALOGMANAGER_H +#define GAME_MWDIALOG_DIALOGMANAGER_H + +#include "../mwworld/ptr.hpp" + +namespace MWWorld +{ + class Environment; +} + +namespace MWDialog +{ + class DialogManager + { + MWWorld::Environment& mEnvironment; + + public: + + DialogManager (MWWorld::Environment& environment); + + void startDialog (const MWWorld::Ptr& actor); + + }; +} + +#endif diff --git a/apps/openmw/mwworld/environment.hpp b/apps/openmw/mwworld/environment.hpp index 0c6476d525..1887e619f3 100644 --- a/apps/openmw/mwworld/environment.hpp +++ b/apps/openmw/mwworld/environment.hpp @@ -21,17 +21,22 @@ namespace MWMechanics class MechanicsManager; } +namespace MWDialog +{ + class DialogManager; +} + namespace MWWorld { class World; ///< Collection of script-accessable sub-systems class Environment - { + { public: Environment() : mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0), - mMechanicsManager (0), mFrameDuration (0) + mMechanicsManager (0), mDialogManager (0), mFrameDuration (0) {} World *mWorld; @@ -39,9 +44,9 @@ namespace MWWorld MWScript::GlobalScripts *mGlobalScripts; MWGui::WindowManager *mWindowManager; MWMechanics::MechanicsManager *mMechanicsManager; + MWDialog::DialogManager *mDialogManager; float mFrameDuration; }; } #endif - From d6541d4f3cdc4b2003c7ee9d8e2e504999d85d9b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 19:10:56 +0200 Subject: [PATCH 05/22] changed file names to ensure consistent spelling --- apps/openmw/CMakeLists.txt | 14 +++++++------- apps/openmw/engine.cpp | 2 +- .../dialoguemanager.cpp} | 2 +- .../dialoguemanager.hpp} | 0 4 files changed, 9 insertions(+), 9 deletions(-) rename apps/openmw/{mwdialog/dialogmanager.cpp => mwdialogue/dialoguemanager.cpp} (91%) rename apps/openmw/{mwdialog/dialogmanager.hpp => mwdialogue/dialoguemanager.hpp} (100%) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index f07143be5d..d27ddae2d2 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -41,13 +41,13 @@ set(GAMEGUI ) source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI}) -set(GAMEDIALOG_HEADER - mwdialog/dialogmanager.hpp +set(GAMEDIALOGUE_HEADER + mwdialogue/dialoguemanager.hpp ) -set(GAMEDIALOG - mwdialog/dialogmanager.cpp +set(GAMEDIALOGUE + mwdialogue/dialoguemanager.cpp ) -source_group(apps\\openmw\\mwdialog FILES ${GAMEDIALOG_HEADER} ${GAMEDIALOG}) +source_group(apps\\openmw\\mwdialogue FILES ${GAMEDIALOGUE_HEADER} ${GAMEDIALOGUE}) set(GAMESCRIPT mwscript/scriptmanager.cpp @@ -162,11 +162,11 @@ set(GAMEMECHANICS_HEADER source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER}) set(OPENMW_CPP ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT} ${GAMESOUND} ${GAMEGUI} ${GAMEWORLD} - ${GAMECLASS} ${GAMEMECHANICS} ${GAMEDIALOG} + ${GAMECLASS} ${GAMEMECHANICS} ${GAMEDIALOGUE} ) set(OPENMW_HEADER ${GAME_HEADER} ${GAMEREND_HEADER} ${GAMEINPUT_HEADER} ${GAMESCRIPT_HEADER} ${GAMESOUND_HEADER} ${GAMEGUI_HEADER} ${GAMEWORLD_HEADER} ${GAMECLASS_HEADER} - ${GAMEMECHANICS_HEADER} ${GAMEDIALOG_HEADER} + ${GAMEMECHANICS_HEADER} ${GAMEDIALOG_HEADERUE} ) # Main executable diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 2cd7386230..35200b2d1e 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -28,7 +28,7 @@ #include "mwclass/classes.hpp" -#include "mwdialog/dialogmanager.hpp" +#include "mwdialogue/dialoguemanager.hpp" #include "mwmechanics/mechanicsmanager.hpp" diff --git a/apps/openmw/mwdialog/dialogmanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp similarity index 91% rename from apps/openmw/mwdialog/dialogmanager.cpp rename to apps/openmw/mwdialogue/dialoguemanager.cpp index 2dfaebb768..d00c0aa83d 100644 --- a/apps/openmw/mwdialog/dialogmanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -1,5 +1,5 @@ -#include "dialogmanager.hpp" +#include "dialoguemanager.hpp" #include "../mwworld/class.hpp" diff --git a/apps/openmw/mwdialog/dialogmanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp similarity index 100% rename from apps/openmw/mwdialog/dialogmanager.hpp rename to apps/openmw/mwdialogue/dialoguemanager.hpp From c806415f08389034a12036c12740a6f115a6e3f3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 19:16:44 +0200 Subject: [PATCH 06/22] changed namespace, class and function names to ensure consistent spelling --- apps/openmw/engine.cpp | 4 ++-- apps/openmw/mwdialogue/dialoguemanager.cpp | 6 +++--- apps/openmw/mwdialogue/dialoguemanager.hpp | 12 ++++++------ apps/openmw/mwworld/environment.hpp | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 35200b2d1e..396e4bad13 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -119,7 +119,7 @@ OMW::Engine::~Engine() delete mEnvironment.mSoundManager; delete mEnvironment.mGlobalScripts; delete mEnvironment.mMechanicsManager; - delete mEnvironment.mDialogManager; + delete mEnvironment.mDialogueManager; delete mScriptManager; delete mScriptContext; } @@ -254,7 +254,7 @@ void OMW::Engine::go() mEnvironment.mWorld->getStore(), *mEnvironment.mWindowManager); // Create dialog system - mEnvironment.mDialogManager = new MWDialog::DialogManager (mEnvironment); + mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment); // load cell ESM::Position pos; diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index d00c0aa83d..22602a3f77 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -5,11 +5,11 @@ #include -namespace MWDialog +namespace MWDialogue { - DialogManager::DialogManager (MWWorld::Environment& environment) : mEnvironment (environment) {} + DialogueManager::DialogueManager (MWWorld::Environment& environment) : mEnvironment (environment) {} - void DialogManager::startDialog (const MWWorld::Ptr& actor) + void DialogueManager::startDialogue (const MWWorld::Ptr& actor) { std::cout << "talking with " << MWWorld::Class::get (actor).getName (actor) << std::endl; } diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp index 8f4067c9ab..b31a3d0632 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.hpp +++ b/apps/openmw/mwdialogue/dialoguemanager.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MMDIALOG_DIALOGMANAGER_H -#define GAME_MWDIALOG_DIALOGMANAGER_H +#ifndef GAME_MMDIALOG_DIALOGUEMANAGER_H +#define GAME_MWDIALOG_DIALOGUEMANAGER_H #include "../mwworld/ptr.hpp" @@ -8,17 +8,17 @@ namespace MWWorld class Environment; } -namespace MWDialog +namespace MWDialogue { - class DialogManager + class DialogueManager { MWWorld::Environment& mEnvironment; public: - DialogManager (MWWorld::Environment& environment); + DialogueManager (MWWorld::Environment& environment); - void startDialog (const MWWorld::Ptr& actor); + void startDialogue (const MWWorld::Ptr& actor); }; } diff --git a/apps/openmw/mwworld/environment.hpp b/apps/openmw/mwworld/environment.hpp index 1887e619f3..f9e2e8a42b 100644 --- a/apps/openmw/mwworld/environment.hpp +++ b/apps/openmw/mwworld/environment.hpp @@ -21,9 +21,9 @@ namespace MWMechanics class MechanicsManager; } -namespace MWDialog +namespace MWDialogue { - class DialogManager; + class DialogueManager; } namespace MWWorld @@ -36,7 +36,7 @@ namespace MWWorld public: Environment() : mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0), - mMechanicsManager (0), mDialogManager (0), mFrameDuration (0) + mMechanicsManager (0), mDialogueManager (0), mFrameDuration (0) {} World *mWorld; @@ -44,7 +44,7 @@ namespace MWWorld MWScript::GlobalScripts *mGlobalScripts; MWGui::WindowManager *mWindowManager; MWMechanics::MechanicsManager *mMechanicsManager; - MWDialog::DialogManager *mDialogManager; + MWDialogue::DialogueManager *mDialogueManager; float mFrameDuration; }; } From b5d59edd446c5c3bbea7cea93c1c0d762b826abf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 19:25:26 +0200 Subject: [PATCH 07/22] re-routed talk action from gui to dialogue manager (master branch should not incooperate this change, because the dialogue window implementer will need the original code for testing) --- apps/openmw/mwworld/actiontalk.cpp | 4 ++-- apps/openmw/mwworld/actiontalk.hpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index 2b4aba735c..7d38c22fd7 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -3,7 +3,7 @@ #include "environment.hpp" -#include "../mwgui/window_manager.hpp" +#include "../mwdialogue/dialoguemanager.hpp" namespace MWWorld { @@ -11,6 +11,6 @@ namespace MWWorld void ActionTalk::execute (Environment& environment) { - environment.mWindowManager->setMode (MWGui::GM_Dialogue); + environment.mDialogueManager->startDialogue (mActor); } } diff --git a/apps/openmw/mwworld/actiontalk.hpp b/apps/openmw/mwworld/actiontalk.hpp index 034d6131c2..a60a61660b 100644 --- a/apps/openmw/mwworld/actiontalk.hpp +++ b/apps/openmw/mwworld/actiontalk.hpp @@ -13,6 +13,7 @@ namespace MWWorld public: ActionTalk (const Ptr& actor); + ///< \param actor The actor the player is talking to virtual void execute (Environment& environment); }; From 305563e5952abaea5481464da3fa58b121870fc6 Mon Sep 17 00:00:00 2001 From: Armin Preiml Date: Sun, 8 Aug 2010 10:07:02 +0200 Subject: [PATCH 08/22] disabled char encoding method for windows, although you'll need to add the iconv libs --- cmake/FindIconv.cmake | 5 ++ components/esm/esm_reader.hpp | 151 ++++++++++++++++++---------------- 2 files changed, 84 insertions(+), 72 deletions(-) diff --git a/cmake/FindIconv.cmake b/cmake/FindIconv.cmake index 000e09b845..571a959afd 100644 --- a/cmake/FindIconv.cmake +++ b/cmake/FindIconv.cmake @@ -14,6 +14,11 @@ IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) SET(ICONV_FIND_QUIETLY TRUE) ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) +IF(WIN32) + SET(ICONV_INCLUDE_DIR $ENV{ICONV_INCLUDE_DIR}) + SET(ICONV_LIBRARIES $ENV{ICONV_LIBRARIES}) +ENDIF(WIN32) + FIND_PATH(ICONV_INCLUDE_DIR iconv.h) FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c) diff --git a/components/esm/esm_reader.hpp b/components/esm/esm_reader.hpp index 70a81e6f45..32f5570ad5 100644 --- a/components/esm/esm_reader.hpp +++ b/components/esm/esm_reader.hpp @@ -9,7 +9,10 @@ #include #include #include -#include + +#ifndef __WIN32__ + #include +#endif #include #include @@ -618,89 +621,93 @@ public: return convertToUTF8(res); } - // Convert a string from the encoding used by Morrowind to UTF-8 - std::string convertToUTF8(std::string input) - { - std::string output = ""; - - //create convert description - iconv_t cd = iconv_open("UTF-8", "WINDOWS-1252"); - - if (cd == (iconv_t)-1) //error handling + // Convert a string from the encoding used by Morrowind to UTF-8 + std::string convertToUTF8 (std::string input) { - std::string errMsg = "Creating description for UTF-8 converting failed: "; +#ifdef __WIN32__ + return input; +#else + std::string output = ""; - switch (errno) //detailed error messages (maybe it contains too much detail :) - { - case EMFILE: - errMsg += "{OPEN_MAX} files descriptors are currently open in the calling process."; - case ENFILE: - errMsg += "Too many files are currently open in the system."; - case ENOMEM: - errMsg +="Insufficient storage space is available."; - case EINVAL: - errMsg += "The conversion specified by fromcode and tocode is not supported by the implementation."; + //create convert description + iconv_t cd = iconv_open ("UTF-8", "WINDOWS-1252"); - default: - errMsg += "Unknown Error\n"; - } - - fail(errMsg); - - } - else - { - const size_t inputSize = input.size(); - - if (inputSize) //input is not empty - { - //convert function doesn't accept const char *, therefore copy content into an char * - std::vector inputBuffer(input.begin(), input.end()); - char *inputBufferBegin = &inputBuffer[0]; - - size_t inputBytesLeft = inputSize; //bytes to convert - - static const size_t outputSize = 1000; - size_t outputBytesLeft; - - char outputBuffer[outputSize]; - char *outputBufferBegin; - - while (inputBytesLeft > 0 ) + if (cd == (iconv_t)-1) //error handling { - outputBytesLeft = outputSize; - outputBufferBegin = outputBuffer; + std::string errMsg = "Creating description for UTF-8 converting failed: "; - if (iconv(cd, &inputBufferBegin, &inputBytesLeft, &outputBufferBegin, &outputBytesLeft) == (size_t)-1) - { - switch (errno) + switch (errno) //detailed error messages (maybe it contains too much detail :) { - case E2BIG: //outputBuffer is full - output += std::string(outputBuffer, outputSize); - break; - case EILSEQ: - fail("Iconv: Invalid multibyte sequence.\n"); - break; - case EINVAL: - fail("Iconv: Incomplete multibyte sequence.\n"); - break; - default: - fail("Iconv: Unknown Error\n"); + case EMFILE: + errMsg += "{OPEN_MAX} files descriptors are currently open in the calling process."; + case ENFILE: + errMsg += "Too many files are currently open in the system."; + case ENOMEM: + errMsg +="Insufficient storage space is available."; + case EINVAL: + errMsg += "The conversion specified by fromcode and tocode is not supported by the implementation."; + + default: + errMsg += "Unknown Error\n"; } - } + fail (errMsg); + + } + else + { + const size_t inputSize = input.size(); + + if (inputSize) //input is not empty + { + //convert function doesn't accept const char *, therefore copy content into an char * + std::vector inputBuffer (input.begin(), input.end()); + char *inputBufferBegin = &inputBuffer[0]; + + size_t inputBytesLeft = inputSize; //bytes to convert + + static const size_t outputSize = 1000; + size_t outputBytesLeft; + + char outputBuffer[outputSize]; + char *outputBufferBegin; + + while (inputBytesLeft > 0) + { + outputBytesLeft = outputSize; + outputBufferBegin = outputBuffer; + + if (iconv (cd, &inputBufferBegin, &inputBytesLeft, &outputBufferBegin, &outputBytesLeft) == (size_t)-1) + { + switch (errno) + { + case E2BIG: //outputBuffer is full + output += std::string (outputBuffer, outputSize); + break; + case EILSEQ: + fail ("Iconv: Invalid multibyte sequence.\n"); + break; + case EINVAL: + fail ("Iconv: Incomplete multibyte sequence.\n"); + break; + default: + fail ("Iconv: Unknown Error\n"); + } + + } + } + + //read only relevant bytes from outputBuffer + output += std::string (outputBuffer, outputSize - outputBytesLeft); + + } } - //read only relevant bytes from outputBuffer - output += std::string(outputBuffer, outputSize - outputBytesLeft); + iconv_close (cd); - } + return output; } - - iconv_close (cd); - - return output; - } +#endif void skip(int bytes) { esm->seek(esm->tell()+bytes); } uint64_t getOffset() { return esm->tell(); } From 9d25e74a051837a1f70dc09b35d55573d0941829 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 11:34:03 +0200 Subject: [PATCH 09/22] on dialogue start run through the info records of dialogue record 'hello'; currently no testing done -> the first info recrod will match --- apps/openmw/mwdialogue/dialoguemanager.cpp | 61 ++++++++++++++++++++++ apps/openmw/mwdialogue/dialoguemanager.hpp | 7 +++ 2 files changed, 68 insertions(+) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 22602a3f77..c11e2bb0d8 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -1,17 +1,78 @@ #include "dialoguemanager.hpp" +#include +#include + +#include + #include "../mwworld/class.hpp" +#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" #include namespace MWDialogue { + bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const + { + // TODO check actor id + // TODO check actor race + // TODO check actor class + // TODO check actor faction + // TODO check player faction + // TODO check cell + // TODO check DATAstruct + // TODO check select structures + + std::cout + << "unchecked entries:" << std::endl + << " actor id: " << info.actor << std::endl + << " actor race: " << info.race << std::endl + << " actor class: " << info.clas << std::endl + << " actor faction: " << info.npcFaction << std::endl + << " player faction: " << info.pcFaction << std::endl + << " cell: " << info.cell << std::endl + << " DATAstruct" << std::endl; + + for (std::vector::const_iterator iter (info.selects.begin()); + iter != info.selects.end(); ++iter) + std::cout << " select: " << iter->selectRule << std::endl; + + return true; + } + DialogueManager::DialogueManager (MWWorld::Environment& environment) : mEnvironment (environment) {} void DialogueManager::startDialogue (const MWWorld::Ptr& actor) { std::cout << "talking with " << MWWorld::Class::get (actor).getName (actor) << std::endl; + + const ESM::Dialogue *dialogue = mEnvironment.mWorld->getStore().dialogs.find ("hello"); + + for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + iter!=dialogue->mInfo.end(); ++iter) + { + if (isMatching (actor, *iter)) + { + // start dialogue + std::cout << "found matching info record" << std::endl; + + std::cout << "response: " << iter->response << std::endl; + + if (!iter->sound.empty()) + { + // TODO play sound + } + + if (!iter->resultScript.empty()) + { + // TODO execute script + } + + break; + } + } } } diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp index b31a3d0632..d51570b11e 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.hpp +++ b/apps/openmw/mwdialogue/dialoguemanager.hpp @@ -3,6 +3,11 @@ #include "../mwworld/ptr.hpp" +namespace ESM +{ + struct DialInfo; +} + namespace MWWorld { class Environment; @@ -14,6 +19,8 @@ namespace MWDialogue { MWWorld::Environment& mEnvironment; + bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const; + public: DialogueManager (MWWorld::Environment& environment); From a25c7bb2c07cbf00cb12e0dc8082947c4d1a9d0a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 11:37:59 +0200 Subject: [PATCH 10/22] added test for cell name --- apps/openmw/mwdialogue/dialoguemanager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index c11e2bb0d8..941c760e77 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -21,7 +21,12 @@ namespace MWDialogue // TODO check actor class // TODO check actor faction // TODO check player faction - // TODO check cell + + // check cell + if (!info.cell.empty()) + if (mEnvironment.mWorld->getPlayerPos().getPlayer().getCell()->cell->name != info.cell) + return false; + // TODO check DATAstruct // TODO check select structures @@ -32,7 +37,6 @@ namespace MWDialogue << " actor class: " << info.clas << std::endl << " actor faction: " << info.npcFaction << std::endl << " player faction: " << info.pcFaction << std::endl - << " cell: " << info.cell << std::endl << " DATAstruct" << std::endl; for (std::vector::const_iterator iter (info.selects.begin()); From 8f4359db08d7ccce87a6723ba41e24d51afa5276 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 13:21:03 +0200 Subject: [PATCH 11/22] added test for select type '3' (Local) --- apps/openmw/mwdialogue/dialoguemanager.cpp | 110 +++++++++++++++++++-- apps/openmw/mwdialogue/dialoguemanager.hpp | 9 +- 2 files changed, 108 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 941c760e77..4f9cf602f1 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -1,7 +1,6 @@ #include "dialoguemanager.hpp" -#include #include #include @@ -9,11 +8,110 @@ #include "../mwworld/class.hpp" #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwworld/refdata.hpp" #include +namespace +{ + template + bool selectCompare (char comp, T1 value1, T2 value2) + { + switch (comp) + { + case '0': return value1==value2; + case '1': return value1!=value2; + case '2': return value1>value2; + case '3': return value1>=value2; + case '4': return value1 + bool checkLocal (char comp, const std::string& name, T value, const MWWorld::Ptr& actor, + const ESMS::ESMStore& store) + { + std::string scriptName = MWWorld::Class::get (actor).getScript (actor); + + if (scriptName.empty()) + return false; // no script + + const ESM::Script *script = store.scripts.find (scriptName); + + int i = 0; + + for (; i (script->varNames.size()); ++i) + if (script->varNames[i]==name) + break; + + if (i>=static_cast (script->varNames.size())) + return false; // script does not have a variable of this name + + const MWScript::Locals& locals = actor.getRefData().getLocals(); + + if (idata.numShorts) + return selectCompare (comp, locals.mShorts[i], value); + else + i -= script->data.numShorts; + + if (idata.numLongs) + return selectCompare (comp, locals.mLongs[i], value); + else + i -= script->data.numShorts; + + return selectCompare (comp, locals.mFloats.at (i), value); + } +} + namespace MWDialogue { + bool DialogueManager::isMatching (const MWWorld::Ptr& actor, + const ESM::DialInfo::SelectStruct& select) const + { + char type = select.selectRule[1]; + + if (type!='0') + { + char comp = select.selectRule[4]; + std::string name = select.selectRule.substr (5); + + // TODO types 1, 2, 4, 5, 6, 7, 8, 9, A, B, C + + switch (type) + { + case '3': // local + + if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || + select.type==ESM::VT_Long) + { + if (!checkLocal (comp, name, select.i, actor, + mEnvironment.mWorld->getStore())) + return false; + } + else if (select.type==ESM::VT_Float) + { + if (!checkLocal (comp, name, select.f, actor, + mEnvironment.mWorld->getStore())) + return false; + } + else + throw std::runtime_error ( + "unsupported variable type in dialogue info select"); + + return true; + + default: + + std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; + } + } + + return true; + } + bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const { // TODO check actor id @@ -28,7 +126,11 @@ namespace MWDialogue return false; // TODO check DATAstruct - // TODO check select structures + + for (std::vector::const_iterator iter (info.selects.begin()); + iter != info.selects.end(); ++iter) + if (!isMatching (actor, *iter)) + return false; std::cout << "unchecked entries:" << std::endl @@ -39,10 +141,6 @@ namespace MWDialogue << " player faction: " << info.pcFaction << std::endl << " DATAstruct" << std::endl; - for (std::vector::const_iterator iter (info.selects.begin()); - iter != info.selects.end(); ++iter) - std::cout << " select: " << iter->selectRule << std::endl; - return true; } diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp index d51570b11e..5b6b262404 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.hpp +++ b/apps/openmw/mwdialogue/dialoguemanager.hpp @@ -1,12 +1,9 @@ #ifndef GAME_MMDIALOG_DIALOGUEMANAGER_H #define GAME_MWDIALOG_DIALOGUEMANAGER_H -#include "../mwworld/ptr.hpp" +#include -namespace ESM -{ - struct DialInfo; -} +#include "../mwworld/ptr.hpp" namespace MWWorld { @@ -19,6 +16,8 @@ namespace MWDialogue { MWWorld::Environment& mEnvironment; + bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo::SelectStruct& select) const; + bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const; public: From 2acfe2297538e674f9889d77a4b0d72f46f699b3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 14:28:35 +0200 Subject: [PATCH 12/22] added test for actor ID --- apps/openmw/mwclass/creature.cpp | 8 ++++++++ apps/openmw/mwclass/creature.hpp | 3 +++ apps/openmw/mwclass/npc.cpp | 8 ++++++++ apps/openmw/mwclass/npc.hpp | 3 +++ apps/openmw/mwdialogue/dialoguemanager.cpp | 7 +++++-- apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 4 ++++ 7 files changed, 36 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 4529094ece..1cdada64c5 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -10,6 +10,14 @@ namespace MWClass { + std::string Creature::getId (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->mId; + } + std::string Creature::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index e964a7708f..85a89a9192 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -9,6 +9,9 @@ namespace MWClass { public: + virtual std::string getId (const MWWorld::Ptr& ptr) const; + ///< Return ID of \a ptr + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index ae647c802e..b6a4bbc058 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -10,6 +10,14 @@ namespace MWClass { + std::string Npc::getId (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->mId; + } + std::string Npc::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 2ef37193a7..a6f4a29652 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -9,6 +9,9 @@ namespace MWClass { public: + virtual std::string getId (const MWWorld::Ptr& ptr) const; + ///< Return ID of \a ptr + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 4f9cf602f1..3c3a60180d 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -114,7 +114,11 @@ namespace MWDialogue bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const { - // TODO check actor id + // actor id + if (!info.actor.empty()) + if (info.actor!=MWWorld::Class::get (actor).getId (actor)) + return false; + // TODO check actor race // TODO check actor class // TODO check actor faction @@ -134,7 +138,6 @@ namespace MWDialogue std::cout << "unchecked entries:" << std::endl - << " actor id: " << info.actor << std::endl << " actor race: " << info.race << std::endl << " actor class: " << info.clas << std::endl << " actor faction: " << info.npcFaction << std::endl diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 85e5140eaf..62e0ee8c9f 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -14,6 +14,11 @@ namespace MWWorld Class::~Class() {} + std::string Class::getId (const Ptr& ptr) const + { + throw std::runtime_error ("class does not support ID retrieval"); + } + MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const { throw std::runtime_error ("class does not have creature stats"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 28d96d69f2..d456cc06b6 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -36,6 +36,10 @@ namespace MWWorld virtual ~Class(); + virtual std::string getId (const Ptr& ptr) const; + ///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval + /// (default implementation: throw an exception) + virtual std::string getName (const Ptr& ptr) const = 0; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. From c7fab9aad6ae1d7231a589c9ed6b39dbb5d83112 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 14:36:45 +0200 Subject: [PATCH 13/22] added test for actor race --- apps/openmw/mwdialogue/dialoguemanager.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 3c3a60180d..26f58dfd26 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -119,7 +119,17 @@ namespace MWDialogue if (info.actor!=MWWorld::Class::get (actor).getId (actor)) return false; - // TODO check actor race + if (!info.race.empty()) + { + ESMS::LiveCellRef *cellRef = actor.get(); + + if (!cellRef) + return false; + + if (info.race!=cellRef->base->race) + return false; + } + // TODO check actor class // TODO check actor faction // TODO check player faction @@ -138,7 +148,6 @@ namespace MWDialogue std::cout << "unchecked entries:" << std::endl - << " actor race: " << info.race << std::endl << " actor class: " << info.clas << std::endl << " actor faction: " << info.npcFaction << std::endl << " player faction: " << info.pcFaction << std::endl From fbe11956a6747e49d5f701ecdebe984384710588 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 14:43:20 +0200 Subject: [PATCH 14/22] added dummy test for select type '1' (Function); always yields false for now --- apps/openmw/mwdialogue/dialoguemanager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 26f58dfd26..11a1cec08c 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -82,6 +82,10 @@ namespace MWDialogue switch (type) { + case '1': // function + + return false; // TODO implement functions + case '3': // local if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || From 11bc13141741f676d8a3b94a2bb0d3a05e5fae3a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 15:09:44 +0200 Subject: [PATCH 15/22] added test for global variables --- apps/openmw/mwdialogue/dialoguemanager.cpp | 74 ++++++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 11a1cec08c..a862af06d7 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -1,6 +1,10 @@ #include "dialoguemanager.hpp" +#include +#include +#include + #include #include @@ -14,6 +18,16 @@ namespace { + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } + template bool selectCompare (char comp, T1 value1, T2 value2) { @@ -64,6 +78,36 @@ namespace return selectCompare (comp, locals.mFloats.at (i), value); } + + template + bool checkGlobal (char comp, const std::string& name, T value, MWWorld::World& world) + { + switch (world.getGlobalVariableType (name)) + { + case 's': + + return selectCompare (comp, value, world.getGlobalVariable (name).mShort); + + case 'l': + + return selectCompare (comp, value, world.getGlobalVariable (name).mLong); + + case 'f': + + return selectCompare (comp, value, world.getGlobalVariable (name).mFloat); + + case ' ': + + world.getGlobalVariable (name); // trigger exception + break; + + default: + + throw std::runtime_error ("unsupported gobal variable type"); + } + + return false; + } } namespace MWDialogue @@ -78,7 +122,7 @@ namespace MWDialogue char comp = select.selectRule[4]; std::string name = select.selectRule.substr (5); - // TODO types 1, 2, 4, 5, 6, 7, 8, 9, A, B, C + // TODO types 4, 5, 6, 7, 8, 9, A, B, C switch (type) { @@ -86,18 +130,37 @@ namespace MWDialogue return false; // TODO implement functions + case '2': // global + + if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || + select.type==ESM::VT_Long) + { + if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld)) + return false; + } + else if (select.type==ESM::VT_Float) + { + if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld)) + return false; + } + else + throw std::runtime_error ( + "unsupported variable type in dialogue info select"); + + return true; + case '3': // local if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || select.type==ESM::VT_Long) { - if (!checkLocal (comp, name, select.i, actor, + if (!checkLocal (comp, toLower (name), select.i, actor, mEnvironment.mWorld->getStore())) return false; } else if (select.type==ESM::VT_Float) { - if (!checkLocal (comp, name, select.f, actor, + if (!checkLocal (comp, toLower (name), select.f, actor, mEnvironment.mWorld->getStore())) return false; } @@ -120,7 +183,7 @@ namespace MWDialogue { // actor id if (!info.actor.empty()) - if (info.actor!=MWWorld::Class::get (actor).getId (actor)) + if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor)) return false; if (!info.race.empty()) @@ -130,7 +193,7 @@ namespace MWDialogue if (!cellRef) return false; - if (info.race!=cellRef->base->race) + if (toLower (info.race)!=toLower (cellRef->base->race)) return false; } @@ -185,6 +248,7 @@ namespace MWDialogue if (!iter->resultScript.empty()) { + std::cout << "script: " << iter->resultScript << std::endl; // TODO execute script } From 594d3cef4f9f16318e978cb38748ac14bbd6a330 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 15:12:53 +0200 Subject: [PATCH 16/22] added test for actor class --- apps/openmw/mwdialogue/dialoguemanager.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index a862af06d7..4f99d3a056 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -197,7 +197,17 @@ namespace MWDialogue return false; } - // TODO check actor class + if (!info.clas.empty()) + { + ESMS::LiveCellRef *cellRef = actor.get(); + + if (!cellRef) + return false; + + if (toLower (info.clas)!=toLower (cellRef->base->cls)) + return false; + } + // TODO check actor faction // TODO check player faction @@ -215,7 +225,6 @@ namespace MWDialogue std::cout << "unchecked entries:" << std::endl - << " actor class: " << info.clas << std::endl << " actor faction: " << info.npcFaction << std::endl << " player faction: " << info.pcFaction << std::endl << " DATAstruct" << std::endl; From 19c5ace6029ac2124915f030932858c1b7f039bc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 15:17:49 +0200 Subject: [PATCH 17/22] added test for actor faction --- apps/openmw/mwdialogue/dialoguemanager.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 4f99d3a056..cbb48c6db2 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -208,7 +208,17 @@ namespace MWDialogue return false; } - // TODO check actor faction + if (!info.npcFaction.empty()) + { + ESMS::LiveCellRef *cellRef = actor.get(); + + if (!cellRef) + return false; + + if (toLower (info.npcFaction)!=toLower (cellRef->base->faction)) + return false; + } + // TODO check player faction // check cell @@ -225,7 +235,6 @@ namespace MWDialogue std::cout << "unchecked entries:" << std::endl - << " actor faction: " << info.npcFaction << std::endl << " player faction: " << info.pcFaction << std::endl << " DATAstruct" << std::endl; From 181b538e4aa7088d3707af4153d4f7753c4dcfca Mon Sep 17 00:00:00 2001 From: Armin Preiml Date: Sun, 8 Aug 2010 17:20:55 +0200 Subject: [PATCH 18/22] restructured ogre nif code (struct -> class with singleton), formated code --- components/nifogre/ogre_nif_loader.cpp | 940 +++++++++++++------------ components/nifogre/ogre_nif_loader.hpp | 68 +- 2 files changed, 547 insertions(+), 461 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 670fba8307..7bcecfd18f 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -26,11 +26,11 @@ #include #include -#include "components/nif/nif_file.hpp" -#include "components/nif/node.hpp" -#include "components/nif/data.hpp" -#include "components/nif/property.hpp" -#include "libs/platform/strings.h" +#include "../nif/nif_file.hpp" +#include "../nif/node.hpp" +#include "../nif/data.hpp" +#include "../nif/property.hpp" +#include // For warning messages #include @@ -45,93 +45,111 @@ using namespace Ogre; using namespace Nif; using namespace Mangle::VFS; -// This is the interface to the Ogre resource system. It allows us to -// load NIFs from BSAs, in the file system and in any other place we -// tell Ogre to look (eg. in zip or rar files.) It's also used to -// check for the existence of texture files, so we can exchange the -// extension from .tga to .dds if the texture is missing. -static OgreVFS *vfs; - -// Singleton instance used by load() -static NIFLoader g_sing; - -// Makeshift error reporting system -static string errName; -static void warn(const string &msg) +NIFLoader& NIFLoader::getSingleton() { - cout << "WARNING (NIF:" << errName << "): " << msg << endl; + static NIFLoader instance; + + return instance; +} + +NIFLoader* NIFLoader::getSingletonPtr() +{ + return &getSingleton(); +} + +void NIFLoader::warn(string msg) +{ + std::cerr << "NIFLoader: Warn:" << msg << "\n"; +} + +void NIFLoader::fail(string msg) +{ + std::cerr << "NIFLoader: Fail: "<< msg << std::endl; + assert(1); } // Helper class that computes the bounding box and of a mesh class BoundsFinder { - struct MaxMinFinder - { - float max, min; - - MaxMinFinder() + struct MaxMinFinder { - min = numeric_limits::infinity(); - max = -min; - } + float max, min; - void add(float f) - { - if(f > max) max = f; - if(f < min) min = f; - } + MaxMinFinder() + { + min = numeric_limits::infinity(); + max = -min; + } - // Return Max(max**2, min**2) - float getMaxSquared() - { - float m1 = max*max; - float m2 = min*min; - if(m1 >= m2) return m1; - return m2; - } - }; + void add(float f) + { + if (f > max) max = f; + if (f < min) min = f; + } - MaxMinFinder X, Y, Z; + // Return Max(max**2, min**2) + float getMaxSquared() + { + float m1 = max*max; + float m2 = min*min; + if (m1 >= m2) return m1; + return m2; + } + }; + + MaxMinFinder X, Y, Z; public: - // Add 'verts' vertices to the calculation. The 'data' pointer is - // expected to point to 3*verts floats representing x,y,z for each - // point. - void add(float *data, int verts) - { - for(int i=0;i OGRE. @@ -177,7 +195,7 @@ static CompareFunction getTestMode(int mode) } */ -static void createMaterial(const String &name, +void NIFLoader::createMaterial(const String &name, const Vector &ambient, const Vector &diffuse, const Vector &specular, @@ -186,207 +204,210 @@ static void createMaterial(const String &name, float alphaFlags, float alphaTest, const String &texName) { - MaterialPtr material = MaterialManager::getSingleton().create(name, "General"); + MaterialPtr material = MaterialManager::getSingleton().create(name, resourceGroup); - // This assigns the texture to this material. If the texture name is - // a file name, and this file exists (in a resource directory), it - // will automatically be loaded when needed. If not (such as for - // internal NIF textures that we might support later), we should - // already have inserted a manual loader for the texture. - if(!texName.empty()) + // This assigns the texture to this material. If the texture name is + // a file name, and this file exists (in a resource directory), it + // will automatically be loaded when needed. If not (such as for + // internal NIF textures that we might support later), we should + // already have inserted a manual loader for the texture. + if (!texName.empty()) { - Pass *pass = material->getTechnique(0)->getPass(0); - /*TextureUnitState *txt =*/ pass->createTextureUnitState(texName); + Pass *pass = material->getTechnique(0)->getPass(0); + /*TextureUnitState *txt =*/ + pass->createTextureUnitState(texName); - /* As of yet UNTESTED code from Chris: - pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC); - pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL); - pass->setDepthCheckEnabled(true); + /* As of yet UNTESTED code from Chris: + pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC); + pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL); + pass->setDepthCheckEnabled(true); - // Add transparency if NiAlphaProperty was present - if(alphaFlags != -1) + // Add transparency if NiAlphaProperty was present + if(alphaFlags != -1) + { + if((alphaFlags&1)) + { + pass->setDepthWriteEnabled(false); + pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf), + getBlendFactor((alphaFlags>>5)&0xf)); + } + else + pass->setDepthWriteEnabled(true); + + if((alphaFlags>>9)&1) + pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7), + alphaTest); + + pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1)); + } + else + pass->setDepthWriteEnabled(true); + */ + + // Add transparency if NiAlphaProperty was present + if (alphaFlags != -1) { - if((alphaFlags&1)) + // The 237 alpha flags are by far the most common. Check + // NiAlphaProperty in nif/property.h if you need to decode + // other values. 237 basically means normal transparencly. + if (alphaFlags == 237) { - pass->setDepthWriteEnabled(false); - pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf), - getBlendFactor((alphaFlags>>5)&0xf)); + // Enable transparency + pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); + + //pass->setDepthCheckEnabled(false); + pass->setDepthWriteEnabled(false); } - else - pass->setDepthWriteEnabled(true); - - if((alphaFlags>>9)&1) - pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7), - alphaTest); - - pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1)); - } - else - pass->setDepthWriteEnabled(true); - */ - - // Add transparency if NiAlphaProperty was present - if(alphaFlags != -1) - { - // The 237 alpha flags are by far the most common. Check - // NiAlphaProperty in nif/property.h if you need to decode - // other values. 237 basically means normal transparencly. - if(alphaFlags == 237) - { - // Enable transparency - pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); - - //pass->setDepthCheckEnabled(false); - pass->setDepthWriteEnabled(false); - } - else - warn("Unhandled alpha setting for texture " + texName); + else + warn("Unhandled alpha setting for texture " + texName); } } - // Add material bells and whistles - material->setAmbient(ambient.array[0], ambient.array[1], ambient.array[2]); - material->setDiffuse(diffuse.array[0], diffuse.array[1], diffuse.array[2], alpha); - material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha); - material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]); - material->setShininess(glossiness); + // Add material bells and whistles + material->setAmbient(ambient.array[0], ambient.array[1], ambient.array[2]); + material->setDiffuse(diffuse.array[0], diffuse.array[1], diffuse.array[2], alpha); + material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha); + material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]); + material->setShininess(glossiness); } // Takes a name and adds a unique part to it. This is just used to // make sure that all materials are given unique names. -static String getUniqueName(const String &input) +String NIFLoader::getUniqueName(const String &input) { - static int addon = 0; - static char buf[8]; - snprintf(buf, 8, "_%d", addon++); + static int addon = 0; + static char buf[8]; + snprintf(buf, 8, "_%d", addon++); - // Don't overflow the buffer - if(addon > 999999) addon = 0; + // Don't overflow the buffer + if (addon > 999999) addon = 0; - return input + buf; + return input + buf; } // Check if the given texture name exists in the real world. If it // does not, change the string IN PLACE to say .dds instead and try // that. The texture may still not exist, but no information of value // is lost in that case. -static void findRealTexture(String &texName) +void NIFLoader::findRealTexture(String &texName) { - assert(vfs); - if(vfs->isFile(texName)) return; + assert(vfs); + if (vfs->isFile(texName)) return; - int len = texName.size(); - if(len < 4) return; + int len = texName.size(); + if (len < 4) return; - // Change texture extension to .dds - texName[len-3] = 'd'; - texName[len-2] = 'd'; - texName[len-1] = 's'; + // Change texture extension to .dds + texName[len-3] = 'd'; + texName[len-2] = 'd'; + texName[len-1] = 's'; } // Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given // mesh. -static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material) +void NIFLoader::createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material) { - NiTriShapeData *data = shape->data.getPtr(); - SubMesh *sub = mesh->createSubMesh(shape->name.toString()); + NiTriShapeData *data = shape->data.getPtr(); + SubMesh *sub = mesh->createSubMesh(shape->name.toString()); - int nextBuf = 0; + int nextBuf = 0; - // This function is just one long stream of Ogre-barf, but it works - // great. + // This function is just one long stream of Ogre-barf, but it works + // great. - // Add vertices - int numVerts = data->vertices.length / 3; - sub->vertexData = new VertexData(); - sub->vertexData->vertexCount = numVerts; - sub->useSharedVertices = false; - VertexDeclaration *decl = sub->vertexData->vertexDeclaration; - decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION); - HardwareVertexBufferSharedPtr vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - VertexElement::getTypeSize(VET_FLOAT3), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true); - VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; - bind->setBinding(nextBuf++, vbuf); + // Add vertices + int numVerts = data->vertices.length / 3; + sub->vertexData = new VertexData(); + sub->vertexData->vertexCount = numVerts; + sub->useSharedVertices = false; + VertexDeclaration *decl = sub->vertexData->vertexDeclaration; + decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION); + HardwareVertexBufferSharedPtr vbuf = + HardwareBufferManager::getSingleton().createVertexBuffer( + VertexElement::getTypeSize(VET_FLOAT3), + numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); + vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true); + VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; + bind->setBinding(nextBuf++, vbuf); - // Vertex normals - if(data->normals.length) + // Vertex normals + if (data->normals.length) { - decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL); - vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( - VertexElement::getTypeSize(VET_FLOAT3), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true); - bind->setBinding(nextBuf++, vbuf); + decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL); + vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + VertexElement::getTypeSize(VET_FLOAT3), + numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); + vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true); + bind->setBinding(nextBuf++, vbuf); } - // Vertex colors - if(data->colors.length) + // Vertex colors + if (data->colors.length) { - const float *colors = data->colors.ptr; - RenderSystem* rs = Root::getSingleton().getRenderSystem(); - std::vector colorsRGB(numVerts); - RGBA *pColour = &colorsRGB.front(); - for(int i=0; iconvertColourValue(ColourValue(colors[0],colors[1],colors[2], - colors[3]),pColour++); - colors += 4; - } - decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE); - vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( - VertexElement::getTypeSize(VET_COLOUR), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true); - bind->setBinding(nextBuf++, vbuf); + const float *colors = data->colors.ptr; + RenderSystem* rs = Root::getSingleton().getRenderSystem(); + std::vector colorsRGB(numVerts); + RGBA *pColour = &colorsRGB.front(); + for (int i=0; iconvertColourValue(ColourValue(colors[0],colors[1],colors[2], + colors[3]),pColour++); + colors += 4; + } + decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE); + vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + VertexElement::getTypeSize(VET_COLOUR), + numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); + vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true); + bind->setBinding(nextBuf++, vbuf); } - // Texture UV coordinates - if(data->uvlist.length) + // Texture UV coordinates + if (data->uvlist.length) { - decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); - vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( - VertexElement::getTypeSize(VET_FLOAT2), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); + decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); + vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + VertexElement::getTypeSize(VET_FLOAT2), + numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, true); - bind->setBinding(nextBuf++, vbuf); + vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, true); + bind->setBinding(nextBuf++, vbuf); } - // Triangle faces - int numFaces = data->triangles.length; - if(numFaces) + // Triangle faces + int numFaces = data->triangles.length; + if (numFaces) { - HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer(HardwareIndexBuffer::IT_16BIT, - numFaces, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); - ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true); - sub->indexData->indexBuffer = ibuf; - sub->indexData->indexCount = numFaces; - sub->indexData->indexStart = 0; + HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). + createIndexBuffer(HardwareIndexBuffer::IT_16BIT, + numFaces, + HardwareBuffer::HBU_STATIC_WRITE_ONLY); + ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true); + sub->indexData->indexBuffer = ibuf; + sub->indexData->indexCount = numFaces; + sub->indexData->indexStart = 0; } - // Set material if one was given - if(!material.empty()) sub->setMaterialName(material); + // Set material if one was given + if (!material.empty()) sub->setMaterialName(material); - /* Old commented D code. Might be useful when reimplementing - animation. - // Assign this submesh to the given bone - VertexBoneAssignment v; - v.boneIndex = ((Bone*)bone)->getHandle(); - v.weight = 1.0; - - std::cerr << "+ Assigning bone index " << v.boneIndex << "\n"; - - for(int i=0; i < numVerts; i++) + // Assign this submesh to the given bone + //TODO: Must use niskininstance! + /*if (bone) { - v.vertexIndex = i; - sub->addBoneAssignment(v); - } - */ + VertexBoneAssignment v; + v.boneIndex = ((Bone*)bone)->getHandle(); + v.weight = 1.0; + + std::cerr << "+ Assigning bone index " << v.boneIndex << "\n"; + + for(int i=0; i < numVerts; i++) + { + v.vertexIndex = i; + sub->addBoneAssignment(v); + } + }*/ + } // Helper math functions. Reinventing linear algebra for the win! @@ -394,351 +415,356 @@ static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material // Computes B = AxB (matrix*matrix) static void matrixMul(const Matrix &A, Matrix &B) { - for(int i=0;i<3;i++) + for (int i=0;i<3;i++) { - float a = B.v[0].array[i]; - float b = B.v[1].array[i]; - float c = B.v[2].array[i]; + float a = B.v[0].array[i]; + float b = B.v[1].array[i]; + float c = B.v[2].array[i]; - B.v[0].array[i] = a*A.v[0].array[0] + b*A.v[0].array[1] + c*A.v[0].array[2]; - B.v[1].array[i] = a*A.v[1].array[0] + b*A.v[1].array[1] + c*A.v[1].array[2]; - B.v[2].array[i] = a*A.v[2].array[0] + b*A.v[2].array[1] + c*A.v[2].array[2]; + B.v[0].array[i] = a*A.v[0].array[0] + b*A.v[0].array[1] + c*A.v[0].array[2]; + B.v[1].array[i] = a*A.v[1].array[0] + b*A.v[1].array[1] + c*A.v[1].array[2]; + B.v[2].array[i] = a*A.v[2].array[0] + b*A.v[2].array[1] + c*A.v[2].array[2]; } } // Computes C = B + AxC*scale static void vectorMulAdd(const Matrix &A, const Vector &B, float *C, float scale) { - // Keep the original values - float a = C[0]; - float b = C[1]; - float c = C[2]; + // Keep the original values + float a = C[0]; + float b = C[1]; + float c = C[2]; - // Perform matrix multiplication, scaling and addition - for(int i=0;i<3;i++) - C[i] = B.array[i] + (a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2])*scale; + // Perform matrix multiplication, scaling and addition + for (int i=0;i<3;i++) + C[i] = B.array[i] + (a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2])*scale; } // Computes B = AxB (matrix*vector) static void vectorMul(const Matrix &A, float *C) { - // Keep the original values - float a = C[0]; - float b = C[1]; - float c = C[2]; + // Keep the original values + float a = C[0]; + float b = C[1]; + float c = C[2]; - // Perform matrix multiplication, scaling and addition - for(int i=0;i<3;i++) - C[i] = a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2]; + // Perform matrix multiplication, scaling and addition + for (int i=0;i<3;i++) + C[i] = a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2]; } -static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFinder &bounds) +void NIFLoader::handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags, BoundsFinder &bounds) { - assert(shape != NULL); + assert(shape != NULL); - // Interpret flags - bool hidden = (flags & 0x01) != 0; // Not displayed - bool collide = (flags & 0x02) != 0; // Use mesh for collision - bool bbcollide = (flags & 0x04) != 0; // Use bounding box for collision + // Interpret flags + bool hidden = (flags & 0x01) != 0; // Not displayed + bool collide = (flags & 0x02) != 0; // Use mesh for collision + bool bbcollide = (flags & 0x04) != 0; // Use bounding box for collision - // Bounding box collision isn't implemented, always use mesh for now. - if(bbcollide) + // Bounding box collision isn't implemented, always use mesh for now. + if (bbcollide) { - collide = true; - bbcollide = false; + collide = true; + bbcollide = false; } - // If the object was marked "NCO" earlier, it shouldn't collide with - // anything. - if(flags & 0x800) - { collide = false; bbcollide = false; } - - if(!collide && !bbcollide && hidden) - // This mesh apparently isn't being used for anything, so don't - // bother setting it up. - return; - - // Material name for this submesh, if any - String material; - - // Skip the entire material phase for hidden nodes - if(!hidden) + // If the object was marked "NCO" earlier, it shouldn't collide with + // anything. + if (flags & 0x800) { - // These are set below if present - NiTexturingProperty *t = NULL; - NiMaterialProperty *m = NULL; - NiAlphaProperty *a = NULL; + collide = false; + bbcollide = false; + } - // Scan the property list for material information - PropertyList &list = shape->props; - int n = list.length(); - for(int i=0; i