1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-05-01 04:11:23 +00:00

Merge branch 'master' of https://github.com/zinnschlag/openmw into tgm

This commit is contained in:
mckibbenta 2013-09-02 18:40:37 -04:00
commit e545f49807
19 changed files with 355 additions and 119 deletions

View file

@ -19,7 +19,7 @@ include (OpenMWMacros)
# Version # Version
set (OPENMW_VERSION_MAJOR 0) set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 25) set (OPENMW_VERSION_MINOR 26)
set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")

View file

@ -3,6 +3,11 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QMessageBox> #include <QMessageBox>
#include <QDir> #include <QDir>
#ifdef __APPLE__
// We need to do this because of Qt: https://bugreports.qt-project.org/browse/QTBUG-22154
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#endif
#include <SDL.h> #include <SDL.h>
#include <cstdlib> #include <cstdlib>

View file

@ -3,6 +3,10 @@
#include <QDir> #include <QDir>
#include <QDebug> #include <QDebug>
#ifdef __APPLE__
// We need to do this because of Qt: https://bugreports.qt-project.org/browse/QTBUG-22154
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#endif
#include <SDL.h> #include <SDL.h>
#include "maindialog.hpp" #include "maindialog.hpp"

View file

@ -33,46 +33,48 @@ namespace MWMechanics
bool AiTravel::execute (const MWWorld::Ptr& actor) bool AiTravel::execute (const MWWorld::Ptr& actor)
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWBase::World *world = MWBase::Environment::get().getWorld();
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY; Movement &movement = actor.getClass().getMovementSettings(actor);
const ESM::Pathgrid *pathgrid = const ESM::Cell *cell = actor.getCell()->mCell;
MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX) MWWorld::Ptr player = world->getPlayer().getPlayer();
if(cell->mData.mX != player.getCell()->mCell->mData.mX)
{ {
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX); int sideX = sgn(cell->mData.mX - player.getCell()->mCell->mData.mX);
//check if actor is near the border of an inactive cell. If so, disable aitravel. //check if actor is near the border of an inactive cell. If so, stop walking.
if(sideX * (pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) >
2.0 - 200)) sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
{ {
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; movement.mPosition[1] = 0;
return true; return false;
} }
} }
if(actor.getCell()->mCell->mData.mY != player.getCell()->mCell->mData.mY) if(cell->mData.mY != player.getCell()->mCell->mData.mY)
{ {
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY); int sideY = sgn(cell->mData.mY - player.getCell()->mCell->mData.mY);
//check if actor is near the border of an inactive cell. If so, disable aitravel. //check if actor is near the border of an inactive cell. If so, stop walking.
if(sideY * (pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) >
2.0 - 200)) sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
{ {
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; movement.mPosition[1] = 0;
return true; return false;
} }
} }
const ESM::Pathgrid *pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell);
bool cellChange = cell->mData.mX != cellX || cell->mData.mY != cellY;
if(!mPathFinder.isPathConstructed() || cellChange) if(!mPathFinder.isPathConstructed() || cellChange)
{ {
cellX = actor.getCell()->mCell->mData.mX; cellX = cell->mData.mX;
cellY = actor.getCell()->mCell->mData.mY; cellY = cell->mData.mY;
float xCell = 0; float xCell = 0;
float yCell = 0; float yCell = 0;
if (actor.getCell()->mCell->isExterior()) if(cell->isExterior())
{ {
xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; xCell = cell->mData.mX * ESM::Land::REAL_SIZE;
yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; yCell = cell->mData.mY * ESM::Land::REAL_SIZE;
} }
ESM::Pathgrid::Point dest; ESM::Pathgrid::Point dest;
@ -90,13 +92,13 @@ namespace MWMechanics
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
{ {
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; movement.mPosition[1] = 0;
return true; return true;
} }
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); world->rotateObject(actor, 0, 0, zAngle, false);
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; movement.mPosition[1] = 1;
return false; return false;
} }

View file

