mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 07:23:51 +00:00
Merge branch 'directories' into next
Conflicts: components/files/multidircollection.hpp components/nifogre/ogre_nif_loader.hpp
This commit is contained in:
commit
bc92b7b1fa
15 changed files with 489 additions and 157 deletions
|
@ -7,6 +7,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <OgreVector3.h>
|
#include <OgreVector3.h>
|
||||||
|
#include <Ogre.h>
|
||||||
|
|
||||||
#include "components/esm/records.hpp"
|
#include "components/esm/records.hpp"
|
||||||
#include <components/esm_store/cell_store.hpp>
|
#include <components/esm_store/cell_store.hpp>
|
||||||
|
@ -92,6 +93,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
std::string effect;
|
std::string effect;
|
||||||
|
|
||||||
MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell();
|
MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell();
|
||||||
|
|
||||||
|
|
||||||
//If the region has changed
|
//If the region has changed
|
||||||
if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){
|
if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){
|
||||||
timer.restart();
|
timer.restart();
|
||||||
|
@ -248,6 +251,11 @@ void OMW::Engine::loadBSA()
|
||||||
std::cout << "Adding " << iter->second.string() << std::endl;
|
std::cout << "Adding " << iter->second.string() << std::endl;
|
||||||
addBSA (iter->second.string());
|
addBSA (iter->second.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string m = mDataDir.string();
|
||||||
|
std::cout << "Data dir" << m << "\n";
|
||||||
|
addDir(m, mFSStrict);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add resources directory
|
// add resources directory
|
||||||
|
@ -345,9 +353,6 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
mOgre.configure(!isFile(ogreCfg.c_str()), cfgUserDir, plugCfg, false);
|
mOgre.configure(!isFile(ogreCfg.c_str()), cfgUserDir, plugCfg, false);
|
||||||
|
|
||||||
addResourcesDirectory (mDataDir / "Meshes");
|
|
||||||
addResourcesDirectory (mDataDir / "Textures");
|
|
||||||
|
|
||||||
// This has to be added BEFORE MyGUI is initialized, as it needs
|
// This has to be added BEFORE MyGUI is initialized, as it needs
|
||||||
// to find core.xml here.
|
// to find core.xml here.
|
||||||
addResourcesDirectory(mResDir / "mygui");
|
addResourcesDirectory(mResDir / "mygui");
|
||||||
|
@ -384,7 +389,7 @@ void OMW::Engine::go()
|
||||||
mOgre.getCamera(),
|
mOgre.getCamera(),
|
||||||
mEnvironment.mWorld->getStore(),
|
mEnvironment.mWorld->getStore(),
|
||||||
(mDataDir),
|
(mDataDir),
|
||||||
mUseSound);
|
mUseSound, mFSStrict);
|
||||||
|
|
||||||
// Create script system
|
// Create script system
|
||||||
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
|
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
|
||||||
|
|
|
@ -95,8 +95,7 @@ namespace MWClass
|
||||||
upperright[uppernumbers++] = npcName + "chest";
|
upperright[uppernumbers++] = npcName + "chest";
|
||||||
neckandup[neckNumbers++] = 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 *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
|
||||||
const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
|
const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
|
||||||
|
@ -113,8 +112,6 @@ namespace MWClass
|
||||||
const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st");
|
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);
|
Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75);
|
||||||
|
|
||||||
if (groin){
|
if (groin){
|
||||||
|
@ -124,10 +121,9 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
if (tail) {
|
if (tail) {
|
||||||
cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, kOgrePi, npcName + "tail", addresses, numbers, "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){
|
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, 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);
|
cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers);
|
||||||
|
@ -218,9 +214,6 @@ namespace MWClass
|
||||||
|
|
||||||
if(hand)
|
if(hand)
|
||||||
{
|
{
|
||||||
//std::cout << "WE FOUND A HAND\n";
|
|
||||||
//-50, 0, -120
|
|
||||||
//std::cout << "WE FOUND HANDS\n";
|
|
||||||
std::string pass;
|
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)
|
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";
|
pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF";
|
||||||
|
@ -230,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
|
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";
|
upperleft[uppernumbers] = npcName + "hand";
|
||||||
upperright[uppernumbers++] = npcName + "hand2";
|
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), upperleft, uppernumbers);
|
||||||
cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers);
|
cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers);
|
||||||
}
|
}
|
||||||
|
@ -244,7 +236,6 @@ namespace MWClass
|
||||||
else
|
else
|
||||||
pass =hands->model; //-50, 0, -120
|
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\\" + 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
|
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";
|
upperleft[uppernumbers] = npcName + "hand";
|
||||||
upperright[uppernumbers++] = npcName + "hand2";
|
upperright[uppernumbers++] = npcName + "hand2";
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "OgreColourValue.h"
|
#include "OgreColourValue.h"
|
||||||
#include <OgreMath.h>
|
#include <OgreMath.h>
|
||||||
|
#include <Ogre.h>
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
@ -74,6 +75,7 @@ namespace MWRender
|
||||||
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst);
|
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst);
|
||||||
|
|
||||||
virtual void insertMesh(const std::string &mesh);
|
virtual void insertMesh(const std::string &mesh);
|
||||||
|
|
||||||
virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements);
|
virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements);
|
||||||
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements);
|
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements);
|
||||||
|
|
||||||
|
|
|
@ -84,20 +84,25 @@ namespace MWSound
|
||||||
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
|
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
|
||||||
// relative to the sound dir, and translates them into full paths
|
// relative to the sound dir, and translates them into full paths
|
||||||
// of existing files in the filesystem, if they exist.
|
// of existing files in the filesystem, if they exist.
|
||||||
|
bool FSstrict;
|
||||||
FileFinder::FileFinder files;
|
FileFinder::FileFinder files;
|
||||||
|
FileFinder::FileFinderStrict strict;
|
||||||
|
FileFinder::FileFinder musicpath;
|
||||||
|
FileFinder::FileFinderStrict musicpathStrict;
|
||||||
|
|
||||||
SoundImpl(Ogre::Root *root, Ogre::Camera *camera,
|
SoundImpl(Ogre::Root *root, Ogre::Camera *camera,
|
||||||
const ESMS::ESMStore &str,
|
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)))
|
: mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY)))
|
||||||
, updater(mgr)
|
, updater(mgr)
|
||||||
, cameraTracker(mgr)
|
, cameraTracker(mgr)
|
||||||
, store(str)
|
, store(str)
|
||||||
, files(soundDir)
|
, files(soundDir), strict(soundDir)
|
||||||
|
,musicpath(musicDir), musicpathStrict(musicDir)
|
||||||
{
|
{
|
||||||
|
FSstrict = fsstrict;
|
||||||
cout << "Sound output: " << SOUND_OUT << endl;
|
cout << "Sound output: " << SOUND_OUT << endl;
|
||||||
cout << "Sound decoder: " << SOUND_IN << endl;
|
cout << "Sound decoder: " << SOUND_IN << endl;
|
||||||
|
|
||||||
// Attach the camera to the camera tracker
|
// Attach the camera to the camera tracker
|
||||||
cameraTracker.followCamera(camera);
|
cameraTracker.followCamera(camera);
|
||||||
|
|
||||||
|
@ -111,6 +116,8 @@ namespace MWSound
|
||||||
cameraTracker.unfollowCamera();
|
cameraTracker.unfollowCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static std::string toMp3(std::string str)
|
static std::string toMp3(std::string str)
|
||||||
{
|
{
|
||||||
std::string::size_type i = str.rfind('.');
|
std::string::size_type i = str.rfind('.');
|
||||||
|
@ -122,25 +129,73 @@ namespace MWSound
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasFile(const std::string &str)
|
bool hasFile(const std::string &str, bool music = false)
|
||||||
|
{
|
||||||
|
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;
|
if(files.has(str)) return true;
|
||||||
// Not found? Try with .mp3
|
|
||||||
return files.has(toMp3(str));
|
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
|
// Convert a Morrowind sound path (eg. Fx\funny.wav) to full path
|
||||||
// with proper slash conversion (eg. datadir/Sound/Fx/funny.wav)
|
// 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
|
// Search and return
|
||||||
if(files.has(str))
|
if(music && musicpath.has(str))
|
||||||
|
return musicpath.lookup(str);
|
||||||
|
else if(files.has(str))
|
||||||
return files.lookup(str);
|
return files.lookup(str);
|
||||||
|
|
||||||
// Try mp3 if the wav wasn't found
|
// Try mp3 if the wav wasn't found
|
||||||
std::string mp3 = toMp3(str);
|
std::string mp3 = toMp3(str);
|
||||||
if(files.has(mp3))
|
if(music && musicpath.has(mp3))
|
||||||
|
return musicpath.lookup(mp3);
|
||||||
|
else if(files.has(mp3))
|
||||||
return files.lookup(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(music && musicpathStrict.has(mp3))
|
||||||
|
return musicpathStrict.lookup(mp3);
|
||||||
|
else if(strict.has(str))
|
||||||
|
return strict.lookup(mp3);
|
||||||
|
}
|
||||||
|
|
||||||
// Give up
|
// Give up
|
||||||
return "";
|
return "";
|
||||||
|
@ -304,15 +359,31 @@ 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,
|
SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera,
|
||||||
const ESMS::ESMStore &store,
|
const ESMS::ESMStore &store,
|
||||||
boost::filesystem::path dataDir,
|
boost::filesystem::path dataDir,
|
||||||
bool useSound)
|
bool useSound, bool fsstrict)
|
||||||
: mData(NULL)
|
: mData(NULL), fsStrict (fsstrict)
|
||||||
{
|
{
|
||||||
MP3Lookup(dataDir / "Music/Explore/");
|
MP3Lookup(dataDir / "Music/Explore/");
|
||||||
if(useSound)
|
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()
|
SoundManager::~SoundManager()
|
||||||
|
@ -321,6 +392,16 @@ namespace MWSound
|
||||||
delete mData;
|
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)
|
void SoundManager::MP3Lookup(boost::filesystem::path dir)
|
||||||
{
|
{
|
||||||
boost::filesystem::directory_iterator dir_iter(dir), dir_end;
|
boost::filesystem::directory_iterator dir_iter(dir), dir_end;
|
||||||
|
@ -353,7 +434,7 @@ namespace MWSound
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::cout << "Playing " << music << "\n";
|
std::cout << "Playing " << music << "\n";
|
||||||
streamMusic(music);
|
streamMusicFull(music);
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
|
@ -397,21 +478,6 @@ namespace MWSound
|
||||||
return !mData->isPlaying(ptr, "_say_sound");
|
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)
|
void SoundManager::playSound (const std::string& soundId, float volume, float pitch)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,16 +30,25 @@ namespace MWSound
|
||||||
|
|
||||||
SoundImpl *mData;
|
SoundImpl *mData;
|
||||||
std::vector<boost::filesystem::path> files;
|
std::vector<boost::filesystem::path> files;
|
||||||
|
bool fsStrict;
|
||||||
|
|
||||||
|
void streamMusicFull (const std::string& filename);
|
||||||
|
///< Play a soundifle
|
||||||
|
/// \param absolute filename
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store,
|
SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store,
|
||||||
boost::filesystem::path dataDir, bool useSound);
|
boost::filesystem::path dataDir, bool useSound, bool fsstrict);
|
||||||
~SoundManager();
|
~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 startRandomTitle();
|
||||||
void MP3Lookup(boost::filesystem::path dir);
|
void MP3Lookup(boost::filesystem::path dir);
|
||||||
//struct SoundImpl;
|
|
||||||
bool isMusicPlaying();
|
bool isMusicPlaying();
|
||||||
|
|
||||||
SoundImpl getMData();
|
SoundImpl getMData();
|
||||||
|
@ -51,9 +60,7 @@ namespace MWSound
|
||||||
bool sayDone (MWWorld::Ptr reference) const;
|
bool sayDone (MWWorld::Ptr reference) const;
|
||||||
///< Is actor not speaking?
|
///< 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);
|
void playSound (const std::string& soundId, float volume, float pitch);
|
||||||
///< Play a sound, independently of 3D-position
|
///< Play a sound, independently of 3D-position
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "bsa_archive.hpp"
|
#include "bsa_archive.hpp"
|
||||||
|
|
||||||
|
#include <OgreFileSystem.h>
|
||||||
#include <OgreArchive.h>
|
#include <OgreArchive.h>
|
||||||
#include <OgreArchiveFactory.h>
|
#include <OgreArchiveFactory.h>
|
||||||
#include <OgreArchiveManager.h>
|
#include <OgreArchiveManager.h>
|
||||||
|
@ -32,7 +33,186 @@
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
using namespace Mangle::Stream;
|
using namespace Mangle::Stream;
|
||||||
|
|
||||||
|
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
|
||||||
|
{
|
||||||
|
bool operator() (const std::string & s1, const std::string & s2) const {
|
||||||
|
//case insensitive version of is_less
|
||||||
|
return lexicographical_compare(s1, s2, boost::algorithm::is_iless());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool fsstrict = false;
|
||||||
|
|
||||||
/// An OGRE Archive wrapping a BSAFile archive
|
/// An OGRE Archive wrapping a BSAFile archive
|
||||||
|
class DirArchive: public Ogre::FileSystemArchive
|
||||||
|
{
|
||||||
|
|
||||||
|
boost::filesystem::path currentdir;
|
||||||
|
std::map<std::string, std::vector<std::string>, ciLessBoost> m;
|
||||||
|
unsigned int cutoff;
|
||||||
|
|
||||||
|
bool comparePortion(std::string file1, std::string file2, int start, int size) const
|
||||||
|
{
|
||||||
|
for(int i = start; i < start+size; i++)
|
||||||
|
{
|
||||||
|
char one = file1.at(i);
|
||||||
|
char two = file2.at(i);
|
||||||
|
if(tolower(one) != tolower(two) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DirArchive(const String& name)
|
||||||
|
: FileSystemArchive(name, "Dir"), currentdir (name)
|
||||||
|
{
|
||||||
|
mType = "Dir";
|
||||||
|
std::string s = name;
|
||||||
|
cutoff = s.size() + 1;
|
||||||
|
if(fsstrict == false)
|
||||||
|
populateMap(currentdir);
|
||||||
|
|
||||||
|
}
|
||||||
|
void populateMap(boost::filesystem::path d){
|
||||||
|
//need to cut off first
|
||||||
|
boost::filesystem::directory_iterator dir_iter(d), dir_end;
|
||||||
|
std::vector<std::string> filesind;
|
||||||
|
boost::filesystem::path f;
|
||||||
|
for(;dir_iter != dir_end; dir_iter++)
|
||||||
|
{
|
||||||
|
if(boost::filesystem::is_directory(*dir_iter))
|
||||||
|
populateMap(*dir_iter);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
f = *dir_iter;
|
||||||
|
std::string s = f.string();
|
||||||
|
|
||||||
|
std::string small;
|
||||||
|
if(cutoff < s.size())
|
||||||
|
small = s.substr(cutoff, s.size() - cutoff);
|
||||||
|
else
|
||||||
|
small = s.substr(cutoff - 1, s.size() - cutoff);
|
||||||
|
|
||||||
|
filesind.push_back(small);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string small;
|
||||||
|
std::string original = d.string();
|
||||||
|
if(cutoff < original.size())
|
||||||
|
small = original.substr(cutoff, original.size() - cutoff);
|
||||||
|
else
|
||||||
|
small = original.substr(cutoff - 1, original.size() - cutoff);
|
||||||
|
m[small] = filesind;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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::string copy = filename;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < filename.size(); i++)
|
||||||
|
{
|
||||||
|
if(copy.at(i) == '\\' ){
|
||||||
|
copy.replace(i, 1, "/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(copy.at(0) == '\\' || copy.at(0) == '/')
|
||||||
|
{
|
||||||
|
copy.erase(0, 1);
|
||||||
|
}
|
||||||
|
if(fsstrict == true)
|
||||||
|
{
|
||||||
|
//std::cout << "fsstrict " << copy << "\n";
|
||||||
|
return FileSystemArchive::exists(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int last = copy.size() - 1;
|
||||||
|
int i = last;
|
||||||
|
|
||||||
|
for (;last >= 0; i--)
|
||||||
|
{
|
||||||
|
if(copy.at(i) == '/' || copy.at(i) == '\\')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string folder = copy.substr(0, i); //folder with no slash
|
||||||
|
|
||||||
|
std::vector<std::string>& current = m[folder];
|
||||||
|
|
||||||
|
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
|
||||||
|
{
|
||||||
|
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
|
||||||
|
return FileSystemArchive::exists(*iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataStreamPtr open(const String& filename, bool readonly = true) const
|
||||||
|
{
|
||||||
|
std::map<std::string, std::vector<std::string>, ciLessBoost> mlocal = m;
|
||||||
|
std::string copy = filename;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < filename.size(); i++)
|
||||||
|
{
|
||||||
|
if(copy.at(i) == '\\' ){
|
||||||
|
copy.replace(i, 1, "/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(copy.at(0) == '\\' || copy.at(0) == '/')
|
||||||
|
{
|
||||||
|
copy.erase(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fsstrict == true)
|
||||||
|
{
|
||||||
|
return FileSystemArchive::open(copy, readonly);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int last = copy.size() - 1;
|
||||||
|
int i = last;
|
||||||
|
|
||||||
|
for (;last >= 0; i--)
|
||||||
|
{
|
||||||
|
if(copy.at(i) == '/' || copy.at(i) == '\\')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string folder = copy.substr(0, i); //folder with no slash
|
||||||
|
std::vector<std::string> current = mlocal[folder];
|
||||||
|
|
||||||
|
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
|
||||||
|
{
|
||||||
|
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
|
||||||
|
return FileSystemArchive::open(*iter, readonly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataStreamPtr p;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class BSAArchive : public Archive
|
class BSAArchive : public Archive
|
||||||
{
|
{
|
||||||
BSAFile arc;
|
BSAFile arc;
|
||||||
|
@ -145,7 +325,27 @@ public:
|
||||||
void destroyInstance( Archive* arch) { delete arch; }
|
void destroyInstance( Archive* arch) { delete arch; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DirArchiveFactory : public FileSystemArchiveFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const String& getType() const
|
||||||
|
{
|
||||||
|
static String name = "Dir";
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Archive *createInstance( const String& name )
|
||||||
|
{
|
||||||
|
return new DirArchive(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyInstance( Archive* arch) { delete arch; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static bool init = false;
|
static bool init = false;
|
||||||
|
static bool init2 = false;
|
||||||
|
|
||||||
static void insertBSAFactory()
|
static void insertBSAFactory()
|
||||||
{
|
{
|
||||||
if(!init)
|
if(!init)
|
||||||
|
@ -155,6 +355,15 @@ static void insertBSAFactory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void insertDirFactory()
|
||||||
|
{
|
||||||
|
if(!init2)
|
||||||
|
{
|
||||||
|
ArchiveManager::getSingleton().addArchiveFactory( new DirArchiveFactory );
|
||||||
|
init2 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The function below is the only publicly exposed part of this file
|
// The function below is the only publicly exposed part of this file
|
||||||
|
|
||||||
void addBSA(const std::string& name, const std::string& group)
|
void addBSA(const std::string& name, const std::string& group)
|
||||||
|
@ -163,3 +372,11 @@ void addBSA(const std::string& name, const std::string& group)
|
||||||
ResourceGroupManager::getSingleton().
|
ResourceGroupManager::getSingleton().
|
||||||
addResourceLocation(name, "BSA", group);
|
addResourceLocation(name, "BSA", group);
|
||||||
}
|
}
|
||||||
|
void addDir(const std::string& name, const bool& fs, const std::string& group)
|
||||||
|
{
|
||||||
|
fsstrict = fs;
|
||||||
|
insertDirFactory();
|
||||||
|
|
||||||
|
ResourceGroupManager::getSingleton().
|
||||||
|
addResourceLocation(name, "Dir", group);
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifndef _BSA_ARCHIVE_H_
|
#ifndef _BSA_ARCHIVE_H_
|
||||||
#define _BSA_ARCHIVE_H_
|
#define _BSA_ARCHIVE_H_
|
||||||
|
@ -29,5 +32,6 @@
|
||||||
/// Add the given BSA file as an input archive in the Ogre resource
|
/// Add the given BSA file as an input archive in the Ogre resource
|
||||||
/// system.
|
/// system.
|
||||||
void addBSA(const std::string& file, const std::string& group="General");
|
void addBSA(const std::string& file, const std::string& group="General");
|
||||||
|
void addDir(const std::string& file, const bool& fs, const std::string& group="General");
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,5 +62,6 @@ public:
|
||||||
|
|
||||||
// The default is to use path_less for equality checks
|
// The default is to use path_less for equality checks
|
||||||
typedef FileFinderT<path_less> FileFinder;
|
typedef FileFinderT<path_less> FileFinder;
|
||||||
|
typedef FileFinderT<path_slash> FileFinderStrict;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,5 +45,40 @@ struct path_less
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct path_slash
|
||||||
|
{
|
||||||
|
int compareChar(char a, char b) const
|
||||||
|
{
|
||||||
|
if(a>b) return 1;
|
||||||
|
else if(a<b) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int comparePathChar(char a, char b) const
|
||||||
|
{
|
||||||
|
if(a == '\\') a = '/';
|
||||||
|
if(b == '\\') b = '/';
|
||||||
|
return compareChar(a,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareString(const char *a, const char *b) const
|
||||||
|
{
|
||||||
|
while(*a && *b)
|
||||||
|
{
|
||||||
|
int i = comparePathChar(*a,*b);
|
||||||
|
if(i != 0) return i;
|
||||||
|
a++; b++;
|
||||||
|
}
|
||||||
|
// At this point, one or both of the chars is a null terminator.
|
||||||
|
// Normal char comparison will get the correct final result here.
|
||||||
|
return compareChar(*a,*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator() (const std::string& a, const std::string& b) const
|
||||||
|
{
|
||||||
|
return compareString(a.c_str(), b.c_str()) < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,11 +23,12 @@ namespace Files
|
||||||
return left<right;
|
return left<right;
|
||||||
|
|
||||||
std::size_t min = std::min (left.length(), right.length());
|
std::size_t min = std::min (left.length(), right.length());
|
||||||
|
std::locale loc;
|
||||||
|
|
||||||
for (std::size_t i=0; i<min; ++i)
|
for (std::size_t i=0; i<min; ++i)
|
||||||
{
|
{
|
||||||
char l = std::tolower (left[i],std::locale());
|
char l = std::tolower (left[i], loc);
|
||||||
char r = std::tolower (right[i],std::locale());
|
char r = std::tolower (right[i], loc);
|
||||||
|
|
||||||
if (l<r)
|
if (l<r)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define _NIF_DATA_H_
|
#define _NIF_DATA_H_
|
||||||
|
|
||||||
#include "controlled.hpp"
|
#include "controlled.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
@ -434,6 +435,7 @@ public:
|
||||||
class NiKeyframeData : public Record
|
class NiKeyframeData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void read(NIFFile *nif)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
// Rotations first
|
// Rotations first
|
||||||
|
@ -468,11 +470,13 @@ public:
|
||||||
|
|
||||||
// Then translation
|
// Then translation
|
||||||
count = nif->getInt();
|
count = nif->getInt();
|
||||||
|
|
||||||
if(count)
|
if(count)
|
||||||
{
|
{
|
||||||
int type = nif->getInt();
|
int type = nif->getInt();
|
||||||
|
|
||||||
if(type == 1) nif->getFloatLen(count*4); // time + translation
|
if(type == 1)
|
||||||
|
nif->getFloatLen(count*4); // time + translation
|
||||||
else if(type == 2)
|
else if(type == 2)
|
||||||
nif->getFloatLen(count*10); // trans1 + forward + backward
|
nif->getFloatLen(count*10); // trans1 + forward + backward
|
||||||
else if(type == 3)
|
else if(type == 3)
|
||||||
|
|
|
@ -131,7 +131,6 @@ class NIFLoader : Ogre::ManualResourceLoader
|
||||||
int counter;
|
int counter;
|
||||||
int numbers;
|
int numbers;
|
||||||
int stack;
|
int stack;
|
||||||
|
|
||||||
std::multimap<std::string,std::string> MaterialMap;
|
std::multimap<std::string,std::string> MaterialMap;
|
||||||
|
|
||||||
// pointer to the ogre mesh which is currently build
|
// pointer to the ogre mesh which is currently build
|
||||||
|
|
Loading…
Reference in a new issue