Merge remote-tracking branch 'zini/master' into animation2

actorid
Chris Robinson 12 years ago
commit 3f19b13695

@ -534,7 +534,9 @@ if (WIN32)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
if (BUILD_ESMTOOL)
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_ESMTOOL)
endif(MSVC)
# Same for MinGW

@ -213,22 +213,26 @@ namespace MWGui
void LoadingScreen::changeWallpaper ()
{
std::vector<std::string> splash;
Ogre::StringVectorPtr resources = Ogre::ResourceGroupManager::getSingleton ().listResourceNames ("General", false);
for (Ogre::StringVector::const_iterator it = resources->begin(); it != resources->end(); ++it)
if (mResources.isNull ())
{
if (it->size() < 6)
continue;
std::string start = it->substr(0, 6);
boost::to_lower(start);
mResources = Ogre::StringVectorPtr (new Ogre::StringVector);
Ogre::StringVectorPtr resources = Ogre::ResourceGroupManager::getSingleton ().listResourceNames ("General", false);
for (Ogre::StringVector::const_iterator it = resources->begin(); it != resources->end(); ++it)
{
if (it->size() < 6)
continue;
std::string start = it->substr(0, 6);
boost::to_lower(start);
if (start == "splash")
splash.push_back (*it);
if (start == "splash")
mResources->push_back (*it);
}
}
if (splash.size())
if (mResources->size())
{
std::string randomSplash = splash[rand() % splash.size()];
std::string randomSplash = mResources->at (rand() % mResources->size());
Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, "General");
mBackgroundImage->setImageTexture (randomSplash);

@ -42,6 +42,7 @@ namespace MWGui
Ogre::Rectangle2D* mRectangle;
Ogre::MaterialPtr mBackgroundMaterial;
Ogre::StringVectorPtr mResources;
bool mLoadingOn;

@ -48,7 +48,7 @@ add_component_dir (misc
add_component_dir (files
linuxpath windowspath macospath fixedpath multidircollection collections fileops configurationmanager
filelibrary ogreplugin
filelibrary ogreplugin constrainedfiledatastream lowlevelfile
)
add_component_dir (compiler

@ -23,94 +23,15 @@
#include "bsa_file.hpp"
#include <stdexcept>
#include <cstdlib>
#include <cassert>
//#include <stdexcept>
//#include <cstdlib>
//#include <cassert>
#include <OgreDataStream.h>
#include "../files/constrainedfiledatastream.hpp"
using namespace std;
using namespace Bsa;
class ConstrainedDataStream : public Ogre::DataStream {
std::ifstream mStream;
const size_t mStart;
size_t mPos;
bool mIsEOF;
public:
ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length)
: mStream(fname.c_str(), std::ios_base::binary), mStart(start), mPos(0), mIsEOF(false)
{
mSize = length;
if(!mStream.seekg(mStart, std::ios_base::beg))
throw std::runtime_error("Error seeking to start of BSA entry");
}
ConstrainedDataStream(const Ogre::String &name, const Ogre::String &fname,
size_t start, size_t length)
: Ogre::DataStream(name), mStream(fname.c_str(), std::ios_base::binary),
mStart(start), mPos(0), mIsEOF(false)
{
mSize = length;
if(!mStream.seekg(mStart, std::ios_base::beg))
throw std::runtime_error("Error seeking to start of BSA entry");
}
virtual size_t read(void *buf, size_t count)
{
mStream.clear();
if(count > mSize-mPos)
{
count = mSize-mPos;
mIsEOF = true;
}
mStream.read(reinterpret_cast<char*>(buf), count);
count = mStream.gcount();
mPos += count;
return count;
}
virtual void skip(long count)
{
if((count >= 0 && (size_t)count <= mSize-mPos) ||
(count < 0 && (size_t)-count <= mPos))
{
mStream.clear();
if(mStream.seekg(count, std::ios_base::cur))
{
mPos += count;
mIsEOF = false;
}
}
}
virtual void seek(size_t pos)
{
if(pos < mSize)
{
mStream.clear();
if(mStream.seekg(pos+mStart, std::ios_base::beg))
{
mPos = pos;
mIsEOF = false;
}
}
}
virtual size_t tell() const
{ return mPos; }
virtual bool eof() const
{ return mIsEOF; }
virtual void close()
{ mStream.close(); }
};
/// Error handling
void BSAFile::fail(const string &msg)
@ -253,5 +174,5 @@ Ogre::DataStreamPtr BSAFile::getFile(const char *file)
fail("File not found: " + string(file));
const FileStruct &fs = files[i];
return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, fs.offset, fs.fileSize));
return openConstrainedFileDataStream (filename.c_str (), fs.offset, fs.fileSize);
}

@ -1,6 +1,8 @@
#include "esmreader.hpp"
#include <stdexcept>
#include "../files/constrainedfiledatastream.hpp"
namespace ESM
{
@ -108,16 +110,12 @@ void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
void ESMReader::open(const std::string &file)
{
std::ifstream *stream = OGRE_NEW_T(std::ifstream, Ogre::MEMCATEGORY_GENERAL)(file.c_str(), std::ios_base::binary);
// Ogre will delete the stream for us
open(Ogre::DataStreamPtr(new Ogre::FileStreamDataStream(stream)), file);
open (openConstrainedFileDataStream (file.c_str ()), file);
}
void ESMReader::openRaw(const std::string &file)
{
std::ifstream *stream = OGRE_NEW_T(std::ifstream, Ogre::MEMCATEGORY_GENERAL)(file.c_str(), std::ios_base::binary);
// Ogre will delete the stream for us
openRaw(Ogre::DataStreamPtr(new Ogre::FileStreamDataStream(stream)), file);
openRaw (openConstrainedFileDataStream (file.c_str ()), file);
}
int64_t ESMReader::getHNLong(const char *name)

@ -0,0 +1,170 @@
#include "constrainedfiledatastream.hpp"
#include "lowlevelfile.hpp"
#include <stdexcept>
#include <cassert>
namespace {
class ConstrainedDataStream : public Ogre::DataStream {
public:
static const size_t sBufferSize = 4096; // somewhat arbitrary though 64KB buffers didn't seem to improve performance any
static const size_t sBufferThreshold = 1024; // reads larger than this bypass buffering as cost of memcpy outweighs cost of system call
ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length)
{
mFile.open (fname.c_str ());
mSize = length != 0xFFFFFFFF ? length : mFile.size () - start;
mPos = 0;
mOrigin = start;
mExtent = start + mSize;
mBufferOrigin = 0;
mBufferExtent = 0;
}
size_t read(void* buf, size_t count)
{
assert (mPos <= mSize);
uint8_t * out = reinterpret_cast <uint8_t *> (buf);
size_t posBeg = mOrigin + mPos;
size_t posEnd = posBeg + count;
if (posEnd > mExtent)
posEnd = mExtent;
size_t posCur = posBeg;
while (posCur != posEnd)
{
size_t readLeft = posEnd - posCur;
if (posCur < mBufferOrigin || posCur >= mBufferExtent)
{
if (readLeft >= sBufferThreshold || (posCur == mOrigin && posEnd == mExtent))
{
assert (mFile.tell () == mBufferExtent);
if (posCur != mBufferExtent)
mFile.seek (posCur);
posCur += mFile.read (out, readLeft);
mBufferOrigin = mBufferExtent = posCur;
mPos = posCur - mOrigin;
return posCur - posBeg;
}
else
{
size_t newBufferOrigin;
if ((posCur < mBufferOrigin) && (mBufferOrigin - posCur < sBufferSize))
newBufferOrigin = std::max (mOrigin, mBufferOrigin > sBufferSize ? mBufferOrigin - sBufferSize : 0);
else
newBufferOrigin = posCur;
fill (newBufferOrigin);
}
}
size_t xfer = std::min (readLeft, mBufferExtent - posCur);
memcpy (out, mBuffer + (posCur - mBufferOrigin), xfer);
posCur += xfer;
out += xfer;
}
count = posEnd - posBeg;
mPos += count;
return count;
}
void skip(long count)
{
assert (mPos <= mSize);
if((count >= 0 && (size_t)count <= mSize-mPos) ||
(count < 0 && (size_t)-count <= mPos))
mPos += count;
}
void seek(size_t pos)
{
assert (mPos <= mSize);
if (pos < mSize)
mPos = pos;
}
virtual size_t tell() const
{
assert (mPos <= mSize);
return mPos;
}
virtual bool eof() const
{
assert (mPos <= mSize);
return mPos == mSize;
}
virtual void close()
{
mFile.close();
}
private:
void fill (size_t newOrigin)
{
assert (mFile.tell () == mBufferExtent);
size_t newExtent = newOrigin + sBufferSize;
if (newExtent > mExtent)
newExtent = mExtent;
size_t oldExtent = mBufferExtent;
if (newOrigin != oldExtent)
mFile.seek (newOrigin);
mBufferOrigin = mBufferExtent = newOrigin;
size_t amountRequested = newExtent - newOrigin;
size_t amountRead = mFile.read (mBuffer, amountRequested);
if (amountRead != amountRequested)
throw std::runtime_error ("An unexpected condition occurred while reading from a file.");
mBufferExtent = newExtent;
}
LowLevelFile mFile;
size_t mOrigin;
size_t mExtent;
size_t mPos;
uint8_t mBuffer [sBufferSize];
size_t mBufferOrigin;
size_t mBufferExtent;
};
} // end of unnamed namespace
Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset, size_t length)
{
return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, offset, length));
}