@ -65,10 +65,11 @@ namespace MWMechanics
bool AiWander::execute (const MWWorld::Ptr& actor) bool AiWander::execute (const MWWorld::Ptr& actor)
{ {
MWBase::World *world = MWBase::Environment::get().getWorld();
if(mDuration) if(mDuration)
{ {
// End package if duration is complete or mid-night hits: // End package if duration is complete or mid-night hits:
MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp(); MWWorld::TimeStamp currentTime = world->getTimeStamp();
if(currentTime.getHour() >= mStartTime.getHour() + mDuration) if(currentTime.getHour() >= mStartTime.getHour() + mDuration)
{ {
if(!mRepeat) if(!mRepeat)
@ -96,8 +97,7 @@ namespace MWMechanics
if(!mStoredAvailableNodes) if(!mStoredAvailableNodes)
{ {
mStoredAvailableNodes = true; mStoredAvailableNodes = true;
mPathgrid = mPathgrid = world->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
mCellX = actor.getCell()->mCell->mData.mX; mCellX = actor.getCell()->mCell->mData.mX;
mCellY = actor.getCell()->mCell->mData.mY; mCellY = actor.getCell()->mCell->mData.mY;
@ -150,37 +150,8 @@ namespace MWMechanics
} }
} }
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
bool cellChange = actor.getCell()->mCell->mData.mX != mCellX || actor.getCell()->mCell->mData.mY != mCellY;
if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
{
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
// FIXME: This *should* pause the AiWander package instead of terminating it.
if(sideX * (pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE /
2.0 - 200))
{
stopWalking(actor);
return true;
}
}
if(actor.getCell()->mCell->mData.mY != player.getCell()->mCell->mData.mY)
{
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
// FIXME: This *should* pause the AiWander package instead of terminating it.
if(sideY * (pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE /
2.0 - 200))
{
stopWalking(actor);
return true;
}
}
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles. // Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
if(mDistance && (cellChange || (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY))) if(mDistance && (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY))
mDistance = 0; mDistance = 0;
if(mChooseAction) if(mChooseAction)
@ -207,7 +178,7 @@ namespace MWMechanics
else else
{ {
// Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander: // Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp(); MWWorld::TimeStamp currentTime = world->getTimeStamp();
mStartTime = currentTime; mStartTime = currentTime;
playIdle(actor, mPlayedIdle); playIdle(actor, mPlayedIdle);
mChooseAction = false; mChooseAction = false;
@ -264,18 +235,10 @@ namespace MWMechanics
if(mWalking) if(mWalking)
{ {
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle,false); world->rotateObject(actor, 0, 0, zAngle, false);
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
// Unclog path nodes by allowing the NPC to be a small distance away from the center. This way two NPCs can be if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
// at the same path node at the same time and both will complete instead of endlessly walking into eachother:
Ogre::Vector3 destNodePos(mCurrentNode.mX, mCurrentNode.mY, mCurrentNode.mZ);
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
actorPos[0] = actorPos[0] - mXCell;
actorPos[1] = actorPos[1] - mYCell;
float distance = actorPos.squaredDistance(destNodePos);
if(distance < 1200 || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
{ {
stopWalking(actor); stopWalking(actor);
mMoveNow = false; mMoveNow = false;

View file

@ -147,13 +147,13 @@ namespace MWMechanics
mIsPathConstructed = false; mIsPathConstructed = false;
} }
void PathFinder::buildPath(ESM::Pathgrid::Point startPoint, ESM::Pathgrid::Point endPoint, void PathFinder::buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,
const ESM::Pathgrid* pathGrid, float xCell, float yCell, bool allowShortcuts) const ESM::Pathgrid *pathGrid, float xCell, float yCell, bool allowShortcuts)
{ {
if(allowShortcuts) if(allowShortcuts)
{ {
if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ, endPoint.mX, endPoint.mY, if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ,
endPoint.mZ)) endPoint.mX, endPoint.mY, endPoint.mZ))
allowShortcuts = false; allowShortcuts = false;
} }
@ -184,14 +184,14 @@ namespace MWMechanics
mIsPathConstructed = false; mIsPathConstructed = false;
} }
float PathFinder::getZAngleToNext(float x, float y) float PathFinder::getZAngleToNext(float x, float y) const
{ {
// This should never happen (programmers should have an if statement checking mIsPathConstructed that prevents this call // This should never happen (programmers should have an if statement checking mIsPathConstructed that prevents this call
// if otherwise). // if otherwise).
if(mPath.empty()) if(mPath.empty())
return 0; return 0;
ESM::Pathgrid::Point nextPoint = *mPath.begin(); const ESM::Pathgrid::Point &nextPoint = *mPath.begin();
float directionX = nextPoint.mX - x; float directionX = nextPoint.mX - x;
float directionY = nextPoint.mY - y; float directionY = nextPoint.mY - y;
float directionResult = sqrt(directionX * directionX + directionY * directionY); float directionResult = sqrt(directionX * directionX + directionY * directionY);
@ -205,7 +205,7 @@ namespace MWMechanics
return true; return true;
ESM::Pathgrid::Point nextPoint = *mPath.begin(); ESM::Pathgrid::Point nextPoint = *mPath.begin();
if(distanceZCorrected(nextPoint, x, y, z) < 40) if(distanceZCorrected(nextPoint, x, y, z) < 64)
{ {
mPath.pop_front(); mPath.pop_front();
if(mPath.empty()) if(mPath.empty())
@ -217,15 +217,5 @@ namespace MWMechanics
return false; return false;
} }
std::list<ESM::Pathgrid::Point> PathFinder::getPath()
{
return mPath;
}
bool PathFinder::isPathConstructed()
{
return mIsPathConstructed;
}
} }

View file

@ -12,15 +12,18 @@ namespace MWMechanics
PathFinder(); PathFinder();
void clearPath(); void clearPath();
void buildPath(ESM::Pathgrid::Point startPoint, ESM::Pathgrid::Point endPoint, void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,
const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0, bool allowShortcuts = 1); const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0,
bool allowShortcuts = true);
bool checkPathCompleted(float x, float y, float z); bool checkPathCompleted(float x, float y, float z);
///< \Returns true if the last point of the path has been reached. ///< \Returns true if the last point of the path has been reached.
float getZAngleToNext(float x, float y); float getZAngleToNext(float x, float y) const;
std::list<ESM::Pathgrid::Point> getPath(); bool isPathConstructed() const
bool isPathConstructed(); {
return mIsPathConstructed;
}
private: private:
std::list<ESM::Pathgrid::Point> mPath; std::list<ESM::Pathgrid::Point> mPath;

View file

@ -370,8 +370,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, playerdirection.y); MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, playerdirection.y);
// explore radius (squared) // explore radius (squared)
const float sqrExploreRadius = (mInterior ? 0.01 : 0.09) * sFogOfWarResolution*sFogOfWarResolution; const float exploreRadius = (mInterior ? 0.1 : 0.3) * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1
const float exploreRadius = (mInterior ? 0.1 : 0.3) * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution const float sqrExploreRadius = Math::Sqr(exploreRadius);
const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space) const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space)
// change the affected fog of war textures (in a 3x3 grid around the player) // change the affected fog of war textures (in a 3x3 grid around the player)
@ -406,11 +406,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
{ {
for (int texU = 0; texU<sFogOfWarResolution; ++texU) for (int texU = 0; texU<sFogOfWarResolution; ++texU)
{ {
// fix into range of 0 ... sFogOfWarResolution float sqrDist = Math::Sqr((texU + mx*(sFogOfWarResolution-1)) - u*(sFogOfWarResolution-1))
int _texU = texU * (float(sFogOfWarResolution+1) / float(sFogOfWarResolution)); + Math::Sqr((texV + my*(sFogOfWarResolution-1)) - v*(sFogOfWarResolution-1));
int _texV = texV * (float(sFogOfWarResolution+1) / float(sFogOfWarResolution));
float sqrDist = Math::Sqr((_texU + mx*sFogOfWarResolution) - u*sFogOfWarResolution) + Math::Sqr((_texV + my*sFogOfWarResolution) - v*sFogOfWarResolution);
uint32 clr = mBuffers[texName][i]; uint32 clr = mBuffers[texName][i];
uint8 alpha = (clr >> 24); uint8 alpha = (clr >> 24);
alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );

View file

@ -1037,7 +1037,6 @@ public:
VideoPlayer::VideoPlayer(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* window) VideoPlayer::VideoPlayer(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* window)
: mState(NULL) : mState(NULL)
, mSceneMgr(sceneMgr) , mSceneMgr(sceneMgr)
, mVideoMaterial(NULL)
, mRectangle(NULL) , mRectangle(NULL)
, mNode(NULL) , mNode(NULL)
, mAllowSkipping(false) , mAllowSkipping(false)

View file

@ -11,14 +11,15 @@ if (GTEST_FOUND AND GMOCK_FOUND)
include_directories(${GMOCK_INCLUDE_DIRS}) include_directories(${GMOCK_INCLUDE_DIRS})
file(GLOB UNITTEST_SRC_FILES file(GLOB UNITTEST_SRC_FILES
components/misc/*.cpp components/misc/test_*.cpp
components/file_finder/test_*.cpp
) )
source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES}) source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
add_executable(openmw_test_suite openmw_test_suite.cpp ${UNITTEST_SRC_FILES}) add_executable(openmw_test_suite openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
target_link_libraries(openmw_test_suite ${GMOCK_BOTH_LIBRARIES} ${GTEST_BOTH_LIBRARIES}) target_link_libraries(openmw_test_suite ${GMOCK_BOTH_LIBRARIES} ${GTEST_BOTH_LIBRARIES} components)
# Fix for not visible pthreads functions for linker with glibc 2.15 # Fix for not visible pthreads functions for linker with glibc 2.15
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
target_link_libraries(openmw_test_suite ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(openmw_test_suite ${CMAKE_THREAD_LIBS_INIT})

View file

@ -0,0 +1,66 @@
#include <gtest/gtest.h>
#include <fstream>
#include "components/file_finder/file_finder.hpp"
struct FileFinderTest : public ::testing::Test
{
protected:
FileFinderTest()
: mTestDir("./filefinder_test_dir/")
, mTestFile("test.txt")
, mTestFileUppercase("TEST.TXT")
, mTestFileNotFound("foobarbaz.txt")
{
}
virtual void SetUp()
{
boost::filesystem::create_directory(boost::filesystem::path(mTestDir));
std::ofstream ofs(std::string(mTestDir + mTestFile).c_str(), std::ofstream::out);
ofs << std::endl;
ofs.close();
}
virtual void TearDown()
{
boost::filesystem::remove_all(boost::filesystem::path(mTestDir));
}
std::string mTestDir;
std::string mTestFile;
std::string mTestFileUppercase;
std::string mTestFileNotFound;
};
TEST_F(FileFinderTest, FileFinder_has_file)
{
FileFinder::FileFinder fileFinder(mTestDir);
ASSERT_TRUE(fileFinder.has(mTestFile));
ASSERT_TRUE(fileFinder.has(mTestFileUppercase));
ASSERT_TRUE(fileFinder.lookup(mTestFile) == std::string(mTestDir + mTestFile));
ASSERT_TRUE(fileFinder.lookup(mTestFileUppercase) == std::string(mTestDir + mTestFile));
}
TEST_F(FileFinderTest, FileFinder_does_not_have_file)
{
FileFinder::FileFinder fileFinder(mTestDir);
ASSERT_FALSE(fileFinder.has(mTestFileNotFound));
ASSERT_TRUE(fileFinder.lookup(mTestFileNotFound).empty());
}
TEST_F(FileFinderTest, FileFinderStrict_has_file)
{
FileFinder::FileFinderStrict fileFinder(mTestDir);
ASSERT_TRUE(fileFinder.has(mTestFile));
ASSERT_FALSE(fileFinder.has(mTestFileUppercase));
ASSERT_TRUE(fileFinder.lookup(mTestFile) == std::string(mTestDir + mTestFile));
ASSERT_FALSE(fileFinder.lookup(mTestFileUppercase) == std::string(mTestDir + mTestFile));
}
TEST_F(FileFinderTest, FileFinderStrict_does_not_have_file)
{
FileFinder::FileFinderStrict fileFinder(mTestDir);
ASSERT_FALSE(fileFinder.has(mTestFileNotFound));
ASSERT_TRUE(fileFinder.lookup(mTestFileNotFound).empty());
}

View file

@ -0,0 +1,74 @@
#include <gtest/gtest.h>
#include <boost/filesystem.hpp>
#include <fstream>
#include "components/file_finder/search.hpp"
struct SearchTest : public ::testing::Test
{
protected:
SearchTest()
: mTestDir("./search_test_dir/")
{
}
virtual void SetUp()
{
boost::filesystem::create_directory(boost::filesystem::path(mTestDir));
std::ofstream ofs(std::string(mTestDir + "test2.txt").c_str(), std::ofstream::out);
ofs << std::endl;
ofs.close();
}
virtual void TearDown()
{
boost::filesystem::remove_all(boost::filesystem::path(mTestDir));
}
std::string mTestDir;
};
TEST_F(SearchTest, file_not_found)
{
struct Result : public FileFinder::ReturnPath
{
Result(const boost::filesystem::path& expectedPath)
: mExpectedPath(expectedPath)
{
}
void add(const boost::filesystem::path& p)
{
ASSERT_FALSE(p == mExpectedPath);
}
private:
boost::filesystem::path mExpectedPath;
} r(boost::filesystem::path(mTestDir + "test.txt"));
FileFinder::find(mTestDir, r, false);
}
TEST_F(SearchTest, file_found)
{
struct Result : public FileFinder::ReturnPath
{
Result(const boost::filesystem::path& expectedPath)
: mExpectedPath(expectedPath)
{
}
void add(const boost::filesystem::path& p)
{
ASSERT_TRUE(p == mExpectedPath);
}
private:
boost::filesystem::path mExpectedPath;
} r(boost::filesystem::path(mTestDir + "test2.txt"));
FileFinder::find(mTestDir, r, false);
}

View file

@ -0,0 +1,33 @@
#include <gtest/gtest.h>
#include "components/misc/slice_array.hpp"
struct SliceArrayTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
}
virtual void TearDown()
{
}
};
TEST_F(SliceArrayTest, hello_string)
{
Misc::SString s("hello");
ASSERT_EQ(sizeof("hello") - 1, s.length);
ASSERT_FALSE(s=="hel");
ASSERT_FALSE(s=="hell");
ASSERT_TRUE(s=="hello");
}
TEST_F(SliceArrayTest, othello_string_with_offset_2_and_size_4)
{
Misc::SString s("othello" + 2, 4);
ASSERT_EQ(sizeof("hell") - 1, s.length);
ASSERT_FALSE(s=="hel");
ASSERT_TRUE(s=="hell");
ASSERT_FALSE(s=="hello");
}

View file

@ -1,7 +1,79 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "components/misc/stringops.hpp"
TEST(simple_test, dummy) struct StringOpsTest : public ::testing::Test
{ {
EXPECT_EQ(true, true); protected:
virtual void SetUp()
{
}
virtual void TearDown()
{
}
};
TEST_F(StringOpsTest, begins_matching)
{
ASSERT_TRUE(Misc::begins("abc", "a"));
ASSERT_TRUE(Misc::begins("abc", "ab"));
ASSERT_TRUE(Misc::begins("abc", "abc"));
ASSERT_TRUE(Misc::begins("abcd", "abc"));
}
TEST_F(StringOpsTest, begins_not_matching)
{
ASSERT_FALSE(Misc::begins("abc", "b"));
ASSERT_FALSE(Misc::begins("abc", "bc"));
ASSERT_FALSE(Misc::begins("abc", "bcd"));
ASSERT_FALSE(Misc::begins("abc", "abcd"));
}
TEST_F(StringOpsTest, ibegins_matching)
{
ASSERT_TRUE(Misc::ibegins("Abc", "a"));
ASSERT_TRUE(Misc::ibegins("aBc", "ab"));
ASSERT_TRUE(Misc::ibegins("abC", "abc"));
ASSERT_TRUE(Misc::ibegins("abcD", "abc"));
}
TEST_F(StringOpsTest, ibegins_not_matching)
{
ASSERT_FALSE(Misc::ibegins("abc", "b"));
ASSERT_FALSE(Misc::ibegins("abc", "bc"));
ASSERT_FALSE(Misc::ibegins("abc", "bcd"));
ASSERT_FALSE(Misc::ibegins("abc", "abcd"));
}
TEST_F(StringOpsTest, ends_matching)
{
ASSERT_TRUE(Misc::ends("abc", "c"));
ASSERT_TRUE(Misc::ends("abc", "bc"));
ASSERT_TRUE(Misc::ends("abc", "abc"));
ASSERT_TRUE(Misc::ends("abcd", "abcd"));
}
TEST_F(StringOpsTest, ends_not_matching)
{
ASSERT_FALSE(Misc::ends("abc", "b"));
ASSERT_FALSE(Misc::ends("abc", "ab"));
ASSERT_FALSE(Misc::ends("abc", "bcd"));
ASSERT_FALSE(Misc::ends("abc", "abcd"));
}
TEST_F(StringOpsTest, iends_matching)
{
ASSERT_TRUE(Misc::iends("Abc", "c"));
ASSERT_TRUE(Misc::iends("aBc", "bc"));
ASSERT_TRUE(Misc::iends("abC", "abc"));
ASSERT_TRUE(Misc::iends("abcD", "abcd"));
}
TEST_F(StringOpsTest, iends_not_matching)
{
ASSERT_FALSE(Misc::iends("abc", "b"));
ASSERT_FALSE(Misc::iends("abc", "ab"));
ASSERT_FALSE(Misc::iends("abc", "bcd"));
ASSERT_FALSE(Misc::iends("abc", "abcd"));
} }

View file

@ -5,8 +5,8 @@
int main(int argc, char** argv) { int main(int argc, char** argv) {
// The following line causes Google Mock to throw an exception on failure, // The following line causes Google Mock to throw an exception on failure,
// which will be interpreted by your testing framework as a test failure. // which will be interpreted by your testing framework as a test failure.
::testing::GTEST_FLAG(throw_on_failure) = true; ::testing::GTEST_FLAG(throw_on_failure) = false;
::testing::InitGoogleMock(&argc, argv); ::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }

View file

@ -4,10 +4,8 @@
#include <SDL_types.h> #include <SDL_types.h>
#include <string> #include <string>
namespace Ogre #include <OgreTexture.h>
{ #include <OgrePrerequisites.h>
class TexturePtr;
}
namespace SFO namespace SFO
{ {

View file

@ -104,6 +104,20 @@ BulletShapeManager::~BulletShapeManager()
sThis = 0; sThis = 0;
} }
#if (OGRE_VERSION >= ((1 << 16) | (9 << 8) | 0))
BulletShapePtr BulletShapeManager::getByName(const Ogre::String& name, const Ogre::String& groupName)
{
return getResourceByName(name, groupName).staticCast<BulletShape>();
}
BulletShapePtr BulletShapeManager::create (const Ogre::String& name, const Ogre::String& group,
bool isManual, Ogre::ManualResourceLoader* loader,
const Ogre::NameValuePairList* createParams)
{
return createResource(name,group,isManual,loader,createParams).staticCast<BulletShape>();
}
#endif
BulletShapePtr BulletShapeManager::load(const Ogre::String &name, const Ogre::String &group) BulletShapePtr BulletShapeManager::load(const Ogre::String &name, const Ogre::String &group)
{ {
BulletShapePtr textf = getByName(name); BulletShapePtr textf = getByName(name);

View file

@ -48,6 +48,8 @@ public:
/** /**
* *
*/ */
#if (OGRE_VERSION < ((1 << 16) | (9 << 8) | 0))
class BulletShapePtr : public Ogre::SharedPtr<BulletShape> class BulletShapePtr : public Ogre::SharedPtr<BulletShape>
{ {
public: public:
@ -91,9 +93,9 @@ public:
return *this; return *this;
} }
}; };
#else
typedef Ogre::SharedPtr<BulletShape> BulletShapePtr;
#endif
/** /**
*Hold any BulletShape that was created by the ManualBulletShapeLoader. *Hold any BulletShape that was created by the ManualBulletShapeLoader.
@ -137,6 +139,19 @@ public:
BulletShapeManager(); BulletShapeManager();
virtual ~BulletShapeManager(); virtual ~BulletShapeManager();
#if (OGRE_VERSION >= ((1 << 16) | (9 << 8) | 0))
/// Get a resource by name
/// @see ResourceManager::getByName
BulletShapePtr getByName(const Ogre::String& name, const Ogre::String& groupName = Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
/// Create a new shape
/// @see ResourceManager::createResource
BulletShapePtr create (const Ogre::String& name, const Ogre::String& group,
bool isManual = false, Ogre::ManualResourceLoader* loader = 0,
const Ogre::NameValuePairList* createParams = 0);
#endif
virtual BulletShapePtr load(const Ogre::String &name, const Ogre::String &group); virtual BulletShapePtr load(const Ogre::String &name, const Ogre::String &group);
static BulletShapeManager &getSingleton(); static BulletShapeManager &getSingleton();

View file

@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind
OpenMW is an attempt at recreating the engine for the popular role-playing game OpenMW is an attempt at recreating the engine for the popular role-playing game
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
Version: 0.25.0 Version: 0.26.0
License: GPL (see GPL3.txt for more information) License: GPL (see GPL3.txt for more information)
Website: http://www.openmw.org Website: http://www.openmw.org
@ -71,13 +71,13 @@ Allowed options:
--new-game [=arg(=1)] (=0) activate char gen/new game mechanics --new-game [=arg(=1)] (=0) activate char gen/new game mechanics
--fs-strict [=arg(=1)] (=0) strict file system handling (no case folding) --fs-strict [=arg(=1)] (=0) strict file system handling (no case folding)
--encoding arg (=win1252) Character encoding used in OpenMW game messages: --encoding arg (=win1252) Character encoding used in OpenMW game messages:
win1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages win1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages
win1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages win1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages
win1252 - Western European (Latin) alphabet, used by default win1252 - Western European (Latin) alphabet, used by default
--fallback arg fallback values --fallback arg fallback values
CHANGELOG CHANGELOG