Commit 2616e60e authored by rogerborg's avatar rogerborg

https://sourceforge.net/tracker2/?func=detail&aid=2473523&group_id=74339&atid=540676

Fix bug in dimension2d::operator+=.  Add operator-= and have operator == use core::equals() while I'm in there.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1984 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 2a3eb2c2
// Copyright (C) 2002-2008 Nikolaus Gebhardt // Copyright (C) 2002-2008 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h // For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_DIMENSION2D_H_INCLUDED__ #ifndef __IRR_DIMENSION2D_H_INCLUDED__
#define __IRR_DIMENSION2D_H_INCLUDED__ #define __IRR_DIMENSION2D_H_INCLUDED__
#include "irrTypes.h" #include "irrTypes.h"
#include "irrMath.h" // for irr::core::equals()
namespace irr
{ namespace irr
namespace core {
{ namespace core
{
//! Specifies a 2 dimensional size.
template <class T> //! Specifies a 2 dimensional size.
class dimension2d template <class T>
{ class dimension2d
public: {
//! Default constructor for empty dimension public:
dimension2d() : Width(0), Height(0) {} //! Default constructor for empty dimension
//! Constructor with width and height dimension2d() : Width(0), Height(0) {}
dimension2d(const T& width, const T& height) //! Constructor with width and height
: Width(width), Height(height) {} dimension2d(const T& width, const T& height)
: Width(width), Height(height) {}
//! Equality operator
bool operator==(const dimension2d<T>& other) const //! Equality operator
{ bool operator==(const dimension2d<T>& other) const
return Width == other.Width && Height == other.Height; {
} return core::equals(Width, other.Width) &&
core::equals(Height, other.Height);
//! Inequality operator }
bool operator!=(const dimension2d<T>& other) const
{ //! Inequality operator
return ! (*this == other); bool operator!=(const dimension2d<T>& other) const
} {
return ! (*this == other);
}
//! Set to new values
dimension2d<T>& set(const T& width, const T& height)
{ //! Set to new values
Width = width; dimension2d<T>& set(const T& width, const T& height)
Height = height; {
return *this; Width = width;
} Height = height;
return *this;
//! Divide width and height by scalar }
dimension2d<T>& operator/=(const T& scale)
{ //! Divide width and height by scalar
Width /= scale; dimension2d<T>& operator/=(const T& scale)
Height /= scale; {
return *this; Width /= scale;
} Height /= scale;
return *this;
//! Divide width and height by scalar }
dimension2d<T> operator/(const T& scale) const
{ //! Divide width and height by scalar
return dimension2d<T>(Width/scale, Height/scale); dimension2d<T> operator/(const T& scale) const
} {
return dimension2d<T>(Width/scale, Height/scale);
//! Multiply width and height by scalar }
dimension2d<T>& operator*=(const T& scale)
{ //! Multiply width and height by scalar
Width *= scale; dimension2d<T>& operator*=(const T& scale)
Height *= scale; {
return *this; Width *= scale;
} Height *= scale;
return *this;
//! Multiply width and height by scalar }
dimension2d<T> operator*(const T& scale) const
{ //! Multiply width and height by scalar
return dimension2d<T>(Width*scale, Height*scale); dimension2d<T> operator*(const T& scale) const
} {
return dimension2d<T>(Width*scale, Height*scale);
//! Add two dimensions }
dimension2d<T>& operator+=(const dimension2d<T>& other)
{ //! Add another dimension to this one.
Width *= other.Width; dimension2d<T>& operator+=(const dimension2d<T>& other)
Height *= other.Height; {
return *this; Width += other.Width;
} Height += other.Height;
return *this;
//! Add two dimensions }
dimension2d<T> operator+(const dimension2d<T>& other) const
{ //! Subtract a dimension from this one
return dimension2d<T>(Width+other.Width, Height+other.Height); dimension2d<T>& operator-=(const dimension2d<T>& other)
} {
Width -= other.Width;
//! Get area Height -= other.Height;
T getArea() const return *this;
{ }
return Width*Height;
}
//! Add two dimensions
//! Get the optimal size according to some properties dimension2d<T> operator+(const dimension2d<T>& other) const
/** This is a function often used for texture dimension {
calculations. The function returns the next larger or return dimension2d<T>(Width+other.Width, Height+other.Height);
smaller dimension which is a power-of-two dimension }
(2^n,2^m) and/or square (Width=Height).
\param requirePowerOfTwo Forces the result to use only //! Get area
powers of two as values. T getArea() const
\param requireSquare Makes width==height in the result {
\param larger Choose whether the result is larger or return Width*Height;
smaller than the current dimension. If one dimension }
need not be changed it is kept with any value of larger.
\return The optimal dimension under the given //! Get the optimal size according to some properties
constraints. */ /** This is a function often used for texture dimension
dimension2d<T> getOptimalSize( calculations. The function returns the next larger or
bool requirePowerOfTwo=true, smaller dimension which is a power-of-two dimension
bool requireSquare=false, (2^n,2^m) and/or square (Width=Height).
bool larger=true) const \param requirePowerOfTwo Forces the result to use only
{ powers of two as values.
u32 i=1; \param requireSquare Makes width==height in the result
u32 j=1; \param larger Choose whether the result is larger or
if (requirePowerOfTwo) smaller than the current dimension. If one dimension
{ need not be changed it is kept with any value of larger.
while (i<(u32)Width) \return The optimal dimension under the given
i<<=1; constraints. */
if (!larger && i!=1 && i!=(u32)Width) dimension2d<T> getOptimalSize(
i>>=1; bool requirePowerOfTwo=true,
while (j<(u32)Height) bool requireSquare=false,
j<<=1; bool larger=true) const
if (!larger && j!=1 && j!=(u32)Height) {
j>>=1; u32 i=1;
} u32 j=1;
else if (requirePowerOfTwo)
{ {
i=(u32)Width; while (i<(u32)Width)
j=(u32)Height; i<<=1;
} if (!larger && i!=1 && i!=(u32)Width)
i>>=1;
if (requireSquare) while (j<(u32)Height)
{ j<<=1;
if ((larger && (i>j)) || (!larger && (i<j))) if (!larger && j!=1 && j!=(u32)Height)
j=i; j>>=1;
else }
i=j; else
} {
return dimension2d<T>((T)i,(T)j); i=(u32)Width;
} j=(u32)Height;
}
//! Get the interpolated dimension
/** \param other Other dimension to interpolate with. if (requireSquare)
\param d Value between 0.0f and 1.0f. {
\return Interpolated dimension. */ if ((larger && (i>j)) || (!larger && (i<j)))
dimension2d<T> getInterpolated(const dimension2d<T>& other, f32 d) const j=i;
{ else
T inv = (T) (1.0f - d); i=j;
return dimension2d<T>(other.Width*inv + Width*d, other.Height*inv + Height*d); }
} return dimension2d<T>((T)i,(T)j);
}
//! Width of the dimension. //! Get the interpolated dimension
T Width; /** \param other Other dimension to interpolate with.
//! Height of the dimension. \param d Value between 0.0f and 1.0f.
T Height; \return Interpolated dimension. */
}; dimension2d<T> getInterpolated(const dimension2d<T>& other, f32 d) const
{
//! Typedef for an f32 dimension. T inv = (T) (1.0f - d);
typedef dimension2d<f32> dimension2df; return dimension2d<T>(other.Width*inv + Width*d, other.Height*inv + Height*d);
//! Typedef for an integer dimension. }
typedef dimension2d<s32> dimension2di;
} // end namespace core //! Width of the dimension.
} // end namespace irr T Width;
//! Height of the dimension.
#endif T Height;
};
//! Typedef for an f32 dimension.
typedef dimension2d<f32> dimension2df;
//! Typedef for an integer dimension.
typedef dimension2d<s32> dimension2di;
} // end namespace core
} // end namespace irr
#endif
// This is the entry point for the Irrlicht test suite. // This is the entry point for the Irrlicht test suite.
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#include "testUtils.h" #include "testUtils.h"
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
#include <vector> #include <vector>
// This is an MSVC pragma to link against the Irrlicht library. // This is an MSVC pragma to link against the Irrlicht library.
// Other builds must link against it in the project files. // Other builds must link against it in the project files.
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma comment(lib, "Irrlicht.lib") #pragma comment(lib, "Irrlicht.lib")
#endif // _MSC_VER #endif // _MSC_VER
typedef struct _STestDefinition typedef struct _STestDefinition
{ {
bool(*testSignature)(void); bool(*testSignature)(void);
const char * testName; const char * testName;
} STestDefinition; } STestDefinition;
//! This is the main entry point for the Irrlicht test suite. //! This is the main entry point for the Irrlicht test suite.
/** \return The number of test that failed, i.e. 0 is success. */ /** \return The number of test that failed, i.e. 0 is success. */
int main(int argumentCount, char * arguments[]) int main(int argumentCount, char * arguments[])
{ {
bool logFileOpened = openTestLog(1 == argumentCount); bool logFileOpened = openTestLog(1 == argumentCount);
assert(logFileOpened); assert(logFileOpened);
if(argumentCount > 3) if(argumentCount > 3)
{ {
logTestString("\nUsage: %s [testNumber] [totalFails]\n"); logTestString("\nUsage: %s [testNumber] [totalFails]\n");
closeTestLog(); closeTestLog();
return 9999; return 9999;
} }
#define TEST(x)\ #define TEST(x)\
{\ {\
extern bool x(void);\ extern bool x(void);\
STestDefinition newTest;\ STestDefinition newTest;\
newTest.testSignature = x;\ newTest.testSignature = x;\
newTest.testName = #x;\ newTest.testName = #x;\
tests.push_back(newTest);\ tests.push_back(newTest);\
} }
std::vector<STestDefinition> tests; std::vector<STestDefinition> tests;
// Note that to interactively debug a test, you will generally want to move it // Note that to interactively debug a test, you will generally want to move it
// (temporarily) to the beginning of the list, since each test runs in its own // (temporarily) to the beginning of the list, since each test runs in its own
// process. // process.
TEST(disambiguateTextures); // Normally you should run this first, since it validates the working directory. TEST(disambiguateTextures); // Normally you should run this first, since it validates the working directory.
TEST(sceneNodeAnimator); TEST(sceneNodeAnimator);
TEST(sceneCollisionManager); TEST(sceneCollisionManager);
TEST(collisionResponseAnimator); TEST(collisionResponseAnimator);
TEST(exports); TEST(exports);
TEST(testVector3d); TEST(testVector3d);
TEST(testVector2d); TEST(testVector2d);
TEST(planeMatrix); TEST(planeMatrix);
TEST(fast_atof); TEST(fast_atof);
TEST(line2dIntersectWith); TEST(line2dIntersectWith);
TEST(drawPixel); TEST(testDimension2d);
TEST(md2Animation); TEST(drawPixel);
TEST(guiDisabledMenu); TEST(md2Animation);
TEST(softwareDevice); TEST(guiDisabledMenu);
TEST(b3dAnimation); TEST(softwareDevice);
TEST(b3dAnimation);
const unsigned int numberOfTests = tests.size();
const unsigned int numberOfTests = tests.size();
unsigned int testToRun = 0;
unsigned int fails = 0; unsigned int testToRun = 0;
unsigned int fails = 0;
if(argumentCount > 1)
{ if(argumentCount > 1)
testToRun = (unsigned int)atoi(arguments[1]); {
if(testToRun >= numberOfTests) testToRun = (unsigned int)atoi(arguments[1]);
{ if(testToRun >= numberOfTests)
logTestString("\nError: invalid test %d (maximum %d)\n", {
testToRun, numberOfTests - 1); logTestString("\nError: invalid test %d (maximum %d)\n",
closeTestLog(); testToRun, numberOfTests - 1);
return 9999; closeTestLog();
} return 9999;
} }
}
if(argumentCount > 2)
fails = (unsigned int)atoi(arguments[2]); if(argumentCount > 2)
fails = (unsigned int)atoi(arguments[2]);
logTestString("\nStarting test %d, '%s'\n",
testToRun, tests[testToRun].testName); logTestString("\nStarting test %d, '%s'\n",
testToRun, tests[testToRun].testName);
bool success = tests[testToRun].testSignature();
bool success = tests[testToRun].testSignature();
if(!success)
{ if(!success)
logTestString("\n\n\n******** Test failure ********\nTest %d '%s' failed\n"\ {
"******** Test failure ********\n", logTestString("\n\n\n******** Test failure ********\nTest %d '%s' failed\n"\
testToRun, tests[testToRun].testName); "******** Test failure ********\n",
fails++; testToRun, tests[testToRun].testName);
} fails++;
}
testToRun++;
if(testToRun < numberOfTests) testToRun++;
{ if(testToRun < numberOfTests)
closeTestLog(); {
char runNextTest[256]; closeTestLog();
(void)sprintf(runNextTest, "%s %d %d", arguments[0], testToRun, fails); char runNextTest[256];
fails = system(runNextTest); (void)sprintf(runNextTest, "%s %d %d", arguments[0], testToRun, fails);
} fails = system(runNextTest);
}
if(1 == testToRun)
{ if(1 == testToRun)
(void)openTestLog(false); {
const int passed = numberOfTests - fails; (void)openTestLog(false);
const int passed = numberOfTests - fails;
logTestString("\nTests finished. %d test%s of %d passed.\n",
passed, 1 == passed ? "" : "s", numberOfTests); logTestString("\nTests finished. %d test%s of %d passed.\n",
passed, 1 == passed ? "" : "s", numberOfTests);
if(0 == fails)
{ if(0 == fails)
time_t rawtime; {
struct tm * timeinfo; time_t rawtime;
(void)time(&rawtime); struct tm * timeinfo;
timeinfo = gmtime(&rawtime); (void)time(&rawtime);
(void)printf("\nTest suite pass at GMT %s\n", asctime(timeinfo)); timeinfo = gmtime(&rawtime);
FILE * testsLastPassedAtFile = fopen("tests-last-passed-at.txt", "w"); (void)printf("\nTest suite pass at GMT %s\n", asctime(timeinfo));
if(testsLastPassedAtFile) FILE * testsLastPassedAtFile = fopen("tests-last-passed-at.txt", "w");
{ if(testsLastPassedAtFile)
(void)fprintf(testsLastPassedAtFile, "Test suite pass at GMT %s\n", asctime(timeinfo)); {
(void)fclose(testsLastPassedAtFile); (void)fprintf(testsLastPassedAtFile, "Test suite pass at GMT %s\n", asctime(timeinfo));
} (void)fclose(testsLastPassedAtFile);
} }
closeTestLog(); }
} closeTestLog();
}
return fails;
} return fails;
}
// Copyright (C) 2008 Colin MacDonald
// No rights reserved: this software is in the public domain.
#include "testUtils.h"
#include "irrlicht.h"
#include <assert.h>
using namespace irr;
using namespace core;
/** Some very basic testing of dimension2df:
operator+=
operator!= (and thus implicitly operator==) */
bool testDimension2d(void)
{
dimension2df dimension(100.f, 100.f);
const dimension2df addDimension(200.f, -200.f);
(void)(dimension += addDimension);
if(dimension != dimension2df(300.f, -100.f))
{
logTestString("dimension2df != produced unexpected result.\n");
assert(false);
return false;
}
(void)(dimension -= addDimension);
if(dimension != dimension2df(100.f, 100.f))
{
logTestString("dimension2df -= produced unexpected result.\n");
assert(false);
return false;
}
return true;
}
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
<Unit filename="sceneCollisionManager.cpp" /> <Unit filename="sceneCollisionManager.cpp" />
<Unit filename="sceneNodeAnimator.cpp" /> <Unit filename="sceneNodeAnimator.cpp" />
<Unit filename="softwareDevice.cpp" /> <Unit filename="softwareDevice.cpp" />
<Unit filename="testDimension2d.cpp" />
<Unit filename="testUtils.cpp" /> <Unit filename="testUtils.cpp" />
<Unit filename="testVector2d.cpp" /> <Unit filename="testVector2d.cpp" />
<Unit filename="testVector3d.cpp" /> <Unit filename="testVector3d.cpp" />
......
...@@ -225,6 +225,10 @@ ...@@ -225,6 +225,10 @@
RelativePath=".\softwareDevice.cpp" RelativePath=".\softwareDevice.cpp"
> >
</File> </File>
<File
RelativePath=".\testDimension2d.cpp"
>
</File>
<File <File
RelativePath=".\testUtils.cpp" RelativePath=".\testUtils.cpp"
> >
......
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
...@@ -221,6 +222,10 @@ ...@@ -221,6 +222,10 @@
RelativePath=".\softwareDevice.cpp" RelativePath=".\softwareDevice.cpp"
> >
</File> </File>
<File
RelativePath=".\testDimension2d.cpp"
>
</File>
<File <File
RelativePath=".\testUtils.cpp" RelativePath=".\testUtils.cpp"
> >
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment