diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a899a5aea..97596301c 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -93,51 +93,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) std::string effect; MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); - /* - ESMS::CellRefList::List creatureData = (current->creatures).list; - ESMS::CellRefList::List::iterator creaturedataiter = creatureData.begin(); - - for(int i = 0; i < creatureData.size(); i++) - { - //std::cout << "Testing" << i < "\n"; - ESMS::LiveCellRef item = *creaturedataiter; - Ogre::Entity* creaturemodel = item.model; - - if(evt.timeSinceLastFrame == 0) - creaturemodel->getSkeleton()->setBindingPose(); - creaturemodel->getSkeleton()->setBlendMode(Ogre::SkeletonAnimationBlendMode::ANIMBLEND_AVERAGE); //ANIMBLEND_AVERAGE - Ogre::AnimationState *mAnimationState = creaturemodel->getAnimationState("WholeThing"); - mAnimationState->setWeight(.5); - mAnimationState->setLoop(true); - //npcmodel->getSkeleton()-> - - mAnimationState->setEnabled(true); - - - - - Ogre::AnimationState *mAnimationState2 = creaturemodel->getAnimationState("WholeThing2"); - mAnimationState2->setLoop(true); - mAnimationState2->setWeight(.5); - mAnimationState2->setEnabled(true); - - mAnimationState2->createBlendMask(creaturemodel->getSkeleton()->getNumBones(),1); - mAnimationState->createBlendMask(creaturemodel->getSkeleton()->getNumBones(),1); - for(int j = 2; j < creaturemodel->getSkeleton()->getNumBones(); j++) - { - mAnimationState->setBlendMaskEntry(j,1); - mAnimationState2->setBlendMaskEntry(j,1); - } - // set skeleton - std::cout << "TimePosition:" << mAnimationState->getTimePosition() << "\n"; - - mAnimationState->addTime(evt.timeSinceLastFrame); - mAnimationState2->addTime(evt.timeSinceLastFrame); - //npcmodel->_updateAnimation(); - //mAnimationState2->setEnabled(true); - creaturedataiter++; - }*/ - //If the region has changed @@ -299,9 +254,7 @@ void OMW::Engine::loadBSA() std::string m = mDataDir.string(); std::cout << "Data dir" << m << "\n"; - addDir(m); - //std::string s = "f\n"; - //std::cout <<"S: " << s.size() << "\n"; + addDir(m, mFSStrict); } @@ -439,7 +392,7 @@ void OMW::Engine::go() mOgre.getCamera(), mEnvironment.mWorld->getStore(), (mDataDir), - mUseSound); + mUseSound, mFSStrict); // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5afc26480..9ef5e6f40 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -95,8 +95,7 @@ namespace MWClass upperright[uppernumbers++] = npcName + "chest"; neckandup[neckNumbers++] = npcName + "chest"; } - //std::cout << "GETTING NPC PART"; - //Orgre::SceneNode test = cellRender.getNpcPart(); + const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); @@ -113,23 +112,18 @@ namespace MWClass const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st"); - //std::cout << "RACE" << bodyRaceID << "\n"; - Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75); if (groin){ - cellRender.insertMesh("Meshes\\2\\red_MJ_hat_org.nif"); //w/W_6th_Hammer.NIF - //bald_MJ_hat.NIF cellRender.insertMesh("meshes\\" + groin->model, pos2, axis, kOgrePi, npcName + "groin", addresses, numbers); addresses2[numbers] = npcName + "groin"; addresses[numbers++] = npcName + "groin"; } if (tail) { cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, kOgrePi, npcName + "tail", addresses, numbers, "tail"); - //std::cout << "TAIL\n"; } - //addresses[1] = npcName + "groin"; + if(upperleg){ cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -16), axis, kOgrePi, npcName + "upper leg", addresses, numbers); //-18 cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers); @@ -220,9 +214,6 @@ namespace MWClass if(hand) { - //std::cout << "WE FOUND A HAND\n"; - //-50, 0, -120 - //std::cout << "WE FOUND HANDS\n"; std::string pass; if(hand->model.compare("b\\B_N_Dark Elf_F_Hands.1st.NIF")==0 && bodyRaceID.compare("b_n_dark elf_m_") == 0) pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF"; @@ -232,7 +223,6 @@ namespace MWClass cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 upperleft[uppernumbers] = npcName + "hand"; upperright[uppernumbers++] = npcName + "hand2"; - //cellRender.rotateMesh(Ogre::Vector3(0, 0,0), kOgrePi, upperleft, uppernumbers); cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); } @@ -246,7 +236,6 @@ namespace MWClass else pass =hands->model; //-50, 0, -120 cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 - //cellRender.insertMesh("meshes\\" + hands->model, Ogre::Vector3(42, 0,110), Ogre::Vector3(1, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 upperleft[uppernumbers] = npcName + "hand"; upperright[uppernumbers++] = npcName + "hand2"; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 564ebe941..abff70664 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -63,7 +63,7 @@ namespace MWSound */ OEManagerPtr mgr; SoundPtr music; - + /* This class calls update() on the sound manager each frame using and Ogre::FrameListener */ @@ -84,20 +84,25 @@ namespace MWSound // finding. It takes DOS paths (any case, \\ slashes or / slashes) // relative to the sound dir, and translates them into full paths // of existing files in the filesystem, if they exist. + bool FSstrict; FileFinder::FileFinder files; + FileFinder::FileFinderStrict strict; + FileFinder::FileFinder musicpath; + FileFinder::FileFinderStrict musicpathStrict; SoundImpl(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &str, - const std::string &soundDir) + const std::string &soundDir, const std::string &musicDir, bool fsstrict) : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) , updater(mgr) , cameraTracker(mgr) , store(str) - , files(soundDir) + , files(soundDir), strict(soundDir) + ,musicpath(musicDir), musicpathStrict(musicDir) { + FSstrict = fsstrict; cout << "Sound output: " << SOUND_OUT << endl; cout << "Sound decoder: " << SOUND_IN << endl; - // Attach the camera to the camera tracker cameraTracker.followCamera(camera); @@ -111,6 +116,8 @@ namespace MWSound cameraTracker.unfollowCamera(); } + + static std::string toMp3(std::string str) { std::string::size_type i = str.rfind('.'); @@ -122,25 +129,71 @@ namespace MWSound return str; } - bool hasFile(const std::string &str) + bool hasFile(const std::string &str, bool music = false) { - if(files.has(str)) return true; - // Not found? Try with .mp3 - return files.has(toMp3(str)); - } + if(FSstrict == false){ + if(music){ + if(musicpath.has(str)) return true; + // Not found? Try with .mp3 + return musicpath.has(toMp3(str)); + } + else + { + if(files.has(str)) return true; + return files.has(toMp3(str)); + } + } + else + { + if(music){ + if(musicpathStrict.has(str)) return true; + // Not found? Try with .mp3 + return musicpathStrict.has(toMp3(str)); + } + else + { + if(strict.has(str)) return true; + return strict.has(toMp3(str)); + } + + } + } // Convert a Morrowind sound path (eg. Fx\funny.wav) to full path // with proper slash conversion (eg. datadir/Sound/Fx/funny.wav) - std::string convertPath(const std::string &str) + std::string convertPath(const std::string &str, bool music = false) { + if(FSstrict == false){ // Search and return - if(files.has(str)) - return files.lookup(str); + if(music && musicpath.has(str)) + return musicpath.lookup(str); + else if(files.has(str)) + return files.lookup(str); + + + // Try mp3 if the wav wasn't found + std::string mp3 = toMp3(str); + if(music && musicpath.has(mp3)) + return musicpath.lookup(mp3); + else if(files.has(mp3)) + return files.lookup(mp3); + } + + else + { + if(music && musicpathStrict.has(str)) + return musicpathStrict.lookup(str); + else if(strict.has(str)) + return strict.lookup(str); + // Try mp3 if the wav wasn't found std::string mp3 = toMp3(str); - if(files.has(mp3)) - return files.lookup(mp3); + if(music && musicpathStrict.has(mp3)) + return musicpathStrict.lookup(mp3); + else if(strict.has(str)) + return strict.lookup(mp3); + } // Give up return ""; @@ -304,15 +357,32 @@ namespace MWSound } }; + void SoundManager::streamMusicFull (const std::string& filename) + { + if(!mData) return; + + // Play the sound and tell it to stream, if possible. TODO: + // Store the reference, the jukebox will need to check status, + // control volume etc. + if (mData->music) + mData->music->stop(); + mData->music = mData->mgr->load(filename); + mData->music->setStreaming(true); + mData->music->setVolume(0.4); + mData->music->play(); + + } + SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &store, boost::filesystem::path dataDir, - bool useSound) + bool useSound, bool fsstrict) : mData(NULL) { + fsStrict = fsstrict; MP3Lookup(dataDir / "Music/Explore/"); if(useSound) - mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string()); + mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string(), (dataDir / "Music").string(), fsstrict); } SoundManager::~SoundManager() @@ -321,6 +391,15 @@ namespace MWSound delete mData; } + void SoundManager::streamMusic(const std::string& filename){ + if(mData->hasFile(filename, true)) + { + std::string fullpath = mData->convertPath(filename, true); + streamMusicFull(fullpath); + } + } + + void SoundManager::MP3Lookup(boost::filesystem::path dir) { boost::filesystem::directory_iterator dir_iter(dir), dir_end; @@ -353,7 +432,7 @@ namespace MWSound try { std::cout << "Playing " << music << "\n"; - streamMusic(music); + streamMusicFull(music); } catch(std::exception &e) { @@ -397,22 +476,7 @@ namespace MWSound return !mData->isPlaying(ptr, "_say_sound"); } - void SoundManager::streamMusic (const std::string& filename) - { - if(!mData) return; - - // Play the sound and tell it to stream, if possible. TODO: - // Store the reference, the jukebox will need to check status, - // control volume etc. - if (mData->music) - mData->music->stop(); - mData->music = mData->mgr->load(filename); - mData->music->setStreaming(true); - mData->music->setVolume(0.4); - mData->music->play(); - - } - + void SoundManager::playSound (const std::string& soundId, float volume, float pitch) { if(!mData) return; diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 8c48986db..ec33f57a2 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -30,13 +30,21 @@ namespace MWSound SoundImpl *mData; std::vector files; + bool fsStrict; + void streamMusicFull (const std::string& filename); + ///< Play a soundifle + /// \param absolute filename - public: + + SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, - boost::filesystem::path dataDir, bool useSound); + boost::filesystem::path dataDir, bool useSound, bool fsstrict); ~SoundManager(); + void streamMusic(const std::string& filename); + ///< Play a soundifle + /// \param filename name of a sound file in "Music/" in the data directory. void startRandomTitle(); void MP3Lookup(boost::filesystem::path dir); //struct SoundImpl; @@ -51,9 +59,7 @@ namespace MWSound bool sayDone (MWWorld::Ptr reference) const; ///< Is actor not speaking? - void streamMusic (const std::string& filename); - ///< Play a soundifle - /// \param filename name of a sound file in "Music/" in the data directory. + void playSound (const std::string& soundId, float volume, float pitch); ///< Play a sound, independently of 3D-position diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 3497ae70e..f1cf21710 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -41,13 +41,15 @@ struct ciLessBoost : std::binary_function } }; +static bool fsstrict = false; + /// An OGRE Archive wrapping a BSAFile archive class DirArchive: public Ogre::FileSystemArchive { boost::filesystem::path currentdir; std::map, ciLessBoost> m; - int cutoff; + unsigned int cutoff; bool comparePortion(std::string file1, std::string file2, int start, int size) const { @@ -65,13 +67,13 @@ class DirArchive: public Ogre::FileSystemArchive DirArchive(const String& name) : FileSystemArchive(name, "Dir") - { mType = "Dir"; + { + mType = "Dir"; currentdir = name; std::string s = name; cutoff = s.size() + 1; - //std::cout << "Cut off:" << cutoff; - - populateMap(currentdir); + if(fsstrict == false) + populateMap(currentdir); } void populateMap(boost::filesystem::path d){ @@ -96,7 +98,6 @@ class DirArchive: public Ogre::FileSystemArchive small = s.substr(cutoff - 1, s.size() - cutoff); filesind.push_back(small); - //std::cout << "File: " << small << "f\n"; } } std::string small; @@ -105,30 +106,22 @@ class DirArchive: public Ogre::FileSystemArchive small = original.substr(cutoff, original.size() - cutoff); else small = original.substr(cutoff - 1, original.size() - cutoff); - //boost::filesystem::path smallp = small; m[small] = filesind; - //std::cout << "Directory: " << small << " " << filesind.size() << "\n"; } - bool isCaseSensitive() const { return false; } + bool isCaseSensitive() const { return fsstrict; } // The archive is loaded in the constructor, and never unloaded. void load() {} void unload() {} bool exists(const String& filename) { - //std::cout << "exists\n"; - //String s = filename; - //FileSystemArchive::findFiles(s, true, false, filenames.getPointer(), f.getPointer()); - // std::cout << "Filenames" << filenames.useCount() << "\n"; - - std::string copy = filename; - - for (int i = 0; i < filename.size(); i++) + + for (unsigned int i = 0; i < filename.size(); i++) { if(copy.at(i) == '\\' ){ copy.replace(i, 1, "/"); @@ -138,14 +131,15 @@ class DirArchive: public Ogre::FileSystemArchive if(copy.at(0) == '\\' || copy.at(0) == '/') { - //std::cout << "Before:" << copy.size() << "\n"; copy.erase(0, 1); - //std::cout << "The copy" << copy << "\n"; - //std::cout << "After:" << copy.size(); } + if(fsstrict == true) + { + //std::cout << "fsstrict " << copy << "\n"; + return FileSystemArchive::exists(copy); + } - //boost::filesystem::path p = copy; int last = copy.size() - 1; int i = last; @@ -156,41 +150,29 @@ class DirArchive: public Ogre::FileSystemArchive break; } - //std::string file = copy.substr(i + 1, copy.size() - i); //filename with no slash std::string folder = copy.substr(0, i); //folder with no slash - //std::transform(file.begin(), file.end(), file.begin(), tolower); - //boost::filesystem::path folderpath = folder; std::vector& current = m[folder]; for(std::vector::iterator iter = current.begin(); iter != current.end(); iter++) { - //std::string loopfile = iter->substr(i + 1, copy.size() - i); //filename with no slash - //std::transform(loopfile.begin(), loopfile.end(), loopfile.begin(), tolower); - //std::string now = *iter; if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){ - //std::cout << "Loopfile:" << copy << "\n"; return FileSystemArchive::exists(*iter); } } - //std::cout << "Filename:" << file << "\n"; - //std::cout << "Full:" << p.string() << "\n"; - //std::cout << "Current:" << folder << "size: " << current.size() << "\n"; - //std::cout << "\nFull:" << p.string() << "\n"<< "Part:" << folderpath.string(); - return false;//FileSystemArchive::exists(copy); + return false; } DataStreamPtr open(const String& filename, bool readonly = true) const { std::map, ciLessBoost> mlocal = m; - //std::cout << "Open\n"; std::string copy = filename; - - for (int i = 0; i < filename.size(); i++) + + for (unsigned int i = 0; i < filename.size(); i++) { if(copy.at(i) == '\\' ){ copy.replace(i, 1, "/"); @@ -200,12 +182,13 @@ class DirArchive: public Ogre::FileSystemArchive if(copy.at(0) == '\\' || copy.at(0) == '/') { - //std::cout << "Before:" << copy.size() << "\n"; copy.erase(0, 1); - //std::cout << "The copy" << copy << "\n"; - //std::cout << "After:" << copy.size(); } - //boost::filesystem::path p = copy; + + if(fsstrict == true){ + return FileSystemArchive::open(copy, readonly); + } + int last = copy.size() - 1; int i = last; @@ -216,28 +199,17 @@ class DirArchive: public Ogre::FileSystemArchive break; } - std::string folder = copy.substr(0, i); //folder with no slash //folder with no slash - - //std::transform(file.begin(), file.end(), file.begin(), tolower); - //boost::filesystem::path folderpath = folder; + std::string folder = copy.substr(0, i); //folder with no slash std::vector current = mlocal[folder]; for(std::vector::iterator iter = current.begin(); iter != current.end(); iter++) { - //std::string loopfile = iter->substr(i + 1, copy.size() - i); //filename with no slash - //std::transform(loopfile.begin(), loopfile.end(), loopfile.begin(), tolower); if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){ - //std::cout << "Loopfile:" << copy << "\n"; return FileSystemArchive::open(*iter, readonly); } } - - //std::cout << "Filename:" << file << "\n"; - //std::cout << "Full:" << p.string() << "\n"; - //std::cout << "Current:" << folder << "size: " << current.size() << "\n"; - //std::cout << "\nFull:" << p.string() << "\n"<< "Part:" << folderpath.string(); DataStreamPtr p; - return p;//FileSystemArchive::open(copy, readonly); + return p; } }; @@ -374,6 +346,7 @@ public: static bool init = false; static bool init2 = false; + static void insertBSAFactory() { if(!init) @@ -400,9 +373,11 @@ void addBSA(const std::string& name, const std::string& group) ResourceGroupManager::getSingleton(). addResourceLocation(name, "BSA", group); } -void addDir(const std::string& name, const std::string& group) +void addDir(const std::string& name, const bool& fs, const std::string& group) { + fsstrict = fs; insertDirFactory(); + ResourceGroupManager::getSingleton(). addResourceLocation(name, "Dir", group); } diff --git a/components/bsa/bsa_archive.hpp b/components/bsa/bsa_archive.hpp index a72f638e3..bf7e7ee51 100644 --- a/components/bsa/bsa_archive.hpp +++ b/components/bsa/bsa_archive.hpp @@ -32,6 +32,6 @@ /// Add the given BSA file as an input archive in the Ogre resource /// system. void addBSA(const std::string& file, const std::string& group="General"); -void addDir(const std::string& file, const std::string& group="General"); +void addDir(const std::string& file, const bool& fs, const std::string& group="General"); #endif diff --git a/components/file_finder/file_finder.hpp b/components/file_finder/file_finder.hpp index cfa07dce9..358563afa 100644 --- a/components/file_finder/file_finder.hpp +++ b/components/file_finder/file_finder.hpp @@ -22,7 +22,7 @@ class FileFinderT { std::string file = pth.string(); std::string key = file.substr(cut); - owner->table[key] = file; + owner->table[key] = file; } }; @@ -50,17 +50,18 @@ public: bool has(const std::string& file) const { - return table.find(file) != table.end(); + return table.find(file) != table.end(); } // Find the full path from a relative path. const std::string &lookup(const std::string& file) const { - return table.find(file)->second; + return table.find(file)->second; } }; // The default is to use path_less for equality checks typedef FileFinderT FileFinder; +typedef FileFinderT FileFinderStrict; } #endif diff --git a/components/file_finder/filename_less.hpp b/components/file_finder/filename_less.hpp index 9f251b1c8..bc3186ce9 100644 --- a/components/file_finder/filename_less.hpp +++ b/components/file_finder/filename_less.hpp @@ -44,6 +44,41 @@ struct path_less return compareString(a.c_str(), b.c_str()) < 0; } }; + +struct path_slash +{ + int compareChar(char a, char b) const + { + if(a>b) return 1; + else if(a