@ -0,0 +1,8 @@
#ifndef COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP
#define COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP
#include <OgreDataStream.h>
Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset = 0, size_t length = 0xFFFFFFFF);
#endif // COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP

@ -0,0 +1,299 @@
#include "lowlevelfile.hpp"
#include <stdexcept>
#include <sstream>
#include <cassert>
#if FILE_API == FILE_API_POSIX
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#if FILE_API == FILE_API_STDIO
/*
*
* Implementation of LowLevelFile methods using c stdio
*
*/
LowLevelFile::LowLevelFile ()
{
mHandle = NULL;
}
LowLevelFile::~LowLevelFile ()
{
if (mHandle != NULL)
fclose (mHandle);
}
void LowLevelFile::open (char const * filename)
{
assert (mHandle == NULL);
mHandle = fopen (filename, "rb");
if (mHandle == NULL)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
}
void LowLevelFile::close ()
{
assert (mHandle != NULL);
fclose (mHandle);
mHandle = NULL;
}
size_t LowLevelFile::size ()
{
assert (mHandle != NULL);
long oldPosition = ftell (mHandle);
if (oldPosition == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (fseek (mHandle, 0, SEEK_END) != 0)
throw std::runtime_error ("A query operation on a file failed.");
long Size = ftell (mHandle);
if (Size == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (fseek (mHandle, oldPosition, SEEK_SET) != 0)
throw std::runtime_error ("A query operation on a file failed.");
return size_t (Size);
}
void LowLevelFile::seek (size_t Position)
{
assert (mHandle != NULL);
if (fseek (mHandle, Position, SEEK_SET) != 0)
throw std::runtime_error ("A seek operation on a file failed.");
}
size_t LowLevelFile::tell ()
{
assert (mHandle != NULL);
long Position = ftell (mHandle);
if (Position == -1)
throw std::runtime_error ("A query operation on a file failed.");
return size_t (Position);
}
size_t LowLevelFile::read (void * data, size_t size)
{
assert (mHandle != NULL);
int amount = fread (data, 1, size, mHandle);
if (amount == 0 && ferror (mHandle))
throw std::runtime_error ("A read operation on a file failed.");
return amount;
}
#elif FILE_API == FILE_API_POSIX
/*
*
* Implementation of LowLevelFile methods using posix IO calls
*
*/
LowLevelFile::LowLevelFile ()
{
mHandle = -1;
}
LowLevelFile::~LowLevelFile ()
{
if (mHandle != -1)
::close (mHandle);
}
void LowLevelFile::open (char const * filename)
{
assert (mHandle == -1);
#ifdef O_BINARY
static const int openFlags = O_RDONLY | O_BINARY;
#else
static const int openFlags = O_RDONLY;
#endif
mHandle = ::open (filename, openFlags, 0);
if (mHandle == -1)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
}
void LowLevelFile::close ()
{
assert (mHandle != -1);
::close (mHandle);
mHandle = -1;
}
size_t LowLevelFile::size ()
{
assert (mHandle != -1);
size_t oldPosition = ::lseek (mHandle, 0, SEEK_CUR);
if (oldPosition == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
size_t Size = ::lseek (mHandle, 0, SEEK_END);
if (Size == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
if (lseek (mHandle, oldPosition, SEEK_SET) == -1)
throw std::runtime_error ("A query operation on a file failed.");
return Size;
}
void LowLevelFile::seek (size_t Position)
{
assert (mHandle != -1);
if (::lseek (mHandle, Position, SEEK_SET) == -1)
throw std::runtime_error ("A seek operation on a file failed.");
}
size_t LowLevelFile::tell ()
{
assert (mHandle != -1);
size_t Position = ::lseek (mHandle, 0, SEEK_CUR);
if (Position == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
return Position;
}
size_t LowLevelFile::read (void * data, size_t size)
{
assert (mHandle != -1);
int amount = ::read (mHandle, data, size);
if (amount == -1)
throw std::runtime_error ("A read operation on a file failed.");
return amount;
}
#elif FILE_API == FILE_API_WIN32
/*
*
* Implementation of LowLevelFile methods using Win32 API calls
*
*/
LowLevelFile::LowLevelFile ()
{
mHandle = INVALID_HANDLE_VALUE;
}
LowLevelFile::~LowLevelFile ()
{
if (mHandle == INVALID_HANDLE_VALUE)
CloseHandle (mHandle);
}
void LowLevelFile::open (char const * filename)
{
assert (mHandle == INVALID_HANDLE_VALUE);
HANDLE handle = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (handle == NULL)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
mHandle = handle;
}
void LowLevelFile::close ()
{
assert (mHandle != INVALID_HANDLE_VALUE);
CloseHandle (mHandle);
mHandle = INVALID_HANDLE_VALUE;
}
size_t LowLevelFile::size ()
{
assert (mHandle != INVALID_HANDLE_VALUE);
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle (mHandle, &info))
throw std::runtime_error ("A query operation on a file failed.");
if (info.nFileSizeHigh != 0)
throw std::runtime_error ("Files greater that 4GB are not supported.");
return info.nFileSizeLow;
}
void LowLevelFile::seek (size_t Position)
{
assert (mHandle != INVALID_HANDLE_VALUE);
if (SetFilePointer (mHandle, Position, NULL, SEEK_SET) == INVALID_SET_FILE_POINTER)
if (GetLastError () != NO_ERROR)
throw std::runtime_error ("A seek operation on a file failed.");
}
size_t LowLevelFile::tell ()
{
assert (mHandle != INVALID_HANDLE_VALUE);
DWORD value = SetFilePointer (mHandle, 0, NULL, SEEK_CUR);
if (value == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
throw std::runtime_error ("A query operation on a file failed.");
return value;
}
size_t LowLevelFile::read (void * data, size_t size)
{
assert (mHandle != INVALID_HANDLE_VALUE);
DWORD read;
if (!ReadFile (mHandle, data, size, &read, NULL))
throw std::runtime_error ("A read operation on a file failed.");
return read;
}
#endif

@ -0,0 +1,56 @@
#ifndef COMPONENTS_FILES_LOWLEVELFILE_HPP
#define COMPONENTS_FILES_LOWLEVELFILE_HPP
#include <OgrePlatform.h>
#include <cstdlib>
#define FILE_API_STDIO 0
#define FILE_API_POSIX 1
#define FILE_API_WIN32 2
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
#define FILE_API FILE_API_POSIX
#elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define FILE_API FILE_API_WIN32
#else
#define FILE_API FILE_API_STDIO
#endif
#if FILE_API == FILE_API_STDIO
#include <cstdio>
#elif FILE_API == FILE_API_POSIX
#elif FILE_API == FILE_API_WIN32
#include <windows.h>
#else
#error Unsupported File API
#endif
class LowLevelFile
{
public:
LowLevelFile ();
~LowLevelFile ();
void open (char const * filename);
void close ();
size_t size ();
void seek (size_t Position);
size_t tell ();
size_t read (void * data, size_t size);
private:
#if FILE_API == FILE_API_STDIO
FILE* mHandle;
#elif FILE_API == FILE_API_POSIX
int mHandle;
#elif FILE_API == FILE_API_WIN32
HANDLE mHandle;
#endif
};
#endif

@ -537,11 +537,23 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam
* textures from tga to dds for increased load speed, but all
* texture file name references were kept as .tga.
*/
texName = "textures\\" + st->filename;
if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName))
static const char * path = "textures\\";
texName = path + st->filename;
Ogre::String::size_type pos = texName.rfind('.');
if (texName.compare (pos, texName.size () - pos, ".dds") != 0)
{
Ogre::String::size_type pos = texName.rfind('.');
// since we know all (GOTY edition or less) textures end
// in .dds, we change the extension
texName.replace(pos, texName.length(), ".dds");
// if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods)
// verify, and revert if false (this call succeeds quickly, but fails slowly)
if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName))
texName = path + st->filename;
}
}
else warn("Found internal texture, ignoring.");

@ -6,6 +6,19 @@
using namespace OEngine::GUI;
/*
* As of MyGUI 3.2.0, MyGUI::OgreDataManager::isDataExist is unnecessarily complex
* this override fixes the resulting performance issue.
*/
class FixedOgreDataManager : public MyGUI::OgreDataManager
{
public:
bool isDataExist(const std::string& _name)
{
return Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup (_name);
}
};
void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging, const std::string& logDir)
{
assert(wnd);
@ -25,11 +38,18 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
if(!logDir.empty())
theLogFile.insert(0, logDir);
// Set up OGRE platform. We might make this more generic later.
mPlatform = new OgrePlatform();
// Set up OGRE platform (bypassing OgrePlatform). We might make this more generic later.
mLogManager = new LogManager();
mRenderManager = new OgreRenderManager();
mDataManager = new FixedOgreDataManager();
LogManager::getInstance().setSTDOutputEnabled(logging);
mPlatform->initialise(wnd, mgr, "General", theLogFile);
if (!theLogFile.empty())
LogManager::getInstance().createDefaultSource(theLogFile);
mRenderManager->initialise(wnd, mgr);
mDataManager->initialise("General");
// Create GUI
mGui = new Gui();
@ -40,11 +60,22 @@ void MyGUIManager::shutdown()
{
mGui->shutdown ();
delete mGui;
if(mPlatform)
if(mRenderManager)
{
mRenderManager->shutdown();
delete mRenderManager;
mRenderManager = NULL;
}
if(mDataManager)
{
mDataManager->shutdown();
delete mDataManager;
mDataManager = NULL;
}
if (mLogManager)
{
mPlatform->shutdown();
delete mPlatform;
delete mLogManager;
mLogManager = NULL;
}
mGui = NULL;
mPlatform = NULL;
}

@ -3,8 +3,10 @@
namespace MyGUI
{
class OgrePlatform;
class Gui;
class LogManager;
class OgreDataManager;
class OgreRenderManager;
}
namespace Ogre
@ -18,12 +20,15 @@ namespace GUI
{
class MyGUIManager
{
MyGUI::OgrePlatform *mPlatform;
MyGUI::Gui *mGui;
MyGUI::LogManager* mLogManager;
MyGUI::OgreDataManager* mDataManager;
MyGUI::OgreRenderManager* mRenderManager;
Ogre::SceneManager* mSceneMgr;
public:
MyGUIManager() : mPlatform(NULL), mGui(NULL) {}
MyGUIManager() : mLogManager(NULL), mDataManager(NULL), mRenderManager(NULL), mGui(NULL) {}
MyGUIManager(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string(""))
{
setup(wnd,mgr,logging, logDir);

Loading…
Cancel
Save