Reformat the code, using:

find -type f |  # list all regular files
  grep -E '\.(h|cpp|mm)$' |  # filter for source files
  grep -v '/mt_' |  # filter out generated files
  grep -v '/vendor/' | # and vendored GL
  grep -v '/test/image_loader_test.cpp' |  # and this file (has giant literals arrays)
  xargs -n 1 -P $(nproc) clang-format -i  # reformat everything

Co-authored-by: numzero <numzer0@yandex.ru>
This commit is contained in:
Desour
2024-03-20 19:35:52 +01:00
committed by sfan5
parent 9814510b1b
commit f5c6d3e945
292 changed files with 37376 additions and 42421 deletions

View File

@ -2,15 +2,13 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CAndroidAssetReader.h"
#include "CReadFile.h"
#include "coreutil.h"
#include "CAndroidAssetFileArchive.h"
#include "CIrrDeviceAndroid.h"
#include "os.h" // for logging (just keep it in even when not needed right now as it's used all the time)
#include "os.h" // for logging (just keep it in even when not needed right now as it's used all the time)
#include <android_native_app_glue.h>
#include <android/native_activity.h>
@ -21,82 +19,78 @@ namespace irr
namespace io
{
CAndroidAssetFileArchive::CAndroidAssetFileArchive(AAssetManager *assetManager, bool ignoreCase, bool ignorePaths)
: CFileList("/asset", ignoreCase, ignorePaths), AssetManager(assetManager)
CAndroidAssetFileArchive::CAndroidAssetFileArchive(AAssetManager *assetManager, bool ignoreCase, bool ignorePaths) :
CFileList("/asset", ignoreCase, ignorePaths), AssetManager(assetManager)
{
}
CAndroidAssetFileArchive::~CAndroidAssetFileArchive()
{
}
//! get the archive type
E_FILE_ARCHIVE_TYPE CAndroidAssetFileArchive::getType() const
{
return EFAT_ANDROID_ASSET;
}
const IFileList* CAndroidAssetFileArchive::getFileList() const
const IFileList *CAndroidAssetFileArchive::getFileList() const
{
// The assert_manager can not read directory names, so
// getFileList returns only files in folders which have been added.
return this;
// The assert_manager can not read directory names, so
// getFileList returns only files in folders which have been added.
return this;
}
//! opens a file by file name
IReadFile* CAndroidAssetFileArchive::createAndOpenFile(const io::path& filename)
IReadFile *CAndroidAssetFileArchive::createAndOpenFile(const io::path &filename)
{
CAndroidAssetReader *reader = new CAndroidAssetReader(AssetManager, filename);
CAndroidAssetReader *reader = new CAndroidAssetReader(AssetManager, filename);
if(reader->isOpen())
if (reader->isOpen())
return reader;
reader->drop();
return NULL;
return NULL;
}
//! opens a file by index
IReadFile* CAndroidAssetFileArchive::createAndOpenFile(u32 index)
IReadFile *CAndroidAssetFileArchive::createAndOpenFile(u32 index)
{
const io::path& filename(getFullFileName(index));
if ( filename.empty() )
const io::path &filename(getFullFileName(index));
if (filename.empty())
return 0;
return createAndOpenFile(filename);
return createAndOpenFile(filename);
}
void CAndroidAssetFileArchive::addDirectoryToFileList(const io::path &dirname_)
{
io::path dirname(dirname_);
fschar_t lastChar = dirname.lastChar();
if ( lastChar == '/' || lastChar == '\\' )
dirname.erase(dirname.size()-1);
if (lastChar == '/' || lastChar == '\\')
dirname.erase(dirname.size() - 1);
// os::Printer::log("addDirectoryToFileList:", dirname.c_str(), ELL_DEBUG);
if (findFile(dirname, true) >= 0 )
return; // was already added
if (findFile(dirname, true) >= 0)
return; // was already added
AAssetDir *dir = AAssetManager_openDir(AssetManager, core::stringc(dirname).c_str());
if(!dir)
if (!dir)
return;
// add directory itself
addItem(dirname, 0, 0, /*isDir*/true, getFileCount());
addItem(dirname, 0, 0, /*isDir*/ true, getFileCount());
// add all files in folder.
// Note: AAssetDir_getNextFileName does not return directory names (neither does any other NDK function)
while(const char *filename = AAssetDir_getNextFileName(dir))
{
core::stringc full_filename= dirname=="" ? filename
: dirname+"/"+filename;
while (const char *filename = AAssetDir_getNextFileName(dir)) {
core::stringc full_filename = dirname == "" ? filename
: dirname + "/" + filename;
// We can't get the size without opening the file - so for performance
// reasons we set the file size to 0.
// TODO: Does this really cost so much performance that it's worth losing this information? Dirs are usually just added once at startup...
addItem(full_filename, /*offet*/0, /*size*/0, /*isDir*/false, getFileCount());
addItem(full_filename, /*offet*/ 0, /*size*/ 0, /*isDir*/ false, getFileCount());
// os::Printer::log("addItem:", full_filename.c_str(), ELL_DEBUG);
}
AAssetDir_close(dir);
@ -104,4 +98,3 @@ void CAndroidAssetFileArchive::addDirectoryToFileList(const io::path &dirname_)
} // end namespace io
} // end namespace irr

View File

@ -18,43 +18,41 @@ namespace io
/*!
Android asset file system written August 2012 by J.Henrichs (later reworked by others).
*/
class CAndroidAssetFileArchive : public virtual IFileArchive,
virtual CFileList
{
public:
class CAndroidAssetFileArchive : public virtual IFileArchive,
virtual CFileList
{
public:
//! constructor
CAndroidAssetFileArchive(AAssetManager *assetManager, bool ignoreCase, bool ignorePaths);
//! constructor
CAndroidAssetFileArchive(AAssetManager *assetManager, bool ignoreCase, bool ignorePaths);
//! destructor
virtual ~CAndroidAssetFileArchive();
//! destructor
virtual ~CAndroidAssetFileArchive();
//! opens a file by file name
virtual IReadFile *createAndOpenFile(const io::path &filename);
//! opens a file by file name
virtual IReadFile* createAndOpenFile(const io::path& filename);
//! opens a file by index
virtual IReadFile *createAndOpenFile(u32 index);
//! opens a file by index
virtual IReadFile* createAndOpenFile(u32 index);
//! returns the list of files
virtual const IFileList *getFileList() const;
//! returns the list of files
virtual const IFileList* getFileList() const;
//! get the archive type
virtual E_FILE_ARCHIVE_TYPE getType() const;
//! get the archive type
virtual E_FILE_ARCHIVE_TYPE getType() const;
//! Add a directory to read files from. Since the Android
//! API does not return names of directories, they need to
//! be added manually.
virtual void addDirectoryToFileList(const io::path &filename);
//! Add a directory to read files from. Since the Android
//! API does not return names of directories, they need to
//! be added manually.
virtual void addDirectoryToFileList(const io::path &filename);
//! return the name (id) of the file Archive
const io::path &getArchiveName() const override { return Path; }
//! return the name (id) of the file Archive
const io::path& getArchiveName() const override {return Path;}
protected:
//! Android's asset manager
AAssetManager *AssetManager;
protected:
//! Android's asset manager
AAssetManager *AssetManager;
}; // CAndroidAssetFileArchive
}; // CAndroidAssetFileArchive
} // end namespace io
} // end namespace irr

View File

@ -17,34 +17,33 @@ namespace irr
namespace io
{
CAndroidAssetReader::CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename)
: AssetManager(assetManager), Filename(filename)
CAndroidAssetReader::CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename) :
AssetManager(assetManager), Filename(filename)
{
Asset = AAssetManager_open(AssetManager,
core::stringc(filename).c_str(),
AASSET_MODE_RANDOM);
core::stringc(filename).c_str(),
AASSET_MODE_RANDOM);
}
CAndroidAssetReader::~CAndroidAssetReader()
{
if(Asset)
if (Asset)
AAsset_close(Asset);
}
size_t CAndroidAssetReader::read(void* buffer, size_t sizeToRead)
size_t CAndroidAssetReader::read(void *buffer, size_t sizeToRead)
{
int readBytes = AAsset_read(Asset, buffer, sizeToRead);
if ( readBytes >= 0 )
if (readBytes >= 0)
return size_t(readBytes);
return 0; // direct fd access is not possible (for example, if the asset is compressed).
return 0; // direct fd access is not possible (for example, if the asset is compressed).
}
bool CAndroidAssetReader::seek(long finalPos, bool relativeMovement)
{
off_t status = AAsset_seek(Asset, finalPos, relativeMovement ? SEEK_CUR : SEEK_SET);
off_t status = AAsset_seek(Asset, finalPos, relativeMovement ? SEEK_CUR : SEEK_SET);
return status+1;
return status + 1;
}
long CAndroidAssetReader::getSize() const
@ -57,12 +56,10 @@ long CAndroidAssetReader::getPos() const
return AAsset_getLength(Asset) - AAsset_getRemainingLength(Asset);
}
const io::path& CAndroidAssetReader::getFileName() const
const io::path &CAndroidAssetReader::getFileName() const
{
return Filename;
}
} // end namespace io
} // end namespace irr

View File

@ -15,51 +15,50 @@ namespace irr
namespace io
{
class CAndroidAssetReader : public virtual IReadFile
{
public:
CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename);
class CAndroidAssetReader : public virtual IReadFile
{
public:
CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename);
virtual ~CAndroidAssetReader();
virtual ~CAndroidAssetReader();
//! Reads an amount of bytes from the file.
/** \param buffer Pointer to buffer where read bytes are written to.
\param sizeToRead Amount of bytes to read from the file.
\return How many bytes were read. */
virtual size_t read(void* buffer, size_t sizeToRead);
//! Reads an amount of bytes from the file.
/** \param buffer Pointer to buffer where read bytes are written to.
\param sizeToRead Amount of bytes to read from the file.
\return How many bytes were read. */
virtual size_t read(void *buffer, size_t sizeToRead);
//! Changes position in file
/** \param finalPos Destination position in the file.
\param relativeMovement If set to true, the position in the file is
changed relative to current position. Otherwise the position is changed
from beginning of file.
\return True if successful, otherwise false. */
virtual bool seek(long finalPos, bool relativeMovement = false);
//! Changes position in file
/** \param finalPos Destination position in the file.
\param relativeMovement If set to true, the position in the file is
changed relative to current position. Otherwise the position is changed
from beginning of file.
\return True if successful, otherwise false. */
virtual bool seek(long finalPos, bool relativeMovement = false);
//! Get size of file.
/** \return Size of the file in bytes. */
virtual long getSize() const;
//! Get size of file.
/** \return Size of the file in bytes. */
virtual long getSize() const;
//! Get the current position in the file.
/** \return Current position in the file in bytes. */
virtual long getPos() const;
//! Get the current position in the file.
/** \return Current position in the file in bytes. */
virtual long getPos() const;
//! Get name of file.
/** \return File name as zero terminated character string. */
virtual const io::path& getFileName() const;
//! Get name of file.
/** \return File name as zero terminated character string. */
virtual const io::path &getFileName() const;
/** Return true if the file could be opened. */
bool isOpen() const { return Asset!=NULL; }
/** Return true if the file could be opened. */
bool isOpen() const { return Asset != NULL; }
private:
//! Android's asset manager
AAssetManager *AssetManager;
private:
//! Android's asset manager
AAssetManager *AssetManager;
// An asset, i.e. file
AAsset *Asset;
path Filename;
};
// An asset, i.e. file
AAsset *Asset;
path Filename;
};
} // end namespace io
} // end namespace irr

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,6 @@
#pragma once
#include "CIrrDeviceStub.h"
#include "IrrlichtDevice.h"
#include "ICursorControl.h"
@ -15,88 +13,86 @@
namespace irr
{
class CIrrDeviceAndroid : public CIrrDeviceStub
{
public:
CIrrDeviceAndroid(const SIrrlichtCreationParameters& param);
class CIrrDeviceAndroid : public CIrrDeviceStub
{
public:
CIrrDeviceAndroid(const SIrrlichtCreationParameters &param);
virtual ~CIrrDeviceAndroid();
virtual ~CIrrDeviceAndroid();
virtual bool run();
virtual bool run();
virtual void yield();
virtual void yield();
virtual void sleep(u32 timeMs, bool pauseTimer = false);
virtual void sleep(u32 timeMs, bool pauseTimer = false);
virtual void setWindowCaption(const wchar_t* text);
virtual void setWindowCaption(const wchar_t *text);
virtual bool isWindowActive() const;
virtual bool isWindowActive() const;
virtual bool isWindowFocused() const;
virtual bool isWindowFocused() const;
virtual bool isWindowMinimized() const;
virtual bool isWindowMinimized() const;
virtual bool isWindowVisible() const;
virtual bool isWindowVisible() const;
virtual void closeDevice();
virtual void closeDevice();
virtual void setResizable(bool resize = false);
virtual void setResizable(bool resize = false);
virtual void minimizeWindow();
virtual void minimizeWindow();
virtual void maximizeWindow();
virtual void maximizeWindow();
virtual void restoreWindow();
virtual void restoreWindow();
virtual core::position2di getWindowPosition();
virtual core::position2di getWindowPosition();
virtual E_DEVICE_TYPE getType() const;
virtual E_DEVICE_TYPE getType() const;
virtual bool activateAccelerometer(float updateInterval);
virtual bool activateAccelerometer(float updateInterval);
virtual bool deactivateAccelerometer();
virtual bool deactivateAccelerometer();
virtual bool isAccelerometerActive();
virtual bool isAccelerometerActive();
virtual bool isAccelerometerAvailable();
virtual bool isAccelerometerAvailable();
virtual bool activateGyroscope(float updateInterval);
virtual bool activateGyroscope(float updateInterval);
virtual bool deactivateGyroscope();
virtual bool deactivateGyroscope();
virtual bool isGyroscopeActive();
virtual bool isGyroscopeActive();
virtual bool isGyroscopeAvailable();
virtual bool isGyroscopeAvailable();
private:
private:
static void handleAndroidCommand(android_app *app, int32_t cmd);
static void handleAndroidCommand(android_app* app, int32_t cmd);
static s32 handleInput(android_app *app, AInputEvent *event);
static s32 handleInput(android_app* app, AInputEvent* event);
void createDriver();
void createDriver();
void createKeyMap();
void createKeyMap();
video::SExposedVideoData &getExposedVideoData();
video::SExposedVideoData& getExposedVideoData();
android_app *Android;
ASensorManager *SensorManager;
ASensorEventQueue *SensorEventQueue;
const ASensor *Accelerometer;
const ASensor *Gyroscope;
android_app* Android;
ASensorManager* SensorManager;
ASensorEventQueue* SensorEventQueue;
const ASensor* Accelerometer;
const ASensor* Gyroscope;
bool Initialized;
bool Stopped;
bool Paused;
bool Focused;
bool Initialized;
bool Stopped;
bool Paused;
bool Focused;
JNIEnv *JNIEnvAttachedToVM;
JNIEnv* JNIEnvAttachedToVM;
video::SExposedVideoData ExposedVideoData;
video::SExposedVideoData ExposedVideoData;
core::array<EKEY_CODE> KeyMap;
};
core::array<EKEY_CODE> KeyMap;
};
} // end namespace irr

View File

@ -14,18 +14,15 @@ jclass CKeyEventWrapper::Class_KeyEvent = 0;
jmethodID CKeyEventWrapper::Method_constructor = 0;
jmethodID CKeyEventWrapper::Method_getUnicodeChar = 0;
CKeyEventWrapper::CKeyEventWrapper(JNIEnv* jniEnv, int action, int code)
: JniEnv(jniEnv), JniKeyEvent(0)
CKeyEventWrapper::CKeyEventWrapper(JNIEnv *jniEnv, int action, int code) :
JniEnv(jniEnv), JniKeyEvent(0)
{
if ( JniEnv )
{
if (!Class_KeyEvent )
{
if (JniEnv) {
if (!Class_KeyEvent) {
// Find java classes & functions on first call
os::Printer::log("CKeyEventWrapper first initialize", ELL_DEBUG);
jclass localClass = JniEnv->FindClass("android/view/KeyEvent");
if (localClass)
{
if (localClass) {
Class_KeyEvent = reinterpret_cast<jclass>(JniEnv->NewGlobalRef(localClass));
}
@ -33,12 +30,9 @@ CKeyEventWrapper::CKeyEventWrapper(JNIEnv* jniEnv, int action, int code)
Method_getUnicodeChar = JniEnv->GetMethodID(Class_KeyEvent, "getUnicodeChar", "(I)I");
}
if ( Class_KeyEvent && Method_constructor )
{
if (Class_KeyEvent && Method_constructor) {
JniKeyEvent = JniEnv->NewObject(Class_KeyEvent, Method_constructor, action, code);
}
else
{
} else {
os::Printer::log("CKeyEventWrapper didn't find JNI classes/methods", ELL_WARNING);
}
}

View File

@ -18,7 +18,7 @@ namespace jni
class CKeyEventWrapper
{
public:
CKeyEventWrapper(JNIEnv* jniEnv, int action, int code);
CKeyEventWrapper(JNIEnv *jniEnv, int action, int code);
~CKeyEventWrapper();
int getUnicodeChar(int metaState);
@ -27,8 +27,8 @@ private:
static jclass Class_KeyEvent;
static jmethodID Method_getUnicodeChar;
static jmethodID Method_constructor;
JNIEnv* JniEnv;
jobject JniKeyEvent; // this object in java
JNIEnv *JniEnv;
jobject JniKeyEvent; // this object in java
};
} // namespace jni

View File

@ -12,125 +12,124 @@ namespace irr
namespace gui
{
const u8 BuiltInFontData[] =
{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
0x04, 0x03, 0x00, 0x00, 0x00, 0x31, 0x10, 0x7c, 0xf8, 0x00, 0x00, 0x00,
0x0f, 0x50, 0x4c, 0x54, 0x45, 0x18, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xc8, 0xc8, 0xae,
0x00, 0x00, 0x05, 0x11, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x62, 0x50,
0x06, 0xf0, 0x62, 0x06, 0xb6, 0xed, 0xf4, 0x3a, 0x0c, 0xff, 0xf1, 0xba,
0x00, 0xb9, 0x41, 0xde, 0x06, 0xd9, 0x7f, 0xba, 0x07, 0x98, 0x10, 0x6a,
0x1f, 0xd2, 0xe2, 0x9f, 0xa0, 0xf8, 0x74, 0xaa, 0x65, 0xc9, 0x32, 0x23,
0x39, 0xc4, 0xc1, 0xe9, 0xc5, 0x83, 0x0b, 0xd6, 0x58, 0x7d, 0xf4, 0xe9,
0xec, 0x6a, 0xac, 0x6b, 0xd5, 0xc7, 0x9e, 0xfc, 0x17, 0x62, 0x09, 0x09,
0x4c, 0x60, 0x59, 0x0b, 0x99, 0x0a, 0x6b, 0xde, 0xc1, 0x60, 0x62, 0x82,
0xd2, 0xc0, 0x00, 0x90, 0x58, 0x21, 0xc2, 0xc6, 0x02, 0xef, 0x00, 0x16,
0xc1, 0x2a, 0x2e, 0x46, 0x13, 0xb5, 0x0a, 0x00, 0x48, 0xc5, 0xef, 0x62,
0x63, 0xde, 0x00, 0xd4, 0x28, 0xea, 0xc7, 0x77, 0x8a, 0x82, 0x07, 0xa0,
0xcb, 0xe0, 0x0c, 0x80, 0x42, 0x41, 0x0b, 0x20, 0x83, 0xb0, 0xc1, 0xc2,
0x8d, 0x22, 0x46, 0x12, 0x13, 0x1c, 0xec, 0x5b, 0x05, 0x03, 0xd0, 0x9d,
0xc9, 0x00, 0xbc, 0x68, 0x21, 0x10, 0xa4, 0x01, 0xe8, 0x8a, 0x68, 0xb1,
0x24, 0x73, 0x88, 0x30, 0x2d, 0xc8, 0x98, 0x11, 0x66, 0x7e, 0x02, 0x7c,
0x26, 0x16, 0x6f, 0xc8, 0xf3, 0x0b, 0x9e, 0xd0, 0xf1, 0xb9, 0xfc, 0x3e,
0x9d, 0x3d, 0x79, 0xd2, 0x61, 0xf4, 0xeb, 0x4c, 0x7e, 0x2c, 0x6e, 0x0e,
0x41, 0x29, 0xab, 0x37, 0x53, 0xed, 0xf2, 0x46, 0xe3, 0x59, 0xfd, 0x53,
0x09, 0x28, 0x80, 0x51, 0x8c, 0xb2, 0x4c, 0x42, 0xca, 0xdc, 0x32, 0xb4,
0x26, 0xc8, 0xb2, 0x9a, 0x0f, 0xee, 0x2e, 0x8c, 0x29, 0x1d, 0xeb, 0xd4,
0x54, 0x3d, 0x00, 0x62, 0x03, 0x70, 0x93, 0xfb, 0x01, 0xdd, 0xa6, 0x52,
0xc2, 0xb8, 0x81, 0x98, 0x3a, 0x4a, 0x01, 0xca, 0x57, 0xdb, 0x92, 0xf0,
0x37, 0xe3, 0x0a, 0x26, 0x15, 0x0d, 0x0d, 0x80, 0x59, 0x2a, 0x8b, 0x1f,
0x01, 0xa6, 0x02, 0x50, 0x3f, 0xcd, 0x3f, 0xb6, 0xe0, 0xb6, 0x40, 0xbd,
0x60, 0x8a, 0x47, 0xb3, 0x66, 0xe6, 0xf3, 0x10, 0xa7, 0x7e, 0x8b, 0x9e,
0x65, 0x18, 0x4f, 0x01, 0xb1, 0x89, 0xc2, 0x7f, 0x2f, 0xe5, 0xe6, 0x10,
0xb4, 0xac, 0xde, 0x4d, 0xb5, 0xcb, 0xdf, 0x34, 0xde, 0x92, 0x1e, 0x1b,
0x73, 0x0f, 0xe7, 0xa0, 0x73, 0x9f, 0x26, 0x94, 0xcb, 0x75, 0x3e, 0x11,
0xdd, 0xfd, 0x40, 0x4f, 0x9b, 0x90, 0x7c, 0x7f, 0x85, 0x63, 0x45, 0x42,
0x30, 0x41, 0x1b, 0x71, 0x67, 0x8a, 0x98, 0x3d, 0x6b, 0x60, 0x07, 0x90,
0xc0, 0x86, 0x59, 0xb1, 0xa9, 0xbc, 0x06, 0x28, 0x11, 0xc4, 0x6c, 0x5c,
0x2e, 0x02, 0x3c, 0x8c, 0xa9, 0xc8, 0xc4, 0x1d, 0xdb, 0x82, 0x24, 0x12,
0xd0, 0x4b, 0x80, 0x2d, 0x3e, 0x52, 0x56, 0x96, 0xa7, 0x4d, 0xf0, 0xd1,
0x42, 0x37, 0xaa, 0x7f, 0xf5, 0x0e, 0x00, 0xdd, 0x01, 0x48, 0xf7, 0x06,
0x0c, 0xf1, 0x00, 0x4c, 0xe1, 0xc9, 0x09, 0x40, 0xf6, 0x16, 0xfe, 0x4d,
0x32, 0x7f, 0x31, 0x7f, 0x2f, 0x43, 0xca, 0xd1, 0x3a, 0x27, 0x9d, 0xfb,
0x34, 0xa1, 0x5c, 0xae, 0xd3, 0x7b, 0xc5, 0x30, 0xf3, 0x5a, 0xce, 0xa3,
0x0e, 0xa3, 0xcd, 0x68, 0x62, 0xc7, 0x46, 0xba, 0xc2, 0x9f, 0x88, 0x00,
0x3c, 0xef, 0x5d, 0xfe, 0x49, 0xe6, 0xf5, 0x69, 0x60, 0x1b, 0x7e, 0x02,
0xf0, 0x6b, 0x00, 0x97, 0xbd, 0x04, 0x85, 0xac, 0x98, 0xb0, 0x62, 0x42,
0x83, 0xc4, 0x32, 0x21, 0x78, 0xad, 0xb9, 0xa3, 0x9a, 0x5c, 0x68, 0x09,
0x17, 0x4d, 0x58, 0xc6, 0x52, 0x9d, 0xd1, 0x96, 0x35, 0x00, 0x6b, 0x3a,
0xdc, 0x2d, 0x00, 0x3b, 0x80, 0x5e, 0x00, 0x34, 0xdd, 0x18, 0x0d, 0x16,
0x5b, 0x05, 0x04, 0xa3, 0xdc, 0x01, 0x98, 0x16, 0xe6, 0x92, 0x56, 0x80,
0xa5, 0x1c, 0x2d, 0x54, 0xf4, 0xe2, 0xac, 0x8e, 0x84, 0x5b, 0x7c, 0x00,
0x46, 0xe4, 0x37, 0x00, 0xcc, 0x4d, 0x9e, 0xc3, 0xcc, 0x67, 0x2f, 0x15,
0x75, 0x46, 0xcb, 0xdc, 0x67, 0x4d, 0xc7, 0x46, 0xd6, 0x4a, 0x2f, 0x18,
0x6f, 0x6b, 0xb9, 0xff, 0x57, 0x4c, 0x16, 0x7e, 0x4b, 0xa9, 0x0c, 0x33,
0x3e, 0x01, 0x30, 0x42, 0xc3, 0xaf, 0xcf, 0x2a, 0x08, 0xa2, 0x8c, 0xfe,
0xac, 0x02, 0x41, 0xdc, 0x3e, 0xf8, 0x14, 0x40, 0x00, 0x9f, 0x56, 0x30,
0x34, 0x07, 0x63, 0xde, 0x95, 0x73, 0xdb, 0xa7, 0x00, 0xf7, 0xbb, 0xf2,
0xdb, 0x3a, 0xdc, 0x5f, 0xf3, 0xbe, 0x61, 0xfb, 0xf6, 0x5d, 0x5a, 0xa7,
0x84, 0x5d, 0xbc, 0xdd, 0x7f, 0x00, 0x36, 0x75, 0xcc, 0x25, 0x7e, 0x90,
0xe4, 0x8d, 0x76, 0x2c, 0xa1, 0x6c, 0xad, 0xcd, 0x09, 0xb3, 0x11, 0x07,
0xd0, 0x18, 0x70, 0x43, 0x9d, 0xa9, 0x11, 0xcb, 0xf7, 0x53, 0x2e, 0x36,
0xa0, 0x13, 0xc0, 0xcc, 0x25, 0xb3, 0x00, 0x06, 0x6c, 0x33, 0x32, 0x4e,
0x13, 0x91, 0x86, 0x30, 0x54, 0x04, 0xe3, 0x22, 0x1d, 0x15, 0xd8, 0x8a,
0x35, 0x15, 0x28, 0x34, 0x67, 0x66, 0x04, 0x1b, 0xec, 0x62, 0x18, 0x77,
0x73, 0x26, 0x59, 0x83, 0x3d, 0xfd, 0x0d, 0x00, 0x01, 0xc6, 0x91, 0x8c,
0x53, 0x43, 0x52, 0x90, 0x0a, 0x36, 0x23, 0x5b, 0x05, 0x36, 0xd9, 0x32,
0x7a, 0x02, 0x35, 0x73, 0x0e, 0xbf, 0x4a, 0x8b, 0x7c, 0x99, 0x96, 0x77,
0xee, 0x95, 0x32, 0x3f, 0xca, 0x93, 0x67, 0xdf, 0xbe, 0xd5, 0x27, 0x25,
0xe9, 0x90, 0xfc, 0xfc, 0x01, 0xd8, 0xd5, 0x9a, 0x8e, 0x0f, 0x7c, 0x61,
0x1e, 0xd2, 0x25, 0xf1, 0x10, 0x17, 0x94, 0xd3, 0xe6, 0xb1, 0x02, 0xff,
0xc3, 0x8f, 0x4b, 0x97, 0x2f, 0x5d, 0xd0, 0x44, 0x66, 0x5b, 0x6b, 0x9c,
0x1b, 0x29, 0x8c, 0x99, 0x05, 0x37, 0x80, 0x86, 0x53, 0x34, 0xe0, 0xd9,
0x76, 0x12, 0x63, 0x8c, 0x62, 0x82, 0xe2, 0xd1, 0x01, 0x25, 0x41, 0x68,
0xee, 0xd7, 0xca, 0x0f, 0x00, 0xe9, 0x47, 0xc2, 0xa6, 0x9e, 0x47, 0xd6,
0x32, 0x8d, 0x41, 0x99, 0xa5, 0xdd, 0x90, 0x58, 0x1c, 0x15, 0x34, 0xd9,
0x0a, 0x96, 0x7e, 0x05, 0x18, 0x53, 0x7d, 0x59, 0x01, 0x39, 0x01, 0x94,
0x90, 0xf8, 0x30, 0xbf, 0xb6, 0x80, 0x6e, 0x00, 0xe8, 0x1e, 0x57, 0x4c,
0x5e, 0xb5, 0xf0, 0xf2, 0x10, 0x7f, 0x27, 0xe0, 0xe7, 0x12, 0xde, 0x90,
0xa1, 0xe7, 0x98, 0x65, 0x4f, 0x7d, 0xf6, 0x69, 0xc6, 0x69, 0x86, 0xc3,
0x7d, 0xd1, 0x9a, 0x8b, 0x12, 0x5a, 0x2a, 0x5d, 0xa9, 0x3e, 0x8e, 0x61,
0xa6, 0x77, 0xf2, 0x0e, 0x9d, 0x26, 0x26, 0x2a, 0x65, 0x98, 0xda, 0x98,
0x26, 0x5f, 0x4b, 0xb7, 0xe3, 0x54, 0xfc, 0xe2, 0x2b, 0x99, 0x44, 0x63,
0xab, 0x03, 0x95, 0xf3, 0x6b, 0x04, 0xac, 0x1b, 0x00, 0x36, 0x59, 0xe3,
0x6f, 0x32, 0x7b, 0x84, 0x7d, 0x07, 0x10, 0x58, 0x94, 0x15, 0xc7, 0xd0,
0x09, 0x47, 0x05, 0xfe, 0x11, 0xc0, 0x02, 0x73, 0x0e, 0xee, 0xa0, 0xa3,
0x82, 0xf0, 0x02, 0x20, 0x73, 0x91, 0x3e, 0x86, 0x0c, 0xd4, 0x71, 0x88,
0xc9, 0x38, 0x63, 0xe6, 0x95, 0x72, 0x6b, 0x80, 0x64, 0xa6, 0x7c, 0x24,
0x7f, 0xcf, 0xf5, 0x72, 0xb2, 0xe3, 0xdd, 0x54, 0xf9, 0x3a, 0x87, 0x7d,
0x5a, 0x4e, 0x5e, 0xf4, 0x59, 0xce, 0x5d, 0xef, 0x64, 0x9e, 0x2d, 0x70,
0xfe, 0x23, 0xac, 0xae, 0x8c, 0x41, 0x55, 0x53, 0xa9, 0x77, 0xfe, 0xaa,
0x50, 0x92, 0x00, 0xf3, 0x03, 0x47, 0x92, 0x00, 0xf6, 0xc3, 0xcf, 0x37,
0x2e, 0x65, 0x8a, 0x8a, 0x82, 0xad, 0x01, 0x38, 0x44, 0xfe, 0xe7, 0x2f,
0x40, 0x9a, 0x99, 0x37, 0x32, 0x62, 0xc2, 0x5d, 0x8d, 0x72, 0x52, 0xc9,
0x0c, 0x0b, 0xa7, 0x85, 0x01, 0xe8, 0x12, 0xa7, 0x06, 0xdf, 0x00, 0x74,
0x00, 0x80, 0x19, 0x00, 0x17, 0xed, 0x50, 0x4c, 0xf4, 0x0b, 0x00, 0x41,
0x67, 0x05, 0xf7, 0x16, 0x20, 0x07, 0x99, 0x91, 0x11, 0x03, 0xf0, 0xbe,
0x08, 0x51, 0xfd, 0x10, 0xc0, 0xed, 0x7a, 0x78, 0x40, 0x39, 0xf9, 0xec,
0x53, 0xe7, 0xd4, 0x57, 0x64, 0xee, 0x16, 0x28, 0x95, 0xd9, 0xff, 0x4f,
0x3c, 0x7f, 0x8f, 0x99, 0xcc, 0x7c, 0x72, 0xb8, 0x46, 0x47, 0x92, 0xf0,
0xb9, 0x14, 0x40, 0xbe, 0x73, 0xd0, 0x2e, 0xdb, 0x5e, 0x81, 0x6b, 0x3d,
0xe7, 0xa1, 0x84, 0x8c, 0xd3, 0x1c, 0x2f, 0x3f, 0xc4, 0x13, 0x40, 0x96,
0x43, 0x20, 0xee, 0x32, 0x62, 0x0a, 0x40, 0x4d, 0x44, 0x41, 0x49, 0x88,
0x63, 0x2d, 0x0f, 0x96, 0x4d, 0x48, 0x19, 0x53, 0x18, 0x17, 0x7f, 0x00,
0x66, 0x4e, 0x62, 0x12, 0x2b, 0x4e, 0xe4, 0x34, 0xcd, 0x98, 0x44, 0x96,
0x21, 0x64, 0x3a, 0x98, 0xae, 0x8d, 0x32, 0x15, 0x28, 0x09, 0x0a, 0xad,
0x60, 0xcd, 0xc3, 0xb4, 0x30, 0x15, 0x30, 0x08, 0x61, 0x00, 0x20, 0xe3,
0x35, 0xd2, 0x33, 0x88, 0xd9, 0xe5, 0x7e, 0x06, 0xb2, 0x06, 0xa0, 0x47,
0x94, 0xec, 0x20, 0xfe, 0x91, 0xa7, 0x73, 0x06, 0xf9, 0x3e, 0x83, 0xf7,
0xf8, 0xd0, 0x0e, 0xda, 0x4d, 0x65, 0xff, 0x3f, 0xf1, 0xfc, 0x7d, 0xcd,
0x64, 0xe6, 0x93, 0x33, 0xf3, 0x21, 0xf2, 0x76, 0x53, 0x78, 0xfc, 0x7f,
0x94, 0xa4, 0x46, 0x17, 0x17, 0x06, 0xca, 0x80, 0xa3, 0x88, 0x03, 0xa5,
0x06, 0x88, 0x30, 0xb0, 0xb8, 0x90, 0x69, 0x88, 0x00, 0xd8, 0x00, 0x17,
0x07, 0x17, 0x41, 0xf2, 0x3c, 0xc2, 0x08, 0x8a, 0x55, 0x47, 0x41, 0x41,
0x07, 0x20, 0x16, 0x21, 0xdb, 0x05, 0x14, 0x19, 0xc0, 0x30, 0x28, 0x0c,
0x70, 0x71, 0x01, 0x06, 0x22, 0x10, 0x90, 0x3d, 0x47, 0x82, 0x48, 0xa6,
0x23, 0x13, 0x8c, 0x02, 0x00, 0xe7, 0xfb, 0x84, 0x1b, 0xf9, 0x8e, 0xc0,
0x23, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
0x82
};
{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
0x04, 0x03, 0x00, 0x00, 0x00, 0x31, 0x10, 0x7c, 0xf8, 0x00, 0x00, 0x00,
0x0f, 0x50, 0x4c, 0x54, 0x45, 0x18, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xc8, 0xc8, 0xae,
0x00, 0x00, 0x05, 0x11, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x62, 0x50,
0x06, 0xf0, 0x62, 0x06, 0xb6, 0xed, 0xf4, 0x3a, 0x0c, 0xff, 0xf1, 0xba,
0x00, 0xb9, 0x41, 0xde, 0x06, 0xd9, 0x7f, 0xba, 0x07, 0x98, 0x10, 0x6a,
0x1f, 0xd2, 0xe2, 0x9f, 0xa0, 0xf8, 0x74, 0xaa, 0x65, 0xc9, 0x32, 0x23,
0x39, 0xc4, 0xc1, 0xe9, 0xc5, 0x83, 0x0b, 0xd6, 0x58, 0x7d, 0xf4, 0xe9,
0xec, 0x6a, 0xac, 0x6b, 0xd5, 0xc7, 0x9e, 0xfc, 0x17, 0x62, 0x09, 0x09,
0x4c, 0x60, 0x59, 0x0b, 0x99, 0x0a, 0x6b, 0xde, 0xc1, 0x60, 0x62, 0x82,
0xd2, 0xc0, 0x00, 0x90, 0x58, 0x21, 0xc2, 0xc6, 0x02, 0xef, 0x00, 0x16,
0xc1, 0x2a, 0x2e, 0x46, 0x13, 0xb5, 0x0a, 0x00, 0x48, 0xc5, 0xef, 0x62,
0x63, 0xde, 0x00, 0xd4, 0x28, 0xea, 0xc7, 0x77, 0x8a, 0x82, 0x07, 0xa0,
0xcb, 0xe0, 0x0c, 0x80, 0x42, 0x41, 0x0b, 0x20, 0x83, 0xb0, 0xc1, 0xc2,
0x8d, 0x22, 0x46, 0x12, 0x13, 0x1c, 0xec, 0x5b, 0x05, 0x03, 0xd0, 0x9d,
0xc9, 0x00, 0xbc, 0x68, 0x21, 0x10, 0xa4, 0x01, 0xe8, 0x8a, 0x68, 0xb1,
0x24, 0x73, 0x88, 0x30, 0x2d, 0xc8, 0x98, 0x11, 0x66, 0x7e, 0x02, 0x7c,
0x26, 0x16, 0x6f, 0xc8, 0xf3, 0x0b, 0x9e, 0xd0, 0xf1, 0xb9, 0xfc, 0x3e,
0x9d, 0x3d, 0x79, 0xd2, 0x61, 0xf4, 0xeb, 0x4c, 0x7e, 0x2c, 0x6e, 0x0e,
0x41, 0x29, 0xab, 0x37, 0x53, 0xed, 0xf2, 0x46, 0xe3, 0x59, 0xfd, 0x53,
0x09, 0x28, 0x80, 0x51, 0x8c, 0xb2, 0x4c, 0x42, 0xca, 0xdc, 0x32, 0xb4,
0x26, 0xc8, 0xb2, 0x9a, 0x0f, 0xee, 0x2e, 0x8c, 0x29, 0x1d, 0xeb, 0xd4,
0x54, 0x3d, 0x00, 0x62, 0x03, 0x70, 0x93, 0xfb, 0x01, 0xdd, 0xa6, 0x52,
0xc2, 0xb8, 0x81, 0x98, 0x3a, 0x4a, 0x01, 0xca, 0x57, 0xdb, 0x92, 0xf0,
0x37, 0xe3, 0x0a, 0x26, 0x15, 0x0d, 0x0d, 0x80, 0x59, 0x2a, 0x8b, 0x1f,
0x01, 0xa6, 0x02, 0x50, 0x3f, 0xcd, 0x3f, 0xb6, 0xe0, 0xb6, 0x40, 0xbd,
0x60, 0x8a, 0x47, 0xb3, 0x66, 0xe6, 0xf3, 0x10, 0xa7, 0x7e, 0x8b, 0x9e,
0x65, 0x18, 0x4f, 0x01, 0xb1, 0x89, 0xc2, 0x7f, 0x2f, 0xe5, 0xe6, 0x10,
0xb4, 0xac, 0xde, 0x4d, 0xb5, 0xcb, 0xdf, 0x34, 0xde, 0x92, 0x1e, 0x1b,
0x73, 0x0f, 0xe7, 0xa0, 0x73, 0x9f, 0x26, 0x94, 0xcb, 0x75, 0x3e, 0x11,
0xdd, 0xfd, 0x40, 0x4f, 0x9b, 0x90, 0x7c, 0x7f, 0x85, 0x63, 0x45, 0x42,
0x30, 0x41, 0x1b, 0x71, 0x67, 0x8a, 0x98, 0x3d, 0x6b, 0x60, 0x07, 0x90,
0xc0, 0x86, 0x59, 0xb1, 0xa9, 0xbc, 0x06, 0x28, 0x11, 0xc4, 0x6c, 0x5c,
0x2e, 0x02, 0x3c, 0x8c, 0xa9, 0xc8, 0xc4, 0x1d, 0xdb, 0x82, 0x24, 0x12,
0xd0, 0x4b, 0x80, 0x2d, 0x3e, 0x52, 0x56, 0x96, 0xa7, 0x4d, 0xf0, 0xd1,
0x42, 0x37, 0xaa, 0x7f, 0xf5, 0x0e, 0x00, 0xdd, 0x01, 0x48, 0xf7, 0x06,
0x0c, 0xf1, 0x00, 0x4c, 0xe1, 0xc9, 0x09, 0x40, 0xf6, 0x16, 0xfe, 0x4d,
0x32, 0x7f, 0x31, 0x7f, 0x2f, 0x43, 0xca, 0xd1, 0x3a, 0x27, 0x9d, 0xfb,
0x34, 0xa1, 0x5c, 0xae, 0xd3, 0x7b, 0xc5, 0x30, 0xf3, 0x5a, 0xce, 0xa3,
0x0e, 0xa3, 0xcd, 0x68, 0x62, 0xc7, 0x46, 0xba, 0xc2, 0x9f, 0x88, 0x00,
0x3c, 0xef, 0x5d, 0xfe, 0x49, 0xe6, 0xf5, 0x69, 0x60, 0x1b, 0x7e, 0x02,
0xf0, 0x6b, 0x00, 0x97, 0xbd, 0x04, 0x85, 0xac, 0x98, 0xb0, 0x62, 0x42,
0x83, 0xc4, 0x32, 0x21, 0x78, 0xad, 0xb9, 0xa3, 0x9a, 0x5c, 0x68, 0x09,
0x17, 0x4d, 0x58, 0xc6, 0x52, 0x9d, 0xd1, 0x96, 0x35, 0x00, 0x6b, 0x3a,
0xdc, 0x2d, 0x00, 0x3b, 0x80, 0x5e, 0x00, 0x34, 0xdd, 0x18, 0x0d, 0x16,
0x5b, 0x05, 0x04, 0xa3, 0xdc, 0x01, 0x98, 0x16, 0xe6, 0x92, 0x56, 0x80,
0xa5, 0x1c, 0x2d, 0x54, 0xf4, 0xe2, 0xac, 0x8e, 0x84, 0x5b, 0x7c, 0x00,
0x46, 0xe4, 0x37, 0x00, 0xcc, 0x4d, 0x9e, 0xc3, 0xcc, 0x67, 0x2f, 0x15,
0x75, 0x46, 0xcb, 0xdc, 0x67, 0x4d, 0xc7, 0x46, 0xd6, 0x4a, 0x2f, 0x18,
0x6f, 0x6b, 0xb9, 0xff, 0x57, 0x4c, 0x16, 0x7e, 0x4b, 0xa9, 0x0c, 0x33,
0x3e, 0x01, 0x30, 0x42, 0xc3, 0xaf, 0xcf, 0x2a, 0x08, 0xa2, 0x8c, 0xfe,
0xac, 0x02, 0x41, 0xdc, 0x3e, 0xf8, 0x14, 0x40, 0x00, 0x9f, 0x56, 0x30,
0x34, 0x07, 0x63, 0xde, 0x95, 0x73, 0xdb, 0xa7, 0x00, 0xf7, 0xbb, 0xf2,
0xdb, 0x3a, 0xdc, 0x5f, 0xf3, 0xbe, 0x61, 0xfb, 0xf6, 0x5d, 0x5a, 0xa7,
0x84, 0x5d, 0xbc, 0xdd, 0x7f, 0x00, 0x36, 0x75, 0xcc, 0x25, 0x7e, 0x90,
0xe4, 0x8d, 0x76, 0x2c, 0xa1, 0x6c, 0xad, 0xcd, 0x09, 0xb3, 0x11, 0x07,
0xd0, 0x18, 0x70, 0x43, 0x9d, 0xa9, 0x11, 0xcb, 0xf7, 0x53, 0x2e, 0x36,
0xa0, 0x13, 0xc0, 0xcc, 0x25, 0xb3, 0x00, 0x06, 0x6c, 0x33, 0x32, 0x4e,
0x13, 0x91, 0x86, 0x30, 0x54, 0x04, 0xe3, 0x22, 0x1d, 0x15, 0xd8, 0x8a,
0x35, 0x15, 0x28, 0x34, 0x67, 0x66, 0x04, 0x1b, 0xec, 0x62, 0x18, 0x77,
0x73, 0x26, 0x59, 0x83, 0x3d, 0xfd, 0x0d, 0x00, 0x01, 0xc6, 0x91, 0x8c,
0x53, 0x43, 0x52, 0x90, 0x0a, 0x36, 0x23, 0x5b, 0x05, 0x36, 0xd9, 0x32,
0x7a, 0x02, 0x35, 0x73, 0x0e, 0xbf, 0x4a, 0x8b, 0x7c, 0x99, 0x96, 0x77,
0xee, 0x95, 0x32, 0x3f, 0xca, 0x93, 0x67, 0xdf, 0xbe, 0xd5, 0x27, 0x25,
0xe9, 0x90, 0xfc, 0xfc, 0x01, 0xd8, 0xd5, 0x9a, 0x8e, 0x0f, 0x7c, 0x61,
0x1e, 0xd2, 0x25, 0xf1, 0x10, 0x17, 0x94, 0xd3, 0xe6, 0xb1, 0x02, 0xff,
0xc3, 0x8f, 0x4b, 0x97, 0x2f, 0x5d, 0xd0, 0x44, 0x66, 0x5b, 0x6b, 0x9c,
0x1b, 0x29, 0x8c, 0x99, 0x05, 0x37, 0x80, 0x86, 0x53, 0x34, 0xe0, 0xd9,
0x76, 0x12, 0x63, 0x8c, 0x62, 0x82, 0xe2, 0xd1, 0x01, 0x25, 0x41, 0x68,
0xee, 0xd7, 0xca, 0x0f, 0x00, 0xe9, 0x47, 0xc2, 0xa6, 0x9e, 0x47, 0xd6,
0x32, 0x8d, 0x41, 0x99, 0xa5, 0xdd, 0x90, 0x58, 0x1c, 0x15, 0x34, 0xd9,
0x0a, 0x96, 0x7e, 0x05, 0x18, 0x53, 0x7d, 0x59, 0x01, 0x39, 0x01, 0x94,
0x90, 0xf8, 0x30, 0xbf, 0xb6, 0x80, 0x6e, 0x00, 0xe8, 0x1e, 0x57, 0x4c,
0x5e, 0xb5, 0xf0, 0xf2, 0x10, 0x7f, 0x27, 0xe0, 0xe7, 0x12, 0xde, 0x90,
0xa1, 0xe7, 0x98, 0x65, 0x4f, 0x7d, 0xf6, 0x69, 0xc6, 0x69, 0x86, 0xc3,
0x7d, 0xd1, 0x9a, 0x8b, 0x12, 0x5a, 0x2a, 0x5d, 0xa9, 0x3e, 0x8e, 0x61,
0xa6, 0x77, 0xf2, 0x0e, 0x9d, 0x26, 0x26, 0x2a, 0x65, 0x98, 0xda, 0x98,
0x26, 0x5f, 0x4b, 0xb7, 0xe3, 0x54, 0xfc, 0xe2, 0x2b, 0x99, 0x44, 0x63,
0xab, 0x03, 0x95, 0xf3, 0x6b, 0x04, 0xac, 0x1b, 0x00, 0x36, 0x59, 0xe3,
0x6f, 0x32, 0x7b, 0x84, 0x7d, 0x07, 0x10, 0x58, 0x94, 0x15, 0xc7, 0xd0,
0x09, 0x47, 0x05, 0xfe, 0x11, 0xc0, 0x02, 0x73, 0x0e, 0xee, 0xa0, 0xa3,
0x82, 0xf0, 0x02, 0x20, 0x73, 0x91, 0x3e, 0x86, 0x0c, 0xd4, 0x71, 0x88,
0xc9, 0x38, 0x63, 0xe6, 0x95, 0x72, 0x6b, 0x80, 0x64, 0xa6, 0x7c, 0x24,
0x7f, 0xcf, 0xf5, 0x72, 0xb2, 0xe3, 0xdd, 0x54, 0xf9, 0x3a, 0x87, 0x7d,
0x5a, 0x4e, 0x5e, 0xf4, 0x59, 0xce, 0x5d, 0xef, 0x64, 0x9e, 0x2d, 0x70,
0xfe, 0x23, 0xac, 0xae, 0x8c, 0x41, 0x55, 0x53, 0xa9, 0x77, 0xfe, 0xaa,
0x50, 0x92, 0x00, 0xf3, 0x03, 0x47, 0x92, 0x00, 0xf6, 0xc3, 0xcf, 0x37,
0x2e, 0x65, 0x8a, 0x8a, 0x82, 0xad, 0x01, 0x38, 0x44, 0xfe, 0xe7, 0x2f,
0x40, 0x9a, 0x99, 0x37, 0x32, 0x62, 0xc2, 0x5d, 0x8d, 0x72, 0x52, 0xc9,
0x0c, 0x0b, 0xa7, 0x85, 0x01, 0xe8, 0x12, 0xa7, 0x06, 0xdf, 0x00, 0x74,
0x00, 0x80, 0x19, 0x00, 0x17, 0xed, 0x50, 0x4c, 0xf4, 0x0b, 0x00, 0x41,
0x67, 0x05, 0xf7, 0x16, 0x20, 0x07, 0x99, 0x91, 0x11, 0x03, 0xf0, 0xbe,
0x08, 0x51, 0xfd, 0x10, 0xc0, 0xed, 0x7a, 0x78, 0x40, 0x39, 0xf9, 0xec,
0x53, 0xe7, 0xd4, 0x57, 0x64, 0xee, 0x16, 0x28, 0x95, 0xd9, 0xff, 0x4f,
0x3c, 0x7f, 0x8f, 0x99, 0xcc, 0x7c, 0x72, 0xb8, 0x46, 0x47, 0x92, 0xf0,
0xb9, 0x14, 0x40, 0xbe, 0x73, 0xd0, 0x2e, 0xdb, 0x5e, 0x81, 0x6b, 0x3d,
0xe7, 0xa1, 0x84, 0x8c, 0xd3, 0x1c, 0x2f, 0x3f, 0xc4, 0x13, 0x40, 0x96,
0x43, 0x20, 0xee, 0x32, 0x62, 0x0a, 0x40, 0x4d, 0x44, 0x41, 0x49, 0x88,
0x63, 0x2d, 0x0f, 0x96, 0x4d, 0x48, 0x19, 0x53, 0x18, 0x17, 0x7f, 0x00,
0x66, 0x4e, 0x62, 0x12, 0x2b, 0x4e, 0xe4, 0x34, 0xcd, 0x98, 0x44, 0x96,
0x21, 0x64, 0x3a, 0x98, 0xae, 0x8d, 0x32, 0x15, 0x28, 0x09, 0x0a, 0xad,
0x60, 0xcd, 0xc3, 0xb4, 0x30, 0x15, 0x30, 0x08, 0x61, 0x00, 0x20, 0xe3,
0x35, 0xd2, 0x33, 0x88, 0xd9, 0xe5, 0x7e, 0x06, 0xb2, 0x06, 0xa0, 0x47,
0x94, 0xec, 0x20, 0xfe, 0x91, 0xa7, 0x73, 0x06, 0xf9, 0x3e, 0x83, 0xf7,
0xf8, 0xd0, 0x0e, 0xda, 0x4d, 0x65, 0xff, 0x3f, 0xf1, 0xfc, 0x7d, 0xcd,
0x64, 0xe6, 0x93, 0x33, 0xf3, 0x21, 0xf2, 0x76, 0x53, 0x78, 0xfc, 0x7f,
0x94, 0xa4, 0x46, 0x17, 0x17, 0x06, 0xca, 0x80, 0xa3, 0x88, 0x03, 0xa5,
0x06, 0x88, 0x30, 0xb0, 0xb8, 0x90, 0x69, 0x88, 0x00, 0xd8, 0x00, 0x17,
0x07, 0x17, 0x41, 0xf2, 0x3c, 0xc2, 0x08, 0x8a, 0x55, 0x47, 0x41, 0x41,
0x07, 0x20, 0x16, 0x21, 0xdb, 0x05, 0x14, 0x19, 0xc0, 0x30, 0x28, 0x0c,
0x70, 0x71, 0x01, 0x06, 0x22, 0x10, 0x90, 0x3d, 0x47, 0x82, 0x48, 0xa6,
0x23, 0x13, 0x8c, 0x02, 0x00, 0xe7, 0xfb, 0x84, 0x1b, 0xf9, 0x8e, 0xc0,
0x23, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
0x82};
const u32 BuiltInFontDataSize = sizeof(BuiltInFontData);
const u32 BuiltInFontDataSize = sizeof(BuiltInFontData);
} // end namespace gui
} // end namespace irr

View File

@ -17,35 +17,33 @@
#include "IFileSystem.h"
#include "quaternion.h"
namespace irr
{
namespace scene
{
//! constructor
CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale)
: IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
StartFrame(0), EndFrame(0), FramesPerSecond(0.025f),
CurrentFrameNr(0.f), LastTimeMs(0),
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
JointMode(EJUOR_NONE), JointsUsed(false),
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
LoopCallBack(0), PassCount(0)
CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh *mesh,
ISceneNode *parent, ISceneManager *mgr, s32 id,
const core::vector3df &position,
const core::vector3df &rotation,
const core::vector3df &scale) :
IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale),
Mesh(0),
StartFrame(0), EndFrame(0), FramesPerSecond(0.025f),
CurrentFrameNr(0.f), LastTimeMs(0),
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
JointMode(EJUOR_NONE), JointsUsed(false),
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
LoopCallBack(0), PassCount(0)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CAnimatedMeshSceneNode");
#endif
#endif
setMesh(mesh);
}
//! destructor
CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
{
@ -55,77 +53,63 @@ CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
Mesh->drop();
}
//! Sets the current frame. From now on the animation is played from this frame.
void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame)
{
// if you pass an out of range value, we just clamp it
CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame );
CurrentFrameNr = core::clamp(frame, (f32)StartFrame, (f32)EndFrame);
beginTransition(); //transit to this frame if enabled
beginTransition(); // transit to this frame if enabled
}
//! Returns the currently displayed frame number.
f32 CAnimatedMeshSceneNode::getFrameNr() const
{
return CurrentFrameNr;
}
//! Get CurrentFrameNr and update transiting settings
void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
{
if (Transiting!=0.f)
{
TransitingBlend += (f32)(timeMs) * Transiting;
if (TransitingBlend > 1.f)
{
Transiting=0.f;
TransitingBlend=0.f;
if (Transiting != 0.f) {
TransitingBlend += (f32)(timeMs)*Transiting;
if (TransitingBlend > 1.f) {
Transiting = 0.f;
TransitingBlend = 0.f;
}
}
if (StartFrame==EndFrame)
{
CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes
}
else if (Looping)
{
if (StartFrame == EndFrame) {
CurrentFrameNr = (f32)StartFrame; // Support for non animated meshes
} else if (Looping) {
// play animation looped
CurrentFrameNr += timeMs * FramesPerSecond;
// We have no interpolation between EndFrame and StartFrame,
// the last frame must be identical to first one with our current solution.
if (FramesPerSecond > 0.f) //forwards...
if (FramesPerSecond > 0.f) // forwards...
{
if (CurrentFrameNr > EndFrame)
CurrentFrameNr = StartFrame + fmodf(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame));
}
else //backwards...
CurrentFrameNr = StartFrame + fmodf(CurrentFrameNr - StartFrame, (f32)(EndFrame - StartFrame));
} else // backwards...
{
if (CurrentFrameNr < StartFrame)
CurrentFrameNr = EndFrame - fmodf(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame));
CurrentFrameNr = EndFrame - fmodf(EndFrame - CurrentFrameNr, (f32)(EndFrame - StartFrame));
}
}
else
{
} else {
// play animation non looped
CurrentFrameNr += timeMs * FramesPerSecond;
if (FramesPerSecond > 0.f) //forwards...
if (FramesPerSecond > 0.f) // forwards...
{
if (CurrentFrameNr > (f32)EndFrame)
{
if (CurrentFrameNr > (f32)EndFrame) {
CurrentFrameNr = (f32)EndFrame;
if (LoopCallBack)
LoopCallBack->OnAnimationEnd(this);
}
}
else //backwards...
} else // backwards...
{
if (CurrentFrameNr < (f32)StartFrame)
{
if (CurrentFrameNr < (f32)StartFrame) {
CurrentFrameNr = (f32)StartFrame;
if (LoopCallBack)
LoopCallBack->OnAnimationEnd(this);
@ -134,17 +118,15 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
}
}
void CAnimatedMeshSceneNode::OnRegisterSceneNode()
{
if (IsVisible && Mesh)
{
if (IsVisible && Mesh) {
// because this node supports rendering of mixed mode meshes consisting of
// transparent and solid material at the same time, we need to go through all
// materials, check of what type they are and register this node for the right
// render pass according to that.
video::IVideoDriver* driver = SceneManager->getVideoDriver();
video::IVideoDriver *driver = SceneManager->getVideoDriver();
PassCount = 0;
int transparentCount = 0;
@ -152,11 +134,10 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
// count transparent and solid materials in this scene node
const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size();
for (u32 i=0; i<numMaterials; ++i)
{
const video::SMaterial& material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
for (u32 i = 0; i < numMaterials; ++i) {
const video::SMaterial &material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
if ( driver->needsTransparentRenderPass(material) )
if (driver->needsTransparentRenderPass(material))
++transparentCount;
else
++solidCount;
@ -177,22 +158,19 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
}
}
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
IMesh *CAnimatedMeshSceneNode::getMeshForCurrentFrame()
{
if(Mesh->getMeshType() != EAMT_SKINNED)
{
s32 frameNr = (s32) getFrameNr();
s32 frameBlend = (s32) (core::fract ( getFrameNr() ) * 1000.f);
if (Mesh->getMeshType() != EAMT_SKINNED) {
s32 frameNr = (s32)getFrameNr();
s32 frameBlend = (s32)(core::fract(getFrameNr()) * 1000.f);
return Mesh->getMesh(frameNr, frameBlend, StartFrame, EndFrame);
}
else
{
} else {
// As multiple scene nodes may be sharing the same skinned mesh, we have to
// re-animate it every frame to ensure that this node gets the mesh that it needs.
CSkinnedMesh* skinnedMesh = static_cast<CSkinnedMesh*>(Mesh);
CSkinnedMesh *skinnedMesh = static_cast<CSkinnedMesh *>(Mesh);
if (JointMode == EJUOR_CONTROL)//write to mesh
if (JointMode == EJUOR_CONTROL) // write to mesh
skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
else
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
@ -200,20 +178,18 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
// Update the skinned mesh for the current joint transforms.
skinnedMesh->skinMesh();
if (JointMode == EJUOR_READ)//read from mesh
if (JointMode == EJUOR_READ) // read from mesh
{
skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes);
//---slow---
for (u32 n=0;n<JointChildSceneNodes.size();++n)
if (JointChildSceneNodes[n]->getParent()==this)
{
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
for (u32 n = 0; n < JointChildSceneNodes.size(); ++n)
if (JointChildSceneNodes[n]->getParent() == this) {
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); // temp, should be an option
}
}
if(JointMode == EJUOR_CONTROL)
{
if (JointMode == EJUOR_CONTROL) {
// For meshes other than EJUOR_CONTROL, this is done by calling animateMesh()
skinnedMesh->updateBoundingBox();
}
@ -222,67 +198,59 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
}
}
//! OnAnimate() is called just before rendering the whole scene.
void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
{
if (LastTimeMs==0) // first frame
if (LastTimeMs == 0) // first frame
{
LastTimeMs = timeMs;
}
// set CurrentFrameNr
buildFrameNr(timeMs-LastTimeMs);
buildFrameNr(timeMs - LastTimeMs);
LastTimeMs = timeMs;
IAnimatedMeshSceneNode::OnAnimate(timeMs);
}
//! renders the node.
void CAnimatedMeshSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
video::IVideoDriver *driver = SceneManager->getVideoDriver();
if (!Mesh || !driver)
return;
const bool isTransparentPass =
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
++PassCount;
scene::IMesh* m = getMeshForCurrentFrame();
scene::IMesh *m = getMeshForCurrentFrame();
if(m)
{
if (m) {
Box = m->getBoundingBox();
}
else
{
#ifdef _DEBUG
os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING);
#endif
} else {
#ifdef _DEBUG
os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING);
#endif
return;
}
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
for (u32 i=0; i<m->getMeshBufferCount(); ++i)
{
for (u32 i = 0; i < m->getMeshBufferCount(); ++i) {
const bool transparent = driver->needsTransparentRenderPass(Materials[i]);
// only render transparent buffer if this is the transparent render pass
// and solid only in solid pass
if (transparent == isTransparentPass)
{
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
if (transparent == isTransparentPass) {
scene::IMeshBuffer *mb = m->getMeshBuffer(i);
const video::SMaterial &material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
if (RenderFromIdentity)
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
else if (Mesh->getMeshType() == EAMT_SKINNED)
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer *)mb)->Transformation);
driver->setMaterial(material);
driver->drawMeshBuffer(mb);
@ -292,27 +260,24 @@ void CAnimatedMeshSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
// for debug purposes only:
if (DebugDataVisible && PassCount==1)
{
if (DebugDataVisible && PassCount == 1) {
video::SMaterial debug_mat;
debug_mat.Lighting = false;
debug_mat.AntiAliasing=0;
debug_mat.AntiAliasing = 0;
driver->setMaterial(debug_mat);
// show normals
if (DebugDataVisible & scene::EDS_NORMALS)
{
if (DebugDataVisible & scene::EDS_NORMALS) {
const f32 debugNormalLength = 1.f;
const video::SColor debugNormalColor = video::SColor(255, 34, 221, 221);
const u32 count = m->getMeshBufferCount();
// draw normals
for (u32 g=0; g < count; ++g)
{
scene::IMeshBuffer* mb = m->getMeshBuffer(g);
for (u32 g = 0; g < count; ++g) {
scene::IMeshBuffer *mb = m->getMeshBuffer(g);
if (RenderFromIdentity)
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
else if (Mesh->getMeshType() == EAMT_SKINNED)
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer *)mb)->Transformation);
driver->drawMeshBufferNormals(mb, debugNormalLength, debugNormalColor);
}
@ -323,90 +288,76 @@ void CAnimatedMeshSceneNode::render()
driver->setMaterial(debug_mat);
if (DebugDataVisible & scene::EDS_BBOX)
driver->draw3DBox(Box, video::SColor(255,255,255,255));
driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
// show bounding box
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
{
for (u32 g=0; g< m->getMeshBufferCount(); ++g)
{
const IMeshBuffer* mb = m->getMeshBuffer(g);
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) {
for (u32 g = 0; g < m->getMeshBufferCount(); ++g) {
const IMeshBuffer *mb = m->getMeshBuffer(g);
if (Mesh->getMeshType() == EAMT_SKINNED)
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
driver->draw3DBox(mb->getBoundingBox(), video::SColor(255,190,128,128));
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer *)mb)->Transformation);
driver->draw3DBox(mb->getBoundingBox(), video::SColor(255, 190, 128, 128));
}
}
// show skeleton
if (DebugDataVisible & scene::EDS_SKELETON)
{
if (Mesh->getMeshType() == EAMT_SKINNED)
{
if (DebugDataVisible & scene::EDS_SKELETON) {
if (Mesh->getMeshType() == EAMT_SKINNED) {
// draw skeleton
for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g)
{
ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g];
for (u32 g = 0; g < ((ISkinnedMesh *)Mesh)->getAllJoints().size(); ++g) {
ISkinnedMesh::SJoint *joint = ((ISkinnedMesh *)Mesh)->getAllJoints()[g];
for (u32 n=0;n<joint->Children.size();++n)
{
for (u32 n = 0; n < joint->Children.size(); ++n) {
driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(),
joint->Children[n]->GlobalAnimatedMatrix.getTranslation(),
video::SColor(255,51,66,255));
video::SColor(255, 51, 66, 255));
}
}
}
}
// show mesh
if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
{
if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) {
debug_mat.Lighting = false;
debug_mat.Wireframe = true;
debug_mat.ZBuffer = video::ECFN_DISABLED;
driver->setMaterial(debug_mat);
for (u32 g=0; g<m->getMeshBufferCount(); ++g)
{
const IMeshBuffer* mb = m->getMeshBuffer(g);
for (u32 g = 0; g < m->getMeshBufferCount(); ++g) {
const IMeshBuffer *mb = m->getMeshBuffer(g);
if (RenderFromIdentity)
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
else if (Mesh->getMeshType() == EAMT_SKINNED)
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer *)mb)->Transformation);
driver->drawMeshBuffer(mb);
}
}
}
}
//! Returns the current start frame number.
s32 CAnimatedMeshSceneNode::getStartFrame() const
{
return StartFrame;
}
//! Returns the current start frame number.
s32 CAnimatedMeshSceneNode::getEndFrame() const
{
return EndFrame;
}
//! sets the frames between the animation is looped.
//! the default is 0 - MaximalFrameCount of the mesh.
bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end)
{
const s32 maxFrameCount = Mesh->getFrameCount() - 1;
if (end < begin)
{
if (end < begin) {
StartFrame = core::s32_clamp(end, 0, maxFrameCount);
EndFrame = core::s32_clamp(begin, StartFrame, maxFrameCount);
}
else
{
} else {
StartFrame = core::s32_clamp(begin, 0, maxFrameCount);
EndFrame = core::s32_clamp(end, StartFrame, maxFrameCount);
}
@ -418,29 +369,25 @@ bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end)
return true;
}
//! sets the speed with witch the animation is played
void CAnimatedMeshSceneNode::setAnimationSpeed(f32 framesPerSecond)
{
FramesPerSecond = framesPerSecond * 0.001f;
}
f32 CAnimatedMeshSceneNode::getAnimationSpeed() const
{
return FramesPerSecond * 1000.f;
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CAnimatedMeshSceneNode::getBoundingBox() const
const core::aabbox3d<f32> &CAnimatedMeshSceneNode::getBoundingBox() const
{
return Box;
}
//! returns the material based on the zero based index i.
video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i)
video::SMaterial &CAnimatedMeshSceneNode::getMaterial(u32 i)
{
if (i >= Materials.size())
return ISceneNode::getMaterial(i);
@ -448,39 +395,33 @@ video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i)
return Materials[i];
}
//! returns amount of materials used by this scene node.
u32 CAnimatedMeshSceneNode::getMaterialCount() const
{
return Materials.size();
}
//! Returns a pointer to a child node, which has the same transformation as
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName)
IBoneSceneNode *CAnimatedMeshSceneNode::getJointNode(const c8 *jointName)
{
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
{
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) {
os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING);
return 0;
}
checkJoints();
ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh;
ISkinnedMesh *skinnedMesh = (ISkinnedMesh *)Mesh;
const std::optional<u32> number = skinnedMesh->getJointNumber(jointName);
if (!number.has_value())
{
if (!number.has_value()) {
os::Printer::log("Joint with specified name not found in skinned mesh", jointName, ELL_DEBUG);
return 0;
}
if (JointChildSceneNodes.size() <= *number)
{
if (JointChildSceneNodes.size() <= *number) {
os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING);
return 0;
}
@ -488,22 +429,18 @@ IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName)
return JointChildSceneNodes[*number];
}
//! Returns a pointer to a child node, which has the same transformation as
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID)
IBoneSceneNode *CAnimatedMeshSceneNode::getJointNode(u32 jointID)
{
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
{
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) {
os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING);
return 0;
}
checkJoints();
if (JointChildSceneNodes.size() <= jointID)
{
if (JointChildSceneNodes.size() <= jointID) {
os::Printer::log("Joint not loaded into node", ELL_WARNING);
return 0;
}
@ -517,26 +454,22 @@ u32 CAnimatedMeshSceneNode::getJointCount() const
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
return 0;
ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh;
ISkinnedMesh *skinnedMesh = (ISkinnedMesh *)Mesh;
return skinnedMesh->getJointCount();
}
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
bool CAnimatedMeshSceneNode::removeChild(ISceneNode *child)
{
if (ISceneNode::removeChild(child))
{
if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created
if (ISceneNode::removeChild(child)) {
if (JointsUsed) // stop weird bugs caused while changing parents as the joints are being created
{
for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
{
if (JointChildSceneNodes[i] == child)
{
JointChildSceneNodes[i] = 0; //remove link to child
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) {
if (JointChildSceneNodes[i] == child) {
JointChildSceneNodes[i] = 0; // remove link to child
break;
}
}
@ -547,7 +480,6 @@ bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
return false;
}
//! Sets looping mode which is on by default. If set to false,
//! animations will not be looped.
void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped)
@ -561,10 +493,9 @@ bool CAnimatedMeshSceneNode::getLoopMode() const
return Looping;
}
//! Sets a callback interface which will be called if an animation
//! playback has ended. Set this to 0 to disable the callback again.
void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* callback)
void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack *callback)
{
if (callback == LoopCallBack)
return;
@ -578,29 +509,25 @@ void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* call
LoopCallBack->grab();
}
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly)
{
ReadOnlyMaterials = readonly;
}
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
bool CAnimatedMeshSceneNode::isReadOnlyMaterials() const
{
return ReadOnlyMaterials;
}
//! Sets a new mesh
void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh *mesh)
{
if (!mesh)
return; // won't set null mesh
if (Mesh != mesh)
{
if (Mesh != mesh) {
if (Mesh)
Mesh->drop();
@ -613,15 +540,13 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
// get materials and bounding box
Box = Mesh->getBoundingBox();
IMesh* m = Mesh->getMesh(0,0);
if (m)
{
IMesh *m = Mesh->getMesh(0, 0);
if (m) {
Materials.clear();
Materials.reallocate(m->getMeshBufferCount());
for (u32 i=0; i<m->getMeshBufferCount(); ++i)
{
IMeshBuffer* mb = m->getMeshBuffer(i);
for (u32 i = 0; i < m->getMeshBufferCount(); ++i) {
IMeshBuffer *mb = m->getMeshBuffer(i);
if (mb)
Materials.push_back(mb->getMaterial());
else
@ -630,18 +555,16 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
}
// clean up joint nodes
if (JointsUsed)
{
JointsUsed=false;
if (JointsUsed) {
JointsUsed = false;
checkJoints();
}
// get start and begin time
setAnimationSpeed(Mesh->getAnimationSpeed()); // NOTE: This had been commented out (but not removed!) in r3526. Which caused meshloader-values for speed to be ignored unless users specified explicitly. Missing a test-case where this could go wrong so I put the code back in.
setFrameLoop(0, Mesh->getFrameCount()-1);
setAnimationSpeed(Mesh->getAnimationSpeed()); // NOTE: This had been commented out (but not removed!) in r3526. Which caused meshloader-values for speed to be ignored unless users specified explicitly. Missing a test-case where this could go wrong so I put the code back in.
setFrameLoop(0, Mesh->getFrameCount() - 1);
}
//! updates the absolute position based on the relative and the parents position
void CAnimatedMeshSceneNode::updateAbsolutePosition()
{
@ -652,15 +575,15 @@ void CAnimatedMeshSceneNode::updateAbsolutePosition()
void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode)
{
checkJoints();
JointMode=mode;
JointMode = mode;
}
//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
//! you must call animateJoints(), or the mesh will not animate
void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
{
const u32 ttime = (u32)core::floor32(time*1000.0f);
if (TransitionTime==ttime)
const u32 ttime = (u32)core::floor32(time * 1000.0f);
if (TransitionTime == ttime)
return;
TransitionTime = ttime;
if (ttime != 0)
@ -669,69 +592,63 @@ void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
setJointMode(EJUOR_NONE);
}
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable)
{
RenderFromIdentity=enable;
RenderFromIdentity = enable;
}
//! updates the joint positions of this mesh
void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
{
if (Mesh && Mesh->getMeshType() == EAMT_SKINNED )
{
if (Mesh && Mesh->getMeshType() == EAMT_SKINNED) {
checkJoints();
const f32 frame = getFrameNr(); //old?
const f32 frame = getFrameNr(); // old?
CSkinnedMesh* skinnedMesh=static_cast<CSkinnedMesh*>(Mesh);
CSkinnedMesh *skinnedMesh = static_cast<CSkinnedMesh *>(Mesh);
skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes );
skinnedMesh->transferOnlyJointsHintsToMesh(JointChildSceneNodes);
skinnedMesh->animateMesh(frame, 1.0f);
skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes);
skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes);
//-----------------------------------------
// Transition
//-----------------------------------------
if (Transiting != 0.f)
{
if (Transiting != 0.f) {
// Init additional matrices
if (PretransitingSave.size()<JointChildSceneNodes.size())
{
for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
if (PretransitingSave.size() < JointChildSceneNodes.size()) {
for (u32 n = PretransitingSave.size(); n < JointChildSceneNodes.size(); ++n)
PretransitingSave.push_back(core::matrix4());
}
for (u32 n=0; n<JointChildSceneNodes.size(); ++n)
{
for (u32 n = 0; n < JointChildSceneNodes.size(); ++n) {
//------Position------
JointChildSceneNodes[n]->setPosition(
core::lerp(
PretransitingSave[n].getTranslation(),
JointChildSceneNodes[n]->getPosition(),
TransitingBlend));
PretransitingSave[n].getTranslation(),
JointChildSceneNodes[n]->getPosition(),
TransitingBlend));
//------Rotation------
//Code is slow, needs to be fixed up
// Code is slow, needs to be fixed up
const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD);
const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD);
const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees() * core::DEGTORAD);
const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation() * core::DEGTORAD);
core::quaternion QRotation;
QRotation.slerp(RotationStart, RotationEnd, TransitingBlend);
core::vector3df tmpVector;
QRotation.toEuler(tmpVector);
tmpVector*=core::RADTODEG; //convert from radians back to degrees
JointChildSceneNodes[n]->setRotation( tmpVector );
tmpVector *= core::RADTODEG; // convert from radians back to degrees
JointChildSceneNodes[n]->setRotation(tmpVector);
//------Scale------
//JointChildSceneNodes[n]->setScale(
// JointChildSceneNodes[n]->setScale(
// core::lerp(
// PretransitingSave[n].getScale(),
// JointChildSceneNodes[n]->getScale(),
@ -739,14 +656,11 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
}
}
if (CalculateAbsolutePositions)
{
if (CalculateAbsolutePositions) {
//---slow---
for (u32 n=0;n<JointChildSceneNodes.size();++n)
{
if (JointChildSceneNodes[n]->getParent()==this)
{
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
for (u32 n = 0; n < JointChildSceneNodes.size(); ++n) {
if (JointChildSceneNodes[n]->getParent() == this) {
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); // temp, should be an option
}
}
}
@ -754,69 +668,64 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
}
/*!
*/
*/
void CAnimatedMeshSceneNode::checkJoints()
{
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
return;
if (!JointsUsed)
{
for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
if (!JointsUsed) {
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i)
removeChild(JointChildSceneNodes[i]);
JointChildSceneNodes.clear();
//Create joints for SkinnedMesh
((CSkinnedMesh*)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager);
((CSkinnedMesh*)Mesh)->recoverJointsFromMesh(JointChildSceneNodes);
// Create joints for SkinnedMesh
((CSkinnedMesh *)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager);
((CSkinnedMesh *)Mesh)->recoverJointsFromMesh(JointChildSceneNodes);
JointsUsed=true;
JointMode=EJUOR_READ;
JointsUsed = true;
JointMode = EJUOR_READ;
}
}
/*!
*/
*/
void CAnimatedMeshSceneNode::beginTransition()
{
if (!JointsUsed)
return;
if (TransitionTime != 0)
{
//Check the array is big enough
if (PretransitingSave.size()<JointChildSceneNodes.size())
{
for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
if (TransitionTime != 0) {
// Check the array is big enough
if (PretransitingSave.size() < JointChildSceneNodes.size()) {
for (u32 n = PretransitingSave.size(); n < JointChildSceneNodes.size(); ++n)
PretransitingSave.push_back(core::matrix4());
}
//Copy the position of joints
for (u32 n=0;n<JointChildSceneNodes.size();++n)
PretransitingSave[n]=JointChildSceneNodes[n]->getRelativeTransformation();
// Copy the position of joints
for (u32 n = 0; n < JointChildSceneNodes.size(); ++n)
PretransitingSave[n] = JointChildSceneNodes[n]->getRelativeTransformation();
Transiting = core::reciprocal((f32)TransitionTime);
}
TransitingBlend = 0.f;
}
/*!
*/
ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
*/
ISceneNode *CAnimatedMeshSceneNode::clone(ISceneNode *newParent, ISceneManager *newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CAnimatedMeshSceneNode* newNode =
new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation,
RelativeRotation, RelativeScale);
CAnimatedMeshSceneNode *newNode =
new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation,
RelativeRotation, RelativeScale);
if (newParent)
{
newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called
if (newParent) {
newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called
newNode->drop();
}
@ -847,6 +756,5 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager*
return newNode;
}
} // end namespace scene
} // end namespace irr

View File

@ -9,173 +9,169 @@
#include "matrix4.h"
namespace irr
{
namespace scene
{
class IDummyTransformationSceneNode;
class IDummyTransformationSceneNode;
class CAnimatedMeshSceneNode : public IAnimatedMeshSceneNode
{
public:
class CAnimatedMeshSceneNode : public IAnimatedMeshSceneNode
{
public:
//! constructor
CAnimatedMeshSceneNode(IAnimatedMesh *mesh, ISceneNode *parent, ISceneManager *mgr, s32 id,
const core::vector3df &position = core::vector3df(0, 0, 0),
const core::vector3df &rotation = core::vector3df(0, 0, 0),
const core::vector3df &scale = core::vector3df(1.0f, 1.0f, 1.0f));
//! constructor
CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
//! destructor
virtual ~CAnimatedMeshSceneNode();
//! destructor
virtual ~CAnimatedMeshSceneNode();
//! sets the current frame. from now on the animation is played from this frame.
void setCurrentFrame(f32 frame) override;
//! sets the current frame. from now on the animation is played from this frame.
void setCurrentFrame(f32 frame) override;
//! frame
void OnRegisterSceneNode() override;
//! frame
void OnRegisterSceneNode() override;
//! OnAnimate() is called just before rendering the whole scene.
void OnAnimate(u32 timeMs) override;
//! OnAnimate() is called just before rendering the whole scene.
void OnAnimate(u32 timeMs) override;
//! renders the node.
void render() override;
//! renders the node.
void render() override;
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32> &getBoundingBox() const override;
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& getBoundingBox() const override;
//! sets the frames between the animation is looped.
//! the default is 0 - MaximalFrameCount of the mesh.
//! NOTE: setMesh will also change this value and set it to the full range of animations of the mesh
bool setFrameLoop(s32 begin, s32 end) override;
//! sets the frames between the animation is looped.
//! the default is 0 - MaximalFrameCount of the mesh.
//! NOTE: setMesh will also change this value and set it to the full range of animations of the mesh
bool setFrameLoop(s32 begin, s32 end) override;
//! Sets looping mode which is on by default. If set to false,
//! animations will not be looped.
void setLoopMode(bool playAnimationLooped) override;
//! Sets looping mode which is on by default. If set to false,
//! animations will not be looped.
void setLoopMode(bool playAnimationLooped) override;
//! returns the current loop mode
bool getLoopMode() const override;
//! returns the current loop mode
bool getLoopMode() const override;
//! Sets a callback interface which will be called if an animation
//! playback has ended. Set this to 0 to disable the callback again.
void setAnimationEndCallback(IAnimationEndCallBack *callback = 0) override;
//! Sets a callback interface which will be called if an animation
//! playback has ended. Set this to 0 to disable the callback again.
void setAnimationEndCallback(IAnimationEndCallBack* callback=0) override;
//! sets the speed with which the animation is played
//! NOTE: setMesh will also change this value and set it to the default speed of the mesh
void setAnimationSpeed(f32 framesPerSecond) override;
//! sets the speed with which the animation is played
//! NOTE: setMesh will also change this value and set it to the default speed of the mesh
void setAnimationSpeed(f32 framesPerSecond) override;
//! gets the speed with which the animation is played
f32 getAnimationSpeed() const override;
//! gets the speed with which the animation is played
f32 getAnimationSpeed() const override;
//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hierarchy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial &getMaterial(u32 i) override;
//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hierarchy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial& getMaterial(u32 i) override;
//! returns amount of materials used by this scene node.
u32 getMaterialCount() const override;
//! returns amount of materials used by this scene node.
u32 getMaterialCount() const override;
//! Returns a pointer to a child node, which has the same transformation as
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
IBoneSceneNode *getJointNode(const c8 *jointName) override;
//! Returns a pointer to a child node, which has the same transformation as
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
IBoneSceneNode* getJointNode(const c8* jointName) override;
//! same as getJointNode(const c8* jointName), but based on id
IBoneSceneNode *getJointNode(u32 jointID) override;
//! same as getJointNode(const c8* jointName), but based on id
IBoneSceneNode* getJointNode(u32 jointID) override;
//! Gets joint count.
u32 getJointCount() const override;
//! Gets joint count.
u32 getJointCount() const override;
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached child.
bool removeChild(ISceneNode *child) override;
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached child.
bool removeChild(ISceneNode* child) override;
//! Returns the current displayed frame number.
f32 getFrameNr() const override;
//! Returns the current start frame number.
s32 getStartFrame() const override;
//! Returns the current end frame number.
s32 getEndFrame() const override;
//! Returns the current displayed frame number.
f32 getFrameNr() const override;
//! Returns the current start frame number.
s32 getStartFrame() const override;
//! Returns the current end frame number.
s32 getEndFrame() const override;
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
referencing this mesh to change too. */
void setReadOnlyMaterials(bool readonly) override;
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
referencing this mesh to change too. */
void setReadOnlyMaterials(bool readonly) override;
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
bool isReadOnlyMaterials() const override;
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
bool isReadOnlyMaterials() const override;
//! Sets a new mesh
void setMesh(IAnimatedMesh *mesh) override;
//! Sets a new mesh
void setMesh(IAnimatedMesh* mesh) override;
//! Returns the current mesh
IAnimatedMesh *getMesh(void) override { return Mesh; }
//! Returns the current mesh
IAnimatedMesh* getMesh(void) override { return Mesh; }
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_ANIMATED_MESH; }
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_ANIMATED_MESH; }
//! updates the absolute position based on the relative and the parents position
void updateAbsolutePosition() override;
//! updates the absolute position based on the relative and the parents position
void updateAbsolutePosition() override;
//! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
void setJointMode(E_JOINT_UPDATE_ON_RENDER mode) override;
//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
//! you must call animateJoints(), or the mesh will not animate
void setTransitionTime(f32 Time) override;
//! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
void setJointMode(E_JOINT_UPDATE_ON_RENDER mode) override;
//! updates the joint positions of this mesh
void animateJoints(bool CalculateAbsolutePositions = true) override;
//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
//! you must call animateJoints(), or the mesh will not animate
void setTransitionTime(f32 Time) override;
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
void setRenderFromIdentity(bool On) override;
//! updates the joint positions of this mesh
void animateJoints(bool CalculateAbsolutePositions=true) override;
//! Creates a clone of this scene node and its children.
/** \param newParent An optional new parent.
\param newManager An optional new scene manager.
\return The newly created clone of this node. */
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
void setRenderFromIdentity( bool On ) override;
private:
//! Get a static mesh for the current frame of this animated mesh
IMesh *getMeshForCurrentFrame();
//! Creates a clone of this scene node and its children.
/** \param newParent An optional new parent.
\param newManager An optional new scene manager.
\return The newly created clone of this node. */
ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) override;
void buildFrameNr(u32 timeMs);
void checkJoints();
void beginTransition();
private:
core::array<video::SMaterial> Materials;
core::aabbox3d<f32> Box;
IAnimatedMesh *Mesh;
//! Get a static mesh for the current frame of this animated mesh
IMesh* getMeshForCurrentFrame();
s32 StartFrame;
s32 EndFrame;
f32 FramesPerSecond;
f32 CurrentFrameNr;
void buildFrameNr(u32 timeMs);
void checkJoints();
void beginTransition();
u32 LastTimeMs;
u32 TransitionTime; // Transition time in millisecs
f32 Transiting; // is mesh transiting (plus cache of TransitionTime)
f32 TransitingBlend; // 0-1, calculated on buildFrameNr
core::array<video::SMaterial> Materials;
core::aabbox3d<f32> Box;
IAnimatedMesh* Mesh;
// 0-unused, 1-get joints only, 2-set joints only, 3-move and set
E_JOINT_UPDATE_ON_RENDER JointMode;
bool JointsUsed;
s32 StartFrame;
s32 EndFrame;
f32 FramesPerSecond;
f32 CurrentFrameNr;
bool Looping;
bool ReadOnlyMaterials;
bool RenderFromIdentity;
u32 LastTimeMs;
u32 TransitionTime; //Transition time in millisecs
f32 Transiting; //is mesh transiting (plus cache of TransitionTime)
f32 TransitingBlend; //0-1, calculated on buildFrameNr
IAnimationEndCallBack *LoopCallBack;
s32 PassCount;
//0-unused, 1-get joints only, 2-set joints only, 3-move and set
E_JOINT_UPDATE_ON_RENDER JointMode;
bool JointsUsed;
bool Looping;
bool ReadOnlyMaterials;
bool RenderFromIdentity;
IAnimationEndCallBack* LoopCallBack;
s32 PassCount;
core::array<IBoneSceneNode* > JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave;
};
core::array<IBoneSceneNode *> JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave;
};
} // end namespace scene
} // end namespace irr

View File

@ -20,8 +20,7 @@ namespace io
class CBoolAttribute : public IAttribute
{
public:
CBoolAttribute(const char* name, bool value)
CBoolAttribute(const char *name, bool value)
{
Name = name;
setBool(value);
@ -69,8 +68,7 @@ public:
class CIntAttribute : public IAttribute
{
public:
CIntAttribute(const char* name, s32 value)
CIntAttribute(const char *name, s32 value)
{
Name = name;
setInt(value);
@ -108,8 +106,7 @@ public:
class CFloatAttribute : public IAttribute
{
public:
CFloatAttribute(const char* name, f32 value)
CFloatAttribute(const char *name, f32 value)
{
Name = name;
setFloat(value);

View File

@ -12,12 +12,12 @@ namespace irr
namespace io
{
CAttributes::CAttributes(video::IVideoDriver* driver)
: Driver(driver)
CAttributes::CAttributes(video::IVideoDriver *driver) :
Driver(driver)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CAttributes");
#endif
#endif
if (Driver)
Driver->grab();
@ -31,30 +31,28 @@ CAttributes::~CAttributes()
Driver->drop();
}
//! Removes all attributes
void CAttributes::clear()
{
for (u32 i=0; i<Attributes.size(); ++i)
for (u32 i = 0; i < Attributes.size(); ++i)
Attributes[i]->drop();
Attributes.clear();
}
//! Returns attribute index from name, -1 if not found
s32 CAttributes::findAttribute(const c8* attributeName) const
s32 CAttributes::findAttribute(const c8 *attributeName) const
{
for (u32 i=0; i<Attributes.size(); ++i)
for (u32 i = 0; i < Attributes.size(); ++i)
if (Attributes[i]->Name == attributeName)
return i;
return -1;
}
IAttribute* CAttributes::getAttributeP(const c8* attributeName) const
IAttribute *CAttributes::getAttributeP(const c8 *attributeName) const
{
for (u32 i=0; i<Attributes.size(); ++i)
for (u32 i = 0; i < Attributes.size(); ++i)
if (Attributes[i]->Name == attributeName)
return Attributes[i];
@ -62,13 +60,12 @@ IAttribute* CAttributes::getAttributeP(const c8* attributeName) const
}
//! Sets a attribute as boolean value
void CAttributes::setAttribute(const c8* attributeName, bool value)
void CAttributes::setAttribute(const c8 *attributeName, bool value)
{
IAttribute* att = getAttributeP(attributeName);
IAttribute *att = getAttributeP(attributeName);
if (att)
att->setBool(value);
else
{
else {
Attributes.push_back(new CBoolAttribute(attributeName, value));
}
}
@ -77,9 +74,9 @@ void CAttributes::setAttribute(const c8* attributeName, bool value)
//! \param attributeName: Name of the attribute to get.
//! \return Returns value of the attribute previously set by setAttribute() as bool
//! or 0 if attribute is not set.
bool CAttributes::getAttributeAsBool(const c8* attributeName, bool defaultNotFound) const
bool CAttributes::getAttributeAsBool(const c8 *attributeName, bool defaultNotFound) const
{
const IAttribute* att = getAttributeP(attributeName);
const IAttribute *att = getAttributeP(attributeName);
if (att)
return att->getBool();
else
@ -87,13 +84,12 @@ bool CAttributes::getAttributeAsBool(const c8* attributeName, bool defaultNotFou
}
//! Sets a attribute as integer value
void CAttributes::setAttribute(const c8* attributeName, s32 value)
void CAttributes::setAttribute(const c8 *attributeName, s32 value)
{
IAttribute* att = getAttributeP(attributeName);
IAttribute *att = getAttributeP(attributeName);
if (att)
att->setInt(value);
else
{
else {
Attributes.push_back(new CIntAttribute(attributeName, value));
}
}
@ -102,9 +98,9 @@ void CAttributes::setAttribute(const c8* attributeName, s32 value)
//! \param attributeName: Name of the attribute to get.
//! \return Returns value of the attribute previously set by setAttribute() as integer
//! or 0 if attribute is not set.
s32 CAttributes::getAttributeAsInt(const c8* attributeName, irr::s32 defaultNotFound) const
s32 CAttributes::getAttributeAsInt(const c8 *attributeName, irr::s32 defaultNotFound) const
{
const IAttribute* att = getAttributeP(attributeName);
const IAttribute *att = getAttributeP(attributeName);
if (att)
return att->getInt();
else
@ -112,9 +108,9 @@ s32 CAttributes::getAttributeAsInt(const c8* attributeName, irr::s32 defaultNotF
}
//! Sets a attribute as float value
void CAttributes::setAttribute(const c8* attributeName, f32 value)
void CAttributes::setAttribute(const c8 *attributeName, f32 value)
{
IAttribute* att = getAttributeP(attributeName);
IAttribute *att = getAttributeP(attributeName);
if (att)
att->setFloat(value);
else
@ -125,9 +121,9 @@ void CAttributes::setAttribute(const c8* attributeName, f32 value)
//! \param attributeName: Name of the attribute to get.
//! \return Returns value of the attribute previously set by setAttribute() as float value
//! or 0 if attribute is not set.
f32 CAttributes::getAttributeAsFloat(const c8* attributeName, irr::f32 defaultNotFound) const
f32 CAttributes::getAttributeAsFloat(const c8 *attributeName, irr::f32 defaultNotFound) const
{
const IAttribute* att = getAttributeP(attributeName);
const IAttribute *att = getAttributeP(attributeName);
if (att)
return att->getFloat();
@ -142,7 +138,7 @@ u32 CAttributes::getAttributeCount() const
//! Returns string attribute name by index.
//! \param index: Index value, must be between 0 and getStringAttributeCount()-1.
const c8* CAttributes::getAttributeName(s32 index) const
const c8 *CAttributes::getAttributeName(s32 index) const
{
if ((u32)index >= Attributes.size())
return 0;
@ -151,11 +147,11 @@ const c8* CAttributes::getAttributeName(s32 index) const
}
//! Returns the type of an attribute
E_ATTRIBUTE_TYPE CAttributes::getAttributeType(const c8* attributeName) const
E_ATTRIBUTE_TYPE CAttributes::getAttributeType(const c8 *attributeName) const
{
E_ATTRIBUTE_TYPE ret = EAT_UNKNOWN;
const IAttribute* att = getAttributeP(attributeName);
const IAttribute *att = getAttributeP(attributeName);
if (att)
ret = att->getType();
@ -205,25 +201,25 @@ bool CAttributes::getAttributeAsBool(s32 index) const
}
//! Adds an attribute as integer
void CAttributes::addInt(const c8* attributeName, s32 value)
void CAttributes::addInt(const c8 *attributeName, s32 value)
{
Attributes.push_back(new CIntAttribute(attributeName, value));
}
//! Adds an attribute as float
void CAttributes::addFloat(const c8* attributeName, f32 value)
void CAttributes::addFloat(const c8 *attributeName, f32 value)
{
Attributes.push_back(new CFloatAttribute(attributeName, value));
}
//! Adds an attribute as bool
void CAttributes::addBool(const c8* attributeName, bool value)
void CAttributes::addBool(const c8 *attributeName, bool value)
{
Attributes.push_back(new CBoolAttribute(attributeName, value));
}
//! Returns if an attribute with a name exists
bool CAttributes::existsAttribute(const c8* attributeName) const
bool CAttributes::existsAttribute(const c8 *attributeName) const
{
return getAttributeP(attributeName) != 0;
}
@ -251,4 +247,3 @@ void CAttributes::setAttribute(s32 index, f32 value)
} // end namespace io
} // end namespace irr

View File

@ -11,19 +11,17 @@ namespace irr
{
namespace video
{
class ITexture;
class IVideoDriver;
class ITexture;
class IVideoDriver;
}
namespace io
{
//! Implementation of the IAttributes interface
class CAttributes : public IAttributes
{
public:
CAttributes(video::IVideoDriver* driver=0);
CAttributes(video::IVideoDriver *driver = 0);
~CAttributes();
//! Returns amount of attributes in this collection of attributes.
@ -31,26 +29,25 @@ public:
//! Returns attribute name by index.
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
const c8* getAttributeName(s32 index) const override;
const c8 *getAttributeName(s32 index) const override;
//! Returns the type of an attribute
//! \param attributeName: Name for the attribute
E_ATTRIBUTE_TYPE getAttributeType(const c8* attributeName) const override;
E_ATTRIBUTE_TYPE getAttributeType(const c8 *attributeName) const override;
//! Returns attribute type by index.
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
E_ATTRIBUTE_TYPE getAttributeType(s32 index) const override;
//! Returns if an attribute with a name exists
bool existsAttribute(const c8* attributeName) const override;
bool existsAttribute(const c8 *attributeName) const override;
//! Returns attribute index from name, -1 if not found
s32 findAttribute(const c8* attributeName) const override;
s32 findAttribute(const c8 *attributeName) const override;
//! Removes all attributes
void clear() override;
/*
Integer Attribute
@ -58,16 +55,16 @@ public:
*/
//! Adds an attribute as integer
void addInt(const c8* attributeName, s32 value) override;
void addInt(const c8 *attributeName, s32 value) override;
//! Sets an attribute as integer value
void setAttribute(const c8* attributeName, s32 value) override;
void setAttribute(const c8 *attributeName, s32 value) override;
//! Gets an attribute as integer value
//! \param attributeName: Name of the attribute to get.
//! \param defaultNotFound Value returned when attributeName was not found
//! \return Returns value of the attribute previously set by setAttribute()
s32 getAttributeAsInt(const c8* attributeName, irr::s32 defaultNotFound=0) const override;
s32 getAttributeAsInt(const c8 *attributeName, irr::s32 defaultNotFound = 0) const override;
//! Gets an attribute as integer value
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
@ -83,16 +80,16 @@ public:
*/
//! Adds an attribute as float
void addFloat(const c8* attributeName, f32 value) override;
void addFloat(const c8 *attributeName, f32 value) override;
//! Sets a attribute as float value
void setAttribute(const c8* attributeName, f32 value) override;
void setAttribute(const c8 *attributeName, f32 value) override;
//! Gets an attribute as float value
//! \param attributeName: Name of the attribute to get.
//! \param defaultNotFound Value returned when attributeName was not found
//! \return Returns value of the attribute previously set by setAttribute()
f32 getAttributeAsFloat(const c8* attributeName, irr::f32 defaultNotFound=0.f) const override;
f32 getAttributeAsFloat(const c8 *attributeName, irr::f32 defaultNotFound = 0.f) const override;
//! Gets an attribute as float value
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
@ -101,22 +98,21 @@ public:
//! Sets an attribute as float value
void setAttribute(s32 index, f32 value) override;
/*
Bool Attribute
*/
//! Adds an attribute as bool
void addBool(const c8* attributeName, bool value) override;
void addBool(const c8 *attributeName, bool value) override;
//! Sets an attribute as boolean value
void setAttribute(const c8* attributeName, bool value) override;
void setAttribute(const c8 *attributeName, bool value) override;
//! Gets an attribute as boolean value
//! \param attributeName: Name of the attribute to get.
//! \param defaultNotFound Value returned when attributeName was not found
//! \return Returns value of the attribute previously set by setAttribute()
bool getAttributeAsBool(const c8* attributeName, bool defaultNotFound=false) const override;
bool getAttributeAsBool(const c8 *attributeName, bool defaultNotFound = false) const override;
//! Gets an attribute as boolean value
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
@ -126,14 +122,12 @@ public:
void setAttribute(s32 index, bool value) override;
protected:
core::array<IAttribute *> Attributes;
core::array<IAttribute*> Attributes;
IAttribute *getAttributeP(const c8 *attributeName) const;
IAttribute* getAttributeP(const c8* attributeName) const;
video::IVideoDriver* Driver;
video::IVideoDriver *Driver;
};
} // end namespace io
} // end namespace irr

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,6 @@
// File format designed by Mark Sibly for the Blitz3D engine and has been
// declared public domain
#pragma once
#include "IMeshLoader.h"
@ -25,35 +24,33 @@ namespace scene
class CB3DMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CB3DMeshFileLoader(scene::ISceneManager* smgr);
CB3DMeshFileLoader(scene::ISceneManager *smgr);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool isALoadableFileExtension(const io::path& filename) const override;
bool isALoadableFileExtension(const io::path &filename) const override;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* createMesh(io::IReadFile* file) override;
IAnimatedMesh *createMesh(io::IReadFile *file) override;
private:
bool load();
bool readChunkNODE(CSkinnedMesh::SJoint* InJoint);
bool readChunkMESH(CSkinnedMesh::SJoint* InJoint);
bool readChunkVRTS(CSkinnedMesh::SJoint* InJoint);
bool readChunkNODE(CSkinnedMesh::SJoint *InJoint);
bool readChunkMESH(CSkinnedMesh::SJoint *InJoint);
bool readChunkVRTS(CSkinnedMesh::SJoint *InJoint);
bool readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 Vertices_Start);
bool readChunkBONE(CSkinnedMesh::SJoint* InJoint);
bool readChunkKEYS(CSkinnedMesh::SJoint* InJoint);
bool readChunkBONE(CSkinnedMesh::SJoint *InJoint);
bool readChunkKEYS(CSkinnedMesh::SJoint *InJoint);
bool readChunkANIM();
bool readChunkTEXS();
bool readChunkBRUS();
std::string readString();
void readFloats(f32* vec, u32 count);
void readFloats(f32 *vec, u32 count);
core::array<SB3dChunk> B3dStack;
@ -66,11 +63,11 @@ private:
core::array<video::S3DVertex2TCoords> BaseVertices;
CSkinnedMesh* AnimatedMesh;
io::IReadFile* B3DFile;
CSkinnedMesh *AnimatedMesh;
io::IReadFile *B3DFile;
//B3Ds have Vertex ID's local within the mesh I don't want this
// Variable needs to be class member due to recursion in calls
// B3Ds have Vertex ID's local within the mesh I don't want this
// Variable needs to be class member due to recursion in calls
u32 VerticesStart;
bool NormalsInFile;
@ -78,6 +75,5 @@ private:
bool ShowWarning;
};
} // end namespace scene
} // end namespace irr

View File

@ -14,15 +14,15 @@ namespace scene
{
//! constructor
CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::dimension2d<f32>& size,
video::SColor colorTop, video::SColor colorBottom)
: IBillboardSceneNode(parent, mgr, id, position)
, Buffer(new SMeshBuffer())
CBillboardSceneNode::CBillboardSceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id,
const core::vector3df &position, const core::dimension2d<f32> &size,
video::SColor colorTop, video::SColor colorBottom) :
IBillboardSceneNode(parent, mgr, id, position),
Buffer(new SMeshBuffer())
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CBillboardSceneNode");
#endif
#endif
setSize(size);
@ -63,12 +63,11 @@ void CBillboardSceneNode::OnRegisterSceneNode()
ISceneNode::OnRegisterSceneNode();
}
//! render
void CBillboardSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
ICameraSceneNode* camera = SceneManager->getActiveCamera();
video::IVideoDriver *driver = SceneManager->getVideoDriver();
ICameraSceneNode *camera = SceneManager->getActiveCamera();
if (!camera || !driver)
return;
@ -80,17 +79,16 @@ void CBillboardSceneNode::render()
driver->setMaterial(Buffer->Material);
driver->drawMeshBuffer(Buffer);
if (DebugDataVisible & scene::EDS_BBOX)
{
if (DebugDataVisible & scene::EDS_BBOX) {
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
video::SMaterial m;
m.Lighting = false;
driver->setMaterial(m);
driver->draw3DBox(BBoxSafe, video::SColor(0,208,195,152));
driver->draw3DBox(BBoxSafe, video::SColor(0, 208, 195, 152));
}
}
void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode *camera)
{
// billboard looks toward camera
core::vector3df pos = getAbsolutePosition();
@ -102,9 +100,8 @@ void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
view.normalize();
core::vector3df horizontal = up.crossProduct(view);
if ( horizontal.getLength() == 0 )
{
horizontal.set(up.Y,up.X,up.Z);
if (horizontal.getLength() == 0) {
horizontal.set(up.Y, up.X, up.Z);
}
horizontal.normalize();
core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth;
@ -117,9 +114,9 @@ void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
view *= -1.0f;
core::array<video::S3DVertex>& vertices = Buffer->Vertices;
core::array<video::S3DVertex> &vertices = Buffer->Vertices;
for (s32 i=0; i<4; ++i)
for (s32 i = 0; i < 4; ++i)
vertices[i].Normal = view;
/* Vertices are:
@ -137,21 +134,20 @@ void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
Buffer->recalculateBoundingBox();
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const
const core::aabbox3d<f32> &CBillboardSceneNode::getBoundingBox() const
{
// Really wrong when scaled (as the node does not scale it's vertices - maybe it should?)
return BBoxSafe;
}
const core::aabbox3d<f32>& CBillboardSceneNode::getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera)
const core::aabbox3d<f32> &CBillboardSceneNode::getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode *camera)
{
updateMesh(camera);
return Buffer->BoundingBox;
}
void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
void CBillboardSceneNode::setSize(const core::dimension2d<f32> &size)
{
Size = size;
@ -162,12 +158,11 @@ void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
if (core::equals(Size.Height, 0.0f))
Size.Height = 1.0f;
const f32 extent = 0.5f*sqrtf(Size.Width*Size.Width + Size.Height*Size.Height);
BBoxSafe.MinEdge.set(-extent,-extent,-extent);
BBoxSafe.MaxEdge.set(extent,extent,extent);
const f32 extent = 0.5f * sqrtf(Size.Width * Size.Width + Size.Height * Size.Height);
BBoxSafe.MinEdge.set(-extent, -extent, -extent);
BBoxSafe.MaxEdge.set(extent, extent, extent);
}
void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth)
{
Size.set(bottomEdgeWidth, height);
@ -176,62 +171,55 @@ void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWi
if (core::equals(Size.Height, 0.0f))
Size.Height = 1.0f;
if (core::equals(Size.Width, 0.f) && core::equals(TopEdgeWidth, 0.f))
{
if (core::equals(Size.Width, 0.f) && core::equals(TopEdgeWidth, 0.f)) {
Size.Width = 1.0f;
TopEdgeWidth = 1.0f;
}
const f32 extent = 0.5f*sqrtf(Size.Width*Size.Width + Size.Height*Size.Height);
BBoxSafe.MinEdge.set(-extent,-extent,-extent);
BBoxSafe.MaxEdge.set(extent,extent,extent);
const f32 extent = 0.5f * sqrtf(Size.Width * Size.Width + Size.Height * Size.Height);
BBoxSafe.MinEdge.set(-extent, -extent, -extent);
BBoxSafe.MaxEdge.set(extent, extent, extent);
}
video::SMaterial& CBillboardSceneNode::getMaterial(u32 i)
video::SMaterial &CBillboardSceneNode::getMaterial(u32 i)
{
return Buffer->Material;
}
//! returns amount of materials used by this scene node.
u32 CBillboardSceneNode::getMaterialCount() const
{
return 1;
}
//! gets the size of the billboard
const core::dimension2d<f32>& CBillboardSceneNode::getSize() const
const core::dimension2d<f32> &CBillboardSceneNode::getSize() const
{
return Size;
}
//! Gets the widths of the top and bottom edges of the billboard.
void CBillboardSceneNode::getSize(f32& height, f32& bottomEdgeWidth,
f32& topEdgeWidth) const
void CBillboardSceneNode::getSize(f32 &height, f32 &bottomEdgeWidth,
f32 &topEdgeWidth) const
{
height = Size.Height;
bottomEdgeWidth = Size.Width;
topEdgeWidth = TopEdgeWidth;
}
//! Set the color of all vertices of the billboard
//! \param overallColor: the color to set
void CBillboardSceneNode::setColor(const video::SColor& overallColor)
void CBillboardSceneNode::setColor(const video::SColor &overallColor)
{
for(u32 vertex = 0; vertex < 4; ++vertex)
for (u32 vertex = 0; vertex < 4; ++vertex)
Buffer->Vertices[vertex].Color = overallColor;
}
//! Set the color of the top and bottom vertices of the billboard
//! \param topColor: the color to set the top vertices
//! \param bottomColor: the color to set the bottom vertices
void CBillboardSceneNode::setColor(const video::SColor& topColor,
const video::SColor& bottomColor)
void CBillboardSceneNode::setColor(const video::SColor &topColor,
const video::SColor &bottomColor)
{
Buffer->Vertices[0].Color = bottomColor;
Buffer->Vertices[1].Color = topColor;
@ -239,43 +227,40 @@ void CBillboardSceneNode::setColor(const video::SColor& topColor,
Buffer->Vertices[3].Color = bottomColor;
}
//! Gets the color of the top and bottom vertices of the billboard
//! \param[out] topColor: stores the color of the top vertices
//! \param[out] bottomColor: stores the color of the bottom vertices
void CBillboardSceneNode::getColor(video::SColor& topColor,
video::SColor& bottomColor) const
void CBillboardSceneNode::getColor(video::SColor &topColor,
video::SColor &bottomColor) const
{
bottomColor = Buffer->Vertices[0].Color;
topColor = Buffer->Vertices[1].Color;
}
//! Creates a clone of this scene node and its children.
ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
ISceneNode *CBillboardSceneNode::clone(ISceneNode *newParent, ISceneManager *newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CBillboardSceneNode* nb = new CBillboardSceneNode(newParent,
newManager, ID, RelativeTranslation, Size);
CBillboardSceneNode *nb = new CBillboardSceneNode(newParent,
newManager, ID, RelativeTranslation, Size);
nb->cloneMembers(this, newManager);
nb->Buffer->Material = Buffer->Material;
nb->Size = Size;
nb->TopEdgeWidth = this->TopEdgeWidth;
video::SColor topColor,bottomColor;
getColor(topColor,bottomColor);
nb->setColor(topColor,bottomColor);
video::SColor topColor, bottomColor;
getColor(topColor, bottomColor);
nb->setColor(topColor, bottomColor);
if ( newParent )
if (newParent)
nb->drop();
return nb;
}
} // end namespace scene
} // end namespace irr

View File

@ -17,12 +17,11 @@ namespace scene
class CBillboardSceneNode : virtual public IBillboardSceneNode
{
public:
//! constructor
CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::dimension2d<f32>& size,
video::SColor colorTop=video::SColor(0xFFFFFFFF),
video::SColor colorBottom=video::SColor(0xFFFFFFFF));
CBillboardSceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id,
const core::vector3df &position, const core::dimension2d<f32> &size,
video::SColor colorTop = video::SColor(0xFFFFFFFF),
video::SColor colorBottom = video::SColor(0xFFFFFFFF));
virtual ~CBillboardSceneNode();
@ -33,43 +32,43 @@ public:
void render() override;
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& getBoundingBox() const override;
const core::aabbox3d<f32> &getBoundingBox() const override;
//! sets the size of the billboard
void setSize(const core::dimension2d<f32>& size) override;
void setSize(const core::dimension2d<f32> &size) override;
//! Sets the widths of the top and bottom edges of the billboard independently.
void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth) override;
//! gets the size of the billboard
const core::dimension2d<f32>& getSize() const override;
const core::dimension2d<f32> &getSize() const override;
//! Gets the widths of the top and bottom edges of the billboard.
void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const override;
void getSize(f32 &height, f32 &bottomEdgeWidth, f32 &topEdgeWidth) const override;
video::SMaterial& getMaterial(u32 i) override;
video::SMaterial &getMaterial(u32 i) override;
//! returns amount of materials used by this scene node.
u32 getMaterialCount() const override;
//! Set the color of all vertices of the billboard
//! \param overallColor: the color to set
void setColor(const video::SColor& overallColor) override;
void setColor(const video::SColor &overallColor) override;
//! Set the color of the top and bottom vertices of the billboard
//! \param topColor: the color to set the top vertices
//! \param bottomColor: the color to set the bottom vertices
virtual void setColor(const video::SColor& topColor,
const video::SColor& bottomColor) override;
virtual void setColor(const video::SColor &topColor,
const video::SColor &bottomColor) override;
//! Gets the color of the top and bottom vertices of the billboard
//! \param[out] topColor: stores the color of the top vertices
//! \param[out] bottomColor: stores the color of the bottom vertices
virtual void getColor(video::SColor& topColor,
video::SColor& bottomColor) const override;
virtual void getColor(video::SColor &topColor,
video::SColor &bottomColor) const override;
//! Get the real boundingbox used by the billboard (which depends on the active camera)
const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) override;
const core::aabbox3d<f32> &getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode *camera) override;
//! Get the amount of mesh buffers.
u32 getMeshBufferCount() const override
@ -78,9 +77,9 @@ public:
}
//! Get pointer to the mesh buffer.
IMeshBuffer* getMeshBuffer(u32 nr) const override
IMeshBuffer *getMeshBuffer(u32 nr) const override
{
if ( nr == 0 )
if (nr == 0)
return Buffer;
return 0;
}
@ -89,13 +88,12 @@ public:
ESCENE_NODE_TYPE getType() const override { return ESNT_BILLBOARD; }
//! Creates a clone of this scene node and its children.
ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) override;
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
protected:
void updateMesh(const irr::scene::ICameraSceneNode* camera);
void updateMesh(const irr::scene::ICameraSceneNode *camera);
private:
//! Size.Width is the bottom edge width
core::dimension2d<f32> Size;
f32 TopEdgeWidth;
@ -104,14 +102,12 @@ private:
// TODO: BUG - still can be wrong with scaling < 1. Billboards should calculate relative coordinates for their mesh
// and then use the node-scaling. But needs some work...
/** Note that we can't use the real boundingbox for culling because at that point
the camera which is used to calculate the billboard is not yet updated. So we only
know the real boundingbox after rendering - which is too late for culling. */
the camera which is used to calculate the billboard is not yet updated. So we only
know the real boundingbox after rendering - which is too late for culling. */
core::aabbox3d<f32> BBoxSafe;
scene::SMeshBuffer* Buffer;
scene::SMeshBuffer *Buffer;
};
} // end namespace scene
} // end namespace irr

File diff suppressed because it is too large Load Diff

View File

@ -12,25 +12,24 @@ namespace scene
{
//! constructor
CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
u32 boneIndex, const std::optional<std::string> &boneName)
: IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex),
AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL)
CBoneSceneNode::CBoneSceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id,
u32 boneIndex, const std::optional<std::string> &boneName) :
IBoneSceneNode(parent, mgr, id),
BoneIndex(boneIndex),
AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CBoneSceneNode");
#endif
#endif
setName(boneName);
}
//! Returns the index of the bone
u32 CBoneSceneNode::getBoneIndex() const
{
return BoneIndex;
}
//! Sets the animation mode of the bone. Returns true if successful.
bool CBoneSceneNode::setAnimationMode(E_BONE_ANIMATION_MODE mode)
{
@ -38,21 +37,18 @@ bool CBoneSceneNode::setAnimationMode(E_BONE_ANIMATION_MODE mode)
return true;
}
//! Gets the current animation mode of the bone
E_BONE_ANIMATION_MODE CBoneSceneNode::getAnimationMode() const
{
return AnimationMode;
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CBoneSceneNode::getBoundingBox() const
const core::aabbox3d<f32> &CBoneSceneNode::getBoundingBox() const
{
return Box;
}
/*
//! Returns the relative transformation of the scene node.
core::matrix4 CBoneSceneNode::getRelativeTransformation() const
@ -61,13 +57,11 @@ core::matrix4 CBoneSceneNode::getRelativeTransformation() const
}
*/
void CBoneSceneNode::OnAnimate(u32 timeMs)
{
if (IsVisible)
{
if (IsVisible) {
// update absolute position
//updateAbsolutePosition();
// updateAbsolutePosition();
// perform the post render process on all children
ISceneNodeList::iterator it = Children.begin();
@ -76,24 +70,20 @@ void CBoneSceneNode::OnAnimate(u32 timeMs)
}
}
void CBoneSceneNode::helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node)
{
Node->updateAbsolutePosition();
ISceneNodeList::const_iterator it = Node->getChildren().begin();
for (; it != Node->getChildren().end(); ++it)
{
helper_updateAbsolutePositionOfAllChildren( (*it) );
for (; it != Node->getChildren().end(); ++it) {
helper_updateAbsolutePositionOfAllChildren((*it));
}
}
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
{
helper_updateAbsolutePositionOfAllChildren( this );
helper_updateAbsolutePositionOfAllChildren(this);
}
} // namespace scene
} // namespace irr

View File

@ -15,59 +15,56 @@ namespace irr
namespace scene
{
class CBoneSceneNode : public IBoneSceneNode
{
public:
//! constructor
CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr,
s32 id=-1, u32 boneIndex=0,
class CBoneSceneNode : public IBoneSceneNode
{
public:
//! constructor
CBoneSceneNode(ISceneNode *parent, ISceneManager *mgr,
s32 id = -1, u32 boneIndex = 0,
const std::optional<std::string> &boneName = std::nullopt);
//! Returns the index of the bone
u32 getBoneIndex() const override;
//! Returns the index of the bone
u32 getBoneIndex() const override;
//! Sets the animation mode of the bone. Returns true if successful.
bool setAnimationMode(E_BONE_ANIMATION_MODE mode) override;
//! Sets the animation mode of the bone. Returns true if successful.
bool setAnimationMode(E_BONE_ANIMATION_MODE mode) override;
//! Gets the current animation mode of the bone
E_BONE_ANIMATION_MODE getAnimationMode() const override;
//! Gets the current animation mode of the bone
E_BONE_ANIMATION_MODE getAnimationMode() const override;
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& getBoundingBox() const override;
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32> &getBoundingBox() const override;
/*
//! Returns the relative transformation of the scene node.
//core::matrix4 getRelativeTransformation() const override;
*/
/*
//! Returns the relative transformation of the scene node.
//core::matrix4 getRelativeTransformation() const override;
*/
void OnAnimate(u32 timeMs) override;
void OnAnimate(u32 timeMs) override;
void updateAbsolutePositionOfAllChildren() override;
void updateAbsolutePositionOfAllChildren() override;
//! How the relative transformation of the bone is used
void setSkinningSpace(E_BONE_SKINNING_SPACE space) override
{
SkinningSpace=space;
}
//! How the relative transformation of the bone is used
void setSkinningSpace(E_BONE_SKINNING_SPACE space) override
{
SkinningSpace = space;
}
E_BONE_SKINNING_SPACE getSkinningSpace() const override
{
return SkinningSpace;
}
E_BONE_SKINNING_SPACE getSkinningSpace() const override
{
return SkinningSpace;
}
private:
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
private:
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
u32 BoneIndex;
u32 BoneIndex;
core::aabbox3d<f32> Box;
E_BONE_ANIMATION_MODE AnimationMode;
E_BONE_SKINNING_SPACE SkinningSpace;
};
core::aabbox3d<f32> Box;
E_BONE_ANIMATION_MODE AnimationMode;
E_BONE_SKINNING_SPACE SkinningSpace;
};
} // end namespace scene
} // end namespace irr

View File

@ -12,29 +12,27 @@ namespace irr
namespace scene
{
//! constructor
CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::vector3df& lookat)
: ICameraSceneNode(parent, mgr, id, position),
BoundingBox(core::vector3df(0, 0, 0)), // Camera has no size. Still not sure if FLT_MAX might be the better variant
Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f),
InputReceiverEnabled(true), TargetAndRotationAreBound(false)
CCameraSceneNode::CCameraSceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id,
const core::vector3df &position, const core::vector3df &lookat) :
ICameraSceneNode(parent, mgr, id, position),
BoundingBox(core::vector3df(0, 0, 0)), // Camera has no size. Still not sure if FLT_MAX might be the better variant
Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f),
InputReceiverEnabled(true), TargetAndRotationAreBound(false)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CCameraSceneNode");
#endif
#endif
// set default projection
Fovy = core::PI / 2.5f; // Field of view, in radians.
Fovy = core::PI / 2.5f; // Field of view, in radians.
Aspect = 4.0f / 3.0f; // Aspect ratio.
const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0;
if (d)
{
if ( d->getCurrentRenderTargetSize().Height )
const video::IVideoDriver *const d = mgr ? mgr->getVideoDriver() : 0;
if (d) {
if (d->getCurrentRenderTargetSize().Height)
Aspect = (f32)d->getCurrentRenderTargetSize().Width /
(f32)d->getCurrentRenderTargetSize().Height;
(f32)d->getCurrentRenderTargetSize().Height;
}
ViewArea.setFarNearDistance(ZFar - ZNear);
@ -42,153 +40,134 @@ CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 i
recalculateViewArea();
}
//! Disables or enables the camera to get key or mouse inputs.
void CCameraSceneNode::setInputReceiverEnabled(bool enabled)
{
InputReceiverEnabled = enabled;
}
//! Returns if the input receiver of the camera is currently enabled.
bool CCameraSceneNode::isInputReceiverEnabled() const
{
return InputReceiverEnabled;
}
//! Sets the projection matrix of the camera.
/** The core::matrix4 class has some methods
to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH
\param projection: The new projection matrix of the camera. */
void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal)
void CCameraSceneNode::setProjectionMatrix(const core::matrix4 &projection, bool isOrthogonal)
{
IsOrthogonal = isOrthogonal;
ViewArea.getTransform ( video::ETS_PROJECTION ) = projection;
ViewArea.getTransform(video::ETS_PROJECTION) = projection;
}
//! Gets the current projection matrix of the camera
//! \return Returns the current projection matrix of the camera.
const core::matrix4& CCameraSceneNode::getProjectionMatrix() const
const core::matrix4 &CCameraSceneNode::getProjectionMatrix() const
{
return ViewArea.getTransform ( video::ETS_PROJECTION );
return ViewArea.getTransform(video::ETS_PROJECTION);
}
//! Gets the current view matrix of the camera
//! \return Returns the current view matrix of the camera.
const core::matrix4& CCameraSceneNode::getViewMatrix() const
const core::matrix4 &CCameraSceneNode::getViewMatrix() const
{
return ViewArea.getTransform ( video::ETS_VIEW );
return ViewArea.getTransform(video::ETS_VIEW);
}
//! Sets a custom view matrix affector. The matrix passed here, will be
//! multiplied with the view matrix when it gets updated.
//! This allows for custom camera setups like, for example, a reflection camera.
/** \param affector: The affector matrix. */
void CCameraSceneNode::setViewMatrixAffector(const core::matrix4& affector)
void CCameraSceneNode::setViewMatrixAffector(const core::matrix4 &affector)
{
Affector = affector;
}
//! Gets the custom view matrix affector.
const core::matrix4& CCameraSceneNode::getViewMatrixAffector() const
const core::matrix4 &CCameraSceneNode::getViewMatrixAffector() const
{
return Affector;
}
//! It is possible to send mouse and key events to the camera. Most cameras
//! may ignore this input, but camera scene nodes which are created for
//! example with scene::ISceneManager::addMayaCameraSceneNode or
//! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input
//! for changing their position, look at target or whatever.
bool CCameraSceneNode::OnEvent(const SEvent& event)
bool CCameraSceneNode::OnEvent(const SEvent &event)
{
// animators have been deleted; nothing happens here now!
return false;
}
//! sets the look at target of the camera
//! \param pos: Look at target of the camera.
void CCameraSceneNode::setTarget(const core::vector3df& pos)
void CCameraSceneNode::setTarget(const core::vector3df &pos)
{
Target = pos;
if(TargetAndRotationAreBound)
{
if (TargetAndRotationAreBound) {
const core::vector3df toTarget = Target - getAbsolutePosition();
ISceneNode::setRotation(toTarget.getHorizontalAngle());
}
}
//! Sets the rotation of the node.
/** This only modifies the relative rotation of the node.
If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's target to match the rotation.
\param rotation New rotation of the node in degrees. */
void CCameraSceneNode::setRotation(const core::vector3df& rotation)
void CCameraSceneNode::setRotation(const core::vector3df &rotation)
{
if(TargetAndRotationAreBound)
if (TargetAndRotationAreBound)
Target = getAbsolutePosition() + rotation.rotationToDirection();
ISceneNode::setRotation(rotation);
}
//! Gets the current look at target of the camera
//! \return Returns the current look at target of the camera
const core::vector3df& CCameraSceneNode::getTarget() const
const core::vector3df &CCameraSceneNode::getTarget() const
{
return Target;
}
//! sets the up vector of the camera
//! \param pos: New upvector of the camera.
void CCameraSceneNode::setUpVector(const core::vector3df& pos)
void CCameraSceneNode::setUpVector(const core::vector3df &pos)
{
UpVector = pos;
}
//! Gets the up vector of the camera.
//! \return Returns the up vector of the camera.
const core::vector3df& CCameraSceneNode::getUpVector() const
const core::vector3df &CCameraSceneNode::getUpVector() const
{
return UpVector;
}
f32 CCameraSceneNode::getNearValue() const
{
return ZNear;
}
f32 CCameraSceneNode::getFarValue() const
{
return ZFar;
}
f32 CCameraSceneNode::getAspectRatio() const
{
return Aspect;
}
f32 CCameraSceneNode::getFOV() const
{
return Fovy;
}
void CCameraSceneNode::setNearValue(f32 f)
{
ZNear = f;
@ -196,7 +175,6 @@ void CCameraSceneNode::setNearValue(f32 f)
ViewArea.setFarNearDistance(ZFar - ZNear);
}
void CCameraSceneNode::setFarValue(f32 f)
{
ZFar = f;
@ -204,48 +182,42 @@ void CCameraSceneNode::setFarValue(f32 f)
ViewArea.setFarNearDistance(ZFar - ZNear);
}
void CCameraSceneNode::setAspectRatio(f32 f)
{
Aspect = f;
recalculateProjectionMatrix();
}
void CCameraSceneNode::setFOV(f32 f)
{
Fovy = f;
recalculateProjectionMatrix();
}
void CCameraSceneNode::recalculateProjectionMatrix()
{
ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar, false);
ViewArea.getTransform(video::ETS_PROJECTION).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar, false);
IsOrthogonal = false;
}
//! prerender
void CCameraSceneNode::OnRegisterSceneNode()
{
if ( SceneManager->getActiveCamera () == this )
if (SceneManager->getActiveCamera() == this)
SceneManager->registerNodeForRendering(this, ESNRP_CAMERA);
ISceneNode::OnRegisterSceneNode();
}
//! render
void CCameraSceneNode::render()
{
updateMatrices();
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if ( driver)
{
driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform ( video::ETS_PROJECTION) );
driver->setTransform(video::ETS_VIEW, ViewArea.getTransform ( video::ETS_VIEW) );
video::IVideoDriver *driver = SceneManager->getVideoDriver();
if (driver) {
driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform(video::ETS_PROJECTION));
driver->setTransform(video::ETS_VIEW, ViewArea.getTransform(video::ETS_VIEW));
}
}
@ -263,8 +235,7 @@ void CCameraSceneNode::updateMatrices()
f32 dp = tgtv.dotProduct(up);
if ( core::equals(core::abs_<f32>(dp), 1.f) )
{
if (core::equals(core::abs_<f32>(dp), 1.f)) {
up.X += 0.5f;
}
@ -274,46 +245,41 @@ void CCameraSceneNode::updateMatrices()
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CCameraSceneNode::getBoundingBox() const
const core::aabbox3d<f32> &CCameraSceneNode::getBoundingBox() const
{
return BoundingBox;
}
//! returns the view frustum.
const SViewFrustum* CCameraSceneNode::getViewFrustum() const
const SViewFrustum *CCameraSceneNode::getViewFrustum() const
{
return &ViewArea;
}
void CCameraSceneNode::recalculateViewArea()
{
ViewArea.cameraPosition = getAbsolutePosition();
core::matrix4 m(core::matrix4::EM4CONST_NOTHING);
m.setbyproduct_nocheck(ViewArea.getTransform(video::ETS_PROJECTION),
ViewArea.getTransform(video::ETS_VIEW));
ViewArea.getTransform(video::ETS_VIEW));
ViewArea.setFrom(m, false);
}
//! Set the binding between the camera's rotation adn target.
void CCameraSceneNode::bindTargetAndRotation(bool bound)
{
TargetAndRotationAreBound = bound;
}
//! Gets the binding between the camera's rotation and target.
bool CCameraSceneNode::getTargetAndRotationBinding(void) const
{
return TargetAndRotationAreBound;
}
//! Creates a clone of this scene node and its children.
ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
ISceneNode *CCameraSceneNode::clone(ISceneNode *newParent, ISceneManager *newManager)
{
ICameraSceneNode::clone(newParent, newManager);
@ -322,8 +288,8 @@ ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan
if (!newManager)
newManager = SceneManager;
CCameraSceneNode* nb = new CCameraSceneNode(newParent,
newManager, ID, RelativeTranslation, Target);
CCameraSceneNode *nb = new CCameraSceneNode(newParent,
newManager, ID, RelativeTranslation, Target);
nb->ISceneNode::cloneMembers(this, newManager);
nb->ICameraSceneNode::cloneMembers(this);
@ -339,12 +305,10 @@ ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan
nb->InputReceiverEnabled = InputReceiverEnabled;
nb->TargetAndRotationAreBound = TargetAndRotationAreBound;
if ( newParent )
if (newParent)
nb->drop();
return nb;
}
} // end namespace
} // end namespace

View File

@ -12,156 +12,154 @@ namespace irr
namespace scene
{
class CCameraSceneNode : public ICameraSceneNode
{
public:
class CCameraSceneNode : public ICameraSceneNode
{
public:
//! constructor
CCameraSceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id,
const core::vector3df &position = core::vector3df(0, 0, 0),
const core::vector3df &lookat = core::vector3df(0, 0, 100));
//! constructor
CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& lookat = core::vector3df(0,0,100));
//! Sets the projection matrix of the camera.
/** The core::matrix4 class has some methods
to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH.
Note that the matrix will only stay as set by this method until one of
the following Methods are called: setNearValue, setFarValue, setAspectRatio, setFOV.
\param projection The new projection matrix of the camera.
\param isOrthogonal Set this to true if the matrix is an orthogonal one (e.g.
from matrix4::buildProjectionMatrixOrthoLH(). */
void setProjectionMatrix(const core::matrix4 &projection, bool isOrthogonal = false) override;
//! Sets the projection matrix of the camera.
/** The core::matrix4 class has some methods
to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH.
Note that the matrix will only stay as set by this method until one of
the following Methods are called: setNearValue, setFarValue, setAspectRatio, setFOV.
\param projection The new projection matrix of the camera.
\param isOrthogonal Set this to true if the matrix is an orthogonal one (e.g.
from matrix4::buildProjectionMatrixOrthoLH(). */
void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false) override;
//! Gets the current projection matrix of the camera
//! \return Returns the current projection matrix of the camera.
const core::matrix4 &getProjectionMatrix() const override;
//! Gets the current projection matrix of the camera
//! \return Returns the current projection matrix of the camera.
const core::matrix4& getProjectionMatrix() const override;
//! Gets the current view matrix of the camera
//! \return Returns the current view matrix of the camera.
const core::matrix4 &getViewMatrix() const override;
//! Gets the current view matrix of the camera
//! \return Returns the current view matrix of the camera.
const core::matrix4& getViewMatrix() const override;
//! Sets a custom view matrix affector.
/** \param affector: The affector matrix. */
void setViewMatrixAffector(const core::matrix4 &affector) override;
//! Sets a custom view matrix affector.
/** \param affector: The affector matrix. */
void setViewMatrixAffector(const core::matrix4& affector) override;
//! Gets the custom view matrix affector.
const core::matrix4 &getViewMatrixAffector() const override;
//! Gets the custom view matrix affector.
const core::matrix4& getViewMatrixAffector() const override;
//! It is possible to send mouse and key events to the camera. Most cameras
//! may ignore this input, but camera scene nodes which are created for
//! example with scene::ISceneManager::addMayaCameraSceneNode or
//! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input
//! for changing their position, look at target or whatever.
bool OnEvent(const SEvent &event) override;
//! It is possible to send mouse and key events to the camera. Most cameras
//! may ignore this input, but camera scene nodes which are created for
//! example with scene::ISceneManager::addMayaCameraSceneNode or
//! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input
//! for changing their position, look at target or whatever.
bool OnEvent(const SEvent& event) override;
//! Sets the look at target of the camera
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's scene node rotation to match the target.
\param pos: Look at target of the camera. */
void setTarget(const core::vector3df &pos) override;
//! Sets the look at target of the camera
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's scene node rotation to match the target.
\param pos: Look at target of the camera. */
void setTarget(const core::vector3df& pos) override;
//! Sets the rotation of the node.
/** This only modifies the relative rotation of the node.
If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's target to match the rotation.
\param rotation New rotation of the node in degrees. */
void setRotation(const core::vector3df &rotation) override;
//! Sets the rotation of the node.
/** This only modifies the relative rotation of the node.
If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's target to match the rotation.
\param rotation New rotation of the node in degrees. */
void setRotation(const core::vector3df& rotation) override;
//! Gets the current look at target of the camera
/** \return The current look at target of the camera */
const core::vector3df &getTarget() const override;
//! Gets the current look at target of the camera
/** \return The current look at target of the camera */
const core::vector3df& getTarget() const override;
//! Sets the up vector of the camera.
//! \param pos: New upvector of the camera.
void setUpVector(const core::vector3df &pos) override;
//! Sets the up vector of the camera.
//! \param pos: New upvector of the camera.
void setUpVector(const core::vector3df& pos) override;
//! Gets the up vector of the camera.
//! \return Returns the up vector of the camera.
const core::vector3df &getUpVector() const override;
//! Gets the up vector of the camera.
//! \return Returns the up vector of the camera.
const core::vector3df& getUpVector() const override;
//! Gets distance from the camera to the near plane.
//! \return Value of the near plane of the camera.
f32 getNearValue() const override;
//! Gets distance from the camera to the near plane.
//! \return Value of the near plane of the camera.
f32 getNearValue() const override;
//! Gets the distance from the camera to the far plane.
//! \return Value of the far plane of the camera.
f32 getFarValue() const override;
//! Gets the distance from the camera to the far plane.
//! \return Value of the far plane of the camera.
f32 getFarValue() const override;
//! Get the aspect ratio of the camera.
//! \return The aspect ratio of the camera.
f32 getAspectRatio() const override;
//! Get the aspect ratio of the camera.
//! \return The aspect ratio of the camera.
f32 getAspectRatio() const override;
//! Gets the field of view of the camera.
//! \return Field of view of the camera
f32 getFOV() const override;
//! Gets the field of view of the camera.
//! \return Field of view of the camera
f32 getFOV() const override;
//! Sets the value of the near clipping plane. (default: 1.0f)
void setNearValue(f32 zn) override;
//! Sets the value of the near clipping plane. (default: 1.0f)
void setNearValue(f32 zn) override;
//! Sets the value of the far clipping plane (default: 2000.0f)
void setFarValue(f32 zf) override;
//! Sets the value of the far clipping plane (default: 2000.0f)
void setFarValue(f32 zf) override;
//! Sets the aspect ratio (default: 4.0f / 3.0f)
void setAspectRatio(f32 aspect) override;
//! Sets the aspect ratio (default: 4.0f / 3.0f)
void setAspectRatio(f32 aspect) override;
//! Sets the field of view (Default: PI / 3.5f)
void setFOV(f32 fovy) override;
//! Sets the field of view (Default: PI / 3.5f)
void setFOV(f32 fovy) override;
//! PreRender event
void OnRegisterSceneNode() override;
//! PreRender event
void OnRegisterSceneNode() override;
//! Render
void render() override;
//! Render
void render() override;
//! Update
void updateMatrices() override;
//! Update
void updateMatrices() override;
//! Returns the axis aligned bounding box of this node
const core::aabbox3d<f32> &getBoundingBox() const override;
//! Returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& getBoundingBox() const override;
//! Returns the view area.
const SViewFrustum *getViewFrustum() const override;
//! Returns the view area.
const SViewFrustum* getViewFrustum() const override;
//! Disables or enables the camera to get key or mouse inputs.
//! If this is set to true, the camera will respond to key inputs
//! otherwise not.
void setInputReceiverEnabled(bool enabled) override;
//! Disables or enables the camera to get key or mouse inputs.
//! If this is set to true, the camera will respond to key inputs
//! otherwise not.
void setInputReceiverEnabled(bool enabled) override;
//! Returns if the input receiver of the camera is currently enabled.
bool isInputReceiverEnabled() const override;
//! Returns if the input receiver of the camera is currently enabled.
bool isInputReceiverEnabled() const override;
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_CAMERA; }
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_CAMERA; }
//! Binds the camera scene node's rotation to its target position and vice versa, or unbinds them.
void bindTargetAndRotation(bool bound) override;
//! Binds the camera scene node's rotation to its target position and vice versa, or unbinds them.
void bindTargetAndRotation(bool bound) override;
//! Queries if the camera scene node's rotation and its target position are bound together.
bool getTargetAndRotationBinding(void) const override;
//! Queries if the camera scene node's rotation and its target position are bound together.
bool getTargetAndRotationBinding(void) const override;
//! Creates a clone of this scene node and its children.
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
//! Creates a clone of this scene node and its children.
ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) override;
protected:
void recalculateProjectionMatrix();
void recalculateViewArea();
protected:
core::aabbox3d<f32> BoundingBox;
void recalculateProjectionMatrix();
void recalculateViewArea();
core::vector3df Target;
core::vector3df UpVector;
core::aabbox3d<f32> BoundingBox;
f32 Fovy; // Field of view, in radians.
f32 Aspect; // Aspect ratio.
f32 ZNear; // value of the near view-plane.
f32 ZFar; // Z-value of the far view-plane.
core::vector3df Target;
core::vector3df UpVector;
SViewFrustum ViewArea;
core::matrix4 Affector;
f32 Fovy; // Field of view, in radians.
f32 Aspect; // Aspect ratio.
f32 ZNear; // value of the near view-plane.
f32 ZFar; // Z-value of the far view-plane.
SViewFrustum ViewArea;
core::matrix4 Affector;
bool InputReceiverEnabled;
bool TargetAndRotationAreBound;
};
bool InputReceiverEnabled;
bool TargetAndRotationAreBound;
};
} // end namespace
} // end namespace

File diff suppressed because it is too large Load Diff

View File

@ -15,37 +15,35 @@ namespace video
class CColorConverter
{
public:
//! converts a monochrome bitmap to A1R5G5B5
static void convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false);
static void convert1BitTo16Bit(const u8 *in, s16 *out, s32 width, s32 height, s32 linepad = 0, bool flip = false);
//! converts a 4 bit palettized image to A1R5G5B5
static void convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false);
static void convert4BitTo16Bit(const u8 *in, s16 *out, s32 width, s32 height, const s32 *palette, s32 linepad = 0, bool flip = false);
//! converts a 8 bit palettized image to A1R5G5B5
static void convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false);
static void convert8BitTo16Bit(const u8 *in, s16 *out, s32 width, s32 height, const s32 *palette, s32 linepad = 0, bool flip = false);
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
static void convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false);
static void convert8BitTo24Bit(const u8 *in, u8 *out, s32 width, s32 height, const u8 *palette, s32 linepad = 0, bool flip = false);
//! converts a 8 bit palettized or non palettized image (A8) into A8R8G8B8
static void convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false);
static void convert8BitTo32Bit(const u8 *in, u8 *out, s32 width, s32 height, const u8 *palette, s32 linepad = 0, bool flip = false);
//! converts R8G8B8 16 bit data to A1R5G5B5 data
static void convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false);
static void convert16BitTo16Bit(const s16 *in, s16 *out, s32 width, s32 height, s32 linepad = 0, bool flip = false);
//! copies R8G8B8 24 bit data to 24 data, and flips and
//! mirrors the image during the process.
static void convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad=0, bool flip=false, bool bgr=false);
static void convert24BitTo24Bit(const u8 *in, u8 *out, s32 width, s32 height, s32 linepad = 0, bool flip = false, bool bgr = false);
//! Resizes the surface to a new size and converts it at the same time
//! to an A8R8G8B8 format, returning the pointer to the new buffer.
static void convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight);
static void convert16bitToA8R8G8B8andResize(const s16 *in, s32 *out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight);
//! copies X8R8G8B8 32 bit data, and flips and
//! mirrors the image during the process.
static void convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip=false);
static void convert32BitTo32Bit(const s32 *in, s32 *out, s32 width, s32 height, s32 linepad, bool flip = false);
//! Functions for converting one image format to another efficiently
//! and hopefully correctly.
@ -56,43 +54,41 @@ public:
//! \param sN number of source pixels to copy
//! \param dP pointer to destination data buffer. must be big enough
//! to hold sN pixels in the output format.
static void convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP);
static void convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP);
static void convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP);
static void convert_A1R5G5B5toR5G5B5A1(const void* sP, s32 sN, void* dP);
static void convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP);
static void convert_A1R5G5B5toR8G8B8(const void *sP, s32 sN, void *dP);
static void convert_A1R5G5B5toB8G8R8(const void *sP, s32 sN, void *dP);
static void convert_A1R5G5B5toA8R8G8B8(const void *sP, s32 sN, void *dP);
static void convert_A1R5G5B5toA1R5G5B5(const void *sP, s32 sN, void *dP);
static void convert_A1R5G5B5toR5G5B5A1(const void *sP, s32 sN, void *dP);
static void convert_A1R5G5B5toR5G6B5(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA1B5G5R5(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toR8G8B8(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toB8G8R8(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toA8R8G8B8(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toA1R5G5B5(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toA1B5G5R5(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toR5G6B5(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP);
static void convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP);
static void convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP);
static void convert_R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP);
static void convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
static void convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toR8G8B8A8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA8B8G8R8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toR3G3B2(const void *sP, s32 sN, void *dP);
static void convert_R8G8B8toR8G8B8(const void *sP, s32 sN, void *dP);
static void convert_R8G8B8toA8R8G8B8(const void *sP, s32 sN, void *dP);
static void convert_R8G8B8toA1R5G5B5(const void *sP, s32 sN, void *dP);
static void convert_R8G8B8toB8G8R8(const void *sP, s32 sN, void *dP);
static void convert_R8G8B8toR5G6B5(const void *sP, s32 sN, void *dP);
static void convert_B8G8R8toA8R8G8B8(const void *sP, s32 sN, void *dP);
static void convert_B8G8R8A8toA8R8G8B8(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toR8G8B8A8(const void *sP, s32 sN, void *dP);
static void convert_A8R8G8B8toA8B8G8R8(const void *sP, s32 sN, void *dP);
static void convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP);
static void convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP);
static void convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP);
static void convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP);
static void convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN,
void* dP, ECOLOR_FORMAT dF);
static void convert_R5G6B5toR5G6B5(const void *sP, s32 sN, void *dP);
static void convert_R5G6B5toR8G8B8(const void *sP, s32 sN, void *dP);
static void convert_R5G6B5toB8G8R8(const void *sP, s32 sN, void *dP);
static void convert_R5G6B5toA8R8G8B8(const void *sP, s32 sN, void *dP);
static void convert_R5G6B5toA1R5G5B5(const void *sP, s32 sN, void *dP);
static void convert_viaFormat(const void *sP, ECOLOR_FORMAT sF, s32 sN,
void *dP, ECOLOR_FORMAT dF);
// Check if convert_viaFormat is usable
static bool canConvertFormat(ECOLOR_FORMAT sourceFormat, ECOLOR_FORMAT destFormat);
};
} // end namespace video
} // end namespace irr

View File

@ -12,33 +12,30 @@ namespace scene
//! constructor
CDummyTransformationSceneNode::CDummyTransformationSceneNode(
ISceneNode* parent, ISceneManager* mgr, s32 id)
: IDummyTransformationSceneNode(parent, mgr, id)
ISceneNode *parent, ISceneManager *mgr, s32 id) :
IDummyTransformationSceneNode(parent, mgr, id)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CDummyTransformationSceneNode");
#endif
#endif
setAutomaticCulling(scene::EAC_OFF);
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CDummyTransformationSceneNode::getBoundingBox() const
const core::aabbox3d<f32> &CDummyTransformationSceneNode::getBoundingBox() const
{
return Box;
}
//! Returns a reference to the current relative transformation matrix.
//! This is the matrix, this scene node uses instead of scale, translation
//! and rotation.
core::matrix4& CDummyTransformationSceneNode::getRelativeTransformationMatrix()
core::matrix4 &CDummyTransformationSceneNode::getRelativeTransformationMatrix()
{
return RelativeTransformationMatrix;
}
//! Returns the relative transformation of the scene node.
core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const
{
@ -46,56 +43,56 @@ core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const
}
//! Creates a clone of this scene node and its children.
ISceneNode* CDummyTransformationSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
ISceneNode *CDummyTransformationSceneNode::clone(ISceneNode *newParent, ISceneManager *newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CDummyTransformationSceneNode* nb = new CDummyTransformationSceneNode(newParent,
newManager, ID);
CDummyTransformationSceneNode *nb = new CDummyTransformationSceneNode(newParent,
newManager, ID);
nb->cloneMembers(this, newManager);
nb->RelativeTransformationMatrix = RelativeTransformationMatrix;
nb->Box = Box;
if ( newParent )
if (newParent)
nb->drop();
return nb;
}
const core::vector3df& CDummyTransformationSceneNode::getScale() const
const core::vector3df &CDummyTransformationSceneNode::getScale() const
{
os::Printer::log("CDummyTransformationSceneNode::getScale() does not contain the relative transformation.", ELL_DEBUG);
return RelativeScale;
}
void CDummyTransformationSceneNode::setScale(const core::vector3df& scale)
void CDummyTransformationSceneNode::setScale(const core::vector3df &scale)
{
os::Printer::log("CDummyTransformationSceneNode::setScale() does not affect the relative transformation.", ELL_DEBUG);
RelativeScale = scale;
}
const core::vector3df& CDummyTransformationSceneNode::getRotation() const
const core::vector3df &CDummyTransformationSceneNode::getRotation() const
{
os::Printer::log("CDummyTransformationSceneNode::getRotation() does not contain the relative transformation.", ELL_DEBUG);
return RelativeRotation;
}
void CDummyTransformationSceneNode::setRotation(const core::vector3df& rotation)
void CDummyTransformationSceneNode::setRotation(const core::vector3df &rotation)
{
os::Printer::log("CDummyTransformationSceneNode::setRotation() does not affect the relative transformation.", ELL_DEBUG);
RelativeRotation = rotation;
}
const core::vector3df& CDummyTransformationSceneNode::getPosition() const
const core::vector3df &CDummyTransformationSceneNode::getPosition() const
{
os::Printer::log("CDummyTransformationSceneNode::getPosition() does not contain the relative transformation.", ELL_DEBUG);
return RelativeTranslation;
}
void CDummyTransformationSceneNode::setPosition(const core::vector3df& newpos)
void CDummyTransformationSceneNode::setPosition(const core::vector3df &newpos)
{
os::Printer::log("CDummyTransformationSceneNode::setPosition() does not affect the relative transformation.", ELL_DEBUG);
RelativeTranslation = newpos;

View File

@ -11,49 +11,45 @@ namespace irr
namespace scene
{
class CDummyTransformationSceneNode : public IDummyTransformationSceneNode
{
public:
class CDummyTransformationSceneNode : public IDummyTransformationSceneNode
{
public:
//! constructor
CDummyTransformationSceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id);
//! constructor
CDummyTransformationSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32> &getBoundingBox() const override;
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& getBoundingBox() const override;
//! Returns a reference to the current relative transformation matrix.
//! This is the matrix, this scene node uses instead of scale, translation
//! and rotation.
core::matrix4 &getRelativeTransformationMatrix() override;
//! Returns a reference to the current relative transformation matrix.
//! This is the matrix, this scene node uses instead of scale, translation
//! and rotation.
core::matrix4& getRelativeTransformationMatrix() override;
//! Returns the relative transformation of the scene node.
core::matrix4 getRelativeTransformation() const override;
//! Returns the relative transformation of the scene node.
core::matrix4 getRelativeTransformation() const override;
//! does nothing.
void render() override {}
//! does nothing.
void render() override {}
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_DUMMY_TRANSFORMATION; }
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_DUMMY_TRANSFORMATION; }
//! Creates a clone of this scene node and its children.
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
//! Creates a clone of this scene node and its children.
ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) override;
private:
// TODO: We can add least add some warnings to find troubles faster until we have
// fixed bug id 2318691.
const core::vector3df &getScale() const override;
void setScale(const core::vector3df &scale) override;
const core::vector3df &getRotation() const override;
void setRotation(const core::vector3df &rotation) override;
const core::vector3df &getPosition() const override;
void setPosition(const core::vector3df &newpos) override;
private:
// TODO: We can add least add some warnings to find troubles faster until we have
// fixed bug id 2318691.
const core::vector3df& getScale() const override;
void setScale(const core::vector3df& scale) override;
const core::vector3df& getRotation() const override;
void setRotation(const core::vector3df& rotation) override;
const core::vector3df& getPosition() const override;
void setPosition(const core::vector3df& newpos) override;
core::matrix4 RelativeTransformationMatrix;
core::aabbox3d<f32> Box;
};
core::matrix4 RelativeTransformationMatrix;
core::aabbox3d<f32> Box;
};
} // end namespace scene
} // end namespace irr

494
source/Irrlicht/CEGLManager.cpp Executable file → Normal file
View File

@ -4,8 +4,8 @@
#include "CEGLManager.h"
#ifdef _IRR_COMPILE_WITH_EGL_MANAGER_
#ifdef _IRR_COMPILE_WITH_EGL_MANAGER_
#include "irrString.h"
#include "irrArray.h"
#include "os.h"
@ -19,32 +19,33 @@ namespace irr
namespace video
{
CEGLManager::CEGLManager() : IContextManager(), EglWindow(0), EglDisplay(EGL_NO_DISPLAY),
EglSurface(EGL_NO_SURFACE), EglContext(EGL_NO_CONTEXT), EglConfig(0), MajorVersion(0), MinorVersion(0)
CEGLManager::CEGLManager() :
IContextManager(), EglWindow(0), EglDisplay(EGL_NO_DISPLAY),
EglSurface(EGL_NO_SURFACE), EglContext(EGL_NO_CONTEXT), EglConfig(0), MajorVersion(0), MinorVersion(0)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CEGLManager");
#endif
#endif
}
CEGLManager::~CEGLManager()
{
destroyContext();
destroySurface();
terminate();
destroyContext();
destroySurface();
terminate();
}
bool CEGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data)
bool CEGLManager::initialize(const SIrrlichtCreationParameters &params, const SExposedVideoData &data)
{
// store new data
Params=params;
Data=data;
Params = params;
Data = data;
if (EglWindow != 0 && EglDisplay != EGL_NO_DISPLAY)
return true;
return true;
// Window is depend on platform.
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
// Window is depend on platform.
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
EglWindow = (NativeWindowType)Data.OpenGLWin32.HWnd;
Data.OpenGLWin32.HDc = GetDC((HWND)EglWindow);
EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLWin32.HDc);
@ -55,7 +56,7 @@ bool CEGLManager::initialize(const SIrrlichtCreationParameters& params, const SE
EglWindow = (NativeWindowType)Data.OpenGLLinux.X11Window;
EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLLinux.X11Display);
#elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window;
EglWindow = (ANativeWindow *)Data.OGLESAndroid.Window;
EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
#elif defined(_IRR_COMPILE_WITH_FB_DEVICE_)
EglWindow = (NativeWindowType)Data.OpenGLFB.Window;
@ -63,26 +64,23 @@ bool CEGLManager::initialize(const SIrrlichtCreationParameters& params, const SE
#endif
// We must check if EGL display is valid.
if (EglDisplay == EGL_NO_DISPLAY)
{
if (EglDisplay == EGL_NO_DISPLAY) {
os::Printer::log("Could not get EGL display.");
terminate();
return false;
}
return false;
}
// Initialize EGL here.
if (!eglInitialize(EglDisplay, &MajorVersion, &MinorVersion))
{
if (!eglInitialize(EglDisplay, &MajorVersion, &MinorVersion)) {
os::Printer::log("Could not initialize EGL display.");
EglDisplay = EGL_NO_DISPLAY;
EglDisplay = EGL_NO_DISPLAY;
terminate();
return false;
}
else
os::Printer::log("EGL version", core::stringc(MajorVersion+(MinorVersion*0.1f)).c_str());
return false;
} else
os::Printer::log("EGL version", core::stringc(MajorVersion + (MinorVersion * 0.1f)).c_str());
return true;
return true;
}
void CEGLManager::terminate()
@ -90,8 +88,7 @@ void CEGLManager::terminate()
if (EglWindow == 0 && EglDisplay == EGL_NO_DISPLAY)
return;
if (EglDisplay != EGL_NO_DISPLAY)
{
if (EglDisplay != EGL_NO_DISPLAY) {
// We should unbind current EGL context before terminate EGL.
eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@ -99,32 +96,31 @@ void CEGLManager::terminate()
EglDisplay = EGL_NO_DISPLAY;
}
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
if (Data.OpenGLWin32.HDc)
{
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
if (Data.OpenGLWin32.HDc) {
ReleaseDC((HWND)EglWindow, (HDC)Data.OpenGLWin32.HDc);
Data.OpenGLWin32.HDc = 0;
}
Data.OpenGLWin32.HDc = 0;
}
#endif
MajorVersion = 0;
MinorVersion = 0;
MajorVersion = 0;
MinorVersion = 0;
}
bool CEGLManager::generateSurface()
{
if (EglDisplay == EGL_NO_DISPLAY)
return false;
if (EglDisplay == EGL_NO_DISPLAY)
return false;
if (EglSurface != EGL_NO_SURFACE)
return true;
if (EglSurface != EGL_NO_SURFACE)
return true;
// We should assign new WindowID on platforms, where WindowID may change at runtime,
// at this time only Android support this feature.
// this needs an update method instead!
// We should assign new WindowID on platforms, where WindowID may change at runtime,
// at this time only Android support this feature.
// this needs an update method instead!
#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window;
EglWindow = (ANativeWindow *)Data.OGLESAndroid.Window;
#endif
#if defined(_IRR_EMSCRIPTEN_PLATFORM_)
@ -135,18 +131,16 @@ bool CEGLManager::generateSurface()
EglConfig = chooseConfig(ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS);
#endif
if ( EglConfig == 0 )
{
if (EglConfig == 0) {
os::Printer::log("Could not get config for EGL display.");
return false;
}
#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
EGLint Format = 0;
eglGetConfigAttrib(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &Format);
EGLint Format = 0;
eglGetConfigAttrib(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &Format);
ANativeWindow_setBuffersGeometry(EglWindow, 0, 0, Format);
ANativeWindow_setBuffersGeometry(EglWindow, 0, 0, Format);
#endif
// Now we are able to create EGL surface.
@ -163,10 +157,10 @@ bool CEGLManager::generateSurface()
eglBindAPI(EGL_OPENGL_ES_API);
#endif
if (Params.Vsync)
if (Params.Vsync)
eglSwapInterval(EglDisplay, 1);
return true;
return true;
}
EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle)
@ -175,8 +169,7 @@ EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle)
// Find proper OpenGL BIT.
EGLint eglOpenGLBIT = 0;
switch (Params.DriverType)
{
switch (Params.DriverType) {
case EDT_OGLES1:
eglOpenGLBIT = EGL_OPENGL_ES_BIT;
break;
@ -188,96 +181,85 @@ EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle)
break;
}
if ( confStyle == ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS )
{
if (confStyle == ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS) {
EGLint Attribs[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, Params.WithAlphaChannel ? 1:0,
EGL_BUFFER_SIZE, Params.Bits,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_DEPTH_SIZE, Params.ZBufferBits,
EGL_STENCIL_SIZE, Params.Stencilbuffer,
EGL_SAMPLE_BUFFERS, Params.AntiAlias ? 1:0,
EGL_SAMPLES, Params.AntiAlias,
#ifdef EGL_VERSION_1_3
EGL_RENDERABLE_TYPE, eglOpenGLBIT,
#endif
EGL_NONE, 0
};
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, Params.WithAlphaChannel ? 1 : 0,
EGL_BUFFER_SIZE, Params.Bits,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_DEPTH_SIZE, Params.ZBufferBits,
EGL_STENCIL_SIZE, Params.Stencilbuffer,
EGL_SAMPLE_BUFFERS, Params.AntiAlias ? 1 : 0,
EGL_SAMPLES, Params.AntiAlias,
#ifdef EGL_VERSION_1_3
EGL_RENDERABLE_TYPE, eglOpenGLBIT,
#endif
EGL_NONE, 0};
EGLint numConfigs = 0;
u32 steps = 5;
// Choose the best EGL config.
// TODO: We should also have a confStyle ECS_EGL_CHOOSE_CLOSEST
// which doesn't take first result of eglChooseConfigs,
// but the closest to requested parameters. eglChooseConfigs
// can return more than 1 result and first one might have
// "better" values than requested (more bits per pixel etc).
// So this returns the config which can do most, not the
// config which is closest to the requested parameters.
// TODO: We should also have a confStyle ECS_EGL_CHOOSE_CLOSEST
// which doesn't take first result of eglChooseConfigs,
// but the closest to requested parameters. eglChooseConfigs
// can return more than 1 result and first one might have
// "better" values than requested (more bits per pixel etc).
// So this returns the config which can do most, not the
// config which is closest to the requested parameters.
//
while (!eglChooseConfig(EglDisplay, Attribs, &configResult, 1, &numConfigs) || !numConfigs)
{
switch (steps)
{
case 5: // samples
if (Attribs[19] > 2) // Params.AntiAlias
while (!eglChooseConfig(EglDisplay, Attribs, &configResult, 1, &numConfigs) || !numConfigs) {
switch (steps) {
case 5: // samples
if (Attribs[19] > 2) // Params.AntiAlias
--Attribs[19];
else
{
Attribs[17] = 0; // Params.Stencilbuffer
Attribs[19] = 0; // Params.AntiAlias
else {
Attribs[17] = 0; // Params.Stencilbuffer
Attribs[19] = 0; // Params.AntiAlias
--steps;
}
break;
case 4: // alpha
if (Attribs[7]) // Params.WithAlphaChannel
case 4: // alpha
if (Attribs[7]) // Params.WithAlphaChannel
{
Attribs[7] = 0;
if (Params.AntiAlias)
{
if (Params.AntiAlias) {
Attribs[17] = 1;
Attribs[19] = Params.AntiAlias;
steps = 5;
}
}
else
} else
--steps;
break;
case 3: // stencil
if (Attribs[15]) // Params.Stencilbuffer
case 3: // stencil
if (Attribs[15]) // Params.Stencilbuffer
{
Attribs[15] = 0;
if (Params.AntiAlias)
{
if (Params.AntiAlias) {
Attribs[17] = 1;
Attribs[19] = Params.AntiAlias;
steps = 5;
}
}
else
} else
--steps;
break;
case 2: // depth size
if (Attribs[13] > 16) // Params.ZBufferBits
case 2: // depth size
if (Attribs[13] > 16) // Params.ZBufferBits
{
Attribs[13] -= 8;
}
else
} else
--steps;
break;
case 1: // buffer size
if (Attribs[9] > 16) // Params.Bits
case 1: // buffer size
if (Attribs[9] > 16) // Params.Bits
{
Attribs[9] -= 8;
}
else
} else
--steps;
break;
default:
@ -299,47 +281,40 @@ EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle)
if (Params.Bits > Attribs[9])
os::Printer::log("No full color buffer.");
}
else if ( confStyle == ECS_IRR_CHOOSE )
{
} else if (confStyle == ECS_IRR_CHOOSE) {
// find number of available configs
EGLint numConfigs;
if ( eglGetConfigs( EglDisplay, NULL, 0, &numConfigs) == EGL_FALSE )
{
if (eglGetConfigs(EglDisplay, NULL, 0, &numConfigs) == EGL_FALSE) {
testEGLError();
return 0;
}
if ( numConfigs <= 0 )
if (numConfigs <= 0)
return 0;
// Get all available configs.
EGLConfig * configs = new EGLConfig[numConfigs];
if ( eglGetConfigs( EglDisplay, configs, numConfigs, &numConfigs) == EGL_FALSE )
{
EGLConfig *configs = new EGLConfig[numConfigs];
if (eglGetConfigs(EglDisplay, configs, numConfigs, &numConfigs) == EGL_FALSE) {
testEGLError();
return 0;
}
// Find the best one.
core::array<SConfigRating> ratings((u32)numConfigs);
for ( u32 i=0; i < (u32)numConfigs; ++i )
{
for (u32 i = 0; i < (u32)numConfigs; ++i) {
SConfigRating r;
r.config = configs[i];
r.rating = rateConfig(r.config, eglOpenGLBIT);
if ( r.rating >= 0 )
if (r.rating >= 0)
ratings.push_back(r);
}
if ( ratings.size() > 0 )
{
if (ratings.size() > 0) {
ratings.sort();
configResult = ratings[0].config;
if ( ratings[0].rating != 0 )
{
if (ratings[0].rating != 0) {
// This is just to print some log info (it also rates again while doing that, but rating is cheap enough, so that doesn't matter here).
rateConfig(ratings[0].config, eglOpenGLBIT, true);
}
@ -356,19 +331,17 @@ irr::s32 CEGLManager::rateConfig(EGLConfig config, EGLint eglOpenGLBIT, bool log
// some values must be there or we ignore the config
#ifdef EGL_VERSION_1_3
EGLint attribRenderableType = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_RENDERABLE_TYPE, &attribRenderableType);
if ( attribRenderableType != eglOpenGLBIT )
{
if ( log )
eglGetConfigAttrib(EglDisplay, config, EGL_RENDERABLE_TYPE, &attribRenderableType);
if (attribRenderableType != eglOpenGLBIT) {
if (log)
os::Printer::log("EGL_RENDERABLE_TYPE != eglOpenGLBIT");
return -1;
}
#endif
EGLint attribSurfaceType = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_SURFACE_TYPE, &attribSurfaceType);
if ( attribSurfaceType != EGL_WINDOW_BIT )
{
if ( log )
eglGetConfigAttrib(EglDisplay, config, EGL_SURFACE_TYPE, &attribSurfaceType);
if (attribSurfaceType != EGL_WINDOW_BIT) {
if (log)
os::Printer::log("EGL_SURFACE_TYPE!= EGL_WINDOW_BIT");
return -1;
}
@ -380,124 +353,104 @@ irr::s32 CEGLManager::rateConfig(EGLConfig config, EGLint eglOpenGLBIT, bool log
int rating = 0;
EGLint attribBufferSize = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_BUFFER_SIZE, &attribBufferSize);
if ( attribBufferSize < Params.Bits )
{
if ( log )
eglGetConfigAttrib(EglDisplay, config, EGL_BUFFER_SIZE, &attribBufferSize);
if (attribBufferSize < Params.Bits) {
if (log)
os::Printer::log("No full color buffer.");
rating += 100;
}
if ( attribBufferSize > Params.Bits )
{
if ( log )
if (attribBufferSize > Params.Bits) {
if (log)
os::Printer::log("Larger color buffer.", ELL_DEBUG);
++rating;
}
EGLint attribRedSize = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_RED_SIZE, &attribRedSize);
if ( attribRedSize < 5 && Params.Bits >= 4 )
eglGetConfigAttrib(EglDisplay, config, EGL_RED_SIZE, &attribRedSize);
if (attribRedSize < 5 && Params.Bits >= 4)
rating += 100;
else if ( attribRedSize < 8 && Params.Bits >= 24)
else if (attribRedSize < 8 && Params.Bits >= 24)
rating += 10;
else if ( attribRedSize >= 8 && Params.Bits < 24 )
rating ++;
else if (attribRedSize >= 8 && Params.Bits < 24)
rating++;
EGLint attribGreenSize = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_GREEN_SIZE, &attribGreenSize);
if ( attribGreenSize < 5 && Params.Bits >= 4 )
eglGetConfigAttrib(EglDisplay, config, EGL_GREEN_SIZE, &attribGreenSize);
if (attribGreenSize < 5 && Params.Bits >= 4)
rating += 100;
else if ( attribGreenSize < 8 && Params.Bits >= 24)
else if (attribGreenSize < 8 && Params.Bits >= 24)
rating += 10;
else if ( attribGreenSize >= 8 && Params.Bits < 24 )
rating ++;
else if (attribGreenSize >= 8 && Params.Bits < 24)
rating++;
EGLint attribBlueSize = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_BLUE_SIZE, &attribBlueSize);
if ( attribBlueSize < 5 && Params.Bits >= 4 )
eglGetConfigAttrib(EglDisplay, config, EGL_BLUE_SIZE, &attribBlueSize);
if (attribBlueSize < 5 && Params.Bits >= 4)
rating += 100;
else if ( attribBlueSize < 8 && Params.Bits >= 24)
else if (attribBlueSize < 8 && Params.Bits >= 24)
rating += 10;
else if ( attribBlueSize >= 8 && Params.Bits < 24 )
rating ++;
else if (attribBlueSize >= 8 && Params.Bits < 24)
rating++;
EGLint attribAlphaSize = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_ALPHA_SIZE, &attribAlphaSize);
if ( Params.WithAlphaChannel && attribAlphaSize == 0 )
{
if ( log )
eglGetConfigAttrib(EglDisplay, config, EGL_ALPHA_SIZE, &attribAlphaSize);
if (Params.WithAlphaChannel && attribAlphaSize == 0) {
if (log)
os::Printer::log("No alpha.");
rating += 10;
}
else if ( !Params.WithAlphaChannel && attribAlphaSize > 0 )
{
if ( log )
} else if (!Params.WithAlphaChannel && attribAlphaSize > 0) {
if (log)
os::Printer::log("Got alpha (unrequested).", ELL_DEBUG);
rating ++;
rating++;
}
EGLint attribStencilSize = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_STENCIL_SIZE, &attribStencilSize);
if ( Params.Stencilbuffer && attribStencilSize == 0 )
{
if ( log )
eglGetConfigAttrib(EglDisplay, config, EGL_STENCIL_SIZE, &attribStencilSize);
if (Params.Stencilbuffer && attribStencilSize == 0) {
if (log)
os::Printer::log("No stencil buffer.");
rating += 10;
}
else if ( !Params.Stencilbuffer && attribStencilSize > 0 )
{
if ( log )
} else if (!Params.Stencilbuffer && attribStencilSize > 0) {
if (log)
os::Printer::log("Got a stencil buffer (unrequested).", ELL_DEBUG);
rating ++;
rating++;
}
EGLint attribDepthSize = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_DEPTH_SIZE, &attribDepthSize);
if ( attribDepthSize < Params.ZBufferBits )
{
if ( log )
{
eglGetConfigAttrib(EglDisplay, config, EGL_DEPTH_SIZE, &attribDepthSize);
if (attribDepthSize < Params.ZBufferBits) {
if (log) {
if (attribDepthSize > 0)
os::Printer::log("No full depth buffer.");
else
os::Printer::log("No depth buffer.");
}
rating += 50;
}
else if ( attribDepthSize != Params.ZBufferBits )
{
if ( log )
{
if ( Params.ZBufferBits == 0 )
} else if (attribDepthSize != Params.ZBufferBits) {
if (log) {
if (Params.ZBufferBits == 0)
os::Printer::log("Got a depth buffer (unrequested).", ELL_DEBUG);
else
os::Printer::log("Got a larger depth buffer.", ELL_DEBUG);
}
rating ++;
rating++;
}
EGLint attribSampleBuffers=0, attribSamples = 0;
eglGetConfigAttrib( EglDisplay, config, EGL_SAMPLE_BUFFERS, &attribSampleBuffers);
eglGetConfigAttrib( EglDisplay, config, EGL_SAMPLES, &attribSamples);
if ( Params.AntiAlias && attribSampleBuffers == 0 )
{
if ( log )
EGLint attribSampleBuffers = 0, attribSamples = 0;
eglGetConfigAttrib(EglDisplay, config, EGL_SAMPLE_BUFFERS, &attribSampleBuffers);
eglGetConfigAttrib(EglDisplay, config, EGL_SAMPLES, &attribSamples);
if (Params.AntiAlias && attribSampleBuffers == 0) {
if (log)
os::Printer::log("No multisampling.");
rating += 20;
}
else if ( Params.AntiAlias && attribSampleBuffers && attribSamples < Params.AntiAlias )
{
if ( log )
} else if (Params.AntiAlias && attribSampleBuffers && attribSamples < Params.AntiAlias) {
if (log)
os::Printer::log("Multisampling with less samples than requested.", ELL_DEBUG);
rating += 10;
}
else if ( Params.AntiAlias && attribSampleBuffers && attribSamples > Params.AntiAlias )
{
if ( log )
} else if (Params.AntiAlias && attribSampleBuffers && attribSamples > Params.AntiAlias) {
if (log)
os::Printer::log("Multisampling with more samples than requested.", ELL_DEBUG);
rating += 5;
}
else if ( !Params.AntiAlias && attribSampleBuffers > 0 )
{
if ( log )
} else if (!Params.AntiAlias && attribSampleBuffers > 0) {
if (log)
os::Printer::log("Got multisampling (unrequested).", ELL_DEBUG);
rating += 3;
}
@ -513,8 +466,8 @@ void CEGLManager::destroySurface()
// We should unbind current EGL context before destroy EGL surface.
eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(EglDisplay, EglSurface);
EglSurface = EGL_NO_SURFACE;
eglDestroySurface(EglDisplay, EglSurface);
EglSurface = EGL_NO_SURFACE;
}
bool CEGLManager::generateContext()
@ -527,8 +480,7 @@ bool CEGLManager::generateContext()
EGLint OpenGLESVersion = 0;
switch (Params.DriverType)
{
switch (Params.DriverType) {
case EDT_OGLES1:
OpenGLESVersion = 1;
break;
@ -540,25 +492,23 @@ bool CEGLManager::generateContext()
break;
}
EGLint ContextAttrib[] =
{
EGLint ContextAttrib[] =
{
#ifdef EGL_VERSION_1_3
EGL_CONTEXT_CLIENT_VERSION, OpenGLESVersion,
EGL_CONTEXT_CLIENT_VERSION, OpenGLESVersion,
#endif
EGL_NONE, 0
};
EGL_NONE, 0};
EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, ContextAttrib);
if (testEGLError())
{
if (testEGLError()) {
os::Printer::log("Could not create EGL context.", ELL_ERROR);
return false;
}
os::Printer::log("EGL context created with OpenGLESVersion: ", core::stringc((int)OpenGLESVersion), ELL_DEBUG);
return true;
return true;
}
void CEGLManager::destroyContext()
@ -570,34 +520,33 @@ void CEGLManager::destroyContext()
eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(EglDisplay, EglContext);
EglContext = EGL_NO_CONTEXT;
EglContext = EGL_NO_CONTEXT;
}
bool CEGLManager::activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero)
bool CEGLManager::activateContext(const SExposedVideoData &videoData, bool restorePrimaryOnZero)
{
eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext);
if (testEGLError())
{
if (testEGLError()) {
os::Printer::log("Could not make EGL context current.");
return false;
}
return true;
}
const SExposedVideoData& CEGLManager::getContext() const
const SExposedVideoData &CEGLManager::getContext() const
{
return Data;
}
void* CEGLManager::getProcAddress(const std::string &procName)
void *CEGLManager::getProcAddress(const std::string &procName)
{
return (void*)eglGetProcAddress(procName.c_str());
return (void *)eglGetProcAddress(procName.c_str());
}
bool CEGLManager::swapBuffers()
{
return (eglSwapBuffers(EglDisplay, EglSurface)==EGL_TRUE);
return (eglSwapBuffers(EglDisplay, EglSurface) == EGL_TRUE);
}
bool CEGLManager::testEGLError()
@ -605,54 +554,53 @@ bool CEGLManager::testEGLError()
#if defined(EGL_VERSION_1_0) && defined(_DEBUG)
EGLint status = eglGetError();
switch (status)
{
case EGL_SUCCESS:
return false;
case EGL_NOT_INITIALIZED :
os::Printer::log("Not Initialized", ELL_ERROR);
break;
case EGL_BAD_ACCESS:
os::Printer::log("Bad Access", ELL_ERROR);
break;
case EGL_BAD_ALLOC:
os::Printer::log("Bad Alloc", ELL_ERROR);
break;
case EGL_BAD_ATTRIBUTE:
os::Printer::log("Bad Attribute", ELL_ERROR);
break;
case EGL_BAD_CONTEXT:
os::Printer::log("Bad Context", ELL_ERROR);
break;
case EGL_BAD_CONFIG:
os::Printer::log("Bad Config", ELL_ERROR);
break;
case EGL_BAD_CURRENT_SURFACE:
os::Printer::log("Bad Current Surface", ELL_ERROR);
break;
case EGL_BAD_DISPLAY:
os::Printer::log("Bad Display", ELL_ERROR);
break;
case EGL_BAD_SURFACE:
os::Printer::log("Bad Surface", ELL_ERROR);
break;
case EGL_BAD_MATCH:
os::Printer::log("Bad Match", ELL_ERROR);
break;
case EGL_BAD_PARAMETER:
os::Printer::log("Bad Parameter", ELL_ERROR);
break;
case EGL_BAD_NATIVE_PIXMAP:
os::Printer::log("Bad Native Pixmap", ELL_ERROR);
break;
case EGL_BAD_NATIVE_WINDOW:
os::Printer::log("Bad Native Window", ELL_ERROR);
break;
case EGL_CONTEXT_LOST:
os::Printer::log("Context Lost", ELL_ERROR);
break;
default:
break;
switch (status) {
case EGL_SUCCESS:
return false;
case EGL_NOT_INITIALIZED:
os::Printer::log("Not Initialized", ELL_ERROR);
break;
case EGL_BAD_ACCESS:
os::Printer::log("Bad Access", ELL_ERROR);
break;
case EGL_BAD_ALLOC:
os::Printer::log("Bad Alloc", ELL_ERROR);
break;
case EGL_BAD_ATTRIBUTE:
os::Printer::log("Bad Attribute", ELL_ERROR);
break;
case EGL_BAD_CONTEXT:
os::Printer::log("Bad Context", ELL_ERROR);
break;
case EGL_BAD_CONFIG:
os::Printer::log("Bad Config", ELL_ERROR);
break;
case EGL_BAD_CURRENT_SURFACE:
os::Printer::log("Bad Current Surface", ELL_ERROR);
break;
case EGL_BAD_DISPLAY:
os::Printer::log("Bad Display", ELL_ERROR);
break;
case EGL_BAD_SURFACE:
os::Printer::log("Bad Surface", ELL_ERROR);
break;
case EGL_BAD_MATCH:
os::Printer::log("Bad Match", ELL_ERROR);
break;
case EGL_BAD_PARAMETER:
os::Printer::log("Bad Parameter", ELL_ERROR);
break;
case EGL_BAD_NATIVE_PIXMAP:
os::Printer::log("Bad Native Pixmap", ELL_ERROR);
break;
case EGL_BAD_NATIVE_WINDOW:
os::Printer::log("Bad Native Window", ELL_ERROR);
break;
case EGL_CONTEXT_LOST:
os::Printer::log("Context Lost", ELL_ERROR);
break;
default:
break;
};
return true;
@ -664,4 +612,4 @@ bool CEGLManager::testEGLError()
}
}
#endif
#endif

186
source/Irrlicht/CEGLManager.h Executable file → Normal file
View File

@ -4,8 +4,8 @@
#pragma once
#ifdef _IRR_COMPILE_WITH_EGL_MANAGER_
#ifdef _IRR_COMPILE_WITH_EGL_MANAGER_
#include <EGL/egl.h>
#include "SIrrCreationParameters.h"
@ -16,99 +16,99 @@ namespace irr
{
namespace video
{
// EGL manager.
class CEGLManager : public IContextManager
// EGL manager.
class CEGLManager : public IContextManager
{
public:
//! Constructor.
CEGLManager();
//! Destructor.
virtual ~CEGLManager();
// Initialize EGL.
/* This method initialize EGLand create EGL display, anyway surface and context
aren't create. */
bool initialize(const SIrrlichtCreationParameters &params, const SExposedVideoData &data) override;
// Terminate EGL.
/* Terminate EGL context. This method break both existed surface and context. */
void terminate() override;
// Create EGL surface.
/* This method create EGL surface. On some platforms eg. Android, we must
recreate surface on each resume, because WindowID may change, so existed
surface may not be valid. If EGL context already exist, this method
automatically activates it. */
bool generateSurface() override;
// Destroy EGL surface.
/* This method destroy EGL. On some platforms eg. Android, we should call
this method on each pause, because after resume this surface may not be valid.
Hovewer this method doesn'r break EGL context. */
void destroySurface() override;
// Create EGL context.
/* This method create and activate EGL context. */
bool generateContext() override;
// Destroy EGL context.
/* This method destroy EGL context. */
void destroyContext() override;
const SExposedVideoData &getContext() const override;
bool activateContext(const SExposedVideoData &videoData, bool restorePrimaryOnZero) override;
// Get procedure address.
void *getProcAddress(const std::string &procName) override;
// Swap buffers.
bool swapBuffers() override;
protected:
enum EConfigStyle
{
public:
//! Constructor.
CEGLManager();
//! Get first result of eglChooseConfigs and if that fails try again by requesting simpler attributes
ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS,
//! Destructor.
virtual ~CEGLManager();
// Initialize EGL.
/* This method initialize EGLand create EGL display, anyway surface and context
aren't create. */
bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data) override;
// Terminate EGL.
/* Terminate EGL context. This method break both existed surface and context. */
void terminate() override;
// Create EGL surface.
/* This method create EGL surface. On some platforms eg. Android, we must
recreate surface on each resume, because WindowID may change, so existed
surface may not be valid. If EGL context already exist, this method
automatically activates it. */
bool generateSurface() override;
// Destroy EGL surface.
/* This method destroy EGL. On some platforms eg. Android, we should call
this method on each pause, because after resume this surface may not be valid.
Hovewer this method doesn'r break EGL context. */
void destroySurface() override;
// Create EGL context.
/* This method create and activate EGL context. */
bool generateContext() override;
// Destroy EGL context.
/* This method destroy EGL context. */
void destroyContext() override;
const SExposedVideoData& getContext() const override;
bool activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero) override;
// Get procedure address.
void* getProcAddress(const std::string &procName) override;
// Swap buffers.
bool swapBuffers() override;
protected:
enum EConfigStyle
{
//! Get first result of eglChooseConfigs and if that fails try again by requesting simpler attributes
ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS,
//! We select our own best fit and avoid using eglChooseConfigs
ECS_IRR_CHOOSE,
};
EGLConfig chooseConfig(EConfigStyle confStyle);
//! Check how close this config is to the parameters we requested
//! returns 0 is perfect, larger values are worse and < 0 is unusable.
irr::s32 rateConfig(EGLConfig config, EGLint eglOpenGLBIT, bool log=false);
// Helper to sort EGLConfig's. (because we got no std::pair....)
struct SConfigRating
{
EGLConfig config;
irr::s32 rating;
bool operator<(const SConfigRating& other) const
{
return rating < other.rating;
}
};
private:
bool testEGLError();
NativeWindowType EglWindow;
EGLDisplay EglDisplay;
EGLSurface EglSurface;
EGLContext EglContext;
EGLConfig EglConfig;
SIrrlichtCreationParameters Params;
SExposedVideoData Data;
EGLint MajorVersion;
EGLint MinorVersion;
//! We select our own best fit and avoid using eglChooseConfigs
ECS_IRR_CHOOSE,
};
EGLConfig chooseConfig(EConfigStyle confStyle);
//! Check how close this config is to the parameters we requested
//! returns 0 is perfect, larger values are worse and < 0 is unusable.
irr::s32 rateConfig(EGLConfig config, EGLint eglOpenGLBIT, bool log = false);
// Helper to sort EGLConfig's. (because we got no std::pair....)
struct SConfigRating
{
EGLConfig config;
irr::s32 rating;
bool operator<(const SConfigRating &other) const
{
return rating < other.rating;
}
};
private:
bool testEGLError();
NativeWindowType EglWindow;
EGLDisplay EglDisplay;
EGLSurface EglSurface;
EGLContext EglContext;
EGLConfig EglConfig;
SIrrlichtCreationParameters Params;
SExposedVideoData Data;
EGLint MajorVersion;
EGLint MinorVersion;
};
}
}
#endif
#endif

View File

@ -11,17 +11,16 @@ namespace scene
{
//! constructor
CEmptySceneNode::CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
: ISceneNode(parent, mgr, id)
CEmptySceneNode::CEmptySceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id) :
ISceneNode(parent, mgr, id)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CEmptySceneNode");
#endif
#endif
setAutomaticCulling(scene::EAC_OFF);
}
//! pre render event
void CEmptySceneNode::OnRegisterSceneNode()
{
@ -31,40 +30,36 @@ void CEmptySceneNode::OnRegisterSceneNode()
ISceneNode::OnRegisterSceneNode();
}
//! render
void CEmptySceneNode::render()
{
// do nothing
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CEmptySceneNode::getBoundingBox() const
const core::aabbox3d<f32> &CEmptySceneNode::getBoundingBox() const
{
return Box;
}
//! Creates a clone of this scene node and its children.
ISceneNode* CEmptySceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
ISceneNode *CEmptySceneNode::clone(ISceneNode *newParent, ISceneManager *newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CEmptySceneNode* nb = new CEmptySceneNode(newParent,
newManager, ID);
CEmptySceneNode *nb = new CEmptySceneNode(newParent,
newManager, ID);
nb->cloneMembers(this, newManager);
nb->Box = Box;
if ( newParent )
if (newParent)
nb->drop();
return nb;
}
} // end namespace scene
} // end namespace irr

View File

@ -11,32 +11,30 @@ namespace irr
namespace scene
{
class CEmptySceneNode : public ISceneNode
{
public:
class CEmptySceneNode : public ISceneNode
{
public:
//! constructor
CEmptySceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id);
//! constructor
CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32> &getBoundingBox() const override;
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& getBoundingBox() const override;
//! This method is called just before the rendering process of the whole scene.
void OnRegisterSceneNode() override;
//! This method is called just before the rendering process of the whole scene.
void OnRegisterSceneNode() override;
//! does nothing.
void render() override;
//! does nothing.
void render() override;
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_EMPTY; }
//! Returns type of the scene node
ESCENE_NODE_TYPE getType() const override { return ESNT_EMPTY; }
//! Creates a clone of this scene node and its children.
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
//! Creates a clone of this scene node and its children.
ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) override;
private:
core::aabbox3d<f32> Box;
};
private:
core::aabbox3d<f32> Box;
};
} // end namespace scene
} // end namespace irr

View File

@ -10,43 +10,36 @@ namespace irr
namespace video
{
CFPSCounter::CFPSCounter()
: FPS(60), Primitive(0), StartTime(0), FramesCounted(0),
PrimitivesCounted(0), PrimitiveAverage(0), PrimitiveTotal(0)
CFPSCounter::CFPSCounter() :
FPS(60), Primitive(0), StartTime(0), FramesCounted(0),
PrimitivesCounted(0), PrimitiveAverage(0), PrimitiveTotal(0)
{
}
//! returns current fps
s32 CFPSCounter::getFPS() const
{
return FPS;
}
//! returns current primitive count
u32 CFPSCounter::getPrimitive() const
{
return Primitive;
}
//! returns average primitive count of last period
u32 CFPSCounter::getPrimitiveAverage() const
{
return PrimitiveAverage;
}
//! returns accumulated primitive count since start
u32 CFPSCounter::getPrimitiveTotal() const
{
return PrimitiveTotal;
}
//! to be called every frame
void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn)
{
@ -57,12 +50,11 @@ void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn)
const u32 milliseconds = now - StartTime;
if (milliseconds >= 1500 )
{
const f32 invMilli = core::reciprocal ( (f32) milliseconds );
if (milliseconds >= 1500) {
const f32 invMilli = core::reciprocal((f32)milliseconds);
FPS = core::ceil32 ( ( 1000 * FramesCounted ) * invMilli );
PrimitiveAverage = core::ceil32 ( ( 1000 * PrimitivesCounted ) * invMilli );
FPS = core::ceil32((1000 * FramesCounted) * invMilli);
PrimitiveAverage = core::ceil32((1000 * PrimitivesCounted) * invMilli);
FramesCounted = 0;
PrimitivesCounted = 0;
@ -70,7 +62,5 @@ void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn)
}
}
} // end namespace video
} // end namespace irr

View File

@ -11,7 +11,6 @@ namespace irr
namespace video
{
class CFPSCounter
{
public:
@ -33,7 +32,6 @@ public:
void registerFrame(u32 now, u32 primitive);
private:
s32 FPS;
u32 Primitive;
u32 StartTime;
@ -44,6 +42,5 @@ private:
u32 PrimitiveTotal;
};
} // end namespace video
} // end namespace irr

View File

@ -15,12 +15,12 @@ namespace io
static const io::path emptyFileListEntry;
CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
: IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
CFileList::CFileList(const io::path &path, bool ignoreCase, bool ignorePaths) :
IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CFileList");
#endif
#endif
Path.replace('\\', '/');
}
@ -40,7 +40,7 @@ void CFileList::sort()
Files.sort();
}
const io::path& CFileList::getFileName(u32 index) const
const io::path &CFileList::getFileName(u32 index) const
{
if (index >= Files.size())
return emptyFileListEntry;
@ -48,9 +48,8 @@ const io::path& CFileList::getFileName(u32 index) const
return Files[index].Name;
}
//! Gets the full name of a file in the list, path included, based on an index.
const io::path& CFileList::getFullFileName(u32 index) const
const io::path &CFileList::getFullFileName(u32 index) const
{
if (index >= Files.size())
return emptyFileListEntry;
@ -59,10 +58,10 @@ const io::path& CFileList::getFullFileName(u32 index) const
}
//! adds a file or folder
u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id)
u32 CFileList::addItem(const io::path &fullPath, u32 offset, u32 size, bool isDirectory, u32 id)
{
SFileListEntry entry;
entry.ID = id ? id : Files.size();
entry.ID = id ? id : Files.size();
entry.Offset = offset;
entry.Size = size;
entry.Name = fullPath;
@ -70,10 +69,9 @@ u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDi
entry.IsDirectory = isDirectory;
// remove trailing slash
if (entry.Name.lastChar() == '/')
{
if (entry.Name.lastChar() == '/') {
entry.IsDirectory = true;
entry.Name[entry.Name.size()-1] = 0;
entry.Name[entry.Name.size() - 1] = 0;
entry.Name.validate();
}
@ -87,7 +85,7 @@ u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDi
if (IgnorePaths)
entry.FullName = entry.Name;
//os::Printer::log(Path.c_str(), entry.FullName);
// os::Printer::log(Path.c_str(), entry.FullName);
Files.push_back(entry);
@ -120,9 +118,8 @@ u32 CFileList::getFileOffset(u32 index) const
return index < Files.size() ? Files[index].Offset : 0;
}
//! Searches for a file or folder within the list, returns the index
s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) const
s32 CFileList::findFile(const io::path &filename, bool isDirectory = false) const
{
SFileListEntry entry;
// we only need FullName to be set for the search
@ -133,10 +130,9 @@ s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) cons
entry.FullName.replace('\\', '/');
// remove trailing slash
if (entry.FullName.lastChar() == '/')
{
if (entry.FullName.lastChar() == '/') {
entry.IsDirectory = true;
entry.FullName[entry.FullName.size()-1] = 0;
entry.FullName[entry.FullName.size() - 1] = 0;
entry.FullName.validate();
}
@ -149,14 +145,11 @@ s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) cons
return Files.binary_search(entry);
}
//! Returns the base path of the file list
const io::path& CFileList::getPath() const
const io::path &CFileList::getPath() const
{
return Path;
}
} // end namespace irr
} // end namespace io

View File

@ -8,7 +8,6 @@
#include "irrString.h"
#include "irrArray.h"
namespace irr
{
namespace io
@ -42,7 +41,7 @@ struct SFileListEntry
bool IsDirectory;
//! The == operator is provided so that CFileList can slowly search the list!
bool operator ==(const struct SFileListEntry& other) const
bool operator==(const struct SFileListEntry &other) const
{
if (IsDirectory != other.IsDirectory)
return false;
@ -51,7 +50,7 @@ struct SFileListEntry
}
//! The < operator is provided so that CFileList can sort and quickly search the list.
bool operator <(const struct SFileListEntry& other) const
bool operator<(const struct SFileListEntry &other) const
{
if (IsDirectory != other.IsDirectory)
return IsDirectory;
@ -60,17 +59,15 @@ struct SFileListEntry
}
};
//! Implementation of a file list
class CFileList : public IFileList
{
public:
// CFileList methods
//! Constructor
/** \param path The path of this file archive */
CFileList(const io::path& path, bool ignoreCase, bool ignorePaths);
CFileList(const io::path &path, bool ignoreCase, bool ignorePaths);
//! Destructor
virtual ~CFileList();
@ -81,7 +78,7 @@ public:
\param offset The offset where the file is stored in an archive
\param size The size of the file in bytes.
\param id The ID of the file in the archive which owns it */
u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0) override;
u32 addItem(const io::path &fullPath, u32 offset, u32 size, bool isDirectory, u32 id = 0) override;
//! Sorts the file list. You should call this after adding any items to the file list
void sort() override;
@ -90,10 +87,10 @@ public:
u32 getFileCount() const override;
//! Gets the name of a file in the list, based on an index.
const io::path& getFileName(u32 index) const override;
const io::path &getFileName(u32 index) const override;
//! Gets the full name of a file in the list, path included, based on an index.
const io::path& getFullFileName(u32 index) const override;
const io::path &getFullFileName(u32 index) const override;
//! Returns the ID of a file in the file list, based on an index.
u32 getID(u32 index) const override;
@ -108,13 +105,12 @@ public:
u32 getFileOffset(u32 index) const override;
//! Searches for a file or folder within the list, returns the index
s32 findFile(const io::path& filename, bool isFolder) const override;
s32 findFile(const io::path &filename, bool isFolder) const override;
//! Returns the base path of the file list
const io::path& getPath() const override;
const io::path &getPath() const override;
protected:
//! Ignore paths when adding or searching for files
bool IgnorePaths;
@ -128,6 +124,5 @@ protected:
core::array<SFileListEntry> Files;
};
} // end namespace irr
} // end namespace io

View File

@ -2,7 +2,6 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CFileSystem.h"
#include "IReadFile.h"
#include "IWriteFile.h"
@ -16,25 +15,25 @@
#include "CWriteFile.h"
#include <list>
#if defined (__STRICT_ANSI__)
#error Compiling with __STRICT_ANSI__ not supported. g++ does set this when compiling with -std=c++11 or -std=c++0x. Use instead -std=gnu++11 or -std=gnu++0x. Or use -U__STRICT_ANSI__ to disable strict ansi.
#if defined(__STRICT_ANSI__)
#error Compiling with __STRICT_ANSI__ not supported. g++ does set this when compiling with -std=c++11 or -std=c++0x. Use instead -std=gnu++11 or -std=gnu++0x. Or use -U__STRICT_ANSI__ to disable strict ansi.
#endif
#if defined (_IRR_WINDOWS_API_)
#include <direct.h> // for _chdir
#include <io.h> // for _access
#include <tchar.h>
#if defined(_IRR_WINDOWS_API_)
#include <direct.h> // for _chdir
#include <io.h> // for _access
#include <tchar.h>
#elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_) || defined(_IRR_ANDROID_PLATFORM_))
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#elif defined(_IRR_EMSCRIPTEN_PLATFORM_)
#include <unistd.h>
#include <unistd.h>
#endif
namespace irr
@ -45,47 +44,41 @@ namespace io
//! constructor
CFileSystem::CFileSystem()
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CFileSystem");
#endif
#endif
setFileListSystem(FILESYSTEM_NATIVE);
//! reset current working directory
getWorkingDirectory();
ArchiveLoader.push_back(new CArchiveLoaderZIP(this));
}
//! destructor
CFileSystem::~CFileSystem()
{
u32 i;
for ( i=0; i < FileArchives.size(); ++i)
{
for (i = 0; i < FileArchives.size(); ++i) {
FileArchives[i]->drop();
}
for ( i=0; i < ArchiveLoader.size(); ++i)
{
for (i = 0; i < ArchiveLoader.size(); ++i) {
ArchiveLoader[i]->drop();
}
}
//! opens a file for read access
IReadFile* CFileSystem::createAndOpenFile(const io::path& filename)
IReadFile *CFileSystem::createAndOpenFile(const io::path &filename)
{
if ( filename.empty() )
if (filename.empty())
return 0;
IReadFile* file = 0;
IReadFile *file = 0;
u32 i;
for (i=0; i< FileArchives.size(); ++i)
{
for (i = 0; i < FileArchives.size(); ++i) {
file = FileArchives[i]->createAndOpenFile(filename);
if (file)
return file;
@ -96,10 +89,9 @@ IReadFile* CFileSystem::createAndOpenFile(const io::path& filename)
return CReadFile::createReadFile(getAbsolutePath(filename));
}
//! Creates an IReadFile interface for treating memory like a file.
IReadFile* CFileSystem::createMemoryReadFile(const void* memory, s32 len,
const io::path& fileName, bool deleteMemoryWhenDropped)
IReadFile *CFileSystem::createMemoryReadFile(const void *memory, s32 len,
const io::path &fileName, bool deleteMemoryWhenDropped)
{
if (!memory)
return 0;
@ -107,10 +99,9 @@ IReadFile* CFileSystem::createMemoryReadFile(const void* memory, s32 len,
return new CMemoryReadFile(memory, len, fileName, deleteMemoryWhenDropped);
}
//! Creates an IReadFile interface for reading files inside files
IReadFile* CFileSystem::createLimitReadFile(const io::path& fileName,
IReadFile* alreadyOpenedFile, long pos, long areaSize)
IReadFile *CFileSystem::createLimitReadFile(const io::path &fileName,
IReadFile *alreadyOpenedFile, long pos, long areaSize)
{
if (!alreadyOpenedFile)
return 0;
@ -118,10 +109,9 @@ IReadFile* CFileSystem::createLimitReadFile(const io::path& fileName,
return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName);
}
//! Creates an IReadFile interface for treating memory like a file.
IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len,
const io::path& fileName, bool deleteMemoryWhenDropped)
IWriteFile *CFileSystem::createMemoryWriteFile(void *memory, s32 len,
const io::path &fileName, bool deleteMemoryWhenDropped)
{
if (!memory)
return 0;
@ -129,16 +119,14 @@ IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len,
return new CMemoryWriteFile(memory, len, fileName, deleteMemoryWhenDropped);
}
//! Opens a file for write access.
IWriteFile* CFileSystem::createAndWriteFile(const io::path& filename, bool append)
IWriteFile *CFileSystem::createAndWriteFile(const io::path &filename, bool append)
{
return CWriteFile::createWriteFile(filename, append);
}
//! Adds an external archive loader to the engine.
void CFileSystem::addArchiveLoader(IArchiveLoader* loader)
void CFileSystem::addArchiveLoader(IArchiveLoader *loader)
{
if (!loader)
return;
@ -154,7 +142,7 @@ u32 CFileSystem::getArchiveLoaderCount() const
}
//! Gets the archive loader by index.
IArchiveLoader* CFileSystem::getArchiveLoader(u32 index) const
IArchiveLoader *CFileSystem::getArchiveLoader(u32 index) const
{
if (index < ArchiveLoader.size())
return ArchiveLoader[index];
@ -166,13 +154,12 @@ IArchiveLoader* CFileSystem::getArchiveLoader(u32 index) const
bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative)
{
bool r = false;
const s32 dest = (s32) sourceIndex + relative;
const s32 dest = (s32)sourceIndex + relative;
const s32 dir = relative < 0 ? -1 : 1;
const s32 sourceEnd = ((s32) FileArchives.size() ) - 1;
const s32 sourceEnd = ((s32)FileArchives.size()) - 1;
IFileArchive *t;
for (s32 s = (s32) sourceIndex;s != dest; s += dir)
{
for (s32 s = (s32)sourceIndex; s != dest; s += dir) {
if (s < 0 || s > sourceEnd || s + dir < 0 || s + dir > sourceEnd)
continue;
@ -184,14 +171,13 @@ bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative)
return r;
}
//! Adds an archive to the file system.
bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase,
bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType,
const core::stringc& password,
IFileArchive** retArchive)
bool CFileSystem::addFileArchive(const io::path &filename, bool ignoreCase,
bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType,
const core::stringc &password,
IFileArchive **retArchive)
{
IFileArchive* archive = 0;
IFileArchive *archive = 0;
bool ret = false;
// see if archive is already added
@ -199,13 +185,10 @@ bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase,
s32 i;
// do we know what type it should be?
if (archiveType == EFAT_UNKNOWN)
{
if (archiveType == EFAT_UNKNOWN) {
// try to load archive based on file name
for (i = ArchiveLoader.size()-1; i >=0 ; --i)
{
if (ArchiveLoader[i]->isALoadableFileFormat(filename))
{
for (i = ArchiveLoader.size() - 1; i >= 0; --i) {
if (ArchiveLoader[i]->isALoadableFileFormat(filename)) {
archive = ArchiveLoader[i]->createArchive(filename, ignoreCase, ignorePaths);
if (archive)
break;
@ -213,16 +196,12 @@ bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase,
}
// try to load archive based on content
if (!archive)
{
io::IReadFile* file = createAndOpenFile(filename);
if (file)
{
for (i = ArchiveLoader.size()-1; i >= 0; --i)
{
if (!archive) {
io::IReadFile *file = createAndOpenFile(filename);
if (file) {
for (i = ArchiveLoader.size() - 1; i >= 0; --i) {
file->seek(0);
if (ArchiveLoader[i]->isALoadableFileFormat(file))
{
if (ArchiveLoader[i]->isALoadableFileFormat(file)) {
file->seek(0);
archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
if (archive)
@ -232,36 +211,28 @@ bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase,
file->drop();
}
}
}
else
{
} else {
// try to open archive based on archive loader type
io::IReadFile* file = 0;
io::IReadFile *file = 0;
for (i = ArchiveLoader.size()-1; i >= 0; --i)
{
if (ArchiveLoader[i]->isALoadableFileFormat(archiveType))
{
for (i = ArchiveLoader.size() - 1; i >= 0; --i) {
if (ArchiveLoader[i]->isALoadableFileFormat(archiveType)) {
// attempt to open file
if (!file)
file = createAndOpenFile(filename);
// is the file open?
if (file)
{
if (file) {
// attempt to open archive
file->seek(0);
if (ArchiveLoader[i]->isALoadableFileFormat(file))
{
if (ArchiveLoader[i]->isALoadableFileFormat(file)) {
file->seek(0);
archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
if (archive)
break;
}
}
else
{
} else {
// couldn't open file
break;
}
@ -273,43 +244,35 @@ bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase,
file->drop();
}
if (archive)
{
if (archive) {
FileArchives.push_back(archive);
if (password.size())
archive->Password=password;
archive->Password = password;
if (retArchive)
*retArchive = archive;
ret = true;
}
else
{
} else {
os::Printer::log("Could not create archive for", filename, ELL_ERROR);
}
return ret;
}
bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase,
bool CFileSystem::addFileArchive(IReadFile *file, bool ignoreCase,
bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType,
const core::stringc& password, IFileArchive** retArchive)
const core::stringc &password, IFileArchive **retArchive)
{
if (!file)
return false;
if (file)
{
IFileArchive* archive = 0;
if (file) {
IFileArchive *archive = 0;
s32 i;
if (archiveType == EFAT_UNKNOWN)
{
if (archiveType == EFAT_UNKNOWN) {
// try to load archive based on file name
for (i = ArchiveLoader.size()-1; i >=0 ; --i)
{
if (ArchiveLoader[i]->isALoadableFileFormat(file->getFileName()))
{
for (i = ArchiveLoader.size() - 1; i >= 0; --i) {
if (ArchiveLoader[i]->isALoadableFileFormat(file->getFileName())) {
archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
if (archive)
break;
@ -317,13 +280,10 @@ bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase,
}
// try to load archive based on content
if (!archive)
{
for (i = ArchiveLoader.size()-1; i >= 0; --i)
{
if (!archive) {
for (i = ArchiveLoader.size() - 1; i >= 0; --i) {
file->seek(0);
if (ArchiveLoader[i]->isALoadableFileFormat(file))
{
if (ArchiveLoader[i]->isALoadableFileFormat(file)) {
file->seek(0);
archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
if (archive)
@ -331,18 +291,13 @@ bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase,
}
}
}
}
else
{
} else {
// try to open archive based on archive loader type
for (i = ArchiveLoader.size()-1; i >= 0; --i)
{
if (ArchiveLoader[i]->isALoadableFileFormat(archiveType))
{
for (i = ArchiveLoader.size() - 1; i >= 0; --i) {
if (ArchiveLoader[i]->isALoadableFileFormat(archiveType)) {
// attempt to open archive
file->seek(0);
if (ArchiveLoader[i]->isALoadableFileFormat(file))
{
if (ArchiveLoader[i]->isALoadableFileFormat(file)) {
file->seek(0);
archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
if (archive)
@ -352,17 +307,14 @@ bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase,
}
}
if (archive)
{
if (archive) {
FileArchives.push_back(archive);
if (password.size())
archive->Password=password;
archive->Password = password;
if (retArchive)
*retArchive = archive;
return true;
}
else
{
} else {
os::Printer::log("Could not create archive for", file->getFileName(), ELL_ERROR);
}
}
@ -370,16 +322,12 @@ bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase,
return false;
}
//! Adds an archive to the file system.
bool CFileSystem::addFileArchive(IFileArchive* archive)
bool CFileSystem::addFileArchive(IFileArchive *archive)
{
if ( archive )
{
for (u32 i=0; i < FileArchives.size(); ++i)
{
if (archive == FileArchives[i])
{
if (archive) {
for (u32 i = 0; i < FileArchives.size(); ++i) {
if (archive == FileArchives[i]) {
return false;
}
}
@ -392,13 +340,11 @@ bool CFileSystem::addFileArchive(IFileArchive* archive)
return false;
}
//! removes an archive from the file system.
bool CFileSystem::removeFileArchive(u32 index)
{
bool ret = false;
if (index < FileArchives.size())
{
if (index < FileArchives.size()) {
FileArchives[index]->drop();
FileArchives.erase(index);
ret = true;
@ -406,85 +352,72 @@ bool CFileSystem::removeFileArchive(u32 index)
return ret;
}
//! removes an archive from the file system.
bool CFileSystem::removeFileArchive(const io::path& filename)
bool CFileSystem::removeFileArchive(const io::path &filename)
{
const path absPath = getAbsolutePath(filename);
for (u32 i=0; i < FileArchives.size(); ++i)
{
for (u32 i = 0; i < FileArchives.size(); ++i) {
if (absPath == FileArchives[i]->getFileList()->getPath())
return removeFileArchive(i);
}
return false;
}
//! Removes an archive from the file system.
bool CFileSystem::removeFileArchive(const IFileArchive* archive)
bool CFileSystem::removeFileArchive(const IFileArchive *archive)
{
for (u32 i=0; i < FileArchives.size(); ++i)
{
if (archive == FileArchives[i])
{
for (u32 i = 0; i < FileArchives.size(); ++i) {
if (archive == FileArchives[i]) {
return removeFileArchive(i);
}
}
return false;
}
//! gets an archive
u32 CFileSystem::getFileArchiveCount() const
{
return FileArchives.size();
}
IFileArchive* CFileSystem::getFileArchive(u32 index)
IFileArchive *CFileSystem::getFileArchive(u32 index)
{
return index < getFileArchiveCount() ? FileArchives[index] : 0;
}
//! Returns the string of the current working directory
const io::path& CFileSystem::getWorkingDirectory()
const io::path &CFileSystem::getWorkingDirectory()
{
EFileSystemType type = FileSystemType;
if (type != FILESYSTEM_NATIVE)
{
if (type != FILESYSTEM_NATIVE) {
type = FILESYSTEM_VIRTUAL;
}
else
{
#if defined(_IRR_WINDOWS_API_)
fschar_t tmp[_MAX_PATH];
_getcwd(tmp, _MAX_PATH);
WorkingDirectory[FILESYSTEM_NATIVE] = tmp;
WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/');
#endif
} else {
#if defined(_IRR_WINDOWS_API_)
fschar_t tmp[_MAX_PATH];
_getcwd(tmp, _MAX_PATH);
WorkingDirectory[FILESYSTEM_NATIVE] = tmp;
WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/');
#endif
#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
// getting the CWD is rather complex as we do not know the size
// so try it until the call was successful
// Note that neither the first nor the second parameter may be 0 according to POSIX
// getting the CWD is rather complex as we do not know the size
// so try it until the call was successful
// Note that neither the first nor the second parameter may be 0 according to POSIX
u32 pathSize=256;
char *tmpPath = new char[pathSize];
while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize)))
{
delete [] tmpPath;
pathSize *= 2;
tmpPath = new char[pathSize];
}
if (tmpPath)
{
WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath;
delete [] tmpPath;
}
#endif
u32 pathSize = 256;
char *tmpPath = new char[pathSize];
while ((pathSize < (1 << 16)) && !(getcwd(tmpPath, pathSize))) {
delete[] tmpPath;
pathSize *= 2;
tmpPath = new char[pathSize];
}
if (tmpPath) {
WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath;
delete[] tmpPath;
}
#endif
WorkingDirectory[type].validate();
}
@ -492,21 +425,17 @@ const io::path& CFileSystem::getWorkingDirectory()
return WorkingDirectory[type];
}
//! Changes the current Working Directory to the given string.
bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory)
bool CFileSystem::changeWorkingDirectoryTo(const io::path &newDirectory)
{
bool success=false;
bool success = false;
if (FileSystemType != FILESYSTEM_NATIVE)
{
if (FileSystemType != FILESYSTEM_NATIVE) {
WorkingDirectory[FILESYSTEM_VIRTUAL] = newDirectory;
// is this empty string constant really intended?
flattenFilename(WorkingDirectory[FILESYSTEM_VIRTUAL], _IRR_TEXT(""));
success = true;
}
else
{
} else {
WorkingDirectory[FILESYSTEM_NATIVE] = newDirectory;
#if defined(_MSC_VER)
@ -519,36 +448,33 @@ bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory)
return success;
}
io::path CFileSystem::getAbsolutePath(const io::path& filename) const
io::path CFileSystem::getAbsolutePath(const io::path &filename) const
{
if ( filename.empty() )
if (filename.empty())
return filename;
#if defined(_IRR_WINDOWS_API_)
fschar_t *p=0;
fschar_t *p = 0;
fschar_t fpath[_MAX_PATH];
p = _fullpath(fpath, filename.c_str(), _MAX_PATH);
core::stringc tmp(p);
tmp.replace('\\', '/');
p = _fullpath(fpath, filename.c_str(), _MAX_PATH);
core::stringc tmp(p);
tmp.replace('\\', '/');
return tmp;
#elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
c8* p=0;
c8 *p = 0;
c8 fpath[4096];
fpath[0]=0;
fpath[0] = 0;
p = realpath(filename.c_str(), fpath);
if (!p)
{
if (!p) {
// content in fpath is unclear at this point
if (!fpath[0]) // seems like fpath wasn't altered, use our best guess
{
io::path tmp(filename);
return flattenFilename(tmp);
}
else
} else
return io::path(fpath);
}
if (filename[filename.size()-1]=='/')
return io::path(p)+_IRR_TEXT("/");
if (filename[filename.size() - 1] == '/')
return io::path(p) + _IRR_TEXT("/");
else
return io::path(p);
#else
@ -556,11 +482,10 @@ io::path CFileSystem::getAbsolutePath(const io::path& filename) const
#endif
}
//! returns the directory part of a filename, i.e. all until the first
//! slash or backslash, excluding it. If no directory path is prefixed, a '.'
//! is returned.
io::path CFileSystem::getFileDir(const io::path& filename) const
io::path CFileSystem::getFileDir(const io::path &filename) const
{
// find last forward or backslash
s32 lastSlash = filename.findLast('/');
@ -573,10 +498,9 @@ io::path CFileSystem::getFileDir(const io::path& filename) const
return _IRR_TEXT(".");
}
//! returns the base part of a filename, i.e. all except for the directory
//! part. If no directory path is prefixed, the full name is returned.
io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtension) const
io::path CFileSystem::getFileBasename(const io::path &filename, bool keepExtension) const
{
// find last forward or backslash
s32 lastSlash = filename.findLast('/');
@ -585,28 +509,26 @@ io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtensi
// get number of chars after last dot
s32 end = 0;
if (!keepExtension)
{
if (!keepExtension) {
// take care to search only after last slash to check only for
// dots in the filename
end = filename.findLast('.');
if (end == -1 || end < lastSlash)
end=0;
end = 0;
else
end = filename.size()-end;
end = filename.size() - end;
}
if ((u32)lastSlash < filename.size())
return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end);
return filename.subString(lastSlash + 1, filename.size() - lastSlash - 1 - end);
else if (end != 0)
return filename.subString(0, filename.size()-end);
return filename.subString(0, filename.size() - end);
else
return filename;
}
//! flatten a path and file name for example: "/you/me/../." becomes "/you"
io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root) const
io::path &CFileSystem::flattenFilename(io::path &directory, const io::path &root) const
{
directory.replace('\\', '/');
if (directory.lastChar() != '/')
@ -617,33 +539,24 @@ io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root
s32 lastpos = 0;
s32 pos = 0;
bool lastWasRealDir=false;
bool lastWasRealDir = false;
while ((pos = directory.findNext('/', lastpos)) >= 0)
{
while ((pos = directory.findNext('/', lastpos)) >= 0) {
subdir = directory.subString(lastpos, pos - lastpos + 1);
if (subdir == _IRR_TEXT("../"))
{
if (lastWasRealDir)
{
if (subdir == _IRR_TEXT("../")) {
if (lastWasRealDir) {
deletePathFromPath(dir, 2);
lastWasRealDir=(dir.size()!=0);
}
else
{
lastWasRealDir = (dir.size() != 0);
} else {
dir.append(subdir);
lastWasRealDir=false;
lastWasRealDir = false;
}
}
else if (subdir == _IRR_TEXT("/"))
{
} else if (subdir == _IRR_TEXT("/")) {
dir = root;
}
else if (subdir != _IRR_TEXT("./"))
{
} else if (subdir != _IRR_TEXT("./")) {
dir.append(subdir);
lastWasRealDir=true;
lastWasRealDir = true;
}
lastpos = pos + 1;
@ -652,11 +565,10 @@ io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root
return directory;
}
//! Get the relative filename, relative to the given directory
path CFileSystem::getRelativeFilename(const path& filename, const path& directory) const
path CFileSystem::getRelativeFilename(const path &filename, const path &directory) const
{
if ( filename.empty() || directory.empty() )
if (filename.empty() || directory.empty())
return filename;
io::path path1, file, ext;
@ -665,59 +577,53 @@ path CFileSystem::getRelativeFilename(const path& filename, const path& director
std::list<io::path> list1, list2;
path1.split(list1, _IRR_TEXT("/\\"), 2);
path2.split(list2, _IRR_TEXT("/\\"), 2);
std::list<io::path>::const_iterator it1,it2;
it1=list1.begin();
it2=list2.begin();
std::list<io::path>::const_iterator it1, it2;
it1 = list1.begin();
it2 = list2.begin();
#if defined (_IRR_WINDOWS_API_)
#if defined(_IRR_WINDOWS_API_)
fschar_t partition1 = 0, partition2 = 0;
io::path prefix1, prefix2;
if ( it1 != list1.end() )
if (it1 != list1.end())
prefix1 = *it1;
if ( it2 != list2.end() )
if (it2 != list2.end())
prefix2 = *it2;
if ( prefix1.size() > 1 && prefix1[1] == _IRR_TEXT(':') )
if (prefix1.size() > 1 && prefix1[1] == _IRR_TEXT(':'))
partition1 = core::locale_lower(prefix1[0]);
if ( prefix2.size() > 1 && prefix2[1] == _IRR_TEXT(':') )
if (prefix2.size() > 1 && prefix2[1] == _IRR_TEXT(':'))
partition2 = core::locale_lower(prefix2[0]);
// must have the same prefix or we can't resolve it to a relative filename
if ( partition1 != partition2 )
{
if (partition1 != partition2) {
return filename;
}
#endif
#endif
for (; it1 != list1.end() && it2 != list2.end()
#if defined (_IRR_WINDOWS_API_)
&& (io::path(*it1).make_lower()==io::path(*it2).make_lower())
#if defined(_IRR_WINDOWS_API_)
&& (io::path(*it1).make_lower() == io::path(*it2).make_lower())
#else
&& (*it1==*it2)
&& (*it1 == *it2)
#endif
;)
{
;) {
++it1;
++it2;
}
path1=_IRR_TEXT("");
path1 = _IRR_TEXT("");
for (; it2 != list2.end(); ++it2)
path1 += _IRR_TEXT("../");
while (it1 != list1.end())
{
while (it1 != list1.end()) {
path1 += *it1++;
path1 += _IRR_TEXT('/');
}
path1 += file;
if (ext.size())
{
if (ext.size()) {
path1 += _IRR_TEXT('.');
path1 += ext;
}
return path1;
}
//! Sets the current file systen type
EFileSystemType CFileSystem::setFileListSystem(EFileSystemType listType)
{
@ -726,87 +632,74 @@ EFileSystemType CFileSystem::setFileListSystem(EFileSystemType listType)
return current;
}
//! Creates a list of files and directories in the current working directory
IFileList* CFileSystem::createFileList()
IFileList *CFileSystem::createFileList()
{
CFileList* r = 0;
CFileList *r = 0;
io::path Path = getWorkingDirectory();
Path.replace('\\', '/');
if (!Path.empty() && Path.lastChar() != '/')
Path.append('/');
//! Construct from native filesystem
if (FileSystemType == FILESYSTEM_NATIVE)
{
// --------------------------------------------
//! Windows version
#ifdef _IRR_WINDOWS_API_
if (FileSystemType == FILESYSTEM_NATIVE) {
// --------------------------------------------
//! Windows version
#ifdef _IRR_WINDOWS_API_
r = new CFileList(Path, true, false);
// intptr_t is optional but supported by MinGW since 2007 or earlier.
// intptr_t is optional but supported by MinGW since 2007 or earlier.
intptr_t hFile;
struct _tfinddata_t c_file;
if( (hFile = _tfindfirst( _T("*"), &c_file )) != (intptr_t)(-1L) )
{
do
{
if ((hFile = _tfindfirst(_T("*"), &c_file)) != (intptr_t)(-1L)) {
do {
r->addItem(Path + c_file.name, 0, c_file.size, (_A_SUBDIR & c_file.attrib) != 0, 0);
}
while( _tfindnext( hFile, &c_file ) == 0 );
} while (_tfindnext(hFile, &c_file) == 0);
_findclose( hFile );
_findclose(hFile);
}
#endif
// --------------------------------------------
//! Linux version
#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
#endif
// --------------------------------------------
//! Linux version
#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
r = new CFileList(Path, false, false);
r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0);
//! We use the POSIX compliant methods instead of scandir
DIR* dirHandle=opendir(Path.c_str());
if (dirHandle)
{
DIR *dirHandle = opendir(Path.c_str());
if (dirHandle) {
struct dirent *dirEntry;
while ((dirEntry=readdir(dirHandle)))
{
while ((dirEntry = readdir(dirHandle))) {
u32 size = 0;
bool isDirectory = false;
if((strcmp(dirEntry->d_name, ".")==0) ||
(strcmp(dirEntry->d_name, "..")==0))
{
if ((strcmp(dirEntry->d_name, ".") == 0) ||
(strcmp(dirEntry->d_name, "..") == 0)) {
continue;
}
struct stat buf;
if (stat(dirEntry->d_name, &buf)==0)
{
if (stat(dirEntry->d_name, &buf) == 0) {
size = buf.st_size;
isDirectory = S_ISDIR(buf.st_mode);
}
#if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__) && !defined(__HAIKU__)
#if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__) && !defined(__HAIKU__)
// only available on some systems
else
{
else {
isDirectory = dirEntry->d_type == DT_DIR;
}
#endif
#endif
r->addItem(Path + dirEntry->d_name, 0, size, isDirectory, 0);
}
closedir(dirHandle);
}
#endif
}
else
{
#endif
} else {
//! create file list for the virtual filesystem
r = new CFileList(Path, false, false);
@ -821,14 +714,11 @@ IFileList* CFileSystem::createFileList()
r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0);
//! merge archives
for (u32 i=0; i < FileArchives.size(); ++i)
{
for (u32 i = 0; i < FileArchives.size(); ++i) {
const IFileList *merge = FileArchives[i]->getFileList();
for (u32 j=0; j < merge->getFileCount(); ++j)
{
if (core::isInSameDirectory(Path, merge->getFullFileName(j)) == 0)
{
for (u32 j = 0; j < merge->getFileCount(); ++j) {
if (core::isInSameDirectory(Path, merge->getFullFileName(j)) == 0) {
r->addItem(merge->getFullFileName(j), merge->getFileOffset(j), merge->getFileSize(j), merge->isDirectory(j), 0);
}
}
@ -841,36 +731,33 @@ IFileList* CFileSystem::createFileList()
}
//! Creates an empty filelist
IFileList* CFileSystem::createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
IFileList *CFileSystem::createEmptyFileList(const io::path &path, bool ignoreCase, bool ignorePaths)
{
return new CFileList(path, ignoreCase, ignorePaths);
}
//! determines if a file exists and would be able to be opened.
bool CFileSystem::existFile(const io::path& filename) const
bool CFileSystem::existFile(const io::path &filename) const
{
for (u32 i=0; i < FileArchives.size(); ++i)
if (FileArchives[i]->getFileList()->findFile(filename)!=-1)
for (u32 i = 0; i < FileArchives.size(); ++i)
if (FileArchives[i]->getFileList()->findFile(filename) != -1)
return true;
#if defined(_MSC_VER)
return (_access(filename.c_str(), 0) != -1);
return (_access(filename.c_str(), 0) != -1);
#elif defined(F_OK)
return (access(filename.c_str(), F_OK) != -1);
return (access(filename.c_str(), F_OK) != -1);
#else
return (access(filename.c_str(), 0) != -1);
#endif
}
//! creates a filesystem which is able to open files from the ordinary file system,
//! and out of zipfiles, which are able to be added to the filesystem.
IFileSystem* createFileSystem()
IFileSystem *createFileSystem()
{
return new CFileSystem();
}
} // end namespace irr
} // end namespace io

View File

@ -12,7 +12,7 @@ namespace irr
namespace io
{
class CZipReader;
class CZipReader;
/*!
FileSystem which uses normal files and one zipfile
@ -20,7 +20,6 @@ namespace io
class CFileSystem : public IFileSystem
{
public:
//! constructor
CFileSystem();
@ -28,114 +27,112 @@ public:
virtual ~CFileSystem();
//! opens a file for read access
IReadFile* createAndOpenFile(const io::path& filename) override;
IReadFile *createAndOpenFile(const io::path &filename) override;
//! Creates an IReadFile interface for accessing memory like a file.
IReadFile* createMemoryReadFile(const void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped = false) override;
IReadFile *createMemoryReadFile(const void *memory, s32 len, const io::path &fileName, bool deleteMemoryWhenDropped = false) override;
//! Creates an IReadFile interface for accessing files inside files
IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) override;
IReadFile *createLimitReadFile(const io::path &fileName, IReadFile *alreadyOpenedFile, long pos, long areaSize) override;
//! Creates an IWriteFile interface for accessing memory like a file.
IWriteFile* createMemoryWriteFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped=false) override;
IWriteFile *createMemoryWriteFile(void *memory, s32 len, const io::path &fileName, bool deleteMemoryWhenDropped = false) override;
//! Opens a file for write access.
IWriteFile* createAndWriteFile(const io::path& filename, bool append=false) override;
IWriteFile *createAndWriteFile(const io::path &filename, bool append = false) override;
//! Adds an archive to the file system.
virtual bool addFileArchive(const io::path& filename,
virtual bool addFileArchive(const io::path &filename,
bool ignoreCase = true, bool ignorePaths = true,
E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN,
const core::stringc& password="",
IFileArchive** retArchive = 0) override;
const core::stringc &password = "",
IFileArchive **retArchive = 0) override;
//! Adds an archive to the file system.
virtual bool addFileArchive(IReadFile* file, bool ignoreCase=true,
bool ignorePaths=true,
E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN,
const core::stringc& password="",
IFileArchive** retArchive = 0) override;
virtual bool addFileArchive(IReadFile *file, bool ignoreCase = true,
bool ignorePaths = true,
E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN,
const core::stringc &password = "",
IFileArchive **retArchive = 0) override;
//! Adds an archive to the file system.
bool addFileArchive(IFileArchive* archive) override;
bool addFileArchive(IFileArchive *archive) override;
//! move the hirarchy of the filesystem. moves sourceIndex relative up or down
bool moveFileArchive(u32 sourceIndex, s32 relative) override;
//! Adds an external archive loader to the engine.
void addArchiveLoader(IArchiveLoader* loader) override;
void addArchiveLoader(IArchiveLoader *loader) override;
//! Returns the total number of archive loaders added.
u32 getArchiveLoaderCount() const override;
//! Gets the archive loader by index.
IArchiveLoader* getArchiveLoader(u32 index) const override;
IArchiveLoader *getArchiveLoader(u32 index) const override;
//! gets the file archive count
u32 getFileArchiveCount() const override;
//! gets an archive
IFileArchive* getFileArchive(u32 index) override;
IFileArchive *getFileArchive(u32 index) override;
//! removes an archive from the file system.
bool removeFileArchive(u32 index) override;
//! removes an archive from the file system.
bool removeFileArchive(const io::path& filename) override;
bool removeFileArchive(const io::path &filename) override;
//! Removes an archive from the file system.
bool removeFileArchive(const IFileArchive* archive) override;
bool removeFileArchive(const IFileArchive *archive) override;
//! Returns the string of the current working directory
const io::path& getWorkingDirectory() override;
const io::path &getWorkingDirectory() override;
//! Changes the current Working Directory to the string given.
//! The string is operating system dependent. Under Windows it will look
//! like this: "drive:\directory\sudirectory\"
bool changeWorkingDirectoryTo(const io::path& newDirectory) override;
bool changeWorkingDirectoryTo(const io::path &newDirectory) override;
//! Converts a relative path to an absolute (unique) path, resolving symbolic links
io::path getAbsolutePath(const io::path& filename) const override;
io::path getAbsolutePath(const io::path &filename) const override;
//! Returns the directory a file is located in.
/** \param filename: The file to get the directory from */
io::path getFileDir(const io::path& filename) const override;
io::path getFileDir(const io::path &filename) const override;
//! Returns the base part of a filename, i.e. the name without the directory
//! part. If no directory is prefixed, the full name is returned.
/** \param filename: The file to get the basename from */
io::path getFileBasename(const io::path& filename, bool keepExtension=true) const override;
io::path getFileBasename(const io::path &filename, bool keepExtension = true) const override;
//! flatten a path and file name for example: "/you/me/../." becomes "/you"
io::path& flattenFilename( io::path& directory, const io::path& root = "/" ) const override;
io::path &flattenFilename(io::path &directory, const io::path &root = "/") const override;
//! Get the relative filename, relative to the given directory
path getRelativeFilename(const path& filename, const path& directory) const override;
path getRelativeFilename(const path &filename, const path &directory) const override;
EFileSystemType setFileListSystem(EFileSystemType listType) override;
//! Creates a list of files and directories in the current working directory
//! and returns it.
IFileList* createFileList() override;
IFileList *createFileList() override;
//! Creates an empty filelist
IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) override;
IFileList *createEmptyFileList(const io::path &path, bool ignoreCase, bool ignorePaths) override;
//! determines if a file exists and would be able to be opened.
bool existFile(const io::path& filename) const override;
bool existFile(const io::path &filename) const override;
private:
//! Currently used FileSystemType
EFileSystemType FileSystemType;
//! WorkingDirectory for Native and Virtual filesystems
io::path WorkingDirectory [2];
io::path WorkingDirectory[2];
//! currently attached ArchiveLoaders
core::array<IArchiveLoader*> ArchiveLoader;
core::array<IArchiveLoader *> ArchiveLoader;
//! currently attached Archives
core::array<IFileArchive*> FileArchives;
core::array<IFileArchive *> FileArchives;
};
} // end namespace irr
} // end namespace io

View File

@ -20,83 +20,89 @@ namespace irr
namespace video
{
CGLXManager::CGLXManager(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata, int screennr)
: Params(params), PrimaryContext(videodata), VisualInfo(0), glxFBConfig(0), GlxWin(0)
CGLXManager::CGLXManager(const SIrrlichtCreationParameters &params, const SExposedVideoData &videodata, int screennr) :
Params(params), PrimaryContext(videodata), VisualInfo(0), glxFBConfig(0), GlxWin(0)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGLXManager");
#endif
#endif
CurrentContext.OpenGLLinux.X11Display=PrimaryContext.OpenGLLinux.X11Display;
CurrentContext.OpenGLLinux.X11Display = PrimaryContext.OpenGLLinux.X11Display;
int major, minor;
Display* display = (Display*)PrimaryContext.OpenGLLinux.X11Display;
const bool isAvailableGLX=glXQueryExtension(display,&major,&minor);
Display *display = (Display *)PrimaryContext.OpenGLLinux.X11Display;
const bool isAvailableGLX = glXQueryExtension(display, &major, &minor);
if (isAvailableGLX && glXQueryVersion(display, &major, &minor))
{
if (isAvailableGLX && glXQueryVersion(display, &major, &minor)) {
#if defined(GLX_VERSION_1_3)
typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
typedef GLXFBConfig *(*PFNGLXCHOOSEFBCONFIGPROC)(Display *dpy, int screen, const int *attrib_list, int *nelements);
PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXChooseFBConfig"));
if (major==1 && minor>2 && glxChooseFBConfig)
{
os::Printer::log("GLX >= 1.3", ELL_DEBUG);
PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte *>("glXChooseFBConfig"));
if (major == 1 && minor > 2 && glxChooseFBConfig) {
os::Printer::log("GLX >= 1.3", ELL_DEBUG);
// attribute array for the draw buffer
int visualAttrBuffer[] =
{
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, Params.WithAlphaChannel?1:0,
GLX_DEPTH_SIZE, Params.ZBufferBits, //10,11
GLX_DOUBLEBUFFER, Params.Doublebuffer?True:False,
GLX_STENCIL_SIZE, Params.Stencilbuffer?1:0,
GLX_RENDER_TYPE,
GLX_RGBA_BIT,
GLX_RED_SIZE,
4,
GLX_GREEN_SIZE,
4,
GLX_BLUE_SIZE,
4,
GLX_ALPHA_SIZE,
Params.WithAlphaChannel ? 1 : 0,
GLX_DEPTH_SIZE,
Params.ZBufferBits, // 10,11
GLX_DOUBLEBUFFER,
Params.Doublebuffer ? True : False,
GLX_STENCIL_SIZE,
Params.Stencilbuffer ? 1 : 0,
#if defined(GLX_VERSION_1_4) && defined(GLX_SAMPLE_BUFFERS) // we need to check the extension string!
GLX_SAMPLE_BUFFERS, 1,
GLX_SAMPLES, Params.AntiAlias, // 18,19
GLX_SAMPLE_BUFFERS,
1,
GLX_SAMPLES,
Params.AntiAlias, // 18,19
#elif defined(GLX_ARB_multisample)
GLX_SAMPLE_BUFFERS_ARB, 1,
GLX_SAMPLES_ARB, Params.AntiAlias, // 18,19
GLX_SAMPLE_BUFFERS_ARB,
1,
GLX_SAMPLES_ARB,
Params.AntiAlias, // 18,19
#elif defined(GLX_SGIS_multisample)
GLX_SAMPLE_BUFFERS_SGIS, 1,
GLX_SAMPLES_SGIS, Params.AntiAlias, // 18,19
GLX_SAMPLE_BUFFERS_SGIS,
1,
GLX_SAMPLES_SGIS,
Params.AntiAlias, // 18,19
#endif
GLX_STEREO, Params.Stereobuffer?True:False,
GLX_STEREO,
Params.Stereobuffer ? True : False,
None
};
GLXFBConfig *configList=0;
int nitems=0;
if (Params.AntiAlias<2)
{
GLXFBConfig *configList = 0;
int nitems = 0;
if (Params.AntiAlias < 2) {
visualAttrBuffer[17] = 0;
visualAttrBuffer[19] = 0;
}
// first round with unchanged values
{
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (!configList && Params.AntiAlias)
{
while (!configList && (visualAttrBuffer[19]>1))
{
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
if (!configList && Params.AntiAlias) {
while (!configList && (visualAttrBuffer[19] > 1)) {
visualAttrBuffer[19] -= 1;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
}
if (!configList)
{
if (!configList) {
visualAttrBuffer[17] = 0;
visualAttrBuffer[19] = 0;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (configList)
{
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
if (configList) {
os::Printer::log("No FSAA available.", ELL_WARNING);
Params.AntiAlias=0;
}
else
{
//reenable multisampling
Params.AntiAlias = 0;
} else {
// reenable multisampling
visualAttrBuffer[17] = 1;
visualAttrBuffer[19] = Params.AntiAlias;
}
@ -107,34 +113,27 @@ os::Printer::log("GLX >= 1.3", ELL_DEBUG);
// If the first round was with stencil flag it's now without
// Other way round also makes sense because some configs
// only have depth buffer combined with stencil buffer
if (!configList)
{
if (!configList) {
if (Params.Stencilbuffer)
os::Printer::log("No stencilbuffer available, disabling stencil shadows.", ELL_WARNING);
Params.Stencilbuffer = !Params.Stencilbuffer;
visualAttrBuffer[15]=Params.Stencilbuffer?1:0;
visualAttrBuffer[15] = Params.Stencilbuffer ? 1 : 0;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (!configList && Params.AntiAlias)
{
while (!configList && (visualAttrBuffer[19]>1))
{
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
if (!configList && Params.AntiAlias) {
while (!configList && (visualAttrBuffer[19] > 1)) {
visualAttrBuffer[19] -= 1;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
}
if (!configList)
{
if (!configList) {
visualAttrBuffer[17] = 0;
visualAttrBuffer[19] = 0;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (configList)
{
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
if (configList) {
os::Printer::log("No FSAA available.", ELL_WARNING);
Params.AntiAlias=0;
}
else
{
//reenable multisampling
Params.AntiAlias = 0;
} else {
// reenable multisampling
visualAttrBuffer[17] = 1;
visualAttrBuffer[19] = Params.AntiAlias;
}
@ -142,91 +141,78 @@ os::Printer::log("GLX >= 1.3", ELL_DEBUG);
}
}
// Next try without double buffer
if (!configList && Params.Doublebuffer)
{
if (!configList && Params.Doublebuffer) {
os::Printer::log("No doublebuffering available.", ELL_WARNING);
Params.Doublebuffer=false;
Params.Doublebuffer = false;
visualAttrBuffer[13] = GLX_DONT_CARE;
Params.Stencilbuffer = false;
visualAttrBuffer[15]=0;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (!configList && Params.AntiAlias)
{
while (!configList && (visualAttrBuffer[19]>1))
{
visualAttrBuffer[15] = 0;
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
if (!configList && Params.AntiAlias) {
while (!configList && (visualAttrBuffer[19] > 1)) {
visualAttrBuffer[19] -= 1;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
}
if (!configList)
{
if (!configList) {
visualAttrBuffer[17] = 0;
visualAttrBuffer[19] = 0;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (configList)
{
configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems);
if (configList) {
os::Printer::log("No FSAA available.", ELL_WARNING);
Params.AntiAlias=0;
}
else
{
//reenable multisampling
Params.AntiAlias = 0;
} else {
// reenable multisampling
visualAttrBuffer[17] = 1;
visualAttrBuffer[19] = Params.AntiAlias;
}
}
}
}
if (configList)
{
glxFBConfig=configList[0];
if (configList) {
glxFBConfig = configList[0];
XFree(configList);
typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
PFNGLXGETVISUALFROMFBCONFIGPROC glxGetVisualFromFBConfig= (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXGetVisualFromFBConfig"));
typedef XVisualInfo *(*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display *dpy, GLXFBConfig config);
PFNGLXGETVISUALFROMFBCONFIGPROC glxGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte *>("glXGetVisualFromFBConfig"));
if (glxGetVisualFromFBConfig)
VisualInfo = glxGetVisualFromFBConfig(display,(GLXFBConfig)glxFBConfig);
VisualInfo = glxGetVisualFromFBConfig(display, (GLXFBConfig)glxFBConfig);
}
}
else
} else
#endif
{
// attribute array for the draw buffer
int visualAttrBuffer[] =
{
GLX_RGBA, GLX_USE_GL,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, Params.WithAlphaChannel?1:0,
GLX_DEPTH_SIZE, Params.ZBufferBits,
GLX_STENCIL_SIZE, Params.Stencilbuffer?1:0, // 12,13
// The following attributes have no flags, but are
// either present or not. As a no-op we use
// GLX_USE_GL, which is silently ignored by glXChooseVisual
Params.Doublebuffer?GLX_DOUBLEBUFFER:GLX_USE_GL, // 14
Params.Stereobuffer?GLX_STEREO:GLX_USE_GL, // 15
None
};
{
GLX_RGBA, GLX_USE_GL,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, Params.WithAlphaChannel ? 1 : 0,
GLX_DEPTH_SIZE, Params.ZBufferBits,
GLX_STENCIL_SIZE, Params.Stencilbuffer ? 1 : 0, // 12,13
// The following attributes have no flags, but are
// either present or not. As a no-op we use
// GLX_USE_GL, which is silently ignored by glXChooseVisual
Params.Doublebuffer ? GLX_DOUBLEBUFFER : GLX_USE_GL, // 14
Params.Stereobuffer ? GLX_STEREO : GLX_USE_GL, // 15
None};
VisualInfo=glXChooseVisual(display, screennr, visualAttrBuffer);
if (!VisualInfo)
{
VisualInfo = glXChooseVisual(display, screennr, visualAttrBuffer);
if (!VisualInfo) {
if (Params.Stencilbuffer)
os::Printer::log("No stencilbuffer available, disabling.", ELL_WARNING);
Params.Stencilbuffer = !Params.Stencilbuffer;
visualAttrBuffer[13]=Params.Stencilbuffer?1:0;
visualAttrBuffer[13] = Params.Stencilbuffer ? 1 : 0;
VisualInfo=glXChooseVisual(display, screennr, visualAttrBuffer);
if (!VisualInfo && Params.Doublebuffer)
{
VisualInfo = glXChooseVisual(display, screennr, visualAttrBuffer);
if (!VisualInfo && Params.Doublebuffer) {
os::Printer::log("No doublebuffering available.", ELL_WARNING);
Params.Doublebuffer=false;
Params.Doublebuffer = false;
visualAttrBuffer[14] = GLX_USE_GL;
VisualInfo=glXChooseVisual(display, screennr, visualAttrBuffer);
VisualInfo = glXChooseVisual(display, screennr, visualAttrBuffer);
}
}
}
}
else
} else
os::Printer::log("No GLX support available. OpenGL driver will not work.", ELL_WARNING);
}
@ -234,19 +220,18 @@ CGLXManager::~CGLXManager()
{
}
bool CGLXManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata)
bool CGLXManager::initialize(const SIrrlichtCreationParameters &params, const SExposedVideoData &videodata)
{
// store params
Params=params;
Params = params;
// set display
CurrentContext.OpenGLLinux.X11Display=videodata.OpenGLLinux.X11Display;
CurrentContext.OpenGLLinux.X11Display = videodata.OpenGLLinux.X11Display;
// now get new window
CurrentContext.OpenGLLinux.X11Window=videodata.OpenGLLinux.X11Window;
if (!PrimaryContext.OpenGLLinux.X11Window)
{
PrimaryContext.OpenGLLinux.X11Window=CurrentContext.OpenGLLinux.X11Window;
CurrentContext.OpenGLLinux.X11Window = videodata.OpenGLLinux.X11Window;
if (!PrimaryContext.OpenGLLinux.X11Window) {
PrimaryContext.OpenGLLinux.X11Window = CurrentContext.OpenGLLinux.X11Window;
}
return true;
@ -254,25 +239,21 @@ bool CGLXManager::initialize(const SIrrlichtCreationParameters& params, const SE
void CGLXManager::terminate()
{
memset((void*)&CurrentContext, 0, sizeof(CurrentContext));
memset((void *)&CurrentContext, 0, sizeof(CurrentContext));
}
bool CGLXManager::generateSurface()
{
if (glxFBConfig)
{
GlxWin=glXCreateWindow((Display*)CurrentContext.OpenGLLinux.X11Display,(GLXFBConfig)glxFBConfig,CurrentContext.OpenGLLinux.X11Window,NULL);
if (!GlxWin)
{
if (glxFBConfig) {
GlxWin = glXCreateWindow((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, CurrentContext.OpenGLLinux.X11Window, NULL);
if (!GlxWin) {
os::Printer::log("Could not create GLX window.", ELL_WARNING);
return false;
}
CurrentContext.OpenGLLinux.GLXWindow=GlxWin;
}
else
{
CurrentContext.OpenGLLinux.GLXWindow=CurrentContext.OpenGLLinux.X11Window;
CurrentContext.OpenGLLinux.GLXWindow = GlxWin;
} else {
CurrentContext.OpenGLLinux.GLXWindow = CurrentContext.OpenGLLinux.X11Window;
}
return true;
}
@ -280,7 +261,7 @@ bool CGLXManager::generateSurface()
void CGLXManager::destroySurface()
{
if (GlxWin)
glXDestroyWindow((Display*)CurrentContext.OpenGLLinux.X11Display, GlxWin);
glXDestroyWindow((Display *)CurrentContext.OpenGLLinux.X11Display, GlxWin);
}
#if defined(GLX_ARB_create_context)
@ -297,25 +278,21 @@ bool CGLXManager::generateContext()
{
GLXContext context = 0;
if (glxFBConfig)
{
if (GlxWin)
{
if (glxFBConfig) {
if (GlxWin) {
#if defined(GLX_ARB_create_context)
PFNGLXCREATECONTEXTATTRIBSARBPROC glxCreateContextAttribsARB=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB"));
PFNGLXCREATECONTEXTATTRIBSARBPROC glxCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(reinterpret_cast<const GLubyte *>("glXCreateContextAttribsARB"));
if (glxCreateContextAttribsARB)
{
if (glxCreateContextAttribsARB) {
os::Printer::log("GLX with GLX_ARB_create_context", ELL_DEBUG);
int contextAttrBuffer[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
// GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
None
};
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
// GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
None};
XErrorHandler old = XSetErrorHandler(IrrIgnoreError);
context = glxCreateContextAttribsARB((Display*)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, NULL, True, contextAttrBuffer);
context = glxCreateContextAttribsARB((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, NULL, True, contextAttrBuffer);
XSetErrorHandler(old);
// transparently fall back to legacy call
}
@ -323,78 +300,59 @@ bool CGLXManager::generateContext()
#endif
{
// create glx context
context = glXCreateNewContext((Display*)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, GLX_RGBA_TYPE, NULL, True);
if (!context)
{
context = glXCreateNewContext((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, GLX_RGBA_TYPE, NULL, True);
if (!context) {
os::Printer::log("Could not create GLX rendering context.", ELL_WARNING);
return false;
}
}
}
else
{
} else {
os::Printer::log("GLX window was not properly created.", ELL_WARNING);
return false;
}
}
else
{
context = glXCreateContext((Display*)CurrentContext.OpenGLLinux.X11Display, VisualInfo, NULL, True);
if (!context)
{
} else {
context = glXCreateContext((Display *)CurrentContext.OpenGLLinux.X11Display, VisualInfo, NULL, True);
if (!context) {
os::Printer::log("Could not create GLX rendering context.", ELL_WARNING);
return false;
}
}
CurrentContext.OpenGLLinux.X11Context=context;
CurrentContext.OpenGLLinux.X11Context = context;
return true;
}
const SExposedVideoData& CGLXManager::getContext() const
const SExposedVideoData &CGLXManager::getContext() const
{
return CurrentContext;
}
bool CGLXManager::activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero)
bool CGLXManager::activateContext(const SExposedVideoData &videoData, bool restorePrimaryOnZero)
{
//TODO: handle restorePrimaryOnZero
// TODO: handle restorePrimaryOnZero
if (videoData.OpenGLLinux.X11Window)
{
if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Context)
{
if (!glXMakeCurrent((Display*)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.GLXWindow, (GLXContext)videoData.OpenGLLinux.X11Context))
{
if (videoData.OpenGLLinux.X11Window) {
if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Context) {
if (!glXMakeCurrent((Display *)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.GLXWindow, (GLXContext)videoData.OpenGLLinux.X11Context)) {
os::Printer::log("Context activation failed.");
return false;
}
else
{
} else {
CurrentContext.OpenGLLinux.GLXWindow = videoData.OpenGLLinux.GLXWindow;
CurrentContext.OpenGLLinux.X11Window = videoData.OpenGLLinux.X11Window;
CurrentContext.OpenGLLinux.X11Display = videoData.OpenGLLinux.X11Display;
}
}
else
{
} else {
// in case we only got a window ID, try with the existing values for display and context
if (!glXMakeCurrent((Display*)PrimaryContext.OpenGLLinux.X11Display, videoData.OpenGLLinux.GLXWindow, (GLXContext)PrimaryContext.OpenGLLinux.X11Context))
{
if (!glXMakeCurrent((Display *)PrimaryContext.OpenGLLinux.X11Display, videoData.OpenGLLinux.GLXWindow, (GLXContext)PrimaryContext.OpenGLLinux.X11Context)) {
os::Printer::log("Context activation failed.");
return false;
}
else
{
} else {
CurrentContext.OpenGLLinux.GLXWindow = videoData.OpenGLLinux.GLXWindow;
CurrentContext.OpenGLLinux.X11Window = videoData.OpenGLLinux.X11Window;
CurrentContext.OpenGLLinux.X11Display = PrimaryContext.OpenGLLinux.X11Display;
}
}
}
else if (!restorePrimaryOnZero && !videoData.OpenGLLinux.X11Window && !videoData.OpenGLLinux.X11Display)
{
if (!glXMakeCurrent((Display*)PrimaryContext.OpenGLLinux.X11Display, None, NULL))
{
} else if (!restorePrimaryOnZero && !videoData.OpenGLLinux.X11Window && !videoData.OpenGLLinux.X11Display) {
if (!glXMakeCurrent((Display *)PrimaryContext.OpenGLLinux.X11Display, None, NULL)) {
os::Printer::log("Render Context reset failed.");
return false;
}
@ -402,15 +360,11 @@ bool CGLXManager::activateContext(const SExposedVideoData& videoData, bool resto
CurrentContext.OpenGLLinux.X11Display = 0;
}
// set back to main context
else if (CurrentContext.OpenGLLinux.X11Display != PrimaryContext.OpenGLLinux.X11Display)
{
if (!glXMakeCurrent((Display*)PrimaryContext.OpenGLLinux.X11Display, PrimaryContext.OpenGLLinux.X11Window, (GLXContext)PrimaryContext.OpenGLLinux.X11Context))
{
else if (CurrentContext.OpenGLLinux.X11Display != PrimaryContext.OpenGLLinux.X11Display) {
if (!glXMakeCurrent((Display *)PrimaryContext.OpenGLLinux.X11Display, PrimaryContext.OpenGLLinux.X11Window, (GLXContext)PrimaryContext.OpenGLLinux.X11Context)) {
os::Printer::log("Context activation failed.");
return false;
}
else
{
} else {
CurrentContext = PrimaryContext;
}
}
@ -419,30 +373,26 @@ bool CGLXManager::activateContext(const SExposedVideoData& videoData, bool resto
void CGLXManager::destroyContext()
{
if (CurrentContext.OpenGLLinux.X11Context)
{
if (GlxWin)
{
if (!glXMakeContextCurrent((Display*)CurrentContext.OpenGLLinux.X11Display, None, None, NULL))
if (CurrentContext.OpenGLLinux.X11Context) {
if (GlxWin) {
if (!glXMakeContextCurrent((Display *)CurrentContext.OpenGLLinux.X11Display, None, None, NULL))
os::Printer::log("Could not release glx context.", ELL_WARNING);
} else {
if (!glXMakeCurrent((Display *)CurrentContext.OpenGLLinux.X11Display, None, NULL))
os::Printer::log("Could not release glx context.", ELL_WARNING);
}
else
{
if (!glXMakeCurrent((Display*)CurrentContext.OpenGLLinux.X11Display, None, NULL))
os::Printer::log("Could not release glx context.", ELL_WARNING);
}
glXDestroyContext((Display*)CurrentContext.OpenGLLinux.X11Display, (GLXContext)CurrentContext.OpenGLLinux.X11Context);
glXDestroyContext((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXContext)CurrentContext.OpenGLLinux.X11Context);
}
}
void* CGLXManager::getProcAddress(const std::string &procName)
void *CGLXManager::getProcAddress(const std::string &procName)
{
return (void*)glXGetProcAddressARB(reinterpret_cast<const GLubyte*>(procName.c_str()));
return (void *)glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.c_str()));
}
bool CGLXManager::swapBuffers()
{
glXSwapBuffers((Display*)CurrentContext.OpenGLLinux.X11Display, CurrentContext.OpenGLLinux.GLXWindow);
glXSwapBuffers((Display *)CurrentContext.OpenGLLinux.X11Display, CurrentContext.OpenGLLinux.GLXWindow);
return true;
}
@ -450,4 +400,3 @@ bool CGLXManager::swapBuffers()
}
#endif

View File

@ -20,56 +20,56 @@ namespace irr
{
namespace video
{
// GLX manager.
class CGLXManager : public IContextManager
{
public:
//! Constructor.
CGLXManager(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata, int screennr);
// GLX manager.
class CGLXManager : public IContextManager
{
public:
//! Constructor.
CGLXManager(const SIrrlichtCreationParameters &params, const SExposedVideoData &videodata, int screennr);
//! Destructor
~CGLXManager();
//! Destructor
~CGLXManager();
// Initialize
bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data) override;
// Initialize
bool initialize(const SIrrlichtCreationParameters &params, const SExposedVideoData &data) override;
// Terminate
void terminate() override;
// Terminate
void terminate() override;
// Create surface.
bool generateSurface() override;
// Create surface.
bool generateSurface() override;
// Destroy surface.
void destroySurface() override;
// Destroy surface.
void destroySurface() override;
// Create context.
bool generateContext() override;
// Create context.
bool generateContext() override;
// Destroy context.
void destroyContext() override;
// Destroy context.
void destroyContext() override;
//! Get current context
const SExposedVideoData& getContext() const override;
//! Get current context
const SExposedVideoData &getContext() const override;
//! Change render context, disable old and activate new defined by videoData
bool activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero) override;
//! Change render context, disable old and activate new defined by videoData
bool activateContext(const SExposedVideoData &videoData, bool restorePrimaryOnZero) override;
// Get procedure address.
void* getProcAddress(const std::string &procName) override;
// Get procedure address.
void *getProcAddress(const std::string &procName) override;
// Swap buffers.
bool swapBuffers() override;
// Swap buffers.
bool swapBuffers() override;
XVisualInfo* getVisual() const {return VisualInfo;} // return XVisualInfo
XVisualInfo *getVisual() const { return VisualInfo; } // return XVisualInfo
private:
SIrrlichtCreationParameters Params;
SExposedVideoData PrimaryContext;
SExposedVideoData CurrentContext;
XVisualInfo* VisualInfo;
void* glxFBConfig; // GLXFBConfig
XID GlxWin; // GLXWindow
};
private:
SIrrlichtCreationParameters Params;
SExposedVideoData PrimaryContext;
SExposedVideoData CurrentContext;
XVisualInfo *VisualInfo;
void *glxFBConfig; // GLXFBConfig
XID GlxWin; // GLXWindow
};
}
}

View File

@ -16,19 +16,19 @@ namespace gui
{
//! constructor
CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool noclip)
: IGUIButton(environment, parent, id, rectangle),
SpriteBank(0), OverrideFont(0),
OverrideColorEnabled(false), OverrideColor(video::SColor(101,255,255,255)),
ClickTime(0), HoverTime(0), FocusTime(0),
ClickShiftState(false), ClickControlState(false),
IsPushButton(false), Pressed(false),
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
CGUIButton::CGUIButton(IGUIEnvironment *environment, IGUIElement *parent,
s32 id, core::rect<s32> rectangle, bool noclip) :
IGUIButton(environment, parent, id, rectangle),
SpriteBank(0), OverrideFont(0),
OverrideColorEnabled(false), OverrideColor(video::SColor(101, 255, 255, 255)),
ClickTime(0), HoverTime(0), FocusTime(0),
ClickShiftState(false), ClickControlState(false),
IsPushButton(false), Pressed(false),
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUIButton");
#endif
#endif
setNotClipped(noclip);
// This element can be tabbed.
@ -36,7 +36,6 @@ CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
setTabOrder(-1);
}
//! destructor
CGUIButton::~CGUIButton()
{
@ -47,29 +46,25 @@ CGUIButton::~CGUIButton()
SpriteBank->drop();
}
//! Sets if the images should be scaled to fit the button
void CGUIButton::setScaleImage(bool scaleImage)
{
ScaleImage = scaleImage;
}
//! Returns whether the button scale the used images
bool CGUIButton::isScalingImage() const
{
return ScaleImage;
}
//! Sets if the button should use the skin to draw its border
void CGUIButton::setDrawBorder(bool border)
{
DrawBorder = border;
}
void CGUIButton::setSpriteBank(IGUISpriteBank* sprites)
void CGUIButton::setSpriteBank(IGUISpriteBank *sprites)
{
if (sprites)
sprites->grab();
@ -80,12 +75,11 @@ void CGUIButton::setSpriteBank(IGUISpriteBank* sprites)
SpriteBank = sprites;
}
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
{
ButtonSprites[(u32)state].Index = index;
ButtonSprites[(u32)state].Color = color;
ButtonSprites[(u32)state].Loop = loop;
ButtonSprites[(u32)state].Index = index;
ButtonSprites[(u32)state].Color = color;
ButtonSprites[(u32)state].Loop = loop;
ButtonSprites[(u32)state].Scale = scale;
}
@ -114,17 +108,15 @@ bool CGUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
}
//! called if an event happened.
bool CGUIButton::OnEvent(const SEvent& event)
bool CGUIButton::OnEvent(const SEvent &event)
{
if (!isEnabled())
return IGUIElement::OnEvent(event);
switch(event.EventType)
{
switch (event.EventType) {
case EET_KEY_INPUT_EVENT:
if (event.KeyInput.PressedDown &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
{
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) {
if (!IsPushButton)
setPressed(true);
else
@ -132,21 +124,16 @@ bool CGUIButton::OnEvent(const SEvent& event)
return true;
}
if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
{
if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE) {
setPressed(false);
return true;
}
else
if (!event.KeyInput.PressedDown && Pressed &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
{
} else if (!event.KeyInput.PressedDown && Pressed &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) {
if (!IsPushButton)
setPressed(false);
if (Parent)
{
if (Parent) {
ClickShiftState = event.KeyInput.Shift;
ClickControlState = event.KeyInput.Control;
@ -161,39 +148,28 @@ bool CGUIButton::OnEvent(const SEvent& event)
}
break;
case EET_GUI_EVENT:
if (event.GUIEvent.Caller == this)
{
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
{
if (event.GUIEvent.Caller == this) {
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) {
if (!IsPushButton)
setPressed(false);
FocusTime = os::Timer::getTime();
}
else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
{
} else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) {
FocusTime = os::Timer::getTime();
}
else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT)
{
} else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT) {
HoverTime = os::Timer::getTime();
}
}
break;
case EET_MOUSE_INPUT_EVENT:
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
{
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
if (!IsPushButton)
setPressed(true);
return true;
}
else
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
{
} else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
bool wasPressed = Pressed;
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) )
{
if (!AbsoluteClippingRect.isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y))) {
if (!IsPushButton)
setPressed(false);
return true;
@ -201,14 +177,12 @@ bool CGUIButton::OnEvent(const SEvent& event)
if (!IsPushButton)
setPressed(false);
else
{
else {
setPressed(!Pressed);
}
if ((!IsPushButton && wasPressed && Parent) ||
(IsPushButton && wasPressed != Pressed))
{
(IsPushButton && wasPressed != Pressed)) {
ClickShiftState = event.MouseInput.Shift;
ClickControlState = event.MouseInput.Control;
@ -230,70 +204,58 @@ bool CGUIButton::OnEvent(const SEvent& event)
return Parent ? Parent->OnEvent(event) : false;
}
//! draws the element and its children
void CGUIButton::draw()
{
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
video::IVideoDriver* driver = Environment->getVideoDriver();
IGUISkin *skin = Environment->getSkin();
video::IVideoDriver *driver = Environment->getVideoDriver();
if (DrawBorder)
{
if (!Pressed)
{
if (DrawBorder) {
if (!Pressed) {
skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect);
}
else
{
} else {
skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect);
}
}
const core::position2di buttonCenter(AbsoluteRect.getCenter());
EGUI_BUTTON_IMAGE_STATE imageState = getImageState(Pressed);
if ( ButtonImages[(u32)imageState].Texture )
{
if (ButtonImages[(u32)imageState].Texture) {
core::position2d<s32> pos(buttonCenter);
core::rect<s32> sourceRect(ButtonImages[(u32)imageState].SourceRect);
if ( sourceRect.getWidth() == 0 && sourceRect.getHeight() == 0 )
sourceRect = core::rect<s32>(core::position2di(0,0), ButtonImages[(u32)imageState].Texture->getOriginalSize());
if (sourceRect.getWidth() == 0 && sourceRect.getHeight() == 0)
sourceRect = core::rect<s32>(core::position2di(0, 0), ButtonImages[(u32)imageState].Texture->getOriginalSize());
pos.X -= sourceRect.getWidth() / 2;
pos.Y -= sourceRect.getHeight() / 2;
if ( Pressed )
{
if (Pressed) {
// Create a pressed-down effect by moving the image when it looks identical to the unpressed state image
EGUI_BUTTON_IMAGE_STATE unpressedState = getImageState(false);
if ( unpressedState == imageState || ButtonImages[(u32)imageState] == ButtonImages[(u32)unpressedState] )
{
if (unpressedState == imageState || ButtonImages[(u32)imageState] == ButtonImages[(u32)unpressedState]) {
pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X);
pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y);
}
}
driver->draw2DImage(ButtonImages[(u32)imageState].Texture,
ScaleImage? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
ScaleImage ? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
sourceRect, &AbsoluteClippingRect,
0, UseAlphaChannel);
}
if (SpriteBank)
{
if (SpriteBank) {
core::position2di pos(buttonCenter);
if ( Pressed )
{
if (Pressed) {
pos.X += skin->getSize(EGDS_BUTTON_PRESSED_SPRITE_OFFSET_X);
pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_SPRITE_OFFSET_Y);
}
if (isEnabled())
{
if (isEnabled()) {
// pressed / unpressed animation
EGUI_BUTTON_STATE state = Pressed ? EGBS_BUTTON_DOWN : EGBS_BUTTON_UP;
drawSprite(state, ClickTime, pos);
@ -305,52 +267,44 @@ void CGUIButton::draw()
// mouse over / off animation
state = Environment->getHovered() == this ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF;
drawSprite(state, HoverTime, pos);
}
else
{
} else {
// draw disabled
drawSprite(EGBS_BUTTON_DISABLED, 0, pos);
}
}
if (Text.size())
{
IGUIFont* font = getActiveFont();
if (Text.size()) {
IGUIFont *font = getActiveFont();
core::rect<s32> rect = AbsoluteRect;
if (Pressed)
{
if (Pressed) {
rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X);
rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y);
}
if (font)
font->draw(Text.c_str(), rect,
getActiveColor(),
true, true, &AbsoluteClippingRect);
getActiveColor(),
true, true, &AbsoluteClippingRect);
}
IGUIElement::draw();
}
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di &center)
{
u32 stateIdx = (u32)state;
if (ButtonSprites[stateIdx].Index != -1)
{
if ( ButtonSprites[stateIdx].Scale )
{
const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};
if (ButtonSprites[stateIdx].Index != -1) {
if (ButtonSprites[stateIdx].Scale) {
const video::SColor colors[] = {ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color};
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect,
&AbsoluteClippingRect, colors,
os::Timer::getTime()-startTime, ButtonSprites[stateIdx].Loop);
}
else
{
os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop);
} else {
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, os::Timer::getTime(),
ButtonSprites[stateIdx].Loop, true);
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, os::Timer::getTime(),
ButtonSprites[stateIdx].Loop, true);
}
}
}
@ -360,27 +314,24 @@ EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
// figure state we should have
EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED;
bool focused = Environment->hasFocus(this);
bool mouseOver = static_cast<const IGUIElement*>(Environment->getHovered()) == this; // (static cast for Borland)
if (isEnabled())
{
if ( pressed )
{
if ( focused && mouseOver )
bool mouseOver = static_cast<const IGUIElement *>(Environment->getHovered()) == this; // (static cast for Borland)
if (isEnabled()) {
if (pressed) {
if (focused && mouseOver)
state = EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER;
else if ( focused )
else if (focused)
state = EGBIS_IMAGE_DOWN_FOCUSED;
else if ( mouseOver )
else if (mouseOver)
state = EGBIS_IMAGE_DOWN_MOUSEOVER;
else
state = EGBIS_IMAGE_DOWN;
}
else // !pressed
} else // !pressed
{
if ( focused && mouseOver )
if (focused && mouseOver)
state = EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER;
else if ( focused )
else if (focused)
state = EGBIS_IMAGE_UP_FOCUSED;
else if ( mouseOver )
else if (mouseOver)
state = EGBIS_IMAGE_UP_MOUSEOVER;
else
state = EGBIS_IMAGE_UP;
@ -388,33 +339,31 @@ EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
}
// find a compatible state that has images
while ( state != EGBIS_IMAGE_UP && !ButtonImages[(u32)state].Texture )
{
switch ( state )
{
case EGBIS_IMAGE_UP_FOCUSED:
state = EGBIS_IMAGE_UP_MOUSEOVER;
break;
case EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER:
state = EGBIS_IMAGE_UP_FOCUSED;
break;
case EGBIS_IMAGE_DOWN_MOUSEOVER:
while (state != EGBIS_IMAGE_UP && !ButtonImages[(u32)state].Texture) {
switch (state) {
case EGBIS_IMAGE_UP_FOCUSED:
state = EGBIS_IMAGE_UP_MOUSEOVER;
break;
case EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER:
state = EGBIS_IMAGE_UP_FOCUSED;
break;
case EGBIS_IMAGE_DOWN_MOUSEOVER:
state = EGBIS_IMAGE_DOWN;
break;
case EGBIS_IMAGE_DOWN_FOCUSED:
state = EGBIS_IMAGE_DOWN_MOUSEOVER;
break;
case EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER:
state = EGBIS_IMAGE_DOWN_FOCUSED;
break;
case EGBIS_IMAGE_DISABLED:
if (pressed)
state = EGBIS_IMAGE_DOWN;
break;
case EGBIS_IMAGE_DOWN_FOCUSED:
state = EGBIS_IMAGE_DOWN_MOUSEOVER;
break;
case EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER:
state = EGBIS_IMAGE_DOWN_FOCUSED;
break;
case EGBIS_IMAGE_DISABLED:
if ( pressed )
state = EGBIS_IMAGE_DOWN;
else
state = EGBIS_IMAGE_UP;
break;
default:
else
state = EGBIS_IMAGE_UP;
break;
default:
state = EGBIS_IMAGE_UP;
}
}
@ -422,7 +371,7 @@ EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
}
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
void CGUIButton::setOverrideFont(IGUIFont* font)
void CGUIButton::setOverrideFont(IGUIFont *font)
{
if (OverrideFont == font)
return;
@ -437,17 +386,17 @@ void CGUIButton::setOverrideFont(IGUIFont* font)
}
//! Gets the override font (if any)
IGUIFont * CGUIButton::getOverrideFont() const
IGUIFont *CGUIButton::getOverrideFont() const
{
return OverrideFont;
}
//! Get the font which is used right now for drawing
IGUIFont* CGUIButton::getActiveFont() const
IGUIFont *CGUIButton::getActiveFont() const
{
if ( OverrideFont )
if (OverrideFont)
return OverrideFont;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (skin)
return skin->getFont(EGDF_BUTTON);
return 0;
@ -467,9 +416,9 @@ video::SColor CGUIButton::getOverrideColor() const
irr::video::SColor CGUIButton::getActiveColor() const
{
if ( OverrideColorEnabled )
if (OverrideColorEnabled)
return OverrideColor;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (skin)
return OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT);
return OverrideColor;
@ -485,16 +434,16 @@ bool CGUIButton::isOverrideColorEnabled() const
return OverrideColorEnabled;
}
void CGUIButton::setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image, const core::rect<s32>& sourceRect)
void CGUIButton::setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture *image, const core::rect<s32> &sourceRect)
{
if ( state >= EGBIS_COUNT )
if (state >= EGBIS_COUNT)
return;
if ( image )
if (image)
image->grab();
u32 stateIdx = (u32)state;
if ( ButtonImages[stateIdx].Texture )
if (ButtonImages[stateIdx].Texture)
ButtonImages[stateIdx].Texture->drop();
ButtonImages[stateIdx].Texture = image;
@ -509,51 +458,43 @@ void CGUIButton::setIsPushButton(bool isPushButton)
IsPushButton = isPushButton;
}
//! Returns if the button is currently pressed
bool CGUIButton::isPressed() const
{
return Pressed;
}
//! Sets the pressed state of the button if this is a pushbutton
void CGUIButton::setPressed(bool pressed)
{
if (Pressed != pressed)
{
if (Pressed != pressed) {
ClickTime = os::Timer::getTime();
Pressed = pressed;
}
}
//! Returns whether the button is a push button
bool CGUIButton::isPushButton() const
{
return IsPushButton;
}
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
void CGUIButton::setUseAlphaChannel(bool useAlphaChannel)
{
UseAlphaChannel = useAlphaChannel;
}
//! Returns if the alpha channel should be used for drawing images on the button
bool CGUIButton::isAlphaChannelUsed() const
{
return UseAlphaChannel;
}
bool CGUIButton::isDrawingBorder() const
{
return DrawBorder;
}
} // end namespace gui
} // end namespace irr

View File

@ -14,228 +14,228 @@ namespace irr
namespace gui
{
class CGUIButton : public IGUIButton
class CGUIButton : public IGUIButton
{
public:
//! constructor
CGUIButton(IGUIEnvironment *environment, IGUIElement *parent,
s32 id, core::rect<s32> rectangle, bool noclip = false);
//! destructor
virtual ~CGUIButton();
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! draws the element and its children
void draw() override;
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
void setOverrideFont(IGUIFont *font = 0) override;
//! Gets the override font (if any)
IGUIFont *getOverrideFont() const override;
//! Get the font which is used right now for drawing
IGUIFont *getActiveFont() const override;
//! Sets another color for the button text.
void setOverrideColor(video::SColor color) override;
//! Gets the override color
video::SColor getOverrideColor(void) const override;
//! Gets the currently used text color
video::SColor getActiveColor() const override;
//! Sets if the button text should use the override color or the color in the gui skin.
void enableOverrideColor(bool enable) override;
//! Checks if an override color is enabled
bool isOverrideColorEnabled(void) const override;
//! Sets an image which should be displayed on the button when it is in the given state.
void setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture *image = 0, const core::rect<s32> &sourceRect = core::rect<s32>(0, 0, 0, 0)) override;
//! Sets an image which should be displayed on the button when it is in normal state.
void setImage(video::ITexture *image = 0) override
{
public:
setImage(EGBIS_IMAGE_UP, image);
}
//! constructor
CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool noclip=false);
//! Sets an image which should be displayed on the button when it is in normal state.
void setImage(video::ITexture *image, const core::rect<s32> &pos) override
{
setImage(EGBIS_IMAGE_UP, image, pos);
}
//! destructor
virtual ~CGUIButton();
//! Sets an image which should be displayed on the button when it is in pressed state.
void setPressedImage(video::ITexture *image = 0) override
{
setImage(EGBIS_IMAGE_DOWN, image);
}
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! Sets an image which should be displayed on the button when it is in pressed state.
void setPressedImage(video::ITexture *image, const core::rect<s32> &pos) override
{
setImage(EGBIS_IMAGE_DOWN, image, pos);
}
//! draws the element and its children
void draw() override;
//! Sets the sprite bank used by the button
void setSpriteBank(IGUISpriteBank *bank = 0) override;
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
void setOverrideFont(IGUIFont* font=0) override;
//! Sets the animated sprite for a specific button state
/** \param index: Number of the sprite within the sprite bank, use -1 for no sprite
\param state: State of the button to set the sprite for
\param index: The sprite number from the current sprite bank
\param color: The color of the sprite
*/
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
video::SColor color = video::SColor(255, 255, 255, 255),
bool loop = false, bool scale = false) override;
//! Gets the override font (if any)
IGUIFont* getOverrideFont() const override;
//! Get the sprite-index for the given state or -1 when no sprite is set
s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override;
//! Get the font which is used right now for drawing
IGUIFont* getActiveFont() const override;
//! Get the sprite color for the given state. Color is only used when a sprite is set.
video::SColor getSpriteColor(EGUI_BUTTON_STATE state) const override;
//! Sets another color for the button text.
void setOverrideColor(video::SColor color) override;
//! Returns if the sprite in the given state does loop
bool getSpriteLoop(EGUI_BUTTON_STATE state) const override;
//! Gets the override color
video::SColor getOverrideColor(void) const override;
//! Returns if the sprite in the given state is scaled
bool getSpriteScale(EGUI_BUTTON_STATE state) const override;
//! Gets the currently used text color
video::SColor getActiveColor() const override;
//! Sets if the button should behave like a push button. Which means it
//! can be in two states: Normal or Pressed. With a click on the button,
//! the user can change the state of the button.
void setIsPushButton(bool isPushButton = true) override;
//! Sets if the button text should use the override color or the color in the gui skin.
void enableOverrideColor(bool enable) override;
//! Checks whether the button is a push button
bool isPushButton() const override;
//! Checks if an override color is enabled
bool isOverrideColorEnabled(void) const override;
//! Sets the pressed state of the button if this is a pushbutton
void setPressed(bool pressed = true) override;
//! Sets an image which should be displayed on the button when it is in the given state.
void setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image=0, const core::rect<s32>& sourceRect=core::rect<s32>(0,0,0,0)) override;
//! Returns if the button is currently pressed
bool isPressed() const override;
//! Sets an image which should be displayed on the button when it is in normal state.
void setImage(video::ITexture* image=0) override
//! Sets if the button should use the skin to draw its border
void setDrawBorder(bool border = true) override;
//! Checks if the button face and border are being drawn
bool isDrawingBorder() const override;
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
void setUseAlphaChannel(bool useAlphaChannel = true) override;
//! Checks if the alpha channel should be used for drawing images on the button
bool isAlphaChannelUsed() const override;
//! Sets if the button should scale the button images to fit
void setScaleImage(bool scaleImage = true) override;
//! Checks whether the button scales the used images
bool isScalingImage() const override;
//! Get if the shift key was pressed in last EGET_BUTTON_CLICKED event
bool getClickShiftState() const override
{
return ClickShiftState;
}
//! Get if the control key was pressed in last EGET_BUTTON_CLICKED event
bool getClickControlState() const override
{
return ClickControlState;
}
protected:
void drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di &center);
EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const;
private:
struct ButtonSprite
{
ButtonSprite() :
Index(-1), Loop(false), Scale(false)
{
setImage(EGBIS_IMAGE_UP, image);
}
//! Sets an image which should be displayed on the button when it is in normal state.
void setImage(video::ITexture* image, const core::rect<s32>& pos) override
bool operator==(const ButtonSprite &other) const
{
setImage(EGBIS_IMAGE_UP, image, pos);
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
}
//! Sets an image which should be displayed on the button when it is in pressed state.
void setPressedImage(video::ITexture* image=0) override
{
setImage(EGBIS_IMAGE_DOWN, image);
}
//! Sets an image which should be displayed on the button when it is in pressed state.
void setPressedImage(video::ITexture* image, const core::rect<s32>& pos) override
{
setImage(EGBIS_IMAGE_DOWN, image, pos);
}
//! Sets the sprite bank used by the button
void setSpriteBank(IGUISpriteBank* bank=0) override;
//! Sets the animated sprite for a specific button state
/** \param index: Number of the sprite within the sprite bank, use -1 for no sprite
\param state: State of the button to set the sprite for
\param index: The sprite number from the current sprite bank
\param color: The color of the sprite
*/
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
video::SColor color=video::SColor(255,255,255,255),
bool loop=false, bool scale=false) override;
//! Get the sprite-index for the given state or -1 when no sprite is set
s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override;
//! Get the sprite color for the given state. Color is only used when a sprite is set.
video::SColor getSpriteColor(EGUI_BUTTON_STATE state) const override;
//! Returns if the sprite in the given state does loop
bool getSpriteLoop(EGUI_BUTTON_STATE state) const override;
//! Returns if the sprite in the given state is scaled
bool getSpriteScale(EGUI_BUTTON_STATE state) const override;
//! Sets if the button should behave like a push button. Which means it
//! can be in two states: Normal or Pressed. With a click on the button,
//! the user can change the state of the button.
void setIsPushButton(bool isPushButton=true) override;
//! Checks whether the button is a push button
bool isPushButton() const override;
//! Sets the pressed state of the button if this is a pushbutton
void setPressed(bool pressed=true) override;
//! Returns if the button is currently pressed
bool isPressed() const override;
//! Sets if the button should use the skin to draw its border
void setDrawBorder(bool border=true) override;
//! Checks if the button face and border are being drawn
bool isDrawingBorder() const override;
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
void setUseAlphaChannel(bool useAlphaChannel=true) override;
//! Checks if the alpha channel should be used for drawing images on the button
bool isAlphaChannelUsed() const override;
//! Sets if the button should scale the button images to fit
void setScaleImage(bool scaleImage=true) override;
//! Checks whether the button scales the used images
bool isScalingImage() const override;
//! Get if the shift key was pressed in last EGET_BUTTON_CLICKED event
bool getClickShiftState() const override
{
return ClickShiftState;
}
//! Get if the control key was pressed in last EGET_BUTTON_CLICKED event
bool getClickControlState() const override
{
return ClickControlState;
}
protected:
void drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center);
EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const;
private:
struct ButtonSprite
{
ButtonSprite() : Index(-1), Loop(false), Scale(false)
{
}
bool operator==(const ButtonSprite& other) const
{
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
}
s32 Index;
video::SColor Color;
bool Loop;
bool Scale;
};
ButtonSprite ButtonSprites[EGBS_COUNT];
IGUISpriteBank* SpriteBank;
struct ButtonImage
{
ButtonImage() : Texture(0), SourceRect(core::rect<s32>(0,0,0,0))
{
}
ButtonImage(const ButtonImage& other) : Texture(0), SourceRect(core::rect<s32>(0,0,0,0))
{
*this = other;
}
~ButtonImage()
{
if ( Texture )
Texture->drop();
}
ButtonImage& operator=(const ButtonImage& other)
{
if ( this == &other )
return *this;
if (other.Texture)
other.Texture->grab();
if ( Texture )
Texture->drop();
Texture = other.Texture;
SourceRect = other.SourceRect;
return *this;
}
bool operator==(const ButtonImage& other) const
{
return Texture == other.Texture && SourceRect == other.SourceRect;
}
video::ITexture* Texture;
core::rect<s32> SourceRect;
};
ButtonImage ButtonImages[EGBIS_COUNT];
IGUIFont* OverrideFont;
bool OverrideColorEnabled;
video::SColor OverrideColor;
u32 ClickTime, HoverTime, FocusTime;
bool ClickShiftState;
bool ClickControlState;
bool IsPushButton;
bool Pressed;
bool UseAlphaChannel;
bool DrawBorder;
bool ScaleImage;
s32 Index;
video::SColor Color;
bool Loop;
bool Scale;
};
ButtonSprite ButtonSprites[EGBS_COUNT];
IGUISpriteBank *SpriteBank;
struct ButtonImage
{
ButtonImage() :
Texture(0), SourceRect(core::rect<s32>(0, 0, 0, 0))
{
}
ButtonImage(const ButtonImage &other) :
Texture(0), SourceRect(core::rect<s32>(0, 0, 0, 0))
{
*this = other;
}
~ButtonImage()
{
if (Texture)
Texture->drop();
}
ButtonImage &operator=(const ButtonImage &other)
{
if (this == &other)
return *this;
if (other.Texture)
other.Texture->grab();
if (Texture)
Texture->drop();
Texture = other.Texture;
SourceRect = other.SourceRect;
return *this;
}
bool operator==(const ButtonImage &other) const
{
return Texture == other.Texture && SourceRect == other.SourceRect;
}
video::ITexture *Texture;
core::rect<s32> SourceRect;
};
ButtonImage ButtonImages[EGBIS_COUNT];
IGUIFont *OverrideFont;
bool OverrideColorEnabled;
video::SColor OverrideColor;
u32 ClickTime, HoverTime, FocusTime;
bool ClickShiftState;
bool ClickControlState;
bool IsPushButton;
bool Pressed;
bool UseAlphaChannel;
bool DrawBorder;
bool ScaleImage;
};
} // end namespace gui
} // end namespace irr

View File

@ -16,47 +16,35 @@ namespace gui
{
//! constructor
CGUICheckBox::CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
: IGUICheckBox(environment, parent, id, rectangle), CheckTime(0), Pressed(false), Checked(checked)
, Border(false), Background(false)
CGUICheckBox::CGUICheckBox(bool checked, IGUIEnvironment *environment, IGUIElement *parent, s32 id, core::rect<s32> rectangle) :
IGUICheckBox(environment, parent, id, rectangle), CheckTime(0), Pressed(false), Checked(checked), Border(false), Background(false)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUICheckBox");
#endif
#endif
// this element can be tabbed into
setTabStop(true);
setTabOrder(-1);
}
//! called if an event happened.
bool CGUICheckBox::OnEvent(const SEvent& event)
bool CGUICheckBox::OnEvent(const SEvent &event)
{
if (isEnabled())
{
switch(event.EventType)
{
if (isEnabled()) {
switch (event.EventType) {
case EET_KEY_INPUT_EVENT:
if (event.KeyInput.PressedDown &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
{
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) {
Pressed = true;
return true;
}
else
if (Pressed && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
{
} else if (Pressed && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE) {
Pressed = false;
return true;
}
else
if (!event.KeyInput.PressedDown && Pressed &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
{
} else if (!event.KeyInput.PressedDown && Pressed &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) {
Pressed = false;
if (Parent)
{
if (Parent) {
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
newEvent.GUIEvent.Caller = this;
@ -69,29 +57,22 @@ bool CGUICheckBox::OnEvent(const SEvent& event)
}
break;
case EET_GUI_EVENT:
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
{
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) {
if (event.GUIEvent.Caller == this)
Pressed = false;
}
break;
case EET_MOUSE_INPUT_EVENT:
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
{
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
Pressed = true;
CheckTime = os::Timer::getTime();
return true;
}
else
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
{
} else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
bool wasPressed = Pressed;
Pressed = false;
if (wasPressed && Parent)
{
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y) ) )
{
if (wasPressed && Parent) {
if (!AbsoluteClippingRect.isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y))) {
Pressed = false;
return true;
}
@ -116,29 +97,25 @@ bool CGUICheckBox::OnEvent(const SEvent& event)
return IGUIElement::OnEvent(event);
}
//! draws the element and its children
void CGUICheckBox::draw()
{
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
if (skin)
{
video::IVideoDriver* driver = Environment->getVideoDriver();
IGUISkin *skin = Environment->getSkin();
if (skin) {
video::IVideoDriver *driver = Environment->getVideoDriver();
core::rect<s32> frameRect(AbsoluteRect);
// draw background
if (Background)
{
if (Background) {
video::SColor bgColor = skin->getColor(gui::EGDC_3D_FACE);
driver->draw2DRectangle(bgColor, frameRect, &AbsoluteClippingRect);
}
// draw the border
if (Border)
{
if (Border) {
skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
frameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X);
@ -148,34 +125,31 @@ void CGUICheckBox::draw()
// the rectangle around the "checked" area.
core::rect<s32> checkRect(frameRect.UpperLeftCorner.X,
((frameRect.getHeight() - height) / 2) + frameRect.UpperLeftCorner.Y,
0, 0);
((frameRect.getHeight() - height) / 2) + frameRect.UpperLeftCorner.Y,
0, 0);
checkRect.LowerRightCorner.X = checkRect.UpperLeftCorner.X + height;
checkRect.LowerRightCorner.Y = checkRect.UpperLeftCorner.Y + height;
EGUI_DEFAULT_COLOR col = EGDC_GRAY_EDITABLE;
if ( isEnabled() )
if (isEnabled())
col = Pressed ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
skin->draw3DSunkenPane(this, skin->getColor(col),
false, true, checkRect, &AbsoluteClippingRect);
false, true, checkRect, &AbsoluteClippingRect);
// the checked icon
if (Checked)
{
if (Checked) {
skin->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(),
CheckTime, os::Timer::getTime(), false, &AbsoluteClippingRect);
CheckTime, os::Timer::getTime(), false, &AbsoluteClippingRect);
}
// associated text
if (Text.size())
{
if (Text.size()) {
checkRect = frameRect;
checkRect.UpperLeftCorner.X += height + 5;
IGUIFont* font = skin->getFont();
if (font)
{
IGUIFont *font = skin->getFont();
if (font) {
font->draw(Text.c_str(), checkRect,
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &AbsoluteClippingRect);
}
@ -184,14 +158,12 @@ void CGUICheckBox::draw()
IGUIElement::draw();
}
//! set if box is checked
void CGUICheckBox::setChecked(bool checked)
{
Checked = checked;
}
//! returns if box is checked
bool CGUICheckBox::isChecked() const
{
@ -222,6 +194,5 @@ bool CGUICheckBox::isDrawBorderEnabled() const
return Border;
}
} // end namespace gui
} // end namespace irr

View File

@ -11,47 +11,45 @@ namespace irr
namespace gui
{
class CGUICheckBox : public IGUICheckBox
{
public:
class CGUICheckBox : public IGUICheckBox
{
public:
//! constructor
CGUICheckBox(bool checked, IGUIEnvironment *environment, IGUIElement *parent, s32 id, core::rect<s32> rectangle);
//! constructor
CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
//! set if box is checked
void setChecked(bool checked) override;
//! set if box is checked
void setChecked(bool checked) override;
//! returns if box is checked
bool isChecked() const override;
//! returns if box is checked
bool isChecked() const override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Checks if background drawing is enabled
/** \return true if background drawing is enabled, false otherwise */
bool isDrawBackgroundEnabled() const override;
//! Checks if background drawing is enabled
/** \return true if background drawing is enabled, false otherwise */
bool isDrawBackgroundEnabled() const override;
//! Sets whether to draw the border
void setDrawBorder(bool draw) override;
//! Sets whether to draw the border
void setDrawBorder(bool draw) override;
//! Checks if border drawing is enabled
/** \return true if border drawing is enabled, false otherwise */
bool isDrawBorderEnabled() const override;
//! Checks if border drawing is enabled
/** \return true if border drawing is enabled, false otherwise */
bool isDrawBorderEnabled() const override;
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! draws the element and its children
void draw() override;
//! draws the element and its children
void draw() override;
private:
u32 CheckTime;
bool Pressed;
bool Checked;
bool Border;
bool Background;
};
private:
u32 CheckTime;
bool Pressed;
bool Checked;
bool Border;
bool Background;
};
} // end namespace gui
} // end namespace irr

View File

@ -19,22 +19,21 @@ namespace gui
{
//! constructor
CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle)
: IGUIComboBox(environment, parent, id, rectangle),
ListButton(nullptr), SelectedText(nullptr), ListBox(nullptr), LastFocus(nullptr),
Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false),
ActiveFont(nullptr)
CGUIComboBox::CGUIComboBox(IGUIEnvironment *environment, IGUIElement *parent,
s32 id, core::rect<s32> rectangle) :
IGUIComboBox(environment, parent, id, rectangle),
ListButton(nullptr), SelectedText(nullptr), ListBox(nullptr), LastFocus(nullptr),
Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false),
ActiveFont(nullptr)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUIComboBox");
#endif
#endif
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
ListButton = Environment->addButton(core::recti(0,0,1,1), this, -1, L"");
if (skin && skin->getSpriteBank())
{
ListButton = Environment->addButton(core::recti(0, 0, 1, 1), this, -1, L"");
if (skin && skin->getSpriteBank()) {
ListButton->setSpriteBank(skin->getSpriteBank());
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
@ -43,7 +42,7 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
ListButton->setSubElement(true);
ListButton->setTabStop(false);
SelectedText = Environment->addStaticText(L"", core::recti(0,0,1,1), false, false, this, -1, false);
SelectedText = Environment->addStaticText(L"", core::recti(0, 0, 1, 1), false, false, this, -1, false);
SelectedText->setSubElement(true);
SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
@ -58,7 +57,6 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
setTabOrder(-1);
}
void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
{
HAlign = horizontal;
@ -66,15 +64,13 @@ void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT ve
SelectedText->setTextAlignment(horizontal, vertical);
}
//! Set the maximal number of rows for the selection listbox
void CGUIComboBox::setMaxSelectionRows(u32 max)
{
MaxSelectionRows = max;
// force recalculation of open listbox
if (ListBox)
{
if (ListBox) {
openCloseMenu();
openCloseMenu();
}
@ -86,16 +82,14 @@ u32 CGUIComboBox::getMaxSelectionRows() const
return MaxSelectionRows;
}
//! Returns amount of items in box
u32 CGUIComboBox::getItemCount() const
{
return Items.size();
}
//! returns string of an item. the idx may be a value from 0 to itemCount-1
const wchar_t* CGUIComboBox::getItem(u32 idx) const
const wchar_t *CGUIComboBox::getItem(u32 idx) const
{
if (idx >= Items.size())
return 0;
@ -113,17 +107,15 @@ u32 CGUIComboBox::getItemData(u32 idx) const
}
//! Returns index based on item data
s32 CGUIComboBox::getIndexForItemData(u32 data ) const
s32 CGUIComboBox::getIndexForItemData(u32 data) const
{
for ( u32 i = 0; i < Items.size (); ++i )
{
if ( Items[i].Data == data )
for (u32 i = 0; i < Items.size(); ++i) {
if (Items[i].Data == data)
return i;
}
return -1;
}
//! Removes an item from the combo box.
void CGUIComboBox::removeItem(u32 idx)
{
@ -136,18 +128,16 @@ void CGUIComboBox::removeItem(u32 idx)
Items.erase(idx);
}
//! Returns caption of this element.
const wchar_t* CGUIComboBox::getText() const
const wchar_t *CGUIComboBox::getText() const
{
return getItem(Selected);
}
//! adds an item and returns the index of it
u32 CGUIComboBox::addItem(const wchar_t* text, u32 data)
u32 CGUIComboBox::addItem(const wchar_t *text, u32 data)
{
Items.push_back( SComboData ( text, data ) );
Items.push_back(SComboData(text, data));
if (Selected == -1)
setSelected(0);
@ -155,7 +145,6 @@ u32 CGUIComboBox::addItem(const wchar_t* text, u32 data)
return Items.size() - 1;
}
//! deletes all items in the combo box
void CGUIComboBox::clear()
{
@ -163,14 +152,12 @@ void CGUIComboBox::clear()
setSelected(-1);
}
//! returns id of selected item. returns -1 if no item is selected.
s32 CGUIComboBox::getSelected() const
{
return Selected;
}
//! sets the selected item. Set this to -1 if no item should be selected
void CGUIComboBox::setSelected(s32 idx)
{
@ -184,7 +171,6 @@ void CGUIComboBox::setSelected(s32 idx)
SelectedText->setText(Items[Selected].Name.c_str());
}
//! Sets the selected item and emits a change event.
/** Set this to -1 if no item should be selected */
void CGUIComboBox::setAndSendSelected(s32 idx)
@ -193,67 +179,54 @@ void CGUIComboBox::setAndSendSelected(s32 idx)
sendSelectionChangedEvent();
}
//! called if an event happened.
bool CGUIComboBox::OnEvent(const SEvent& event)
bool CGUIComboBox::OnEvent(const SEvent &event)
{
if (isEnabled())
{
switch(event.EventType)
{
if (isEnabled()) {
switch (event.EventType) {
case EET_KEY_INPUT_EVENT:
if (ListBox && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
{
if (ListBox && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE) {
// hide list box
openCloseMenu();
return true;
}
else
if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)
{
if (!event.KeyInput.PressedDown)
{
} else if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE) {
if (!event.KeyInput.PressedDown) {
openCloseMenu();
}
ListButton->setPressed(ListBox == nullptr);
return true;
}
else
if (event.KeyInput.PressedDown)
{
} else if (event.KeyInput.PressedDown) {
s32 oldSelected = Selected;
bool absorb = true;
switch (event.KeyInput.Key)
{
case KEY_DOWN:
setSelected(Selected+1);
break;
case KEY_UP:
setSelected(Selected-1);
break;
case KEY_HOME:
case KEY_PRIOR:
setSelected(0);
break;
case KEY_END:
case KEY_NEXT:
setSelected((s32)Items.size()-1);
break;
default:
absorb = false;
switch (event.KeyInput.Key) {
case KEY_DOWN:
setSelected(Selected + 1);
break;
case KEY_UP:
setSelected(Selected - 1);
break;
case KEY_HOME:
case KEY_PRIOR:
setSelected(0);
break;
case KEY_END:
case KEY_NEXT:
setSelected((s32)Items.size() - 1);
break;
default:
absorb = false;
}
if (Selected <0)
if (Selected < 0)
setSelected(0);
if (Selected >= (s32)Items.size())
setSelected((s32)Items.size() -1);
setSelected((s32)Items.size() - 1);
if (Selected != oldSelected)
{
if (Selected != oldSelected) {
sendSelectionChangedEvent();
return true;
}
@ -265,31 +238,27 @@ bool CGUIComboBox::OnEvent(const SEvent& event)
case EET_GUI_EVENT:
switch(event.GUIEvent.EventType)
{
switch (event.GUIEvent.EventType) {
case EGET_ELEMENT_FOCUS_LOST:
if (ListBox &&
(Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) &&
event.GUIEvent.Element != this &&
!isMyChild(event.GUIEvent.Element) &&
!ListBox->isMyChild(event.GUIEvent.Element))
{
(Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller)) &&
event.GUIEvent.Element != this &&
!isMyChild(event.GUIEvent.Element) &&
!ListBox->isMyChild(event.GUIEvent.Element)) {
openCloseMenu();
}
break;
case EGET_BUTTON_CLICKED:
if (event.GUIEvent.Caller == ListButton)
{
if (event.GUIEvent.Caller == ListButton) {
openCloseMenu();
return true;
}
break;
case EGET_LISTBOX_SELECTED_AGAIN:
case EGET_LISTBOX_CHANGED:
if (event.GUIEvent.Caller == ListBox)
{
if (event.GUIEvent.Caller == ListBox) {
setSelected(ListBox->getSelected());
if (Selected <0 || Selected >= (s32)Items.size())
if (Selected < 0 || Selected >= (s32)Items.size())
setSelected(-1);
openCloseMenu();
@ -302,53 +271,48 @@ bool CGUIComboBox::OnEvent(const SEvent& event)
break;
case EET_MOUSE_INPUT_EVENT:
switch(event.MouseInput.Event)
{
case EMIE_LMOUSE_PRESSED_DOWN:
{
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
// send to list box
if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event))
return true;
switch (event.MouseInput.Event) {
case EMIE_LMOUSE_PRESSED_DOWN: {
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
// send to list box
if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event))
return true;
}
case EMIE_LMOUSE_LEFT_UP:
{
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
// send to list box
if (!(ListBox &&
return true;
}
case EMIE_LMOUSE_LEFT_UP: {
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
// send to list box
if (!(ListBox &&
ListBox->getAbsolutePosition().isPointInside(p) &&
ListBox->OnEvent(event)))
{
openCloseMenu();
}
ListBox->OnEvent(event))) {
openCloseMenu();
}
return true;
}
case EMIE_MOUSE_WHEEL: {
// Try scrolling parent first
if (IGUIElement::OnEvent(event))
return true;
s32 oldSelected = Selected;
setSelected(Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1));
if (Selected < 0)
setSelected(0);
if (Selected >= (s32)Items.size())
setSelected((s32)Items.size() - 1);
if (Selected != oldSelected) {
sendSelectionChangedEvent();
return true;
}
case EMIE_MOUSE_WHEEL:
{
// Try scrolling parent first
if (IGUIElement::OnEvent(event))
return true;
s32 oldSelected = Selected;
setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1));
if (Selected <0)
setSelected(0);
if (Selected >= (s32)Items.size())
setSelected((s32)Items.size() -1);
if (Selected != oldSelected) {
sendSelectionChangedEvent();
return true;
}
return false;
}
return false;
}
default:
break;
}
@ -361,11 +325,9 @@ bool CGUIComboBox::OnEvent(const SEvent& event)
return IGUIElement::OnEvent(event);
}
void CGUIComboBox::sendSelectionChangedEvent()
{
if (Parent)
{
if (Parent) {
SEvent event;
event.EventType = EET_GUI_EVENT;
@ -378,8 +340,7 @@ void CGUIComboBox::sendSelectionChangedEvent()
void CGUIComboBox::updateListButtonWidth(s32 width)
{
if (ListButton->getRelativePosition().getWidth() != width)
{
if (ListButton->getRelativePosition().getWidth() != width) {
core::rect<s32> r;
r.UpperLeftCorner.X = RelativeRect.getWidth() - width - 2;
r.LowerRightCorner.X = RelativeRect.getWidth() - 2;
@ -401,65 +362,54 @@ void CGUIComboBox::draw()
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
updateListButtonWidth(skin->getSize(EGDS_SCROLLBAR_SIZE));
// font changed while the listbox is open?
if ( ActiveFont != skin->getFont() && ListBox )
{
if (ActiveFont != skin->getFont() && ListBox) {
// close and re-open to use new font-size
openCloseMenu();
openCloseMenu();
}
IGUIElement *currentFocus = Environment->getFocus();
if (currentFocus != LastFocus)
{
if (currentFocus != LastFocus) {
HasFocus = currentFocus == this || isMyChild(currentFocus);
LastFocus = currentFocus;
}
// set colors each time as skin-colors can be changed
SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT));
if(isEnabled())
{
if (isEnabled()) {
SelectedText->setDrawBackground(HasFocus);
SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT));
}
else
{
} else {
SelectedText->setDrawBackground(false);
SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT));
}
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
core::rect<s32> frameRect(AbsoluteRect);
// draw the border
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT),
true, true, frameRect, &AbsoluteClippingRect);
true, true, frameRect, &AbsoluteClippingRect);
// draw children
IGUIElement::draw();
}
void CGUIComboBox::openCloseMenu()
{
if (ListBox)
{
if (ListBox) {
// close list box
Environment->setFocus(this);
ListBox->remove();
ListBox = nullptr;
}
else
{
} else {
if (Parent) {
SEvent event;
event.EventType = EET_GUI_EVENT;
@ -474,7 +424,7 @@ void CGUIComboBox::openCloseMenu()
Parent->bringToFront(this);
}
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
u32 h = Items.size();
if (h > getMaxSelectionRows())
@ -488,7 +438,7 @@ void CGUIComboBox::openCloseMenu()
// open list box
core::rect<s32> r(0, AbsoluteRect.getHeight(),
AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);
AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);
ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true);
ListBox->setSubElement(true);
@ -497,9 +447,9 @@ void CGUIComboBox::openCloseMenu()
// ensure that list box is always completely visible
if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight())
ListBox->setRelativePosition( core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) );
ListBox->setRelativePosition(core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0));
for (s32 i=0; i<(s32)Items.size(); ++i)
for (s32 i = 0; i < (s32)Items.size(); ++i)
ListBox->addItem(Items[i].Name.c_str());
ListBox->setSelected(Selected);
@ -509,6 +459,5 @@ void CGUIComboBox::openCloseMenu()
}
}
} // end namespace gui
} // end namespace irr

View File

@ -13,96 +13,92 @@ namespace irr
{
namespace gui
{
class IGUIButton;
class IGUIListBox;
class IGUIButton;
class IGUIListBox;
//! Single line edit box for editing simple text.
class CGUIComboBox : public IGUIComboBox
{
public:
//! constructor
CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
//! Single line edit box for editing simple text.
class CGUIComboBox : public IGUIComboBox
{
public:
//! constructor
CGUIComboBox(IGUIEnvironment *environment, IGUIElement *parent,
s32 id, core::rect<s32> rectangle);
//! Returns amount of items in box
u32 getItemCount() const override;
//! Returns amount of items in box
u32 getItemCount() const override;
//! returns string of an item. the idx may be a value from 0 to itemCount-1
const wchar_t* getItem(u32 idx) const override;
//! returns string of an item. the idx may be a value from 0 to itemCount-1
const wchar_t *getItem(u32 idx) const override;
//! Returns item data of an item. the idx may be a value from 0 to itemCount-1
u32 getItemData(u32 idx) const override;
//! Returns item data of an item. the idx may be a value from 0 to itemCount-1
u32 getItemData(u32 idx) const override;
//! Returns index based on item data
s32 getIndexForItemData( u32 data ) const override;
//! Returns index based on item data
s32 getIndexForItemData(u32 data) const override;
//! adds an item and returns the index of it
u32 addItem(const wchar_t* text, u32 data) override;
//! adds an item and returns the index of it
u32 addItem(const wchar_t *text, u32 data) override;
//! Removes an item from the combo box.
void removeItem(u32 id) override;
//! Removes an item from the combo box.
void removeItem(u32 id) override;
//! deletes all items in the combo box
void clear() override;
//! deletes all items in the combo box
void clear() override;
//! returns the text of the currently selected item
const wchar_t* getText() const override;
//! returns the text of the currently selected item
const wchar_t *getText() const override;
//! returns id of selected item. returns -1 if no item is selected.
s32 getSelected() const override;
//! returns id of selected item. returns -1 if no item is selected.
s32 getSelected() const override;
//! sets the selected item. Set this to -1 if no item should be selected
void setSelected(s32 idx) override;
//! sets the selected item. Set this to -1 if no item should be selected
void setSelected(s32 idx) override;
//! Sets the selected item and emits a change event.
/** Set this to -1 if no item should be selected */
void setAndSendSelected(s32 idx) override;
//! Sets the selected item and emits a change event.
/** Set this to -1 if no item should be selected */
void setAndSendSelected(s32 idx) override;
//! sets the text alignment of the text part
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
//! sets the text alignment of the text part
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
//! Set the maximal number of rows for the selection listbox
void setMaxSelectionRows(u32 max) override;
//! Set the maximal number of rows for the selection listbox
void setMaxSelectionRows(u32 max) override;
//! Get the maximal number of rows for the selection listbox
u32 getMaxSelectionRows() const override;
//! Get the maximal number of rows for the selection listbox
u32 getMaxSelectionRows() const override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! draws the element and its children
void draw() override;
//! draws the element and its children
void draw() override;
private:
private:
void openCloseMenu();
void sendSelectionChangedEvent();
void updateListButtonWidth(s32 width);
void openCloseMenu();
void sendSelectionChangedEvent();
void updateListButtonWidth(s32 width);
IGUIButton *ListButton;
IGUIStaticText *SelectedText;
IGUIListBox *ListBox;
IGUIElement *LastFocus;
IGUIButton* ListButton;
IGUIStaticText* SelectedText;
IGUIListBox* ListBox;
IGUIElement *LastFocus;
struct SComboData
{
SComboData(const wchar_t *text, u32 data) :
Name(text), Data(data) {}
struct SComboData
{
SComboData ( const wchar_t * text, u32 data )
: Name (text), Data ( data ) {}
core::stringw Name;
u32 Data;
};
core::array< SComboData > Items;
s32 Selected;
EGUI_ALIGNMENT HAlign, VAlign;
u32 MaxSelectionRows;
bool HasFocus;
IGUIFont* ActiveFont;
core::stringw Name;
u32 Data;
};
core::array<SComboData> Items;
s32 Selected;
EGUI_ALIGNMENT HAlign, VAlign;
u32 MaxSelectionRows;
bool HasFocus;
IGUIFont *ActiveFont;
};
} // end namespace gui
} // end namespace irr

File diff suppressed because it is too large Load Diff

View File

@ -12,187 +12,185 @@ namespace irr
{
namespace gui
{
class CGUIEditBox : public IGUIEditBox
{
public:
class CGUIEditBox : public IGUIEditBox
{
public:
//! constructor
CGUIEditBox(const wchar_t *text, bool border, IGUIEnvironment *environment,
IGUIElement *parent, s32 id, const core::rect<s32> &rectangle);
//! constructor
CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
//! destructor
virtual ~CGUIEditBox();
//! destructor
virtual ~CGUIEditBox();
//! Sets another skin independent font.
void setOverrideFont(IGUIFont *font = 0) override;
//! Sets another skin independent font.
void setOverrideFont(IGUIFont* font=0) override;
//! Gets the override font (if any)
/** \return The override font (may be 0) */
IGUIFont *getOverrideFont() const override;
//! Gets the override font (if any)
/** \return The override font (may be 0) */
IGUIFont* getOverrideFont() const override;
//! Get the font which is used right now for drawing
/** Currently this is the override font when one is set and the
font of the active skin otherwise */
IGUIFont *getActiveFont() const override;
//! Get the font which is used right now for drawing
/** Currently this is the override font when one is set and the
font of the active skin otherwise */
IGUIFont* getActiveFont() const override;
//! Sets another color for the text.
void setOverrideColor(video::SColor color) override;
//! Sets another color for the text.
void setOverrideColor(video::SColor color) override;
//! Gets the override color
video::SColor getOverrideColor() const override;
//! Gets the override color
video::SColor getOverrideColor() const override;
//! Sets if the text should use the override color or the
//! color in the gui skin.
void enableOverrideColor(bool enable) override;
//! Sets if the text should use the override color or the
//! color in the gui skin.
void enableOverrideColor(bool enable) override;
//! Checks if an override color is enabled
/** \return true if the override color is enabled, false otherwise */
bool isOverrideColorEnabled(void) const override;
//! Checks if an override color is enabled
/** \return true if the override color is enabled, false otherwise */
bool isOverrideColorEnabled(void) const override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Checks if background drawing is enabled
bool isDrawBackgroundEnabled() const override;
//! Checks if background drawing is enabled
bool isDrawBackgroundEnabled() const override;
//! Turns the border on or off
void setDrawBorder(bool border) override;
//! Turns the border on or off
void setDrawBorder(bool border) override;
//! Checks if border drawing is enabled
bool isDrawBorderEnabled() const override;
//! Checks if border drawing is enabled
bool isDrawBorderEnabled() const override;
//! Enables or disables word wrap for using the edit box as multiline text editor.
void setWordWrap(bool enable) override;
//! Enables or disables word wrap for using the edit box as multiline text editor.
void setWordWrap(bool enable) override;
//! Checks if word wrap is enabled
//! \return true if word wrap is enabled, false otherwise
bool isWordWrapEnabled() const override;
//! Checks if word wrap is enabled
//! \return true if word wrap is enabled, false otherwise
bool isWordWrapEnabled() const override;
//! Enables or disables newlines.
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
instead a newline character will be inserted. */
void setMultiLine(bool enable) override;
//! Enables or disables newlines.
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
instead a newline character will be inserted. */
void setMultiLine(bool enable) override;
//! Checks if multi line editing is enabled
//! \return true if mult-line is enabled, false otherwise
bool isMultiLineEnabled() const override;
//! Checks if multi line editing is enabled
//! \return true if mult-line is enabled, false otherwise
bool isMultiLineEnabled() const override;
//! Enables or disables automatic scrolling with cursor position
//! \param enable: If set to true, the text will move around with the cursor position
void setAutoScroll(bool enable) override;
//! Enables or disables automatic scrolling with cursor position
//! \param enable: If set to true, the text will move around with the cursor position
void setAutoScroll(bool enable) override;
//! Checks to see if automatic scrolling is enabled
//! \return true if automatic scrolling is enabled, false if not
bool isAutoScrollEnabled() const override;
//! Checks to see if automatic scrolling is enabled
//! \return true if automatic scrolling is enabled, false if not
bool isAutoScrollEnabled() const override;
//! Gets the size area of the text in the edit box
//! \return Returns the size in pixels of the text
core::dimension2du getTextDimension() override;
//! Gets the size area of the text in the edit box
//! \return Returns the size in pixels of the text
core::dimension2du getTextDimension() override;
//! Sets text justification
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
//! Sets text justification
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! draws the element and its children
void draw() override;
//! draws the element and its children
void draw() override;
//! Sets the new caption of this element.
void setText(const wchar_t *text) override;
//! Sets the new caption of this element.
void setText(const wchar_t* text) override;
//! Sets the maximum amount of characters which may be entered in the box.
//! \param max: Maximum amount of characters. If 0, the character amount is
//! infinity.
void setMax(u32 max) override;
//! Sets the maximum amount of characters which may be entered in the box.
//! \param max: Maximum amount of characters. If 0, the character amount is
//! infinity.
void setMax(u32 max) override;
//! Returns maximum amount of characters, previously set by setMax();
u32 getMax() const override;
//! Returns maximum amount of characters, previously set by setMax();
u32 getMax() const override;
//! Set the character used for the cursor.
/** By default it's "_" */
void setCursorChar(const wchar_t cursorChar) override;
//! Set the character used for the cursor.
/** By default it's "_" */
void setCursorChar(const wchar_t cursorChar) override;
//! Get the character used for the cursor.
wchar_t getCursorChar() const override;
//! Get the character used for the cursor.
wchar_t getCursorChar() const override;
//! Set the blinktime for the cursor. 2x blinktime is one full cycle.
//** \param timeMs Blinktime in milliseconds. When set to 0 the cursor is constantly on without blinking */
void setCursorBlinkTime(irr::u32 timeMs) override;
//! Set the blinktime for the cursor. 2x blinktime is one full cycle.
//** \param timeMs Blinktime in milliseconds. When set to 0 the cursor is constantly on without blinking */
void setCursorBlinkTime(irr::u32 timeMs) override;
//! Get the cursor blinktime
irr::u32 getCursorBlinkTime() const override;
//! Get the cursor blinktime
irr::u32 getCursorBlinkTime() const override;
//! Sets whether the edit box is a password box. Setting this to true will
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
\param passwordBox: true to enable password, false to disable
\param passwordChar: the character that is displayed instead of letters */
void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*') override;
//! Sets whether the edit box is a password box. Setting this to true will
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
\param passwordBox: true to enable password, false to disable
\param passwordChar: the character that is displayed instead of letters */
void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*') override;
//! Returns true if the edit box is currently a password box.
bool isPasswordBox() const override;
//! Returns true if the edit box is currently a password box.
bool isPasswordBox() const override;
//! Updates the absolute position, splits text if required
void updateAbsolutePosition() override;
//! Updates the absolute position, splits text if required
void updateAbsolutePosition() override;
//! Returns whether the element takes input from the IME
bool acceptsIME() override;
//! Returns whether the element takes input from the IME
bool acceptsIME() override;
protected:
//! Breaks the single text line.
void breakText();
//! sets the area of the given line
void setTextRect(s32 line);
//! returns the line number that the cursor is on
s32 getLineFromPos(s32 pos);
//! adds a letter to the edit box
void inputChar(wchar_t c);
//! adds a string to the edit box
void inputString(const core::stringw &str);
//! calculates the current scroll position
void calculateScrollPos();
//! calculated the FrameRect
void calculateFrameRect();
//! send some gui event to parent
void sendGuiEvent(EGUI_EVENT_TYPE type);
//! set text markers
void setTextMarkers(s32 begin, s32 end);
//! delete current selection or next char
bool keyDelete();
protected:
//! Breaks the single text line.
void breakText();
//! sets the area of the given line
void setTextRect(s32 line);
//! returns the line number that the cursor is on
s32 getLineFromPos(s32 pos);
//! adds a letter to the edit box
void inputChar(wchar_t c);
//! adds a string to the edit box
void inputString(const core::stringw &str);
//! calculates the current scroll position
void calculateScrollPos();
//! calculated the FrameRect
void calculateFrameRect();
//! send some gui event to parent
void sendGuiEvent(EGUI_EVENT_TYPE type);
//! set text markers
void setTextMarkers(s32 begin, s32 end);
//! delete current selection or next char
bool keyDelete();
bool processKey(const SEvent &event);
bool processMouse(const SEvent &event);
s32 getCursorPos(s32 x, s32 y);
bool processKey(const SEvent& event);
bool processMouse(const SEvent& event);
s32 getCursorPos(s32 x, s32 y);
bool OverwriteMode;
bool MouseMarking;
bool Border;
bool Background;
bool OverrideColorEnabled;
s32 MarkBegin;
s32 MarkEnd;
bool OverwriteMode;
bool MouseMarking;
bool Border;
bool Background;
bool OverrideColorEnabled;
s32 MarkBegin;
s32 MarkEnd;
video::SColor OverrideColor;
gui::IGUIFont *OverrideFont, *LastBreakFont;
IOSOperator *Operator;
video::SColor OverrideColor;
gui::IGUIFont *OverrideFont, *LastBreakFont;
IOSOperator* Operator;
u32 BlinkStartTime;
irr::u32 CursorBlinkTime;
core::stringw CursorChar; // IGUIFont::draw needs stringw instead of wchar_t
s32 CursorPos;
s32 HScrollPos, VScrollPos; // scroll position in characters
u32 Max;
u32 BlinkStartTime;
irr::u32 CursorBlinkTime;
core::stringw CursorChar; // IGUIFont::draw needs stringw instead of wchar_t
s32 CursorPos;
s32 HScrollPos, VScrollPos; // scroll position in characters
u32 Max;
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
wchar_t PasswordChar;
EGUI_ALIGNMENT HAlign, VAlign;
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
wchar_t PasswordChar;
EGUI_ALIGNMENT HAlign, VAlign;
core::array< core::stringw > BrokenText;
core::array< s32 > BrokenTextPositions;
core::rect<s32> CurrentTextRect, FrameRect; // temporary values
};
core::array<core::stringw> BrokenText;
core::array<s32> BrokenTextPositions;
core::rect<s32> CurrentTextRect, FrameRect; // temporary values
};
} // end namespace gui
} // end namespace irr

File diff suppressed because it is too large Load Diff

View File

@ -19,9 +19,8 @@ namespace gui
class CGUIEnvironment : public IGUIEnvironment, public IGUIElement
{
public:
//! constructor
CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op);
CGUIEnvironment(io::IFileSystem *fs, video::IVideoDriver *driver, IOSOperator *op);
//! destructor
virtual ~CGUIEnvironment();
@ -30,131 +29,131 @@ public:
void drawAll(bool useScreenSize) override;
//! returns the current video driver
video::IVideoDriver* getVideoDriver() const override;
video::IVideoDriver *getVideoDriver() const override;
//! returns pointer to the filesystem
io::IFileSystem* getFileSystem() const override;
io::IFileSystem *getFileSystem() const override;
//! returns a pointer to the OS operator
IOSOperator* getOSOperator() const override;
IOSOperator *getOSOperator() const override;
//! posts an input event to the environment
bool postEventFromUser(const SEvent& event) override;
bool postEventFromUser(const SEvent &event) override;
//! This sets a new event receiver for gui events. Usually you do not have to
//! use this method, it is used by the internal engine.
void setUserEventReceiver(IEventReceiver* evr) override;
void setUserEventReceiver(IEventReceiver *evr) override;
//! removes all elements from the environment
void clear() override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
bool OnEvent(const SEvent &event) override;
//! returns the current gui skin
IGUISkin* getSkin() const override;
IGUISkin *getSkin() const override;
//! Sets a new GUI Skin
void setSkin(IGUISkin* skin) override;
void setSkin(IGUISkin *skin) override;
//! Creates a new GUI Skin based on a template.
/** \return Returns a pointer to the created skin.
If you no longer need the skin, you should call IGUISkin::drop().
See IReferenceCounted::drop() for more information. */
IGUISkin* createSkin(EGUI_SKIN_TYPE type) override;
IGUISkin *createSkin(EGUI_SKIN_TYPE type) override;
//! Creates the image list from the given texture.
virtual IGUIImageList* createImageList(video::ITexture* texture,
core::dimension2d<s32> imageSize, bool useAlphaChannel) override;
virtual IGUIImageList *createImageList(video::ITexture *texture,
core::dimension2d<s32> imageSize, bool useAlphaChannel) override;
//! returns the font
IGUIFont* getFont(const io::path& filename) override;
IGUIFont *getFont(const io::path &filename) override;
//! add an externally loaded font
IGUIFont* addFont(const io::path& name, IGUIFont* font) override;
IGUIFont *addFont(const io::path &name, IGUIFont *font) override;
//! remove loaded font
void removeFont(IGUIFont* font) override;
void removeFont(IGUIFont *font) override;
//! returns default font
IGUIFont* getBuiltInFont() const override;
IGUIFont *getBuiltInFont() const override;
//! returns the sprite bank
IGUISpriteBank* getSpriteBank(const io::path& filename) override;
IGUISpriteBank *getSpriteBank(const io::path &filename) override;
//! returns the sprite bank
IGUISpriteBank* addEmptySpriteBank(const io::path& name) override;
IGUISpriteBank *addEmptySpriteBank(const io::path &name) override;
//! adds an button. The returned pointer must not be dropped.
IGUIButton* addButton(const core::rect<s32>& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext = 0) override;
IGUIButton *addButton(const core::rect<s32> &rectangle, IGUIElement *parent = 0, s32 id = -1, const wchar_t *text = 0, const wchar_t *tooltiptext = 0) override;
//! adds a scrollbar. The returned pointer must not be dropped.
virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1) override;
virtual IGUIScrollBar *addScrollBar(bool horizontal, const core::rect<s32> &rectangle,
IGUIElement *parent = 0, s32 id = -1) override;
//! Adds an image element.
virtual IGUIImage* addImage(video::ITexture* image, core::position2d<s32> pos,
bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) override;
virtual IGUIImage *addImage(video::ITexture *image, core::position2d<s32> pos,
bool useAlphaChannel = true, IGUIElement *parent = 0, s32 id = -1, const wchar_t *text = 0) override;
//! adds an image. The returned pointer must not be dropped.
virtual IGUIImage* addImage(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, bool useAlphaChannel=true) override;
virtual IGUIImage *addImage(const core::rect<s32> &rectangle,
IGUIElement *parent = 0, s32 id = -1, const wchar_t *text = 0, bool useAlphaChannel = true) override;
//! adds a checkbox
virtual IGUICheckBox* addCheckBox(bool checked, const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) override;
virtual IGUICheckBox *addCheckBox(bool checked, const core::rect<s32> &rectangle,
IGUIElement *parent = 0, s32 id = -1, const wchar_t *text = 0) override;
//! adds a list box
virtual IGUIListBox* addListBox(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) override;
virtual IGUIListBox *addListBox(const core::rect<s32> &rectangle,
IGUIElement *parent = 0, s32 id = -1, bool drawBackground = false) override;
//! Adds a file open dialog.
virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title = 0,
bool modal=true, IGUIElement* parent=0, s32 id=-1,
bool restoreCWD=false, io::path::char_type* startDir=0) override;
virtual IGUIFileOpenDialog *addFileOpenDialog(const wchar_t *title = 0,
bool modal = true, IGUIElement *parent = 0, s32 id = -1,
bool restoreCWD = false, io::path::char_type *startDir = 0) override;
//! adds a static text. The returned pointer must not be dropped.
virtual IGUIStaticText* addStaticText(const wchar_t* text, const core::rect<s32>& rectangle,
bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, bool drawBackground = false) override;
virtual IGUIStaticText *addStaticText(const wchar_t *text, const core::rect<s32> &rectangle,
bool border = false, bool wordWrap = true, IGUIElement *parent = 0, s32 id = -1, bool drawBackground = false) override;
//! Adds an edit box. The returned pointer must not be dropped.
virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect<s32>& rectangle,
bool border=false, IGUIElement* parent=0, s32 id=-1) override;
virtual IGUIEditBox *addEditBox(const wchar_t *text, const core::rect<s32> &rectangle,
bool border = false, IGUIElement *parent = 0, s32 id = -1) override;
//! Adds a tab control to the environment.
virtual IGUITabControl* addTabControl(const core::rect<s32>& rectangle,
IGUIElement* parent=0, bool fillbackground=false, bool border=true, s32 id=-1) override;
virtual IGUITabControl *addTabControl(const core::rect<s32> &rectangle,
IGUIElement *parent = 0, bool fillbackground = false, bool border = true, s32 id = -1) override;
//! Adds tab to the environment.
virtual IGUITab* addTab(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1) override;
virtual IGUITab *addTab(const core::rect<s32> &rectangle,
IGUIElement *parent = 0, s32 id = -1) override;
//! Adds a combo box to the environment.
virtual IGUIComboBox* addComboBox(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1) override;
virtual IGUIComboBox *addComboBox(const core::rect<s32> &rectangle,
IGUIElement *parent = 0, s32 id = -1) override;
//! sets the focus to an element
bool setFocus(IGUIElement* element) override;
bool setFocus(IGUIElement *element) override;
//! removes the focus from an element
bool removeFocus(IGUIElement* element) override;
bool removeFocus(IGUIElement *element) override;
//! Returns if the element has focus
bool hasFocus(const IGUIElement* element, bool checkSubElements=false) const override;
bool hasFocus(const IGUIElement *element, bool checkSubElements = false) const override;
//! Returns the element with the focus
IGUIElement* getFocus() const override;
IGUIElement *getFocus() const override;
//! Returns the element last known to be under the mouse
IGUIElement* getHovered() const override;
IGUIElement *getHovered() const override;
//! Returns the root gui element.
IGUIElement* getRootGUIElement() override;
IGUIElement *getRootGUIElement() override;
void OnPostRender( u32 time ) override;
void OnPostRender(u32 time) override;
//! Find the next element which would be selected when pressing the tab-key
IGUIElement* getNextElement(bool reverse=false, bool group=false) override;
IGUIElement *getNextElement(bool reverse = false, bool group = false) override;
//! Set the way the gui will handle focus changes
void setFocusBehavior(u32 flags) override;
@ -163,10 +162,9 @@ public:
u32 getFocusBehavior() const override;
//! Adds a IGUIElement to deletion queue.
void addToDeletionQueue(IGUIElement* element) override;
void addToDeletionQueue(IGUIElement *element) override;
private:
//! clears the deletion queue
void clearDeletionQueue();
@ -177,9 +175,9 @@ private:
struct SFont
{
io::SNamedPath NamedPath;
IGUIFont* Font;
IGUIFont *Font;
bool operator < (const SFont& other) const
bool operator<(const SFont &other) const
{
return (NamedPath < other.NamedPath);
}
@ -188,9 +186,9 @@ private:
struct SSpriteBank
{
io::SNamedPath NamedPath;
IGUISpriteBank* Bank;
IGUISpriteBank *Bank;
bool operator < (const SSpriteBank& other) const
bool operator<(const SSpriteBank &other) const
{
return (NamedPath < other.NamedPath);
}
@ -198,7 +196,7 @@ private:
struct SToolTip
{
IGUIStaticText* Element;
IGUIStaticText *Element;
u32 LastTime;
u32 EnterTime;
u32 LaunchTime;
@ -209,17 +207,17 @@ private:
core::array<SFont> Fonts;
core::array<SSpriteBank> Banks;
video::IVideoDriver* Driver;
IGUIElement* Hovered;
IGUIElement* HoveredNoSubelement; // subelements replaced by their parent, so you only have 'real' elements here
IGUIElement* Focus;
video::IVideoDriver *Driver;
IGUIElement *Hovered;
IGUIElement *HoveredNoSubelement; // subelements replaced by their parent, so you only have 'real' elements here
IGUIElement *Focus;
core::position2d<s32> LastHoveredMousePos;
IGUISkin* CurrentSkin;
io::IFileSystem* FileSystem;
IEventReceiver* UserReceiver;
IOSOperator* Operator;
IGUISkin *CurrentSkin;
io::IFileSystem *FileSystem;
IEventReceiver *UserReceiver;
IOSOperator *Operator;
u32 FocusFlags;
core::array<IGUIElement*> DeletionQueue;
core::array<IGUIElement *> DeletionQueue;
static const io::path DefaultFontName;
};

View File

@ -22,46 +22,41 @@ namespace gui
const s32 FOD_WIDTH = 350;
const s32 FOD_HEIGHT = 250;
//! constructor
CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title,
IGUIEnvironment* environment, IGUIElement* parent, s32 id,
bool restoreCWD, io::path::char_type* startDir)
: IGUIFileOpenDialog(environment, parent, id,
core::rect<s32>((parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2,
(parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2,
(parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2+FOD_WIDTH,
(parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2+FOD_HEIGHT)),
FileNameText(0), FileList(0), Dragging(false)
CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t *title,
IGUIEnvironment *environment, IGUIElement *parent, s32 id,
bool restoreCWD, io::path::char_type *startDir) :
IGUIFileOpenDialog(environment, parent, id,
core::rect<s32>((parent->getAbsolutePosition().getWidth() - FOD_WIDTH) / 2,
(parent->getAbsolutePosition().getHeight() - FOD_HEIGHT) / 2,
(parent->getAbsolutePosition().getWidth() - FOD_WIDTH) / 2 + FOD_WIDTH,
(parent->getAbsolutePosition().getHeight() - FOD_HEIGHT) / 2 + FOD_HEIGHT)),
FileNameText(0), FileList(0), Dragging(false)
{
#ifdef _DEBUG
#ifdef _DEBUG
IGUIElement::setDebugName("CGUIFileOpenDialog");
#endif
#endif
Text = title;
FileSystem = Environment?Environment->getFileSystem():0;
FileSystem = Environment ? Environment->getFileSystem() : 0;
if (FileSystem)
{
if (FileSystem) {
FileSystem->grab();
if (restoreCWD)
RestoreDirectory = FileSystem->getWorkingDirectory();
if (startDir)
{
if (startDir) {
StartDirectory = startDir;
FileSystem->changeWorkingDirectoryTo(startDir);
}
}
else
} else
return;
IGUISpriteBank* sprites = 0;
video::SColor color(255,255,255,255);
IGUISkin* skin = Environment->getSkin();
if (skin)
{
IGUISpriteBank *sprites = 0;
video::SColor color(255, 255, 255, 255);
IGUISkin *skin = Environment->getSkin();
if (skin) {
sprites = skin->getSpriteBank();
color = skin->getColor(EGDC_WINDOW_SYMBOL);
}
@ -70,11 +65,10 @@ CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title,
const s32 posx = RelativeRect.getWidth() - buttonw - 4;
CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
CloseButton->setSubElement(true);
CloseButton->setTabStop(false);
if (sprites && skin)
{
if (sprites && skin) {
CloseButton->setSpriteBank(sprites);
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color);
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color);
@ -83,25 +77,25 @@ CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title,
CloseButton->grab();
OKButton = Environment->addButton(
core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
core::rect<s32>(RelativeRect.getWidth() - 80, 30, RelativeRect.getWidth() - 10, 50),
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
OKButton->setSubElement(true);
OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
OKButton->grab();
CancelButton = Environment->addButton(
core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
core::rect<s32>(RelativeRect.getWidth() - 80, 55, RelativeRect.getWidth() - 10, 75),
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
CancelButton->setSubElement(true);
CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
CancelButton->grab();
FileBox = Environment->addListBox(core::rect<s32>(10, 55, RelativeRect.getWidth()-90, 230), this, -1, true);
FileBox = Environment->addListBox(core::rect<s32>(10, 55, RelativeRect.getWidth() - 90, 230), this, -1, true);
FileBox->setSubElement(true);
FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
FileBox->grab();
FileNameText = Environment->addEditBox(0, core::rect<s32>(10, 30, RelativeRect.getWidth()-90, 50), true, this);
FileNameText = Environment->addEditBox(0, core::rect<s32>(10, 30, RelativeRect.getWidth() - 90, 50), true, this);
FileNameText->setSubElement(true);
FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
FileNameText->grab();
@ -111,7 +105,6 @@ CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title,
fillListBox();
}
//! destructor
CGUIFileOpenDialog::~CGUIFileOpenDialog()
{
@ -130,8 +123,7 @@ CGUIFileOpenDialog::~CGUIFileOpenDialog()
if (FileNameText)
FileNameText->drop();
if (FileSystem)
{
if (FileSystem) {
// revert to original CWD if path was set in constructor
if (RestoreDirectory.size())
FileSystem->changeWorkingDirectoryTo(RestoreDirectory);
@ -142,139 +134,114 @@ CGUIFileOpenDialog::~CGUIFileOpenDialog()
FileList->drop();
}
//! returns the filename of the selected file. Returns NULL, if no file was selected.
const wchar_t* CGUIFileOpenDialog::getFileName() const
const wchar_t *CGUIFileOpenDialog::getFileName() const
{
return FileNameW.c_str();
}
const io::path& CGUIFileOpenDialog::getFileNameP() const
const io::path &CGUIFileOpenDialog::getFileNameP() const
{
return FileName;
}
//! Returns the directory of the selected file. Returns NULL, if no directory was selected.
const io::path& CGUIFileOpenDialog::getDirectoryName() const
const io::path &CGUIFileOpenDialog::getDirectoryName() const
{
return FileDirectoryFlat;
}
const wchar_t* CGUIFileOpenDialog::getDirectoryNameW() const
const wchar_t *CGUIFileOpenDialog::getDirectoryNameW() const
{
return FileDirectoryFlatW.c_str();
}
void CGUIFileOpenDialog::setFileName(const irr::io::path& name)
void CGUIFileOpenDialog::setFileName(const irr::io::path &name)
{
FileName = name;
pathToStringW(FileNameW, FileName);
}
void CGUIFileOpenDialog::setDirectoryName(const irr::io::path& name)
void CGUIFileOpenDialog::setDirectoryName(const irr::io::path &name)
{
FileDirectory = name;
FileDirectoryFlat = name;
FileSystem->flattenFilename (FileDirectoryFlat );
FileSystem->flattenFilename(FileDirectoryFlat);
pathToStringW(FileDirectoryFlatW, FileDirectoryFlat);
}
//! called if an event happened.
bool CGUIFileOpenDialog::OnEvent(const SEvent& event)
bool CGUIFileOpenDialog::OnEvent(const SEvent &event)
{
if (isEnabled())
{
switch(event.EventType)
{
if (isEnabled()) {
switch (event.EventType) {
case EET_GUI_EVENT:
switch(event.GUIEvent.EventType)
{
switch (event.GUIEvent.EventType) {
case EGET_ELEMENT_FOCUS_LOST:
Dragging = false;
break;
case EGET_BUTTON_CLICKED:
if (event.GUIEvent.Caller == CloseButton ||
event.GUIEvent.Caller == CancelButton)
{
event.GUIEvent.Caller == CancelButton) {
sendCancelEvent();
remove();
return true;
}
else
if (event.GUIEvent.Caller == OKButton )
{
if ( FileDirectory != L"" )
{
sendSelectedEvent( EGET_DIRECTORY_SELECTED );
} else if (event.GUIEvent.Caller == OKButton) {
if (FileDirectory != L"") {
sendSelectedEvent(EGET_DIRECTORY_SELECTED);
}
if ( FileName != L"" )
{
sendSelectedEvent( EGET_FILE_SELECTED );
if (FileName != L"") {
sendSelectedEvent(EGET_FILE_SELECTED);
remove();
return true;
}
}
break;
case EGET_LISTBOX_CHANGED:
{
s32 selected = FileBox->getSelected();
if (FileList && FileSystem)
{
if (FileList->isDirectory(selected))
{
setFileName("");
setDirectoryName(FileList->getFullFileName(selected));
}
else
{
setDirectoryName("");
setFileName(FileList->getFullFileName(selected));
}
return true;
case EGET_LISTBOX_CHANGED: {
s32 selected = FileBox->getSelected();
if (FileList && FileSystem) {
if (FileList->isDirectory(selected)) {
setFileName("");
setDirectoryName(FileList->getFullFileName(selected));
} else {
setDirectoryName("");
setFileName(FileList->getFullFileName(selected));
}
return true;
}
break;
} break;
case EGET_LISTBOX_SELECTED_AGAIN:
{
const s32 selected = FileBox->getSelected();
if (FileList && FileSystem)
{
if (FileList->isDirectory(selected))
{
setDirectoryName(FileList->getFullFileName(selected));
FileSystem->changeWorkingDirectoryTo(FileDirectory );
fillListBox();
setFileName("");
}
else
{
setFileName(FileList->getFullFileName(selected));
}
return true;
case EGET_LISTBOX_SELECTED_AGAIN: {
const s32 selected = FileBox->getSelected();
if (FileList && FileSystem) {
if (FileList->isDirectory(selected)) {
setDirectoryName(FileList->getFullFileName(selected));
FileSystem->changeWorkingDirectoryTo(FileDirectory);
fillListBox();
setFileName("");
} else {
setFileName(FileList->getFullFileName(selected));
}
return true;
}
break;
} break;
case EGET_EDITBOX_ENTER:
if (event.GUIEvent.Caller == FileNameText)
{
io::path dir( FileNameText->getText () );
if ( FileSystem->changeWorkingDirectoryTo( dir ) )
{
if (event.GUIEvent.Caller == FileNameText) {
io::path dir(FileNameText->getText());
if (FileSystem->changeWorkingDirectoryTo(dir)) {
fillListBox();
setFileName("");
}
return true;
}
break;
break;
default:
break;
}
break;
case EET_MOUSE_INPUT_EVENT:
switch(event.MouseInput.Event)
{
switch (event.MouseInput.Event) {
case EMIE_MOUSE_WHEEL:
return FileBox->OnEvent(event);
case EMIE_LMOUSE_PRESSED_DOWN:
@ -287,17 +254,16 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event)
return true;
case EMIE_MOUSE_MOVED:
if ( !event.MouseInput.isLeftPressed () )
if (!event.MouseInput.isLeftPressed())
Dragging = false;
if (Dragging)
{
if (Dragging) {
// gui window should not be dragged outside its parent
if (Parent)
if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)
if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X + 1 ||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y + 1 ||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X - 1 ||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y - 1)
return true;
@ -318,26 +284,24 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event)
return IGUIElement::OnEvent(event);
}
//! draws the element and its children
void CGUIFileOpenDialog::draw()
{
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
core::rect<s32> rect = AbsoluteRect;
rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
rect, &AbsoluteClippingRect);
rect, &AbsoluteClippingRect);
if (Text.size())
{
if (Text.size()) {
rect.UpperLeftCorner.X += 2;
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
IGUIFont* font = skin->getFont(EGDF_WINDOW);
IGUIFont *font = skin->getFont(EGDF_WINDOW);
if (font)
font->draw(Text.c_str(), rect,
skin->getColor(EGDC_ACTIVE_CAPTION),
@ -347,7 +311,7 @@ void CGUIFileOpenDialog::draw()
IGUIElement::draw();
}
void CGUIFileOpenDialog::pathToStringW(irr::core::stringw& result, const irr::io::path& p)
void CGUIFileOpenDialog::pathToStringW(irr::core::stringw &result, const irr::io::path &p)
{
core::multibyteToWString(result, p);
}
@ -368,17 +332,14 @@ void CGUIFileOpenDialog::fillListBox()
FileList = FileSystem->createFileList();
core::stringw s;
if (FileList)
{
for (u32 i=0; i < FileList->getFileCount(); ++i)
{
if (FileList) {
for (u32 i = 0; i < FileList->getFileCount(); ++i) {
pathToStringW(s, FileList->getFileName(i));
FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
}
}
if (FileNameText)
{
if (FileNameText) {
setDirectoryName(FileSystem->getWorkingDirectory());
pathToStringW(s, FileDirectory);
FileNameText->setText(s.c_str());
@ -386,7 +347,7 @@ void CGUIFileOpenDialog::fillListBox()
}
//! sends the event that the file has been selected.
void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type)
void CGUIFileOpenDialog::sendSelectedEvent(EGUI_EVENT_TYPE type)
{
SEvent event;
event.EventType = EET_GUI_EVENT;
@ -396,7 +357,6 @@ void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type)
Parent->OnEvent(event);
}
//! sends the event that the file choose process has been cancelled
void CGUIFileOpenDialog::sendCancelEvent()
{

View File

@ -15,73 +15,70 @@ namespace irr
namespace gui
{
class CGUIFileOpenDialog : public IGUIFileOpenDialog
{
public:
class CGUIFileOpenDialog : public IGUIFileOpenDialog
{
public:
//! constructor
CGUIFileOpenDialog(const wchar_t *title, IGUIEnvironment *environment,
IGUIElement *parent, s32 id, bool restoreCWD = false,
io::path::char_type *startDir = 0);
//! constructor
CGUIFileOpenDialog(const wchar_t* title, IGUIEnvironment* environment,
IGUIElement* parent, s32 id, bool restoreCWD=false,
io::path::char_type* startDir=0);
//! destructor
virtual ~CGUIFileOpenDialog();
//! destructor
virtual ~CGUIFileOpenDialog();
//! returns the filename of the selected file. Returns NULL, if no file was selected.
const wchar_t *getFileName() const override;
//! returns the filename of the selected file. Returns NULL, if no file was selected.
const wchar_t* getFileName() const override;
//! Returns the filename of the selected file. Is empty if no file was selected.
const io::path &getFileNameP() const override;
//! Returns the filename of the selected file. Is empty if no file was selected.
const io::path& getFileNameP() const override;
//! Returns the directory of the selected file. Returns NULL, if no directory was selected.
const io::path &getDirectoryName() const override;
//! Returns the directory of the selected file. Returns NULL, if no directory was selected.
const io::path& getDirectoryName() const override;
//! Returns the directory of the selected file converted to wide characters. Returns NULL if no directory was selected.
const wchar_t *getDirectoryNameW() const override;
//! Returns the directory of the selected file converted to wide characters. Returns NULL if no directory was selected.
const wchar_t* getDirectoryNameW() const override;
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! draws the element and its children
void draw() override;
//! draws the element and its children
void draw() override;
protected:
void setFileName(const irr::io::path &name);
void setDirectoryName(const irr::io::path &name);
protected:
//! Ensure filenames are converted correct depending on wide-char settings
void pathToStringW(irr::core::stringw &result, const irr::io::path &p);
void setFileName(const irr::io::path& name);
void setDirectoryName(const irr::io::path& name);
//! fills the listbox with files.
void fillListBox();
//! Ensure filenames are converted correct depending on wide-char settings
void pathToStringW(irr::core::stringw& result, const irr::io::path& p);
//! sends the event that the file has been selected.
void sendSelectedEvent(EGUI_EVENT_TYPE type);
//! fills the listbox with files.
void fillListBox();
//! sends the event that the file choose process has been canceld
void sendCancelEvent();
//! sends the event that the file has been selected.
void sendSelectedEvent( EGUI_EVENT_TYPE type );
//! sends the event that the file choose process has been canceld
void sendCancelEvent();
core::position2d<s32> DragStart;
io::path FileName;
core::stringw FileNameW;
io::path FileDirectory;
io::path FileDirectoryFlat;
core::stringw FileDirectoryFlatW;
io::path RestoreDirectory;
io::path StartDirectory;
IGUIButton* CloseButton;
IGUIButton* OKButton;
IGUIButton* CancelButton;
IGUIListBox* FileBox;
IGUIEditBox* FileNameText;
IGUIElement* EventParent;
io::IFileSystem* FileSystem;
io::IFileList* FileList;
bool Dragging;
};
core::position2d<s32> DragStart;
io::path FileName;
core::stringw FileNameW;
io::path FileDirectory;
io::path FileDirectoryFlat;
core::stringw FileDirectoryFlatW;
io::path RestoreDirectory;
io::path StartDirectory;
IGUIButton *CloseButton;
IGUIButton *OKButton;
IGUIButton *CancelButton;
IGUIListBox *FileBox;
IGUIEditBox *FileNameText;
IGUIElement *EventParent;
io::IFileSystem *FileSystem;
io::IFileList *FileList;
bool Dragging;
};
} // end namespace gui
} // end namespace irr

View File

@ -17,21 +17,20 @@ namespace gui
{
//! constructor
CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path& filename)
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path &filename) :
Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUIFont");
#endif
#endif
if (Environment)
{
if (Environment) {
// don't grab environment, to avoid circular references
Driver = Environment->getVideoDriver();
SpriteBank = Environment->getSpriteBank(filename);
if (!SpriteBank) // could be default-font which has no file
if (!SpriteBank) // could be default-font which has no file
SpriteBank = Environment->addEmptySpriteBank(filename);
if (SpriteBank)
SpriteBank->grab();
@ -40,18 +39,16 @@ CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path& filename)
if (Driver)
Driver->grab();
setInvisibleCharacters ( L" " );
setInvisibleCharacters(L" ");
}
//! destructor
CGUIFont::~CGUIFont()
{
if (Driver)
Driver->drop();
if (SpriteBank)
{
if (SpriteBank) {
SpriteBank->drop();
// TODO: spritebank still exists in gui-environment and should be removed here when it's
// reference-count is 1. Just can't do that from here at the moment.
@ -60,7 +57,6 @@ CGUIFont::~CGUIFont()
}
}
#if 0
//! loads a font file from xml
bool CGUIFont::load(io::IXMLReader* xml, const io::path& directory)
@ -196,25 +192,23 @@ bool CGUIFont::load(io::IXMLReader* xml, const io::path& directory)
}
#endif
void CGUIFont::setMaxHeight()
{
if ( !SpriteBank )
if (!SpriteBank)
return;
MaxHeight = 0;
core::array< core::rect<s32> >& p = SpriteBank->getPositions();
core::array<core::rect<s32>> &p = SpriteBank->getPositions();
for (u32 i=0; i<p.size(); ++i)
{
for (u32 i = 0; i < p.size(); ++i) {
const s32 t = p[i].getHeight();
if (t>MaxHeight)
if (t > MaxHeight)
MaxHeight = t;
}
}
void CGUIFont::pushTextureCreationFlags(bool(&flags)[3])
void CGUIFont::pushTextureCreationFlags(bool (&flags)[3])
{
flags[0] = Driver->getTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2);
flags[1] = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
@ -225,7 +219,7 @@ void CGUIFont::pushTextureCreationFlags(bool(&flags)[3])
Driver->setTextureCreationFlag(video::ETCF_ALLOW_MEMORY_COPY, true);
}
void CGUIFont::popTextureCreationFlags(const bool(&flags)[3])
void CGUIFont::popTextureCreationFlags(const bool (&flags)[3])
{
Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, flags[0]);
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flags[1]);
@ -233,51 +227,48 @@ void CGUIFont::popTextureCreationFlags(const bool(&flags)[3])
}
//! loads a font file, native file needed, for texture parsing
bool CGUIFont::load(io::IReadFile* file)
bool CGUIFont::load(io::IReadFile *file)
{
if (!Driver)
return false;
return loadTexture(Driver->createImageFromFile(file),
file->getFileName());
file->getFileName());
}
//! loads a font file, native file needed, for texture parsing
bool CGUIFont::load(const io::path& filename)
bool CGUIFont::load(const io::path &filename)
{
if (!Driver)
return false;
return loadTexture(Driver->createImageFromFile( filename ),
filename);
return loadTexture(Driver->createImageFromFile(filename),
filename);
}
//! load & prepare font from ITexture
bool CGUIFont::loadTexture(video::IImage* image, const io::path& name)
bool CGUIFont::loadTexture(video::IImage *image, const io::path &name)
{
if (!image || !SpriteBank)
return false;
s32 lowerRightPositions = 0;
video::IImage* tmpImage=image;
bool deleteTmpImage=false;
switch(image->getColorFormat())
{
video::IImage *tmpImage = image;
bool deleteTmpImage = false;
switch (image->getColorFormat()) {
case video::ECF_R5G6B5:
tmpImage = Driver->createImage(video::ECF_A1R5G5B5,image->getDimension());
tmpImage = Driver->createImage(video::ECF_A1R5G5B5, image->getDimension());
image->copyTo(tmpImage);
deleteTmpImage=true;
deleteTmpImage = true;
break;
case video::ECF_A1R5G5B5:
case video::ECF_A8R8G8B8:
break;
case video::ECF_R8G8B8:
tmpImage = Driver->createImage(video::ECF_A8R8G8B8,image->getDimension());
tmpImage = Driver->createImage(video::ECF_A8R8G8B8, image->getDimension());
image->copyTo(tmpImage);
deleteTmpImage=true;
deleteTmpImage = true;
break;
default:
os::Printer::log("Unknown texture format provided for CGUIFont::loadTexture", ELL_ERROR);
@ -290,14 +281,12 @@ bool CGUIFont::loadTexture(video::IImage* image, const io::path& name)
// output warnings
if (!lowerRightPositions || !SpriteBank->getSprites().size())
os::Printer::log("Either no upper or lower corner pixels in the font file. If this font was made using the new font tool, please load the XML file instead. If not, the font may be corrupted.", ELL_ERROR);
else
if (lowerRightPositions != (s32)SpriteBank->getPositions().size())
else if (lowerRightPositions != (s32)SpriteBank->getPositions().size())
os::Printer::log("The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.", ELL_ERROR);
bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions );
bool ret = (!SpriteBank->getSprites().empty() && lowerRightPositions);
if ( ret )
{
if (ret) {
bool flags[3];
pushTextureCreationFlags(flags);
@ -314,42 +303,34 @@ bool CGUIFont::loadTexture(video::IImage* image, const io::path& name)
return ret;
}
void CGUIFont::readPositions(video::IImage* image, s32& lowerRightPositions)
void CGUIFont::readPositions(video::IImage *image, s32 &lowerRightPositions)
{
if (!SpriteBank )
if (!SpriteBank)
return;
const core::dimension2d<u32> size = image->getDimension();
video::SColor colorTopLeft = image->getPixel(0,0);
video::SColor colorTopLeft = image->getPixel(0, 0);
colorTopLeft.setAlpha(255);
image->setPixel(0,0,colorTopLeft);
video::SColor colorLowerRight = image->getPixel(1,0);
video::SColor colorBackGround = image->getPixel(2,0);
image->setPixel(0, 0, colorTopLeft);
video::SColor colorLowerRight = image->getPixel(1, 0);
video::SColor colorBackGround = image->getPixel(2, 0);
video::SColor colorBackGroundTransparent = 0;
image->setPixel(1,0,colorBackGround);
image->setPixel(1, 0, colorBackGround);
// start parsing
core::position2d<s32> pos(0,0);
for (pos.Y=0; pos.Y<(s32)size.Height; ++pos.Y)
{
for (pos.X=0; pos.X<(s32)size.Width; ++pos.X)
{
core::position2d<s32> pos(0, 0);
for (pos.Y = 0; pos.Y < (s32)size.Height; ++pos.Y) {
for (pos.X = 0; pos.X < (s32)size.Width; ++pos.X) {
const video::SColor c = image->getPixel(pos.X, pos.Y);
if (c == colorTopLeft)
{
if (c == colorTopLeft) {
image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos));
}
else
if (c == colorLowerRight)
{
} else if (c == colorLowerRight) {
// too many lower right points
if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
{
if (SpriteBank->getPositions().size() <= (u32)lowerRightPositions) {
lowerRightPositions = 0;
return;
}
@ -376,33 +357,27 @@ void CGUIFont::readPositions(video::IImage* image, s32& lowerRightPositions)
CharacterMap[ch] = lowerRightPositions;
++lowerRightPositions;
}
else
if (c == colorBackGround)
} else if (c == colorBackGround)
image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
}
}
}
//! set an Pixel Offset on Drawing ( scale position on width )
void CGUIFont::setKerningWidth(s32 kerning)
{
GlobalKerningWidth = kerning;
}
//! set an Pixel Offset on Drawing ( scale position on width )
s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
s32 CGUIFont::getKerningWidth(const wchar_t *thisLetter, const wchar_t *previousLetter) const
{
s32 ret = GlobalKerningWidth;
if (thisLetter)
{
if (thisLetter) {
ret += Areas[getAreaFromCharacter(*thisLetter)].overhang;
if (previousLetter)
{
if (previousLetter) {
ret += Areas[getAreaFromCharacter(*previousLetter)].underhang;
}
}
@ -410,28 +385,24 @@ s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previous
return ret;
}
//! set an Pixel Offset on Drawing ( scale position on height )
void CGUIFont::setKerningHeight(s32 kerning)
{
GlobalKerningHeight = kerning;
}
//! set an Pixel Offset on Drawing ( scale position on height )
s32 CGUIFont::getKerningHeight () const
s32 CGUIFont::getKerningHeight() const
{
return GlobalKerningHeight;
}
//! returns the sprite number from a given character
u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const
{
return Areas[getAreaFromCharacter(*c)].spriteno;
}
s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const
{
auto n = CharacterMap.find(c);
@ -441,33 +412,29 @@ s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const
return WrongCharacter;
}
void CGUIFont::setInvisibleCharacters( const wchar_t *s )
void CGUIFont::setInvisibleCharacters(const wchar_t *s)
{
Invisible = s;
}
//! returns the dimension of text
core::dimension2d<u32> CGUIFont::getDimension(const wchar_t* text) const
core::dimension2d<u32> CGUIFont::getDimension(const wchar_t *text) const
{
core::dimension2d<u32> dim(0, 0);
core::dimension2d<u32> thisLine(0, MaxHeight);
for (const wchar_t* p = text; *p; ++p)
{
bool lineBreak=false;
for (const wchar_t *p = text; *p; ++p) {
bool lineBreak = false;
if (*p == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if (p[1] == L'\n') // Windows breaks
++p;
}
else if (*p == L'\n') // Unix breaks
} else if (*p == L'\n') // Unix breaks
{
lineBreak = true;
}
if (lineBreak)
{
if (lineBreak) {
dim.Height += thisLine.Height;
if (dim.Width < thisLine.Width)
dim.Width = thisLine.Width;
@ -489,15 +456,14 @@ core::dimension2d<u32> CGUIFont::getDimension(const wchar_t* text) const
}
//! draws some text and clips it to the specified rectangle if wanted
void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color,
bool hcenter, bool vcenter, const core::rect<s32>* clip
)
void CGUIFont::draw(const core::stringw &text, const core::rect<s32> &position,
video::SColor color,
bool hcenter, bool vcenter, const core::rect<s32> *clip)
{
if (!Driver || !SpriteBank)
return;
core::dimension2d<s32> textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension width is < position width
core::dimension2d<s32> textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension width is < position width
core::position2d<s32> offset = position.UpperLeftCorner;
if (hcenter || vcenter || clip)
@ -509,8 +475,7 @@ void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
if (vcenter)
offset.Y += (position.getHeight() - textDimension.Height) >> 1;
if (clip)
{
if (clip) {
core::rect<s32> clippedRect(offset, textDimension);
clippedRect.clipAgainst(*clip);
if (!clippedRect.isValid())
@ -520,39 +485,34 @@ void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
core::array<u32> indices(text.size());
core::array<core::position2di> offsets(text.size());
for(u32 i = 0;i < text.size();i++)
{
for (u32 i = 0; i < text.size(); i++) {
wchar_t c = text[i];
bool lineBreak=false;
if ( c == L'\r') // Mac or Windows breaks
bool lineBreak = false;
if (c == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if ( text[i + 1] == L'\n') // Windows breaks
if (text[i + 1] == L'\n') // Windows breaks
c = text[++i];
}
else if ( c == L'\n') // Unix breaks
} else if (c == L'\n') // Unix breaks
{
lineBreak = true;
}
if (lineBreak)
{
if (lineBreak) {
offset.Y += MaxHeight;
offset.X = position.UpperLeftCorner.X;
if ( hcenter )
{
if (hcenter) {
offset.X += (position.getWidth() - textDimension.Width) >> 1;
}
continue;
}
SFontArea& area = Areas[getAreaFromCharacter(c)];
SFontArea &area = Areas[getAreaFromCharacter(c)];
offset.X += area.underhang;
if ( Invisible.findFirst ( c ) < 0 )
{
if (Invisible.findFirst(c) < 0) {
indices.push_back(area.spriteno);
offsets.push_back(offset);
}
@ -563,16 +523,14 @@ void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color);
}
//! Calculates the index of the character in the text which is on a specific position.
s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
s32 CGUIFont::getCharacterFromPos(const wchar_t *text, s32 pixel_x) const
{
s32 x = 0;
s32 idx = 0;
while (text[idx])
{
const SFontArea& a = Areas[getAreaFromCharacter(text[idx])];
while (text[idx]) {
const SFontArea &a = Areas[getAreaFromCharacter(text[idx])];
x += a.width + a.overhang + a.underhang + GlobalKerningWidth;
@ -585,8 +543,7 @@ s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
return -1;
}
IGUISpriteBank* CGUIFont::getSpriteBank() const
IGUISpriteBank *CGUIFont::getSpriteBank() const
{
return SpriteBank;
}

View File

@ -15,91 +15,90 @@ namespace irr
namespace video
{
class IVideoDriver;
class IImage;
class IVideoDriver;
class IImage;
}
namespace gui
{
class IGUIEnvironment;
class IGUIEnvironment;
class CGUIFont : public IGUIFontBitmap
{
public:
//! constructor
CGUIFont(IGUIEnvironment* env, const io::path& filename);
CGUIFont(IGUIEnvironment *env, const io::path &filename);
//! destructor
virtual ~CGUIFont();
//! loads a font from a texture file
bool load(const io::path& filename);
bool load(const io::path &filename);
//! loads a font from a texture file
bool load(io::IReadFile* file);
bool load(io::IReadFile *file);
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter=false,
bool vcenter=false, const core::rect<s32>* clip=0) override;
virtual void draw(const core::stringw &text, const core::rect<s32> &position,
video::SColor color, bool hcenter = false,
bool vcenter = false, const core::rect<s32> *clip = 0) override;
//! returns the dimension of a text
core::dimension2d<u32> getDimension(const wchar_t* text) const override;
core::dimension2d<u32> getDimension(const wchar_t *text) const override;
//! Calculates the index of the character in the text which is on a specific position.
s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const override;
s32 getCharacterFromPos(const wchar_t *text, s32 pixel_x) const override;
//! Returns the type of this font
EGUI_FONT_TYPE getType() const override { return EGFT_BITMAP; }
//! set an Pixel Offset on Drawing ( scale position on width )
void setKerningWidth (s32 kerning) override;
void setKerningHeight (s32 kerning) override;
void setKerningWidth(s32 kerning) override;
void setKerningHeight(s32 kerning) override;
//! set an Pixel Offset on Drawing ( scale position on width )
s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const override;
s32 getKerningWidth(const wchar_t *thisLetter = 0, const wchar_t *previousLetter = 0) const override;
s32 getKerningHeight() const override;
//! gets the sprite bank
IGUISpriteBank* getSpriteBank() const override;
IGUISpriteBank *getSpriteBank() const override;
//! returns the sprite number from a given character
u32 getSpriteNoFromChar(const wchar_t *c) const override;
void setInvisibleCharacters( const wchar_t *s ) override;
void setInvisibleCharacters(const wchar_t *s) override;
private:
struct SFontArea
{
SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
s32 underhang;
s32 overhang;
s32 width;
u32 spriteno;
SFontArea() :
underhang(0), overhang(0), width(0), spriteno(0) {}
s32 underhang;
s32 overhang;
s32 width;
u32 spriteno;
};
//! load & prepare font from ITexture
bool loadTexture(video::IImage * image, const io::path& name);
bool loadTexture(video::IImage *image, const io::path &name);
void readPositions(video::IImage* texture, s32& lowerRightPositions);
void readPositions(video::IImage *texture, s32 &lowerRightPositions);
s32 getAreaFromCharacter (const wchar_t c) const;
s32 getAreaFromCharacter(const wchar_t c) const;
void setMaxHeight();
void pushTextureCreationFlags(bool(&flags)[3]);
void popTextureCreationFlags(const bool(&flags)[3]);
void pushTextureCreationFlags(bool (&flags)[3]);
void popTextureCreationFlags(const bool (&flags)[3]);
core::array<SFontArea> Areas;
std::map<wchar_t, s32> CharacterMap;
video::IVideoDriver* Driver;
IGUISpriteBank* SpriteBank;
IGUIEnvironment* Environment;
u32 WrongCharacter;
s32 MaxHeight;
s32 GlobalKerningWidth, GlobalKerningHeight;
core::array<SFontArea> Areas;
std::map<wchar_t, s32> CharacterMap;
video::IVideoDriver *Driver;
IGUISpriteBank *SpriteBank;
IGUIEnvironment *Environment;
u32 WrongCharacter;
s32 MaxHeight;
s32 GlobalKerningWidth, GlobalKerningHeight;
core::stringw Invisible;
};

View File

@ -13,18 +13,16 @@ namespace irr
namespace gui
{
//! constructor
CGUIImage::CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
: IGUIImage(environment, parent, id, rectangle), Texture(0), Color(255,255,255,255),
UseAlphaChannel(false), ScaleImage(false), DrawBounds(0.f, 0.f, 1.f, 1.f), DrawBackground(true)
CGUIImage::CGUIImage(IGUIEnvironment *environment, IGUIElement *parent, s32 id, core::rect<s32> rectangle) :
IGUIImage(environment, parent, id, rectangle), Texture(0), Color(255, 255, 255, 255),
UseAlphaChannel(false), ScaleImage(false), DrawBounds(0.f, 0.f, 1.f, 1.f), DrawBackground(true)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUIImage");
#endif
#endif
}
//! destructor
CGUIImage::~CGUIImage()
{
@ -32,9 +30,8 @@ CGUIImage::~CGUIImage()
Texture->drop();
}
//! sets an image
void CGUIImage::setImage(video::ITexture* image)
void CGUIImage::setImage(video::ITexture *image)
{
if (image == Texture)
return;
@ -49,7 +46,7 @@ void CGUIImage::setImage(video::ITexture* image)
}
//! Gets the image texture
video::ITexture* CGUIImage::getImage() const
video::ITexture *CGUIImage::getImage() const
{
return Texture;
}
@ -72,39 +69,32 @@ void CGUIImage::draw()
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
video::IVideoDriver* driver = Environment->getVideoDriver();
IGUISkin *skin = Environment->getSkin();
video::IVideoDriver *driver = Environment->getVideoDriver();
if (Texture)
{
if (Texture) {
core::rect<s32> sourceRect(SourceRect);
if (sourceRect.getWidth() == 0 || sourceRect.getHeight() == 0)
{
if (sourceRect.getWidth() == 0 || sourceRect.getHeight() == 0) {
sourceRect = core::rect<s32>(core::dimension2di(Texture->getOriginalSize()));
}
if (ScaleImage)
{
const video::SColor Colors[] = {Color,Color,Color,Color};
if (ScaleImage) {
const video::SColor Colors[] = {Color, Color, Color, Color};
core::rect<s32> clippingRect(AbsoluteClippingRect);
checkBounds(clippingRect);
driver->draw2DImage(Texture, AbsoluteRect, sourceRect,
&clippingRect, Colors, UseAlphaChannel);
}
else
{
&clippingRect, Colors, UseAlphaChannel);
} else {
core::rect<s32> clippingRect(AbsoluteRect.UpperLeftCorner, sourceRect.getSize());
checkBounds(clippingRect);
clippingRect.clipAgainst(AbsoluteClippingRect);
driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner, sourceRect,
&clippingRect, Color, UseAlphaChannel);
&clippingRect, Color, UseAlphaChannel);
}
}
else if ( DrawBackground )
{
} else if (DrawBackground) {
core::rect<s32> clippingRect(AbsoluteClippingRect);
checkBounds(clippingRect);
@ -114,21 +104,18 @@ void CGUIImage::draw()
IGUIElement::draw();
}
//! sets if the image should use its alpha channel to draw itself
void CGUIImage::setUseAlphaChannel(bool use)
{
UseAlphaChannel = use;
}
//! sets if the image should use its alpha channel to draw itself
void CGUIImage::setScaleImage(bool scale)
{
ScaleImage = scale;
}
//! Returns true if the image is scaled to fit, false if not
bool CGUIImage::isImageScaled() const
{
@ -142,7 +129,7 @@ bool CGUIImage::isAlphaChannelUsed() const
}
//! Sets the source rectangle of the image. By default the full image is used.
void CGUIImage::setSourceRect(const core::rect<s32>& sourceRect)
void CGUIImage::setSourceRect(const core::rect<s32> &sourceRect)
{
SourceRect = sourceRect;
}
@ -154,16 +141,16 @@ core::rect<s32> CGUIImage::getSourceRect() const
}
//! Restrict target drawing-area.
void CGUIImage::setDrawBounds(const core::rect<f32>& drawBoundUVs)
void CGUIImage::setDrawBounds(const core::rect<f32> &drawBoundUVs)
{
DrawBounds = drawBoundUVs;
DrawBounds.UpperLeftCorner.X = core::clamp(DrawBounds.UpperLeftCorner.X, 0.f, 1.f);
DrawBounds.UpperLeftCorner.Y = core::clamp(DrawBounds.UpperLeftCorner.Y, 0.f, 1.f);
DrawBounds.LowerRightCorner.X = core::clamp(DrawBounds.LowerRightCorner.X, 0.f, 1.f);
DrawBounds.LowerRightCorner.X = core::clamp(DrawBounds.LowerRightCorner.X, 0.f, 1.f);
if ( DrawBounds.UpperLeftCorner.X > DrawBounds.LowerRightCorner.X )
if (DrawBounds.UpperLeftCorner.X > DrawBounds.LowerRightCorner.X)
DrawBounds.UpperLeftCorner.X = DrawBounds.LowerRightCorner.X;
if ( DrawBounds.UpperLeftCorner.Y > DrawBounds.LowerRightCorner.Y )
if (DrawBounds.UpperLeftCorner.Y > DrawBounds.LowerRightCorner.Y)
DrawBounds.UpperLeftCorner.Y = DrawBounds.LowerRightCorner.Y;
}
@ -173,6 +160,5 @@ core::rect<f32> CGUIImage::getDrawBounds() const
return DrawBounds;
}
} // end namespace gui
} // end namespace irr

View File

@ -11,89 +11,87 @@ namespace irr
namespace gui
{
class CGUIImage : public IGUIImage
class CGUIImage : public IGUIImage
{
public:
//! constructor
CGUIImage(IGUIEnvironment *environment, IGUIElement *parent, s32 id, core::rect<s32> rectangle);
//! destructor
virtual ~CGUIImage();
//! sets an image
void setImage(video::ITexture *image) override;
//! Gets the image texture
video::ITexture *getImage() const override;
//! sets the color of the image
void setColor(video::SColor color) override;
//! sets if the image should scale to fit the element
void setScaleImage(bool scale) override;
//! draws the element and its children
void draw() override;
//! sets if the image should use its alpha channel to draw itself
void setUseAlphaChannel(bool use) override;
//! Gets the color of the image
video::SColor getColor() const override;
//! Returns true if the image is scaled to fit, false if not
bool isImageScaled() const override;
//! Returns true if the image is using the alpha channel, false if not
bool isAlphaChannelUsed() const override;
//! Sets the source rectangle of the image. By default the full image is used.
void setSourceRect(const core::rect<s32> &sourceRect) override;
//! Returns the customized source rectangle of the image to be used.
core::rect<s32> getSourceRect() const override;
//! Restrict drawing-area.
void setDrawBounds(const core::rect<f32> &drawBoundUVs) override;
//! Get drawing-area restrictions.
core::rect<f32> getDrawBounds() const override;
//! Sets whether to draw a background color (EGDC_3D_DARK_SHADOW) when no texture is set
void setDrawBackground(bool draw) override
{
public:
DrawBackground = draw;
}
//! constructor
CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
//! Checks if a background is drawn when no texture is set
bool isDrawBackgroundEnabled() const override
{
return DrawBackground;
}
//! destructor
virtual ~CGUIImage();
protected:
void checkBounds(core::rect<s32> &rect)
{
f32 clipWidth = (f32)rect.getWidth();
f32 clipHeight = (f32)rect.getHeight();
//! sets an image
void setImage(video::ITexture* image) override;
//! Gets the image texture
video::ITexture* getImage() const override;
//! sets the color of the image
void setColor(video::SColor color) override;
//! sets if the image should scale to fit the element
void setScaleImage(bool scale) override;
//! draws the element and its children
void draw() override;
//! sets if the image should use its alpha channel to draw itself
void setUseAlphaChannel(bool use) override;
//! Gets the color of the image
video::SColor getColor() const override;
//! Returns true if the image is scaled to fit, false if not
bool isImageScaled() const override;
//! Returns true if the image is using the alpha channel, false if not
bool isAlphaChannelUsed() const override;
//! Sets the source rectangle of the image. By default the full image is used.
void setSourceRect(const core::rect<s32>& sourceRect) override;
//! Returns the customized source rectangle of the image to be used.
core::rect<s32> getSourceRect() const override;
//! Restrict drawing-area.
void setDrawBounds(const core::rect<f32>& drawBoundUVs) override;
//! Get drawing-area restrictions.
core::rect<f32> getDrawBounds() const override;
//! Sets whether to draw a background color (EGDC_3D_DARK_SHADOW) when no texture is set
void setDrawBackground(bool draw) override
{
DrawBackground = draw;
}
//! Checks if a background is drawn when no texture is set
bool isDrawBackgroundEnabled() const override
{
return DrawBackground;
}
protected:
void checkBounds(core::rect<s32>& rect)
{
f32 clipWidth = (f32)rect.getWidth();
f32 clipHeight = (f32)rect.getHeight();
rect.UpperLeftCorner.X += core::round32(DrawBounds.UpperLeftCorner.X*clipWidth);
rect.UpperLeftCorner.Y += core::round32(DrawBounds.UpperLeftCorner.Y*clipHeight);
rect.LowerRightCorner.X -= core::round32((1.f-DrawBounds.LowerRightCorner.X)*clipWidth);
rect.LowerRightCorner.Y -= core::round32((1.f-DrawBounds.LowerRightCorner.Y)*clipHeight);
}
private:
video::ITexture* Texture;
video::SColor Color;
bool UseAlphaChannel;
bool ScaleImage;
core::rect<s32> SourceRect;
core::rect<f32> DrawBounds;
bool DrawBackground;
};
rect.UpperLeftCorner.X += core::round32(DrawBounds.UpperLeftCorner.X * clipWidth);
rect.UpperLeftCorner.Y += core::round32(DrawBounds.UpperLeftCorner.Y * clipHeight);
rect.LowerRightCorner.X -= core::round32((1.f - DrawBounds.LowerRightCorner.X) * clipWidth);
rect.LowerRightCorner.Y -= core::round32((1.f - DrawBounds.LowerRightCorner.Y) * clipHeight);
}
private:
video::ITexture *Texture;
video::SColor Color;
bool UseAlphaChannel;
bool ScaleImage;
core::rect<s32> SourceRect;
core::rect<f32> DrawBounds;
bool DrawBackground;
};
} // end namespace gui
} // end namespace irr

View File

@ -4,55 +4,47 @@
#include "CGUIImageList.h"
namespace irr
{
namespace gui
{
//! constructor
CGUIImageList::CGUIImageList( video::IVideoDriver* driver )
: Driver( driver ),
Texture( 0 ),
ImageCount( 0 ),
ImageSize( 0, 0 ),
ImagesPerRow( 0 ),
UseAlphaChannel( false )
CGUIImageList::CGUIImageList(video::IVideoDriver *driver) :
Driver(driver),
Texture(0),
ImageCount(0),
ImageSize(0, 0),
ImagesPerRow(0),
UseAlphaChannel(false)
{
#ifdef _DEBUG
setDebugName( "CGUIImageList" );
#endif
#ifdef _DEBUG
setDebugName("CGUIImageList");
#endif
if( Driver )
{
if (Driver) {
Driver->grab();
}
}
//! destructor
CGUIImageList::~CGUIImageList()
{
if( Driver )
{
if (Driver) {
Driver->drop();
}
if( Texture )
{
if (Texture) {
Texture->drop();
}
}
//! Creates the image list from texture.
bool CGUIImageList::createImageList(video::ITexture* texture,
core::dimension2d<s32> imageSize,
bool useAlphaChannel)
bool CGUIImageList::createImageList(video::ITexture *texture,
core::dimension2d<s32> imageSize,
bool useAlphaChannel)
{
if( !texture )
{
if (!texture) {
return false;
}
@ -70,23 +62,22 @@ bool CGUIImageList::createImageList(video::ITexture* texture,
}
//! Draws an image and clips it to the specified rectangle if wanted
void CGUIImageList::draw( s32 index, const core::position2d<s32>& destPos,
const core::rect<s32>* clip /*= 0*/ )
void CGUIImageList::draw(s32 index, const core::position2d<s32> &destPos,
const core::rect<s32> *clip /*= 0*/)
{
core::rect<s32> sourceRect;
if( !Driver || index < 0 || index >= ImageCount )
{
if (!Driver || index < 0 || index >= ImageCount) {
return;
}
sourceRect.UpperLeftCorner.X = ( index % ImagesPerRow ) * ImageSize.Width;
sourceRect.UpperLeftCorner.Y = ( index / ImagesPerRow ) * ImageSize.Height;
sourceRect.UpperLeftCorner.X = (index % ImagesPerRow) * ImageSize.Width;
sourceRect.UpperLeftCorner.Y = (index / ImagesPerRow) * ImageSize.Height;
sourceRect.LowerRightCorner.X = sourceRect.UpperLeftCorner.X + ImageSize.Width;
sourceRect.LowerRightCorner.Y = sourceRect.UpperLeftCorner.Y + ImageSize.Height;
Driver->draw2DImage( Texture, destPos, sourceRect, clip,
video::SColor( 255, 255, 255, 255 ), UseAlphaChannel );
Driver->draw2DImage(Texture, destPos, sourceRect, clip,
video::SColor(255, 255, 255, 255), UseAlphaChannel);
}
} // end namespace gui

View File

@ -14,9 +14,8 @@ namespace gui
class CGUIImageList : public IGUIImageList
{
public:
//! constructor
CGUIImageList( video::IVideoDriver* Driver );
CGUIImageList(video::IVideoDriver *Driver);
//! destructor
virtual ~CGUIImageList();
@ -27,36 +26,39 @@ public:
//! \param useAlphaChannel: true if the alpha channel from the texture should be used
//! \return
//! true if the image list was created
bool createImageList(video::ITexture* texture,
core::dimension2d<s32> imageSize,
bool useAlphaChannel);
bool createImageList(video::ITexture *texture,
core::dimension2d<s32> imageSize,
bool useAlphaChannel);
//! Draws an image and clips it to the specified rectangle if wanted
//! \param index: Index of the image
//! \param destPos: Position of the image to draw
//! \param clip: Optional pointer to a rectangle against which the text will be clipped.
//! If the pointer is null, no clipping will be done.
virtual void draw( s32 index, const core::position2d<s32>& destPos,
const core::rect<s32>* clip = 0 ) override;
virtual void draw(s32 index, const core::position2d<s32> &destPos,
const core::rect<s32> *clip = 0) override;
//! Returns the count of Images in the list.
//! \return Returns the count of Images in the list.
s32 getImageCount() const override
{ return ImageCount; }
{
return ImageCount;
}
//! Returns the size of the images in the list.
//! \return Returns the size of the images in the list.
core::dimension2d<s32> getImageSize() const override
{ return ImageSize; }
{
return ImageSize;
}
private:
video::IVideoDriver* Driver;
video::ITexture* Texture;
s32 ImageCount;
core::dimension2d<s32> ImageSize;
s32 ImagesPerRow;
bool UseAlphaChannel;
video::IVideoDriver *Driver;
video::ITexture *Texture;
s32 ImageCount;
core::dimension2d<s32> ImageSize;
s32 ImagesPerRow;
bool UseAlphaChannel;
};
} // end namespace gui

View File

@ -19,24 +19,25 @@ namespace gui
{
//! constructor
CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool clip,
bool drawBack, bool moveOverSelect)
: IGUIListBox(environment, parent, id, rectangle), Selected(-1),
ItemHeight(0),ItemHeightOverride(0),
TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0),
ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack),
MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true)
CGUIListBox::CGUIListBox(IGUIEnvironment *environment, IGUIElement *parent,
s32 id, core::rect<s32> rectangle, bool clip,
bool drawBack, bool moveOverSelect) :
IGUIListBox(environment, parent, id, rectangle),
Selected(-1),
ItemHeight(0), ItemHeightOverride(0),
TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0),
ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack),
MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUIListBox");
#endif
#endif
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
ScrollBar = new CGUIScrollBar(false, Environment, this, -1,
core::recti(0, 0, 1, 1),
!clip);
core::recti(0, 0, 1, 1),
!clip);
ScrollBar->setSubElement(true);
ScrollBar->setTabStop(false);
ScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
@ -54,7 +55,6 @@ CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
updateAbsolutePosition();
}
//! destructor
CGUIListBox::~CGUIListBox()
{
@ -68,53 +68,45 @@ CGUIListBox::~CGUIListBox()
IconBank->drop();
}
//! returns amount of list items
u32 CGUIListBox::getItemCount() const
{
return Items.size();
}
//! returns string of a list item. the may be a value from 0 to itemCount-1
const wchar_t* CGUIListBox::getListItem(u32 id) const
const wchar_t *CGUIListBox::getListItem(u32 id) const
{
if (id>=Items.size())
if (id >= Items.size())
return 0;
return Items[id].Text.c_str();
}
//! Returns the icon of an item
s32 CGUIListBox::getIcon(u32 id) const
{
if (id>=Items.size())
if (id >= Items.size())
return -1;
return Items[id].Icon;
}
//! adds a list item, returns id of item
u32 CGUIListBox::addItem(const wchar_t* text)
u32 CGUIListBox::addItem(const wchar_t *text)
{
return addItem(text, -1);
}
//! adds a list item, returns id of item
void CGUIListBox::removeItem(u32 id)
{
if (id >= Items.size())
return;
if ((u32)Selected==id)
{
if ((u32)Selected == id) {
Selected = -1;
}
else if ((u32)Selected > id)
{
} else if ((u32)Selected > id) {
Selected -= 1;
selectTime = os::Timer::getTime();
}
@ -124,19 +116,16 @@ void CGUIListBox::removeItem(u32 id)
recalculateItemHeight();
}
s32 CGUIListBox::getItemAt(s32 xpos, s32 ypos) const
{
if ( xpos < AbsoluteRect.UpperLeftCorner.X || xpos >= AbsoluteRect.LowerRightCorner.X
|| ypos < AbsoluteRect.UpperLeftCorner.Y || ypos >= AbsoluteRect.LowerRightCorner.Y
)
if (xpos < AbsoluteRect.UpperLeftCorner.X || xpos >= AbsoluteRect.LowerRightCorner.X || ypos < AbsoluteRect.UpperLeftCorner.Y || ypos >= AbsoluteRect.LowerRightCorner.Y)
return -1;
if ( ItemHeight == 0 )
if (ItemHeight == 0)
return -1;
s32 item = ((ypos - AbsoluteRect.UpperLeftCorner.Y - 1) + ScrollBar->getPos()) / ItemHeight;
if ( item < 0 || item >= (s32)Items.size())
if (item < 0 || item >= (s32)Items.size())
return -1;
return item;
@ -154,23 +143,20 @@ void CGUIListBox::clear()
recalculateItemHeight();
}
void CGUIListBox::recalculateItemHeight()
{
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (Font != skin->getFont())
{
if (Font != skin->getFont()) {
if (Font)
Font->drop();
Font = skin->getFont();
if ( 0 == ItemHeightOverride )
if (0 == ItemHeightOverride)
ItemHeight = 0;
if (Font)
{
if ( 0 == ItemHeightOverride )
if (Font) {
if (0 == ItemHeightOverride)
ItemHeight = Font->getDimension(L"A").Height + 4;
Font->grab();
@ -178,12 +164,12 @@ void CGUIListBox::recalculateItemHeight()
}
TotalItemHeight = ItemHeight * Items.size();
ScrollBar->setMax( core::max_(0, TotalItemHeight - AbsoluteRect.getHeight()) );
ScrollBar->setMax(core::max_(0, TotalItemHeight - AbsoluteRect.getHeight()));
s32 minItemHeight = ItemHeight > 0 ? ItemHeight : 1;
ScrollBar->setSmallStep ( minItemHeight );
ScrollBar->setLargeStep ( 2*minItemHeight );
ScrollBar->setSmallStep(minItemHeight);
ScrollBar->setLargeStep(2 * minItemHeight);
if ( TotalItemHeight <= AbsoluteRect.getHeight() )
if (TotalItemHeight <= AbsoluteRect.getHeight())
ScrollBar->setVisible(false);
else
ScrollBar->setVisible(true);
@ -195,11 +181,10 @@ s32 CGUIListBox::getSelected() const
return Selected;
}
//! sets the selected item. Set this to -1 if no item should be selected
void CGUIListBox::setSelected(s32 id)
{
if ((u32)id>=Items.size())
if ((u32)id >= Items.size())
Selected = -1;
else
Selected = id;
@ -214,69 +199,61 @@ void CGUIListBox::setSelected(const wchar_t *item)
{
s32 index = -1;
if ( item )
{
for ( index = 0; index < (s32) Items.size(); ++index )
{
if ( Items[index].Text == item )
if (item) {
for (index = 0; index < (s32)Items.size(); ++index) {
if (Items[index].Text == item)
break;
}
}
setSelected ( index );
setSelected(index);
}
//! called if an event happened.
bool CGUIListBox::OnEvent(const SEvent& event)
bool CGUIListBox::OnEvent(const SEvent &event)
{
if (isEnabled())
{
switch(event.EventType)
{
if (isEnabled()) {
switch (event.EventType) {
case EET_KEY_INPUT_EVENT:
if (event.KeyInput.PressedDown &&
(event.KeyInput.Key == KEY_DOWN ||
event.KeyInput.Key == KEY_UP ||
event.KeyInput.Key == KEY_HOME ||
event.KeyInput.Key == KEY_END ||
event.KeyInput.Key == KEY_NEXT ||
event.KeyInput.Key == KEY_PRIOR ) )
{
(event.KeyInput.Key == KEY_DOWN ||
event.KeyInput.Key == KEY_UP ||
event.KeyInput.Key == KEY_HOME ||
event.KeyInput.Key == KEY_END ||
event.KeyInput.Key == KEY_NEXT ||
event.KeyInput.Key == KEY_PRIOR)) {
s32 oldSelected = Selected;
switch (event.KeyInput.Key)
{
case KEY_DOWN:
Selected += 1;
break;
case KEY_UP:
Selected -= 1;
break;
case KEY_HOME:
Selected = 0;
break;
case KEY_END:
Selected = (s32)Items.size()-1;
break;
case KEY_NEXT:
Selected += AbsoluteRect.getHeight() / ItemHeight;
break;
case KEY_PRIOR:
Selected -= AbsoluteRect.getHeight() / ItemHeight;
break;
default:
break;
switch (event.KeyInput.Key) {
case KEY_DOWN:
Selected += 1;
break;
case KEY_UP:
Selected -= 1;
break;
case KEY_HOME:
Selected = 0;
break;
case KEY_END:
Selected = (s32)Items.size() - 1;
break;
case KEY_NEXT:
Selected += AbsoluteRect.getHeight() / ItemHeight;
break;
case KEY_PRIOR:
Selected -= AbsoluteRect.getHeight() / ItemHeight;
break;
default:
break;
}
if (Selected<0)
if (Selected < 0)
Selected = 0;
if (Selected >= (s32)Items.size())
Selected = Items.size() - 1; // will set Selected to -1 for empty listboxes which is correct
Selected = Items.size() - 1; // will set Selected to -1 for empty listboxes which is correct
recalculateScrollPos();
// post the news
if (oldSelected != Selected && Parent && !Selecting && !MoveOverSelect)
{
if (oldSelected != Selected && Parent && !Selecting && !MoveOverSelect) {
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
@ -286,12 +263,8 @@ bool CGUIListBox::OnEvent(const SEvent& event)
}
return true;
}
else
if (!event.KeyInput.PressedDown && ( event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE ) )
{
if (Parent)
{
} else if (!event.KeyInput.PressedDown && (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) {
if (Parent) {
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
@ -300,27 +273,19 @@ bool CGUIListBox::OnEvent(const SEvent& event)
Parent->OnEvent(e);
}
return true;
}
else if (event.KeyInput.Key == KEY_TAB )
{
} else if (event.KeyInput.Key == KEY_TAB) {
return false;
}
else if (event.KeyInput.PressedDown && event.KeyInput.Char)
{
} else if (event.KeyInput.PressedDown && event.KeyInput.Char) {
// change selection based on text as it is typed.
u32 now = os::Timer::getTime();
if (now - LastKeyTime < 500)
{
if (now - LastKeyTime < 500) {
// add to key buffer if it isn't a key repeat
if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.KeyInput.Char))
{
if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.KeyInput.Char)) {
KeyBuffer += L" ";
KeyBuffer[KeyBuffer.size()-1] = event.KeyInput.Char;
KeyBuffer[KeyBuffer.size() - 1] = event.KeyInput.Char;
}
}
else
{
} else {
KeyBuffer = L" ";
KeyBuffer[0] = event.KeyInput.Char;
}
@ -329,22 +294,17 @@ bool CGUIListBox::OnEvent(const SEvent& event)
// find the selected item, starting at the current selection
s32 start = Selected;
// dont change selection if the key buffer matches the current item
if (Selected > -1 && KeyBuffer.size() > 1)
{
if (Selected > -1 && KeyBuffer.size() > 1) {
if (Items[Selected].Text.size() >= KeyBuffer.size() &&
KeyBuffer.equals_ignore_case(Items[Selected].Text.subString(0,KeyBuffer.size())))
KeyBuffer.equals_ignore_case(Items[Selected].Text.subString(0, KeyBuffer.size())))
return true;
}
s32 current;
for (current = start+1; current < (s32)Items.size(); ++current)
{
if (Items[current].Text.size() >= KeyBuffer.size())
{
if (KeyBuffer.equals_ignore_case(Items[current].Text.subString(0,KeyBuffer.size())))
{
if (Parent && Selected != current && !Selecting && !MoveOverSelect)
{
for (current = start + 1; current < (s32)Items.size(); ++current) {
if (Items[current].Text.size() >= KeyBuffer.size()) {
if (KeyBuffer.equals_ignore_case(Items[current].Text.subString(0, KeyBuffer.size()))) {
if (Parent && Selected != current && !Selecting && !MoveOverSelect) {
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
@ -357,14 +317,10 @@ bool CGUIListBox::OnEvent(const SEvent& event)
}
}
}
for (current = 0; current <= start; ++current)
{
if (Items[current].Text.size() >= KeyBuffer.size())
{
if (KeyBuffer.equals_ignore_case(Items[current].Text.subString(0,KeyBuffer.size())))
{
if (Parent && Selected != current && !Selecting && !MoveOverSelect)
{
for (current = 0; current <= start; ++current) {
if (Items[current].Text.size() >= KeyBuffer.size()) {
if (KeyBuffer.equals_ignore_case(Items[current].Text.subString(0, KeyBuffer.size()))) {
if (Parent && Selected != current && !Selecting && !MoveOverSelect) {
Selected = current;
SEvent e;
e.EventType = EET_GUI_EVENT;
@ -384,62 +340,53 @@ bool CGUIListBox::OnEvent(const SEvent& event)
break;
case EET_GUI_EVENT:
switch(event.GUIEvent.EventType)
{
switch (event.GUIEvent.EventType) {
case gui::EGET_SCROLL_BAR_CHANGED:
if (event.GUIEvent.Caller == ScrollBar)
return true;
break;
case gui::EGET_ELEMENT_FOCUS_LOST:
{
if (event.GUIEvent.Caller == this)
Selecting = false;
case gui::EGET_ELEMENT_FOCUS_LOST: {
if (event.GUIEvent.Caller == this)
Selecting = false;
}
default:
break;
}
break;
case EET_MOUSE_INPUT_EVENT: {
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
switch (event.MouseInput.Event) {
case EMIE_MOUSE_WHEEL:
ScrollBar->setPos(ScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1) * -ItemHeight / 2);
return true;
case EMIE_LMOUSE_PRESSED_DOWN: {
Selecting = true;
return true;
}
case EMIE_LMOUSE_LEFT_UP: {
Selecting = false;
if (isPointInside(p))
selectNew(event.MouseInput.Y);
return true;
}
case EMIE_MOUSE_MOVED:
if (Selecting || MoveOverSelect) {
if (isPointInside(p)) {
selectNew(event.MouseInput.Y, true);
return true;
}
}
default:
break;
}
break;
case EET_MOUSE_INPUT_EVENT:
{
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
switch(event.MouseInput.Event)
{
case EMIE_MOUSE_WHEEL:
ScrollBar->setPos(ScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-ItemHeight/2);
return true;
case EMIE_LMOUSE_PRESSED_DOWN:
{
Selecting = true;
return true;
}
case EMIE_LMOUSE_LEFT_UP:
{
Selecting = false;
if (isPointInside(p))
selectNew(event.MouseInput.Y);
return true;
}
case EMIE_MOUSE_MOVED:
if (Selecting || MoveOverSelect)
{
if (isPointInside(p))
{
selectNew(event.MouseInput.Y, true);
return true;
}
}
default:
break;
}
}
break;
} break;
default:
break;
}
@ -448,14 +395,13 @@ bool CGUIListBox::OnEvent(const SEvent& event)
return IGUIElement::OnEvent(event);
}
void CGUIListBox::selectNew(s32 ypos, bool onlyHover)
{
u32 now = os::Timer::getTime();
s32 oldSelected = Selected;
Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos);
if (Selected<0 && !Items.empty())
if (Selected < 0 && !Items.empty())
Selected = 0;
recalculateScrollPos();
@ -463,8 +409,7 @@ void CGUIListBox::selectNew(s32 ypos, bool onlyHover)
gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED;
selectTime = now;
// post the news
if (Parent && !onlyHover)
{
if (Parent && !onlyHover) {
SEvent event;
event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this;
@ -474,7 +419,6 @@ void CGUIListBox::selectNew(s32 ypos, bool onlyHover)
}
}
//! Update the position and size of the listbox, and update the scrollbar
void CGUIListBox::updateAbsolutePosition()
{
@ -483,7 +427,6 @@ void CGUIListBox::updateAbsolutePosition()
recalculateItemHeight();
}
//! draws the element and its children
void CGUIListBox::draw()
{
@ -492,10 +435,10 @@ void CGUIListBox::draw()
recalculateItemHeight(); // if the font changed
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
updateScrollBarSize(skin->getSize(EGDS_SCROLLBAR_SIZE));
core::rect<s32>* clipRect = 0;
core::rect<s32> *clipRect = 0;
// draw background
core::rect<s32> frameRect(AbsoluteRect);
@ -511,7 +454,7 @@ void CGUIListBox::draw()
clientClip.clipAgainst(AbsoluteClippingRect);
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT), true,
DrawBack, frameRect, &AbsoluteClippingRect);
DrawBack, frameRect, &AbsoluteClippingRect);
if (clipRect)
clientClip.clipAgainst(*clipRect);
@ -528,57 +471,45 @@ void CGUIListBox::draw()
bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar));
for (s32 i=0; i<(s32)Items.size(); ++i)
{
for (s32 i = 0; i < (s32)Items.size(); ++i) {
if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y &&
frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y)
{
frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y) {
if (i == Selected && hl)
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip);
core::rect<s32> textRect = frameRect;
textRect.UpperLeftCorner.X += 3;
if (Font)
{
if (IconBank && (Items[i].Icon > -1))
{
if (Font) {
if (IconBank && (Items[i].Icon > -1)) {
core::position2di iconPos = textRect.UpperLeftCorner;
iconPos.Y += textRect.getHeight() / 2;
iconPos.X += ItemsIconWidth/2;
iconPos.X += ItemsIconWidth / 2;
if ( i==Selected && hl )
{
IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ?
getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT),
selectTime, os::Timer::getTime(), false, true);
}
else
{
IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON),
0 , (i==Selected) ? os::Timer::getTime() : 0, false, true);
if (i == Selected && hl) {
IconBank->draw2DSprite((u32)Items[i].Icon, iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ? getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT),
selectTime, os::Timer::getTime(), false, true);
} else {
IconBank->draw2DSprite((u32)Items[i].Icon, iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON),
0, (i == Selected) ? os::Timer::getTime() : 0, false, true);
}
}
textRect.UpperLeftCorner.X += ItemsIconWidth+3;
textRect.UpperLeftCorner.X += ItemsIconWidth + 3;
if ( i==Selected && hl )
{
if (i == Selected && hl) {
Font->draw(Items[i].Text.c_str(), textRect,
hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ?
getItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_TEXT_HIGHLIGHT),
false, true, &clientClip);
}
else
{
hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ? getItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_TEXT_HIGHLIGHT),
false, true, &clientClip);
} else {
Font->draw(Items[i].Text.c_str(), textRect,
hasItemOverrideColor(i, EGUI_LBC_TEXT) ? getItemOverrideColor(i, EGUI_LBC_TEXT) : getItemDefaultColor(EGUI_LBC_TEXT),
false, true, &clientClip);
hasItemOverrideColor(i, EGUI_LBC_TEXT) ? getItemOverrideColor(i, EGUI_LBC_TEXT) : getItemDefaultColor(EGUI_LBC_TEXT),
false, true, &clientClip);
}
textRect.UpperLeftCorner.X -= ItemsIconWidth+3;
textRect.UpperLeftCorner.X -= ItemsIconWidth + 3;
}
}
@ -589,9 +520,8 @@ void CGUIListBox::draw()
IGUIElement::draw();
}
//! adds an list item with an icon
u32 CGUIListBox::addItem(const wchar_t* text, s32 icon)
u32 CGUIListBox::addItem(const wchar_t *text, s32 icon)
{
ListItem i;
i.Text = text;
@ -604,10 +534,9 @@ u32 CGUIListBox::addItem(const wchar_t* text, s32 icon)
return Items.size() - 1;
}
void CGUIListBox::setSpriteBank(IGUISpriteBank* bank)
void CGUIListBox::setSpriteBank(IGUISpriteBank *bank)
{
if ( bank == IconBank )
if (bank == IconBank)
return;
if (IconBank)
IconBank->drop();
@ -617,7 +546,6 @@ void CGUIListBox::setSpriteBank(IGUISpriteBank* bank)
IconBank->grab();
}
void CGUIListBox::recalculateScrollPos()
{
if (!AutoScroll)
@ -625,21 +553,16 @@ void CGUIListBox::recalculateScrollPos()
const s32 selPos = (getSelected() == -1 ? TotalItemHeight : getSelected() * ItemHeight) - ScrollBar->getPos();
if (selPos < 0)
{
if (selPos < 0) {
ScrollBar->setPos(ScrollBar->getPos() + selPos);
}
else
if (selPos > AbsoluteRect.getHeight() - ItemHeight)
{
} else if (selPos > AbsoluteRect.getHeight() - ItemHeight) {
ScrollBar->setPos(ScrollBar->getPos() + selPos - AbsoluteRect.getHeight() + ItemHeight);
}
}
void CGUIListBox::updateScrollBarSize(s32 size)
{
if ( size != ScrollBar->getRelativePosition().getWidth() )
{
if (size != ScrollBar->getRelativePosition().getWidth()) {
core::recti r(RelativeRect.getWidth() - size, 0, RelativeRect.getWidth(), RelativeRect.getHeight());
ScrollBar->setRelativePosition(r);
}
@ -650,17 +573,14 @@ void CGUIListBox::setAutoScrollEnabled(bool scroll)
AutoScroll = scroll;
}
bool CGUIListBox::isAutoScrollEnabled() const
{
return AutoScroll;
}
bool CGUIListBox::getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const
bool CGUIListBox::getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc &useColorLabel, core::stringc &colorLabel) const
{
switch ( colorType )
{
switch (colorType) {
case EGUI_LBC_TEXT:
useColorLabel = "UseColText";
colorLabel = "ColText";
@ -683,16 +603,13 @@ bool CGUIListBox::getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::str
return true;
}
void CGUIListBox::recalculateItemWidth(s32 icon)
{
if (IconBank && icon > -1 &&
IconBank->getSprites().size() > (u32)icon &&
IconBank->getSprites()[(u32)icon].Frames.size())
{
IconBank->getSprites().size() > (u32)icon &&
IconBank->getSprites()[(u32)icon].Frames.size()) {
u32 rno = IconBank->getSprites()[(u32)icon].Frames[0].rectNumber;
if (IconBank->getPositions().size() > rno)
{
if (IconBank->getPositions().size() > rno) {
const s32 w = IconBank->getPositions()[rno].getWidth();
if (w > ItemsIconWidth)
ItemsIconWidth = w;
@ -700,10 +617,9 @@ void CGUIListBox::recalculateItemWidth(s32 icon)
}
}
void CGUIListBox::setItem(u32 index, const wchar_t* text, s32 icon)
void CGUIListBox::setItem(u32 index, const wchar_t *text, s32 icon)
{
if ( index >= Items.size() )
if (index >= Items.size())
return;
Items[index].Text = text;
@ -713,10 +629,9 @@ void CGUIListBox::setItem(u32 index, const wchar_t* text, s32 icon)
recalculateItemWidth(icon);
}
//! Insert the item at the given index
//! Return the index on success or -1 on failure.
s32 CGUIListBox::insertItem(u32 index, const wchar_t* text, s32 icon)
s32 CGUIListBox::insertItem(u32 index, const wchar_t *text, s32 icon)
{
ListItem i;
i.Text = text;
@ -729,10 +644,9 @@ s32 CGUIListBox::insertItem(u32 index, const wchar_t* text, s32 icon)
return index;
}
void CGUIListBox::swapItems(u32 index1, u32 index2)
{
if ( index1 >= Items.size() || index2 >= Items.size() )
if (index1 >= Items.size() || index2 >= Items.size())
return;
ListItem dummmy = Items[index1];
@ -740,100 +654,89 @@ void CGUIListBox::swapItems(u32 index1, u32 index2)
Items[index2] = dummmy;
}
void CGUIListBox::setItemOverrideColor(u32 index, video::SColor color)
{
for ( u32 c=0; c < EGUI_LBC_COUNT; ++c )
{
for (u32 c = 0; c < EGUI_LBC_COUNT; ++c) {
Items[index].OverrideColors[c].Use = true;
Items[index].OverrideColors[c].Color = color;
}
}
void CGUIListBox::setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color)
{
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
if (index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT)
return;
Items[index].OverrideColors[colorType].Use = true;
Items[index].OverrideColors[colorType].Color = color;
}
void CGUIListBox::clearItemOverrideColor(u32 index)
{
for (u32 c=0; c < (u32)EGUI_LBC_COUNT; ++c )
{
for (u32 c = 0; c < (u32)EGUI_LBC_COUNT; ++c) {
Items[index].OverrideColors[c].Use = false;
}
}
void CGUIListBox::clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType)
{
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
if (index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT)
return;
Items[index].OverrideColors[colorType].Use = false;
}
bool CGUIListBox::hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const
{
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
if (index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT)
return false;
return Items[index].OverrideColors[colorType].Use;
}
video::SColor CGUIListBox::getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const
{
if ( (u32)index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
if ((u32)index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT)
return video::SColor();
return Items[index].OverrideColors[colorType].Color;
}
video::SColor CGUIListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const
{
IGUISkin* skin = Environment->getSkin();
if ( !skin )
IGUISkin *skin = Environment->getSkin();
if (!skin)
return video::SColor();
switch ( colorType )
{
case EGUI_LBC_TEXT:
return skin->getColor(EGDC_BUTTON_TEXT);
case EGUI_LBC_TEXT_HIGHLIGHT:
return skin->getColor(EGDC_HIGH_LIGHT_TEXT);
case EGUI_LBC_ICON:
return skin->getColor(EGDC_ICON);
case EGUI_LBC_ICON_HIGHLIGHT:
return skin->getColor(EGDC_ICON_HIGH_LIGHT);
default:
return video::SColor();
switch (colorType) {
case EGUI_LBC_TEXT:
return skin->getColor(EGDC_BUTTON_TEXT);
case EGUI_LBC_TEXT_HIGHLIGHT:
return skin->getColor(EGDC_HIGH_LIGHT_TEXT);
case EGUI_LBC_ICON:
return skin->getColor(EGDC_ICON);
case EGUI_LBC_ICON_HIGHLIGHT:
return skin->getColor(EGDC_ICON_HIGH_LIGHT);
default:
return video::SColor();
}
}
//! set global itemHeight
void CGUIListBox::setItemHeight( s32 height )
void CGUIListBox::setItemHeight(s32 height)
{
ItemHeight = height;
ItemHeightOverride = 1;
}
//! Sets whether to draw the background
void CGUIListBox::setDrawBackground(bool draw)
{
DrawBack = draw;
DrawBack = draw;
}
//! Access the vertical scrollbar
IGUIScrollBar* CGUIListBox::getVerticalScrollBar() const
IGUIScrollBar *CGUIListBox::getVerticalScrollBar() const
{
return ScrollBar;
}

View File

@ -12,164 +12,162 @@ namespace irr
namespace gui
{
class IGUIFont;
class IGUIScrollBar;
class IGUIFont;
class IGUIScrollBar;
class CGUIListBox : public IGUIListBox
class CGUIListBox : public IGUIListBox
{
public:
//! constructor
CGUIListBox(IGUIEnvironment *environment, IGUIElement *parent,
s32 id, core::rect<s32> rectangle, bool clip = true,
bool drawBack = false, bool moveOverSelect = false);
//! destructor
virtual ~CGUIListBox();
//! returns amount of list items
u32 getItemCount() const override;
//! returns string of a list item. the id may be a value from 0 to itemCount-1
const wchar_t *getListItem(u32 id) const override;
//! adds an list item, returns id of item
u32 addItem(const wchar_t *text) override;
//! clears the list
void clear() override;
//! returns id of selected item. returns -1 if no item is selected.
s32 getSelected() const override;
//! sets the selected item. Set this to -1 if no item should be selected
void setSelected(s32 id) override;
//! sets the selected item. Set this to -1 if no item should be selected
void setSelected(const wchar_t *item) override;
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! draws the element and its children
void draw() override;
//! adds an list item with an icon
//! \param text Text of list entry
//! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon
//! \return
//! returns the id of the new created item
u32 addItem(const wchar_t *text, s32 icon) override;
//! Returns the icon of an item
s32 getIcon(u32 id) const override;
//! removes an item from the list
void removeItem(u32 id) override;
//! get the the id of the item at the given absolute coordinates
s32 getItemAt(s32 xpos, s32 ypos) const override;
//! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of
//! the built-in-font by default. A sprite can be displayed in front of every list item.
//! An icon is an index within the icon sprite bank. Several default icons are available in the
//! skin through getIcon
void setSpriteBank(IGUISpriteBank *bank) override;
//! set whether the listbox should scroll to newly selected items
void setAutoScrollEnabled(bool scroll) override;
//! returns true if automatic scrolling is enabled, false if not.
bool isAutoScrollEnabled() const override;
//! Update the position and size of the listbox, and update the scrollbar
void updateAbsolutePosition() override;
//! set all item colors at given index to color
void setItemOverrideColor(u32 index, video::SColor color) override;
//! set all item colors of specified type at given index to color
void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color) override;
//! clear all item colors at index
void clearItemOverrideColor(u32 index) override;
//! clear item color at index for given colortype
void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) override;
//! has the item at index its color overwritten?
bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const override;
//! return the overwrite color at given item index.
video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const override;
//! return the default color which is used for the given colorType
video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const override;
//! set the item at the given index
void setItem(u32 index, const wchar_t *text, s32 icon) override;
//! Insert the item at the given index
//! Return the index on success or -1 on failure.
s32 insertItem(u32 index, const wchar_t *text, s32 icon) override;
//! Swap the items at the given indices
void swapItems(u32 index1, u32 index2) override;
//! set global itemHeight
void setItemHeight(s32 height) override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Access the vertical scrollbar
IGUIScrollBar *getVerticalScrollBar() const override;
private:
struct ListItem
{
public:
//! constructor
CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool clip=true,
bool drawBack=false, bool moveOverSelect=false);
core::stringw Text;
s32 Icon = -1;
//! destructor
virtual ~CGUIListBox();
//! returns amount of list items
u32 getItemCount() const override;
//! returns string of a list item. the id may be a value from 0 to itemCount-1
const wchar_t* getListItem(u32 id) const override;
//! adds an list item, returns id of item
u32 addItem(const wchar_t* text) override;
//! clears the list
void clear() override;
//! returns id of selected item. returns -1 if no item is selected.
s32 getSelected() const override;
//! sets the selected item. Set this to -1 if no item should be selected
void setSelected(s32 id) override;
//! sets the selected item. Set this to -1 if no item should be selected
void setSelected(const wchar_t *item) override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! draws the element and its children
void draw() override;
//! adds an list item with an icon
//! \param text Text of list entry
//! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon
//! \return
//! returns the id of the new created item
u32 addItem(const wchar_t* text, s32 icon) override;
//! Returns the icon of an item
s32 getIcon(u32 id) const override;
//! removes an item from the list
void removeItem(u32 id) override;
//! get the the id of the item at the given absolute coordinates
s32 getItemAt(s32 xpos, s32 ypos) const override;
//! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of
//! the built-in-font by default. A sprite can be displayed in front of every list item.
//! An icon is an index within the icon sprite bank. Several default icons are available in the
//! skin through getIcon
void setSpriteBank(IGUISpriteBank* bank) override;
//! set whether the listbox should scroll to newly selected items
void setAutoScrollEnabled(bool scroll) override;
//! returns true if automatic scrolling is enabled, false if not.
bool isAutoScrollEnabled() const override;
//! Update the position and size of the listbox, and update the scrollbar
void updateAbsolutePosition() override;
//! set all item colors at given index to color
void setItemOverrideColor(u32 index, video::SColor color) override;
//! set all item colors of specified type at given index to color
void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color) override;
//! clear all item colors at index
void clearItemOverrideColor(u32 index) override;
//! clear item color at index for given colortype
void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) override;
//! has the item at index its color overwritten?
bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const override;
//! return the overwrite color at given item index.
video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const override;
//! return the default color which is used for the given colorType
video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const override;
//! set the item at the given index
void setItem(u32 index, const wchar_t* text, s32 icon) override;
//! Insert the item at the given index
//! Return the index on success or -1 on failure.
s32 insertItem(u32 index, const wchar_t* text, s32 icon) override;
//! Swap the items at the given indices
void swapItems(u32 index1, u32 index2) override;
//! set global itemHeight
void setItemHeight( s32 height ) override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Access the vertical scrollbar
IGUIScrollBar* getVerticalScrollBar() const override;
private:
struct ListItem
// A multicolor extension
struct ListItemOverrideColor
{
core::stringw Text;
s32 Icon = -1;
// A multicolor extension
struct ListItemOverrideColor
{
bool Use = false;
video::SColor Color;
};
ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT]{};
bool Use = false;
video::SColor Color;
};
void recalculateItemHeight();
void selectNew(s32 ypos, bool onlyHover=false);
void recalculateScrollPos();
void updateScrollBarSize(s32 size);
// extracted that function to avoid copy&paste code
void recalculateItemWidth(s32 icon);
// get labels used for serialization
bool getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const;
core::array< ListItem > Items;
s32 Selected;
s32 ItemHeight;
s32 ItemHeightOverride;
s32 TotalItemHeight;
s32 ItemsIconWidth;
gui::IGUIFont* Font;
gui::IGUISpriteBank* IconBank;
gui::IGUIScrollBar* ScrollBar;
u32 selectTime;
u32 LastKeyTime;
core::stringw KeyBuffer;
bool Selecting;
bool DrawBack;
bool MoveOverSelect;
bool AutoScroll;
bool HighlightWhenNotFocused;
ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT]{};
};
void recalculateItemHeight();
void selectNew(s32 ypos, bool onlyHover = false);
void recalculateScrollPos();
void updateScrollBarSize(s32 size);
// extracted that function to avoid copy&paste code
void recalculateItemWidth(s32 icon);
// get labels used for serialization
bool getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc &useColorLabel, core::stringc &colorLabel) const;
core::array<ListItem> Items;
s32 Selected;
s32 ItemHeight;
s32 ItemHeightOverride;
s32 TotalItemHeight;
s32 ItemsIconWidth;
gui::IGUIFont *Font;
gui::IGUISpriteBank *IconBank;
gui::IGUIScrollBar *ScrollBar;
u32 selectTime;
u32 LastKeyTime;
core::stringw KeyBuffer;
bool Selecting;
bool DrawBack;
bool MoveOverSelect;
bool AutoScroll;
bool HighlightWhenNotFocused;
};
} // end namespace gui
} // end namespace irr

View File

@ -17,20 +17,20 @@ namespace irr
namespace gui
{
//! constructor
CGUIScrollBar::CGUIScrollBar(bool horizontal, IGUIEnvironment* environment,
IGUIElement* parent, s32 id,
core::rect<s32> rectangle, bool noclip)
: IGUIScrollBar(environment, parent, id, rectangle), UpButton(0),
DownButton(0), Dragging(false), Horizontal(horizontal),
DraggedBySlider(false), TrayClick(false), Pos(0), DrawPos(0),
DrawHeight(0), Min(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0),
LastChange(0)
CGUIScrollBar::CGUIScrollBar(bool horizontal, IGUIEnvironment *environment,
IGUIElement *parent, s32 id,
core::rect<s32> rectangle, bool noclip) :
IGUIScrollBar(environment, parent, id, rectangle),
UpButton(0),
DownButton(0), Dragging(false), Horizontal(horizontal),
DraggedBySlider(false), TrayClick(false), Pos(0), DrawPos(0),
DrawHeight(0), Min(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0),
LastChange(0)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUIScrollBar");
#endif
#endif
refreshControls();
@ -43,7 +43,6 @@ CGUIScrollBar::CGUIScrollBar(bool horizontal, IGUIEnvironment* environment,
setPos(0);
}
//! destructor
CGUIScrollBar::~CGUIScrollBar()
{
@ -54,48 +53,42 @@ CGUIScrollBar::~CGUIScrollBar()
DownButton->drop();
}
//! called if an event happened.
bool CGUIScrollBar::OnEvent(const SEvent& event)
bool CGUIScrollBar::OnEvent(const SEvent &event)
{
if (isEnabled())
{
if (isEnabled()) {
switch(event.EventType)
{
switch (event.EventType) {
case EET_KEY_INPUT_EVENT:
if (event.KeyInput.PressedDown)
{
if (event.KeyInput.PressedDown) {
const s32 oldPos = Pos;
bool absorb = true;
switch (event.KeyInput.Key)
{
switch (event.KeyInput.Key) {
case KEY_LEFT:
case KEY_UP:
setPos(Pos-SmallStep);
setPos(Pos - SmallStep);
break;
case KEY_RIGHT:
case KEY_DOWN:
setPos(Pos+SmallStep);
setPos(Pos + SmallStep);
break;
case KEY_HOME:
setPos(Min);
break;
case KEY_PRIOR:
setPos(Pos-LargeStep);
setPos(Pos - LargeStep);
break;
case KEY_END:
setPos(Max);
break;
case KEY_NEXT:
setPos(Pos+LargeStep);
setPos(Pos + LargeStep);
break;
default:
absorb = false;
}
if (Pos != oldPos)
{
if (Pos != oldPos) {
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
newEvent.GUIEvent.Caller = this;
@ -108,13 +101,11 @@ bool CGUIScrollBar::OnEvent(const SEvent& event)
}
break;
case EET_GUI_EVENT:
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
{
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) {
if (event.GUIEvent.Caller == UpButton)
setPos(Pos-SmallStep);
else
if (event.GUIEvent.Caller == DownButton)
setPos(Pos+SmallStep);
setPos(Pos - SmallStep);
else if (event.GUIEvent.Caller == DownButton)
setPos(Pos + SmallStep);
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
@ -124,29 +115,22 @@ bool CGUIScrollBar::OnEvent(const SEvent& event)
Parent->OnEvent(newEvent);
return true;
}
else
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
{
} else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) {
if (event.GUIEvent.Caller == this)
Dragging = false;
}
break;
case EET_MOUSE_INPUT_EVENT:
{
case EET_MOUSE_INPUT_EVENT: {
const core::position2di p(event.MouseInput.X, event.MouseInput.Y);
bool isInside = isPointInside ( p );
switch(event.MouseInput.Event)
{
bool isInside = isPointInside(p);
switch (event.MouseInput.Event) {
case EMIE_MOUSE_WHEEL:
if (Environment->hasFocus(this))
{
if (Environment->hasFocus(this)) {
// thanks to a bug report by REAPER
// thanks to tommi by tommi for another bugfix
// everybody needs a little thanking. hallo niko!;-)
setPos( getPos() +
( (event.MouseInput.Wheel < 0 ? -1 : 1) * SmallStep * (Horizontal ? 1 : -1 ) )
);
setPos(getPos() +
((event.MouseInput.Wheel < 0 ? -1 : 1) * SmallStep * (Horizontal ? 1 : -1)));
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
@ -157,10 +141,8 @@ bool CGUIScrollBar::OnEvent(const SEvent& event)
return true;
}
break;
case EMIE_LMOUSE_PRESSED_DOWN:
{
if (isInside)
{
case EMIE_LMOUSE_PRESSED_DOWN: {
if (isInside) {
Dragging = true;
DraggedBySlider = SliderRect.isPointInside(p);
TrayClick = !DraggedBySlider;
@ -170,55 +152,44 @@ bool CGUIScrollBar::OnEvent(const SEvent& event)
break;
}
case EMIE_LMOUSE_LEFT_UP:
case EMIE_MOUSE_MOVED:
{
if ( !event.MouseInput.isLeftPressed () )
case EMIE_MOUSE_MOVED: {
if (!event.MouseInput.isLeftPressed())
Dragging = false;
if ( !Dragging )
{
if ( event.MouseInput.Event == EMIE_MOUSE_MOVED )
if (!Dragging) {
if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
break;
return isInside;
}
if ( event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP )
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
Dragging = false;
const s32 newPos = getPosFromMousePos(p);
const s32 oldPos = Pos;
if (!DraggedBySlider)
{
if ( isInside )
{
if (!DraggedBySlider) {
if (isInside) {
DraggedBySlider = SliderRect.isPointInside(p);
TrayClick = !DraggedBySlider;
}
if (DraggedBySlider)
{
if (DraggedBySlider) {
setPos(newPos);
}
else
{
} else {
TrayClick = false;
if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
return isInside;
}
}
if (DraggedBySlider)
{
if (DraggedBySlider) {
setPos(newPos);
}
else
{
} else {
DesiredPos = newPos;
}
if (Pos != oldPos && Parent)
{
if (Pos != oldPos && Parent) {
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
newEvent.GUIEvent.Caller = this;
@ -243,23 +214,19 @@ bool CGUIScrollBar::OnEvent(const SEvent& event)
void CGUIScrollBar::OnPostRender(u32 timeMs)
{
if (Dragging && !DraggedBySlider && TrayClick && timeMs > LastChange + 200)
{
if (Dragging && !DraggedBySlider && TrayClick && timeMs > LastChange + 200) {
LastChange = timeMs;
const s32 oldPos = Pos;
if (DesiredPos >= Pos + LargeStep)
setPos(Pos + LargeStep);
else
if (DesiredPos <= Pos - LargeStep)
else if (DesiredPos <= Pos - LargeStep)
setPos(Pos - LargeStep);
else
if (DesiredPos >= Pos - LargeStep && DesiredPos <= Pos + LargeStep)
else if (DesiredPos >= Pos - LargeStep && DesiredPos <= Pos + LargeStep)
setPos(DesiredPos);
if (Pos != oldPos && Parent)
{
if (Pos != oldPos && Parent) {
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
newEvent.GUIEvent.Caller = this;
@ -268,7 +235,6 @@ void CGUIScrollBar::OnPostRender(u32 timeMs)
Parent->OnEvent(newEvent);
}
}
}
//! draws the element and its children
@ -277,34 +243,27 @@ void CGUIScrollBar::draw()
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (!skin)
return;
video::SColor iconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
if ( iconColor != CurrentIconColor )
{
if (iconColor != CurrentIconColor) {
refreshControls();
}
SliderRect = AbsoluteRect;
// draws the background
skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), SliderRect, &AbsoluteClippingRect);
if ( core::isnotzero ( range() ) )
{
if (core::isnotzero(range())) {
// recalculate slider rectangle
if (Horizontal)
{
SliderRect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X + DrawPos + RelativeRect.getHeight() - DrawHeight/2;
if (Horizontal) {
SliderRect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X + DrawPos + RelativeRect.getHeight() - DrawHeight / 2;
SliderRect.LowerRightCorner.X = SliderRect.UpperLeftCorner.X + DrawHeight;
}
else
{
SliderRect.UpperLeftCorner.Y = AbsoluteRect.UpperLeftCorner.Y + DrawPos + RelativeRect.getWidth() - DrawHeight/2;
} else {
SliderRect.UpperLeftCorner.Y = AbsoluteRect.UpperLeftCorner.Y + DrawPos + RelativeRect.getWidth() - DrawHeight / 2;
SliderRect.LowerRightCorner.Y = SliderRect.UpperLeftCorner.Y + DrawHeight;
}
@ -315,64 +274,53 @@ void CGUIScrollBar::draw()
IGUIElement::draw();
}
void CGUIScrollBar::updateAbsolutePosition()
{
IGUIElement::updateAbsolutePosition();
// todo: properly resize
refreshControls();
setPos ( Pos );
setPos(Pos);
}
//!
s32 CGUIScrollBar::getPosFromMousePos(const core::position2di &pos) const
{
f32 w, p;
if (Horizontal)
{
w = RelativeRect.getWidth() - f32(RelativeRect.getHeight())*3.0f;
p = pos.X - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight()*1.5f;
if (Horizontal) {
w = RelativeRect.getWidth() - f32(RelativeRect.getHeight()) * 3.0f;
p = pos.X - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight() * 1.5f;
} else {
w = RelativeRect.getHeight() - f32(RelativeRect.getWidth()) * 3.0f;
p = pos.Y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth() * 1.5f;
}
else
{
w = RelativeRect.getHeight() - f32(RelativeRect.getWidth())*3.0f;
p = pos.Y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth()*1.5f;
}
return (s32) ( p/w * range() ) + Min;
return (s32)(p / w * range()) + Min;
}
//! sets the position of the scrollbar
void CGUIScrollBar::setPos(s32 pos)
{
Pos = core::s32_clamp ( pos, Min, Max );
Pos = core::s32_clamp(pos, Min, Max);
if ( core::isnotzero ( range() ) )
{
if (Horizontal)
{
f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / range();
DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getHeight() * 0.5f));
if (core::isnotzero(range())) {
if (Horizontal) {
f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight() * 3.0f)) / range();
DrawPos = (s32)(((Pos - Min) * f) + ((f32)RelativeRect.getHeight() * 0.5f));
DrawHeight = RelativeRect.getHeight();
}
else
{
f32 f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / range();
} else {
f32 f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth() * 3.0f)) / range();
DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getWidth() * 0.5f));
DrawPos = (s32)(((Pos - Min) * f) + ((f32)RelativeRect.getWidth() * 0.5f));
DrawHeight = RelativeRect.getWidth();
}
}
}
//! gets the small step value
s32 CGUIScrollBar::getSmallStep() const
{
return SmallStep;
}
//! sets the small step value
void CGUIScrollBar::setSmallStep(s32 step)
{
@ -382,14 +330,12 @@ void CGUIScrollBar::setSmallStep(s32 step)
SmallStep = 10;
}
//! gets the small step value
s32 CGUIScrollBar::getLargeStep() const
{
return LargeStep;
}
//! sets the small step value
void CGUIScrollBar::setLargeStep(s32 step)
{
@ -399,22 +345,20 @@ void CGUIScrollBar::setLargeStep(s32 step)
LargeStep = 50;
}
//! gets the maximum value of the scrollbar.
s32 CGUIScrollBar::getMax() const
{
return Max;
}
//! sets the maximum value of the scrollbar.
void CGUIScrollBar::setMax(s32 max)
{
Max = max;
if ( Min > Max )
if (Min > Max)
Min = Max;
bool enable = core::isnotzero ( range() );
bool enable = core::isnotzero(range());
UpButton->setEnabled(enable);
DownButton->setEnabled(enable);
setPos(Pos);
@ -426,107 +370,91 @@ s32 CGUIScrollBar::getMin() const
return Min;
}
//! sets the minimum value of the scrollbar.
void CGUIScrollBar::setMin(s32 min)
{
Min = min;
if ( Max < Min )
if (Max < Min)
Max = Min;
bool enable = core::isnotzero ( range() );
bool enable = core::isnotzero(range());
UpButton->setEnabled(enable);
DownButton->setEnabled(enable);
setPos(Pos);
}
//! gets the current position of the scrollbar
s32 CGUIScrollBar::getPos() const
{
return Pos;
}
//! refreshes the position and text on child buttons
void CGUIScrollBar::refreshControls()
{
CurrentIconColor = video::SColor(255,255,255,255);
CurrentIconColor = video::SColor(255, 255, 255, 255);
IGUISkin* skin = Environment->getSkin();
IGUISpriteBank* sprites = 0;
IGUISkin *skin = Environment->getSkin();
IGUISpriteBank *sprites = 0;
if (skin)
{
if (skin) {
sprites = skin->getSpriteBank();
CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
}
if (Horizontal)
{
if (Horizontal) {
const s32 h = RelativeRect.getHeight();
const s32 w = (h < RelativeRect.getWidth() / 2) ? h : RelativeRect.getWidth() / 2;
if (!UpButton)
{
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, w, h), NoClip);
if (!UpButton) {
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0, 0, w, h), NoClip);
UpButton->setSubElement(true);
UpButton->setTabStop(false);
}
if (sprites)
{
if (sprites) {
UpButton->setSpriteBank(sprites);
UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor);
UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor);
}
UpButton->setRelativePosition(core::rect<s32>(0,0, w, h));
UpButton->setRelativePosition(core::rect<s32>(0, 0, w, h));
UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
if (!DownButton)
{
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(RelativeRect.getWidth()-w, 0, RelativeRect.getWidth(), h), NoClip);
if (!DownButton) {
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(RelativeRect.getWidth() - w, 0, RelativeRect.getWidth(), h), NoClip);
DownButton->setSubElement(true);
DownButton->setTabStop(false);
}
if (sprites)
{
if (sprites) {
DownButton->setSpriteBank(sprites);
DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor);
DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor);
}
DownButton->setRelativePosition(core::rect<s32>(RelativeRect.getWidth()-w, 0, RelativeRect.getWidth(), h));
DownButton->setRelativePosition(core::rect<s32>(RelativeRect.getWidth() - w, 0, RelativeRect.getWidth(), h));
DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
}
else
{
} else {
const s32 w = RelativeRect.getWidth();
const s32 h = (w < RelativeRect.getHeight() / 2) ? w : RelativeRect.getHeight() / 2;
if (!UpButton)
{
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, w, h), NoClip);
if (!UpButton) {
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0, 0, w, h), NoClip);
UpButton->setSubElement(true);
UpButton->setTabStop(false);
}
if (sprites)
{
if (sprites) {
UpButton->setSpriteBank(sprites);
UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor);
UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor);
}
UpButton->setRelativePosition(core::rect<s32>(0,0, w, h));
UpButton->setRelativePosition(core::rect<s32>(0, 0, w, h));
UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
if (!DownButton)
{
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,RelativeRect.getHeight()-h, w, RelativeRect.getHeight()), NoClip);
if (!DownButton) {
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0, RelativeRect.getHeight() - h, w, RelativeRect.getHeight()), NoClip);
DownButton->setSubElement(true);
DownButton->setTabStop(false);
}
if (sprites)
{
if (sprites) {
DownButton->setSpriteBank(sprites);
DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor);
DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor);
}
DownButton->setRelativePosition(core::rect<s32>(0,RelativeRect.getHeight()-h, w, RelativeRect.getHeight()));
DownButton->setRelativePosition(core::rect<s32>(0, RelativeRect.getHeight() - h, w, RelativeRect.getHeight()));
DownButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
}
}

View File

@ -12,87 +12,84 @@ namespace irr
namespace gui
{
class CGUIScrollBar : public IGUIScrollBar
{
public:
class CGUIScrollBar : public IGUIScrollBar
{
public:
//! constructor
CGUIScrollBar(bool horizontal, IGUIEnvironment *environment,
IGUIElement *parent, s32 id, core::rect<s32> rectangle,
bool noclip = false);
//! constructor
CGUIScrollBar(bool horizontal, IGUIEnvironment* environment,
IGUIElement* parent, s32 id, core::rect<s32> rectangle,
bool noclip=false);
//! destructor
virtual ~CGUIScrollBar();
//! destructor
virtual ~CGUIScrollBar();
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! draws the element and its children
void draw() override;
//! draws the element and its children
void draw() override;
void OnPostRender(u32 timeMs) override;
void OnPostRender(u32 timeMs) override;
//! gets the maximum value of the scrollbar.
s32 getMax() const override;
//! sets the maximum value of the scrollbar.
void setMax(s32 max) override;
//! gets the maximum value of the scrollbar.
s32 getMax() const override;
//! gets the minimum value of the scrollbar.
s32 getMin() const override;
//! sets the maximum value of the scrollbar.
void setMax(s32 max) override;
//! sets the minimum value of the scrollbar.
void setMin(s32 min) override;
//! gets the minimum value of the scrollbar.
s32 getMin() const override;
//! gets the small step value
s32 getSmallStep() const override;
//! sets the minimum value of the scrollbar.
void setMin(s32 min) override;
//! sets the small step value
void setSmallStep(s32 step) override;
//! gets the small step value
s32 getSmallStep() const override;
//! gets the large step value
s32 getLargeStep() const override;
//! sets the small step value
void setSmallStep(s32 step) override;
//! sets the large step value
void setLargeStep(s32 step) override;
//! gets the large step value
s32 getLargeStep() const override;
//! gets the current position of the scrollbar
s32 getPos() const override;
//! sets the large step value
void setLargeStep(s32 step) override;
//! sets the position of the scrollbar
void setPos(s32 pos) override;
//! gets the current position of the scrollbar
s32 getPos() const override;
//! updates the rectangle
void updateAbsolutePosition() override;
//! sets the position of the scrollbar
void setPos(s32 pos) override;
private:
void refreshControls();
s32 getPosFromMousePos(const core::position2di &p) const;
//! updates the rectangle
void updateAbsolutePosition() override;
IGUIButton *UpButton;
IGUIButton *DownButton;
private:
core::rect<s32> SliderRect;
void refreshControls();
s32 getPosFromMousePos(const core::position2di &p) const;
bool Dragging;
bool Horizontal;
bool DraggedBySlider;
bool TrayClick;
s32 Pos;
s32 DrawPos;
s32 DrawHeight;
s32 Min;
s32 Max;
s32 SmallStep;
s32 LargeStep;
s32 DesiredPos;
u32 LastChange;
video::SColor CurrentIconColor;
IGUIButton* UpButton;
IGUIButton* DownButton;
core::rect<s32> SliderRect;
bool Dragging;
bool Horizontal;
bool DraggedBySlider;
bool TrayClick;
s32 Pos;
s32 DrawPos;
s32 DrawHeight;
s32 Min;
s32 Max;
s32 SmallStep;
s32 LargeStep;
s32 DesiredPos;
u32 LastChange;
video::SColor CurrentIconColor;
f32 range () const { return (f32) ( Max - Min ); }
};
f32 range() const { return (f32)(Max - Min); }
};
} // end namespace gui
} // end namespace irr

View File

@ -15,41 +15,39 @@ namespace irr
namespace gui
{
CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver)
: SpriteBank(0), Driver(driver), Type(type)
CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver *driver) :
SpriteBank(0), Driver(driver), Type(type)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUISkin");
#endif
if ((Type == EGST_WINDOWS_CLASSIC) || (Type == EGST_WINDOWS_METALLIC))
{
Colors[EGDC_3D_DARK_SHADOW] = video::SColor(101,50,50,50);
Colors[EGDC_3D_SHADOW] = video::SColor(101,130,130,130);
Colors[EGDC_3D_FACE] = video::SColor(101,210,210,210);
Colors[EGDC_3D_HIGH_LIGHT] = video::SColor(101,255,255,255);
Colors[EGDC_3D_LIGHT] = video::SColor(101,210,210,210);
Colors[EGDC_ACTIVE_BORDER] = video::SColor(101,16,14,115);
Colors[EGDC_ACTIVE_CAPTION] = video::SColor(255,255,255,255);
Colors[EGDC_APP_WORKSPACE] = video::SColor(101,100,100,100);
Colors[EGDC_BUTTON_TEXT] = video::SColor(240,10,10,10);
Colors[EGDC_GRAY_TEXT] = video::SColor(240,130,130,130);
Colors[EGDC_HIGH_LIGHT] = video::SColor(101,8,36,107);
Colors[EGDC_HIGH_LIGHT_TEXT] = video::SColor(240,255,255,255);
Colors[EGDC_INACTIVE_BORDER] = video::SColor(101,165,165,165);
Colors[EGDC_INACTIVE_CAPTION] = video::SColor(255,30,30,30);
Colors[EGDC_TOOLTIP] = video::SColor(200,0,0,0);
Colors[EGDC_TOOLTIP_BACKGROUND] = video::SColor(200,255,255,225);
Colors[EGDC_SCROLLBAR] = video::SColor(101,230,230,230);
Colors[EGDC_WINDOW] = video::SColor(101,255,255,255);
Colors[EGDC_WINDOW_SYMBOL] = video::SColor(200,10,10,10);
Colors[EGDC_ICON] = video::SColor(200,255,255,255);
Colors[EGDC_ICON_HIGH_LIGHT] = video::SColor(200,8,36,107);
Colors[EGDC_GRAY_WINDOW_SYMBOL] = video::SColor(240,100,100,100);
Colors[EGDC_EDITABLE] = video::SColor(255,255,255,255);
Colors[EGDC_GRAY_EDITABLE] = video::SColor(255,120,120,120);
Colors[EGDC_FOCUSED_EDITABLE] = video::SColor(255,240,240,255);
#endif
if ((Type == EGST_WINDOWS_CLASSIC) || (Type == EGST_WINDOWS_METALLIC)) {
Colors[EGDC_3D_DARK_SHADOW] = video::SColor(101, 50, 50, 50);
Colors[EGDC_3D_SHADOW] = video::SColor(101, 130, 130, 130);
Colors[EGDC_3D_FACE] = video::SColor(101, 210, 210, 210);
Colors[EGDC_3D_HIGH_LIGHT] = video::SColor(101, 255, 255, 255);
Colors[EGDC_3D_LIGHT] = video::SColor(101, 210, 210, 210);
Colors[EGDC_ACTIVE_BORDER] = video::SColor(101, 16, 14, 115);
Colors[EGDC_ACTIVE_CAPTION] = video::SColor(255, 255, 255, 255);
Colors[EGDC_APP_WORKSPACE] = video::SColor(101, 100, 100, 100);
Colors[EGDC_BUTTON_TEXT] = video::SColor(240, 10, 10, 10);
Colors[EGDC_GRAY_TEXT] = video::SColor(240, 130, 130, 130);
Colors[EGDC_HIGH_LIGHT] = video::SColor(101, 8, 36, 107);
Colors[EGDC_HIGH_LIGHT_TEXT] = video::SColor(240, 255, 255, 255);
Colors[EGDC_INACTIVE_BORDER] = video::SColor(101, 165, 165, 165);
Colors[EGDC_INACTIVE_CAPTION] = video::SColor(255, 30, 30, 30);
Colors[EGDC_TOOLTIP] = video::SColor(200, 0, 0, 0);
Colors[EGDC_TOOLTIP_BACKGROUND] = video::SColor(200, 255, 255, 225);
Colors[EGDC_SCROLLBAR] = video::SColor(101, 230, 230, 230);
Colors[EGDC_WINDOW] = video::SColor(101, 255, 255, 255);
Colors[EGDC_WINDOW_SYMBOL] = video::SColor(200, 10, 10, 10);
Colors[EGDC_ICON] = video::SColor(200, 255, 255, 255);
Colors[EGDC_ICON_HIGH_LIGHT] = video::SColor(200, 8, 36, 107);
Colors[EGDC_GRAY_WINDOW_SYMBOL] = video::SColor(240, 100, 100, 100);
Colors[EGDC_EDITABLE] = video::SColor(255, 255, 255, 255);
Colors[EGDC_GRAY_EDITABLE] = video::SColor(255, 120, 120, 120);
Colors[EGDC_FOCUSED_EDITABLE] = video::SColor(255, 240, 240, 255);
Sizes[EGDS_SCROLLBAR_SIZE] = 14;
Sizes[EGDS_MENU_HEIGHT] = 30;
@ -65,36 +63,34 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver)
Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 2;
Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 0;
}
else
{
//0x80a6a8af
Colors[EGDC_3D_DARK_SHADOW] = 0x60767982;
//Colors[EGDC_3D_FACE] = 0xc0c9ccd4; // tab background
Colors[EGDC_3D_FACE] = 0xc0cbd2d9; // tab background
Colors[EGDC_3D_SHADOW] = 0x50e4e8f1; // tab background, and left-top highlight
Colors[EGDC_3D_HIGH_LIGHT] = 0x40c7ccdc;
Colors[EGDC_3D_LIGHT] = 0x802e313a;
Colors[EGDC_ACTIVE_BORDER] = 0x80404040; // window title
Colors[EGDC_ACTIVE_CAPTION] = 0xffd0d0d0;
Colors[EGDC_APP_WORKSPACE] = 0xc0646464; // unused
Colors[EGDC_BUTTON_TEXT] = 0xd0161616;
Colors[EGDC_GRAY_TEXT] = 0x3c141414;
Colors[EGDC_HIGH_LIGHT] = 0x6c606060;
Colors[EGDC_HIGH_LIGHT_TEXT] = 0xd0e0e0e0;
Colors[EGDC_INACTIVE_BORDER] = 0xf0a5a5a5;
Colors[EGDC_INACTIVE_CAPTION] = 0xffd2d2d2;
Colors[EGDC_TOOLTIP] = 0xf00f2033;
Colors[EGDC_TOOLTIP_BACKGROUND] = 0xc0cbd2d9;
Colors[EGDC_SCROLLBAR] = 0xf0e0e0e0;
Colors[EGDC_WINDOW] = 0xf0f0f0f0;
Colors[EGDC_WINDOW_SYMBOL] = 0xd0161616;
Colors[EGDC_ICON] = 0xd0161616;
Colors[EGDC_ICON_HIGH_LIGHT] = 0xd0606060;
Colors[EGDC_GRAY_WINDOW_SYMBOL] = 0x3c101010;
Colors[EGDC_EDITABLE] = 0xf0ffffff;
Colors[EGDC_GRAY_EDITABLE] = 0xf0cccccc;
Colors[EGDC_FOCUSED_EDITABLE] = 0xf0fffff0;
} else {
// 0x80a6a8af
Colors[EGDC_3D_DARK_SHADOW] = 0x60767982;
// Colors[EGDC_3D_FACE] = 0xc0c9ccd4; // tab background
Colors[EGDC_3D_FACE] = 0xc0cbd2d9; // tab background
Colors[EGDC_3D_SHADOW] = 0x50e4e8f1; // tab background, and left-top highlight
Colors[EGDC_3D_HIGH_LIGHT] = 0x40c7ccdc;
Colors[EGDC_3D_LIGHT] = 0x802e313a;
Colors[EGDC_ACTIVE_BORDER] = 0x80404040; // window title
Colors[EGDC_ACTIVE_CAPTION] = 0xffd0d0d0;
Colors[EGDC_APP_WORKSPACE] = 0xc0646464; // unused
Colors[EGDC_BUTTON_TEXT] = 0xd0161616;
Colors[EGDC_GRAY_TEXT] = 0x3c141414;
Colors[EGDC_HIGH_LIGHT] = 0x6c606060;
Colors[EGDC_HIGH_LIGHT_TEXT] = 0xd0e0e0e0;
Colors[EGDC_INACTIVE_BORDER] = 0xf0a5a5a5;
Colors[EGDC_INACTIVE_CAPTION] = 0xffd2d2d2;
Colors[EGDC_TOOLTIP] = 0xf00f2033;
Colors[EGDC_TOOLTIP_BACKGROUND] = 0xc0cbd2d9;
Colors[EGDC_SCROLLBAR] = 0xf0e0e0e0;
Colors[EGDC_WINDOW] = 0xf0f0f0f0;
Colors[EGDC_WINDOW_SYMBOL] = 0xd0161616;
Colors[EGDC_ICON] = 0xd0161616;
Colors[EGDC_ICON_HIGH_LIGHT] = 0xd0606060;
Colors[EGDC_GRAY_WINDOW_SYMBOL] = 0x3c101010;
Colors[EGDC_EDITABLE] = 0xf0ffffff;
Colors[EGDC_GRAY_EDITABLE] = 0xf0cccccc;
Colors[EGDC_FOCUSED_EDITABLE] = 0xf0fffff0;
Sizes[EGDS_SCROLLBAR_SIZE] = 14;
Sizes[EGDS_MENU_HEIGHT] = 48;
@ -159,18 +155,16 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver)
Icons[EGDI_FILE] = 245;
Icons[EGDI_DIRECTORY] = 246;
for (u32 i=0; i<EGDF_COUNT; ++i)
for (u32 i = 0; i < EGDF_COUNT; ++i)
Fonts[i] = 0;
UseGradient = (Type == EGST_WINDOWS_METALLIC) || (Type == EGST_BURNING_SKIN) ;
UseGradient = (Type == EGST_WINDOWS_METALLIC) || (Type == EGST_BURNING_SKIN);
}
//! destructor
CGUISkin::~CGUISkin()
{
for (u32 i=0; i<EGDF_COUNT; ++i)
{
for (u32 i = 0; i < EGDF_COUNT; ++i) {
if (Fonts[i])
Fonts[i]->drop();
}
@ -179,7 +173,6 @@ CGUISkin::~CGUISkin()
SpriteBank->drop();
}
//! returns default color
video::SColor CGUISkin::getColor(EGUI_DEFAULT_COLOR color) const
{
@ -189,7 +182,6 @@ video::SColor CGUISkin::getColor(EGUI_DEFAULT_COLOR color) const
return video::SColor();
}
//! sets a default color
void CGUISkin::setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor)
{
@ -197,7 +189,6 @@ void CGUISkin::setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor)
Colors[which] = newColor;
}
//! returns size for the given size type
s32 CGUISkin::getSize(EGUI_DEFAULT_SIZE size) const
{
@ -207,7 +198,6 @@ s32 CGUISkin::getSize(EGUI_DEFAULT_SIZE size) const
return 0;
}
//! sets a default size
void CGUISkin::setSize(EGUI_DEFAULT_SIZE which, s32 size)
{
@ -215,9 +205,8 @@ void CGUISkin::setSize(EGUI_DEFAULT_SIZE which, s32 size)
Sizes[which] = size;
}
//! returns the default font
IGUIFont* CGUISkin::getFont(EGUI_DEFAULT_FONT which) const
IGUIFont *CGUISkin::getFont(EGUI_DEFAULT_FONT which) const
{
if (((u32)which < EGDF_COUNT) && Fonts[which])
return Fonts[which];
@ -225,15 +214,13 @@ IGUIFont* CGUISkin::getFont(EGUI_DEFAULT_FONT which) const
return Fonts[EGDF_DEFAULT];
}
//! sets a default font
void CGUISkin::setFont(IGUIFont* font, EGUI_DEFAULT_FONT which)
void CGUISkin::setFont(IGUIFont *font, EGUI_DEFAULT_FONT which)
{
if ((u32)which >= EGDF_COUNT)
return;
if (font)
{
if (font) {
font->grab();
if (Fonts[which])
Fonts[which]->drop();
@ -242,16 +229,14 @@ void CGUISkin::setFont(IGUIFont* font, EGUI_DEFAULT_FONT which)
}
}
//! gets the sprite bank stored
IGUISpriteBank* CGUISkin::getSpriteBank() const
IGUISpriteBank *CGUISkin::getSpriteBank() const
{
return SpriteBank;
}
//! set a new sprite bank or remove one by passing 0
void CGUISkin::setSpriteBank(IGUISpriteBank* bank)
void CGUISkin::setSpriteBank(IGUISpriteBank *bank)
{
if (bank)
bank->grab();
@ -262,7 +247,6 @@ void CGUISkin::setSpriteBank(IGUISpriteBank* bank)
SpriteBank = bank;
}
//! Returns a default icon
u32 CGUISkin::getIcon(EGUI_DEFAULT_ICON icon) const
{
@ -272,7 +256,6 @@ u32 CGUISkin::getIcon(EGUI_DEFAULT_ICON icon) const
return 0;
}
//! Sets a default icon
void CGUISkin::setIcon(EGUI_DEFAULT_ICON icon, u32 index)
{
@ -280,10 +263,9 @@ void CGUISkin::setIcon(EGUI_DEFAULT_ICON icon, u32 index)
Icons[icon] = index;
}
//! Returns a default text. For example for Message box button captions:
//! "OK", "Cancel", "Yes", "No" and so on.
const wchar_t* CGUISkin::getDefaultText(EGUI_DEFAULT_TEXT text) const
const wchar_t *CGUISkin::getDefaultText(EGUI_DEFAULT_TEXT text) const
{
if ((u32)text < EGDT_COUNT)
return Texts[text].c_str();
@ -291,16 +273,14 @@ const wchar_t* CGUISkin::getDefaultText(EGUI_DEFAULT_TEXT text) const
return Texts[0].c_str();
}
//! Sets a default text. For example for Message box button captions:
//! "OK", "Cancel", "Yes", "No" and so on.
void CGUISkin::setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText)
void CGUISkin::setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t *newText)
{
if ((u32)which < EGDT_COUNT)
Texts[which] = newText;
}
//! draws a standard 3d button pane
/** Used for drawing for example buttons in normal state.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
@ -310,24 +290,22 @@ EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly. */
void CGUISkin::draw3DButtonPaneStandard(IGUIElement* element,
const core::rect<s32>& r,
const core::rect<s32>* clip)
void CGUISkin::draw3DButtonPaneStandard(IGUIElement *element,
const core::rect<s32> &r,
const core::rect<s32> *clip)
{
if (!Driver)
return;
core::rect<s32> rect = r;
if ( Type == EGST_BURNING_SKIN )
{
if (Type == EGST_BURNING_SKIN) {
rect.UpperLeftCorner.X -= 1;
rect.UpperLeftCorner.Y -= 1;
rect.LowerRightCorner.X += 1;
rect.LowerRightCorner.Y += 1;
draw3DSunkenPane(element,
getColor( EGDC_WINDOW ).getInterpolated( 0xFFFFFFFF, 0.9f )
,false, true, rect, clip);
getColor(EGDC_WINDOW).getInterpolated(0xFFFFFFFF, 0.9f), false, true, rect, clip);
return;
}
@ -344,19 +322,15 @@ void CGUISkin::draw3DButtonPaneStandard(IGUIElement* element,
rect.LowerRightCorner.X -= 1;
rect.LowerRightCorner.Y -= 1;
if (!UseGradient)
{
if (!UseGradient) {
Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip);
}
else
{
} else {
const video::SColor c1 = getColor(EGDC_3D_FACE);
const video::SColor c2 = c1.getInterpolated(getColor(EGDC_3D_DARK_SHADOW), 0.4f);
Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
}
}
//! draws a pressed 3d button pane
/** Used for drawing for example buttons in pressed state.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
@ -366,9 +340,9 @@ EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly. */
void CGUISkin::draw3DButtonPanePressed(IGUIElement* element,
const core::rect<s32>& r,
const core::rect<s32>* clip)
void CGUISkin::draw3DButtonPanePressed(IGUIElement *element,
const core::rect<s32> &r,
const core::rect<s32> *clip)
{
if (!Driver)
return;
@ -387,19 +361,15 @@ void CGUISkin::draw3DButtonPanePressed(IGUIElement* element,
rect.UpperLeftCorner.X += 1;
rect.UpperLeftCorner.Y += 1;
if (!UseGradient)
{
if (!UseGradient) {
Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip);
}
else
{
} else {
const video::SColor c1 = getColor(EGDC_3D_FACE);
const video::SColor c2 = c1.getInterpolated(getColor(EGDC_3D_DARK_SHADOW), 0.4f);
Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
}
}
//! draws a sunken 3d pane
/** Used for drawing the background of edit, combo or check boxes.
\param element: Pointer to the element which wishes to draw this. This parameter
@ -410,10 +380,10 @@ implementations to find out how to draw the part exactly.
deep into the ground.
\param rect: Defining area where to draw.
\param clip: Clip area. */
void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
bool flat, bool fillBackGround,
const core::rect<s32>& r,
const core::rect<s32>* clip)
void CGUISkin::draw3DSunkenPane(IGUIElement *element, video::SColor bgcolor,
bool flat, bool fillBackGround,
const core::rect<s32> &r,
const core::rect<s32> *clip)
{
if (!Driver)
return;
@ -423,34 +393,31 @@ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
if (fillBackGround)
Driver->draw2DRectangle(bgcolor, rect, clip);
if (flat)
{
if (flat) {
// draw flat sunken pane
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top
++rect.UpperLeftCorner.Y;
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left
rect = r;
++rect.UpperLeftCorner.Y;
rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right
rect = r;
++rect.UpperLeftCorner.X;
rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
--rect.LowerRightCorner.X;
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom
}
else
{
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom
} else {
// draw deep sunken pane
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top
++rect.UpperLeftCorner.X;
++rect.UpperLeftCorner.Y;
--rect.LowerRightCorner.X;
@ -458,10 +425,10 @@ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip);
rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y+1;
rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y + 1;
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left
++rect.UpperLeftCorner.X;
++rect.UpperLeftCorner.Y;
++rect.LowerRightCorner.X;
@ -471,7 +438,7 @@ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
rect = r;
rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
++rect.UpperLeftCorner.Y;
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right
--rect.UpperLeftCorner.X;
++rect.UpperLeftCorner.Y;
--rect.LowerRightCorner.X;
@ -482,7 +449,7 @@ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
++rect.UpperLeftCorner.X;
rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
--rect.LowerRightCorner.X;
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom
++rect.UpperLeftCorner.X;
--rect.UpperLeftCorner.Y;
--rect.LowerRightCorner.X;
@ -491,19 +458,16 @@ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
}
}
//! draws a window background
// return where to draw title bar text.
core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32>& r,
const core::rect<s32>* clip,
core::rect<s32>* checkClientArea)
core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement *element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32> &r,
const core::rect<s32> *clip,
core::rect<s32> *checkClientArea)
{
if (!Driver)
{
if ( checkClientArea )
{
if (!Driver) {
if (checkClientArea) {
*checkClientArea = r;
}
return r;
@ -513,16 +477,14 @@ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
// top border
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
if ( !checkClientArea )
{
if (!checkClientArea) {
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
}
// left border
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
if ( !checkClientArea )
{
if (!checkClientArea) {
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
}
@ -531,8 +493,7 @@ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
rect.LowerRightCorner.X = r.LowerRightCorner.X;
rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y;
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
if ( !checkClientArea )
{
if (!checkClientArea) {
Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip);
}
@ -541,8 +502,7 @@ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
rect.LowerRightCorner.X -= 1;
rect.UpperLeftCorner.Y += 1;
rect.LowerRightCorner.Y -= 1;
if ( !checkClientArea )
{
if (!checkClientArea) {
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip);
}
@ -551,8 +511,7 @@ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
rect.LowerRightCorner.X = r.LowerRightCorner.X;
if ( !checkClientArea )
{
if (!checkClientArea) {
Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip);
}
@ -561,37 +520,29 @@ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
rect.LowerRightCorner.X -= 1;
rect.UpperLeftCorner.Y -= 1;
rect.LowerRightCorner.Y -= 1;
if ( !checkClientArea )
{
if (!checkClientArea) {
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip);
}
// client area for background
rect = r;
rect.UpperLeftCorner.X +=1;
rect.UpperLeftCorner.Y +=1;
rect.UpperLeftCorner.X += 1;
rect.UpperLeftCorner.Y += 1;
rect.LowerRightCorner.X -= 2;
rect.LowerRightCorner.Y -= 2;
if (checkClientArea)
{
if (checkClientArea) {
*checkClientArea = rect;
}
if ( !checkClientArea )
{
if (!UseGradient)
{
if (!checkClientArea) {
if (!UseGradient) {
Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip);
}
else if ( Type == EGST_BURNING_SKIN )
{
const video::SColor c1 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.9f );
const video::SColor c2 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.8f );
} else if (Type == EGST_BURNING_SKIN) {
const video::SColor c1 = getColor(EGDC_WINDOW).getInterpolated(0xFFFFFFFF, 0.9f);
const video::SColor c2 = getColor(EGDC_WINDOW).getInterpolated(0xFFFFFFFF, 0.8f);
Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
}
else
{
} else {
const video::SColor c2 = getColor(EGDC_3D_SHADOW);
const video::SColor c1 = getColor(EGDC_3D_FACE);
Driver->draw2DRectangle(rect, c1, c1, c1, c2, clip);
@ -605,26 +556,19 @@ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
rect.LowerRightCorner.X -= 2;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + getSize(EGDS_WINDOW_BUTTON_WIDTH) + 2;
if (drawTitleBar )
{
if (checkClientArea)
{
if (drawTitleBar) {
if (checkClientArea) {
(*checkClientArea).UpperLeftCorner.Y = rect.LowerRightCorner.Y;
}
else
{
} else {
// draw title bar
//if (!UseGradient)
// if (!UseGradient)
// Driver->draw2DRectangle(titleBarColor, rect, clip);
//else
if ( Type == EGST_BURNING_SKIN )
{
const video::SColor c = titleBarColor.getInterpolated( video::SColor(titleBarColor.getAlpha(),255,255,255), 0.8f);
// else
if (Type == EGST_BURNING_SKIN) {
const video::SColor c = titleBarColor.getInterpolated(video::SColor(titleBarColor.getAlpha(), 255, 255, 255), 0.8f);
Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, clip);
}
else
{
const video::SColor c = titleBarColor.getInterpolated(video::SColor(titleBarColor.getAlpha(),0,0,0), 0.2f);
} else {
const video::SColor c = titleBarColor.getInterpolated(video::SColor(titleBarColor.getAlpha(), 0, 0, 0), 0.2f);
Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, clip);
}
}
@ -633,7 +577,6 @@ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element,
return rect;
}
//! draws a standard 3d menu pane
/** Used for drawing for menus and context menus.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
@ -643,16 +586,15 @@ is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param rect: Defining area where to draw.
\param clip: Clip area. */
void CGUISkin::draw3DMenuPane(IGUIElement* element,
const core::rect<s32>& r, const core::rect<s32>* clip)
void CGUISkin::draw3DMenuPane(IGUIElement *element,
const core::rect<s32> &r, const core::rect<s32> *clip)
{
if (!Driver)
return;
core::rect<s32> rect = r;
if ( Type == EGST_BURNING_SKIN )
{
if (Type == EGST_BURNING_SKIN) {
rect.UpperLeftCorner.Y -= 3;
draw3DButtonPaneStandard(element, rect, clip);
return;
@ -698,22 +640,20 @@ void CGUISkin::draw3DMenuPane(IGUIElement* element,
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip);
rect = r;
rect.UpperLeftCorner.X +=1;
rect.UpperLeftCorner.Y +=1;
rect.UpperLeftCorner.X += 1;
rect.UpperLeftCorner.Y += 1;
rect.LowerRightCorner.X -= 2;
rect.LowerRightCorner.Y -= 2;
if (!UseGradient)
Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip);
else
{
else {
const video::SColor c1 = getColor(EGDC_3D_FACE);
const video::SColor c2 = getColor(EGDC_3D_SHADOW);
Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
}
}
//! draws a standard 3d tool bar
/** Used for drawing for toolbars and menus.
\param element: Pointer to the element which wishes to draw this. This parameter
@ -721,9 +661,9 @@ is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param rect: Defining area where to draw.
\param clip: Clip area. */
void CGUISkin::draw3DToolBar(IGUIElement* element,
const core::rect<s32>& r,
const core::rect<s32>* clip)
void CGUISkin::draw3DToolBar(IGUIElement *element,
const core::rect<s32> &r,
const core::rect<s32> *clip)
{
if (!Driver)
return;
@ -739,28 +679,21 @@ void CGUISkin::draw3DToolBar(IGUIElement* element,
rect = r;
rect.LowerRightCorner.Y -= 1;
if (!UseGradient)
{
if (!UseGradient) {
Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip);
}
else
if ( Type == EGST_BURNING_SKIN )
{
} else if (Type == EGST_BURNING_SKIN) {
const video::SColor c1 = 0xF0000000 | getColor(EGDC_3D_FACE).color;
const video::SColor c2 = 0xF0000000 | getColor(EGDC_3D_SHADOW).color;
rect.LowerRightCorner.Y += 1;
Driver->draw2DRectangle(rect, c1, c2, c1, c2, clip);
}
else
{
} else {
const video::SColor c1 = getColor(EGDC_3D_FACE);
const video::SColor c2 = getColor(EGDC_3D_SHADOW);
Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
}
}
//! draws a tab button
/** Used for drawing for tab buttons on top of tabs.
\param element: Pointer to the element which wishes to draw this. This parameter
@ -769,16 +702,15 @@ implementations to find out how to draw the part exactly.
\param active: Specifies if the tab is currently active.
\param rect: Defining area where to draw.
\param clip: Clip area. */
void CGUISkin::draw3DTabButton(IGUIElement* element, bool active,
const core::rect<s32>& frameRect, const core::rect<s32>* clip, EGUI_ALIGNMENT alignment)
void CGUISkin::draw3DTabButton(IGUIElement *element, bool active,
const core::rect<s32> &frameRect, const core::rect<s32> *clip, EGUI_ALIGNMENT alignment)
{
if (!Driver)
return;
core::rect<s32> tr = frameRect;
if ( alignment == EGUIA_UPPERLEFT )
{
if (alignment == EGUIA_UPPERLEFT) {
tr.LowerRightCorner.X -= 2;
tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1;
tr.UpperLeftCorner.X += 1;
@ -806,9 +738,7 @@ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active,
tr.UpperLeftCorner.X += 1;
tr.UpperLeftCorner.Y += 1;
Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), tr, clip);
}
else
{
} else {
tr.LowerRightCorner.X -= 2;
tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1;
tr.UpperLeftCorner.X += 1;
@ -831,7 +761,7 @@ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active,
// draw right middle gray shadow
tr.LowerRightCorner.X += 1;
tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1;
//tr.LowerRightCorner.Y -= 1;
// tr.LowerRightCorner.Y -= 1;
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip);
tr.LowerRightCorner.X += 1;
@ -841,7 +771,6 @@ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active,
}
}
//! draws a tab control body
/** \param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
@ -850,22 +779,20 @@ implementations to find out how to draw the part exactly.
\param background: Specifies if the background should be drawn.
\param rect: Defining area where to draw.
\param clip: Clip area. */
void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background,
const core::rect<s32>& rect, const core::rect<s32>* clip, s32 tabHeight, EGUI_ALIGNMENT alignment)
void CGUISkin::draw3DTabBody(IGUIElement *element, bool border, bool background,
const core::rect<s32> &rect, const core::rect<s32> *clip, s32 tabHeight, EGUI_ALIGNMENT alignment)
{
if (!Driver)
return;
core::rect<s32> tr = rect;
if ( tabHeight == -1 )
if (tabHeight == -1)
tabHeight = getSize(gui::EGDS_BUTTON_HEIGHT);
// draw border.
if (border)
{
if ( alignment == EGUIA_UPPERLEFT )
{
if (border) {
if (alignment == EGUIA_UPPERLEFT) {
// draw left hightlight
tr.UpperLeftCorner.Y += tabHeight + 2;
tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
@ -880,9 +807,7 @@ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background,
tr = rect;
tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1;
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip);
}
else
{
} else {
// draw left hightlight
tr.LowerRightCorner.Y -= tabHeight + 2;
tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
@ -900,30 +825,25 @@ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background,
}
}
if (background)
{
if ( alignment == EGUIA_UPPERLEFT )
{
if (background) {
if (alignment == EGUIA_UPPERLEFT) {
tr = rect;
tr.UpperLeftCorner.Y += tabHeight + 2;
tr.LowerRightCorner.X -= 1;
tr.UpperLeftCorner.X += 1;
tr.LowerRightCorner.Y -= 1;
}
else
{
} else {
tr = rect;
tr.UpperLeftCorner.X += 1;
tr.UpperLeftCorner.Y -= 1;
tr.LowerRightCorner.X -= 1;
tr.LowerRightCorner.Y -= tabHeight + 2;
//tr.UpperLeftCorner.X += 1;
// tr.UpperLeftCorner.X += 1;
}
if (!UseGradient)
Driver->draw2DRectangle(getColor(EGDC_3D_FACE), tr, clip);
else
{
else {
video::SColor c1 = getColor(EGDC_3D_FACE);
video::SColor c2 = getColor(EGDC_3D_SHADOW);
Driver->draw2DRectangle(tr, c1, c1, c2, c2, clip);
@ -931,7 +851,6 @@ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background,
}
}
//! draws an icon, usually from the skin's sprite bank
/** \param parent: Pointer to the element which wishes to draw this icon.
This parameter is usually not used by IGUISkin, but can be used for example
@ -942,30 +861,28 @@ by more complex implementations to find out how to draw the part exactly.
\param currenttime: The present time, used to calculate the frame number
\param loop: Whether the animation should loop or not
\param clip: Clip area. */
void CGUISkin::drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
const core::position2di position,
u32 starttime, u32 currenttime,
bool loop, const core::rect<s32>* clip)
void CGUISkin::drawIcon(IGUIElement *element, EGUI_DEFAULT_ICON icon,
const core::position2di position,
u32 starttime, u32 currenttime,
bool loop, const core::rect<s32> *clip)
{
if (!SpriteBank)
return;
bool gray = element && !element->isEnabled();
SpriteBank->draw2DSprite(Icons[icon], position, clip,
Colors[gray? EGDC_GRAY_WINDOW_SYMBOL : EGDC_WINDOW_SYMBOL], starttime, currenttime, loop, true);
Colors[gray ? EGDC_GRAY_WINDOW_SYMBOL : EGDC_WINDOW_SYMBOL], starttime, currenttime, loop, true);
}
EGUI_SKIN_TYPE CGUISkin::getType() const
{
return Type;
}
//! draws a 2d rectangle.
void CGUISkin::draw2DRectangle(IGUIElement* element,
const video::SColor &color, const core::rect<s32>& pos,
const core::rect<s32>* clip)
void CGUISkin::draw2DRectangle(IGUIElement *element,
const video::SColor &color, const core::rect<s32> &pos,
const core::rect<s32> *clip)
{
Driver->draw2DRectangle(color, pos, clip);
}

View File

@ -11,221 +11,216 @@ namespace irr
{
namespace video
{
class IVideoDriver;
class IVideoDriver;
}
namespace gui
{
class CGUISkin : public IGUISkin
{
public:
class CGUISkin : public IGUISkin
{
public:
CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver *driver);
CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver);
//! destructor
virtual ~CGUISkin();
//! destructor
virtual ~CGUISkin();
//! returns default color
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
//! returns default color
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
//! sets a default color
void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor) override;
//! sets a default color
void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor) override;
//! returns size for the given size type
s32 getSize(EGUI_DEFAULT_SIZE size) const override;
//! returns size for the given size type
s32 getSize(EGUI_DEFAULT_SIZE size) const override;
//! sets a default size
void setSize(EGUI_DEFAULT_SIZE which, s32 size) override;
//! sets a default size
void setSize(EGUI_DEFAULT_SIZE which, s32 size) override;
//! returns the default font
IGUIFont *getFont(EGUI_DEFAULT_FONT which = EGDF_DEFAULT) const override;
//! returns the default font
IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const override;
//! sets a default font
void setFont(IGUIFont *font, EGUI_DEFAULT_FONT which = EGDF_DEFAULT) override;
//! sets a default font
void setFont(IGUIFont* font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT) override;
//! sets the sprite bank used for drawing icons
void setSpriteBank(IGUISpriteBank *bank) override;
//! sets the sprite bank used for drawing icons
void setSpriteBank(IGUISpriteBank* bank) override;
//! gets the sprite bank used for drawing icons
IGUISpriteBank *getSpriteBank() const override;
//! gets the sprite bank used for drawing icons
IGUISpriteBank* getSpriteBank() const override;
//! Returns a default icon
/** Returns the sprite index within the sprite bank */
u32 getIcon(EGUI_DEFAULT_ICON icon) const override;
//! Returns a default icon
/** Returns the sprite index within the sprite bank */
u32 getIcon(EGUI_DEFAULT_ICON icon) const override;
//! Sets a default icon
/** Sets the sprite index used for drawing icons like arrows,
close buttons and ticks in checkboxes
\param icon: Enum specifying which icon to change
\param index: The sprite index used to draw this icon */
void setIcon(EGUI_DEFAULT_ICON icon, u32 index) override;
//! Sets a default icon
/** Sets the sprite index used for drawing icons like arrows,
close buttons and ticks in checkboxes
\param icon: Enum specifying which icon to change
\param index: The sprite index used to draw this icon */
void setIcon(EGUI_DEFAULT_ICON icon, u32 index) override;
//! Returns a default text.
/** For example for Message box button captions:
"OK", "Cancel", "Yes", "No" and so on. */
const wchar_t *getDefaultText(EGUI_DEFAULT_TEXT text) const override;
//! Returns a default text.
/** For example for Message box button captions:
"OK", "Cancel", "Yes", "No" and so on. */
const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const override;
//! Sets a default text.
/** For example for Message box button captions:
"OK", "Cancel", "Yes", "No" and so on. */
void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t *newText) override;
//! Sets a default text.
/** For example for Message box button captions:
"OK", "Cancel", "Yes", "No" and so on. */
void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText) override;
//! draws a standard 3d button pane
/** Used for drawing for example buttons in normal state.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param rect: Defining area where to draw.
\param clip: Clip area.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly. */
virtual void draw3DButtonPaneStandard(IGUIElement *element,
const core::rect<s32> &rect,
const core::rect<s32> *clip = 0) override;
//! draws a standard 3d button pane
/** Used for drawing for example buttons in normal state.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param rect: Defining area where to draw.
\param clip: Clip area.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly. */
virtual void draw3DButtonPaneStandard(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0) override;
//! draws a pressed 3d button pane
/** Used for drawing for example buttons in pressed state.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param rect: Defining area where to draw.
\param clip: Clip area.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly. */
virtual void draw3DButtonPanePressed(IGUIElement *element,
const core::rect<s32> &rect,
const core::rect<s32> *clip = 0) override;
//! draws a pressed 3d button pane
/** Used for drawing for example buttons in pressed state.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param rect: Defining area where to draw.
\param clip: Clip area.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly. */
virtual void draw3DButtonPanePressed(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0) override;
//! draws a sunken 3d pane
/** Used for drawing the background of edit, combo or check boxes.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param bgcolor: Background color.
\param flat: Specifies if the sunken pane should be flat or displayed as sunken
deep into the ground.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DSunkenPane(IGUIElement *element,
video::SColor bgcolor, bool flat,
bool fillBackGround,
const core::rect<s32> &rect,
const core::rect<s32> *clip = 0) override;
//! draws a sunken 3d pane
/** Used for drawing the background of edit, combo or check boxes.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param bgcolor: Background color.
\param flat: Specifies if the sunken pane should be flat or displayed as sunken
deep into the ground.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DSunkenPane(IGUIElement* element,
video::SColor bgcolor, bool flat,
bool fillBackGround,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0) override;
//! draws a window background
/** Used for drawing the background of dialogs and windows.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param titleBarColor: Title color.
\param drawTitleBar: True to enable title drawing.
\param rect: Defining area where to draw.
\param clip: Clip area.
\param checkClientArea: When set to non-null the function will not draw anything,
but will instead return the clientArea which can be used for drawing by the calling window.
That is the area without borders and without titlebar.
\return Returns rect where it would be good to draw title bar text. This will
work even when checkClientArea is set to a non-null value.*/
virtual core::rect<s32> draw3DWindowBackground(IGUIElement *element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32> &rect,
const core::rect<s32> *clip,
core::rect<s32> *checkClientArea) override;
//! draws a window background
/** Used for drawing the background of dialogs and windows.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param titleBarColor: Title color.
\param drawTitleBar: True to enable title drawing.
\param rect: Defining area where to draw.
\param clip: Clip area.
\param checkClientArea: When set to non-null the function will not draw anything,
but will instead return the clientArea which can be used for drawing by the calling window.
That is the area without borders and without titlebar.
\return Returns rect where it would be good to draw title bar text. This will
work even when checkClientArea is set to a non-null value.*/
virtual core::rect<s32> draw3DWindowBackground(IGUIElement* element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32>& rect,
const core::rect<s32>* clip,
core::rect<s32>* checkClientArea) override;
//! draws a standard 3d menu pane
/** Used for drawing for menus and context menus.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DMenuPane(IGUIElement *element,
const core::rect<s32> &rect,
const core::rect<s32> *clip = 0) override;
//! draws a standard 3d menu pane
/** Used for drawing for menus and context menus.
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DMenuPane(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0) override;
//! draws a standard 3d tool bar
/** Used for drawing for toolbars and menus.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DToolBar(IGUIElement *element,
const core::rect<s32> &rect,
const core::rect<s32> *clip = 0) override;
//! draws a standard 3d tool bar
/** Used for drawing for toolbars and menus.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DToolBar(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0) override;
//! draws a tab button
/** Used for drawing for tab buttons on top of tabs.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param active: Specifies if the tab is currently active.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DTabButton(IGUIElement *element, bool active,
const core::rect<s32> &rect, const core::rect<s32> *clip = 0,
EGUI_ALIGNMENT alignment = EGUIA_UPPERLEFT) override;
//! draws a tab button
/** Used for drawing for tab buttons on top of tabs.
\param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param active: Specifies if the tab is currently active.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DTabButton(IGUIElement* element, bool active,
const core::rect<s32>& rect, const core::rect<s32>* clip=0,
EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT) override;
//! draws a tab control body
/** \param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param border: Specifies if the border should be drawn.
\param background: Specifies if the background should be drawn.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DTabBody(IGUIElement *element, bool border, bool background,
const core::rect<s32> &rect, const core::rect<s32> *clip = 0, s32 tabHeight = -1,
EGUI_ALIGNMENT alignment = EGUIA_UPPERLEFT) override;
//! draws a tab control body
/** \param element: Pointer to the element which wishes to draw this. This parameter
is usually not used by ISkin, but can be used for example by more complex
implementations to find out how to draw the part exactly.
\param border: Specifies if the border should be drawn.
\param background: Specifies if the background should be drawn.
\param rect: Defining area where to draw.
\param clip: Clip area. */
virtual void draw3DTabBody(IGUIElement* element, bool border, bool background,
const core::rect<s32>& rect, const core::rect<s32>* clip=0, s32 tabHeight=-1,
EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT) override;
//! draws an icon, usually from the skin's sprite bank
/** \param element: Pointer to the element which wishes to draw this icon.
This parameter is usually not used by IGUISkin, but can be used for example
by more complex implementations to find out how to draw the part exactly.
\param icon: Specifies the icon to be drawn.
\param position: The position to draw the icon
\param starttime: The time at the start of the animation
\param currenttime: The present time, used to calculate the frame number
\param loop: Whether the animation should loop or not
\param clip: Clip area. */
virtual void drawIcon(IGUIElement *element, EGUI_DEFAULT_ICON icon,
const core::position2di position,
u32 starttime = 0, u32 currenttime = 0,
bool loop = false, const core::rect<s32> *clip = 0) override;
//! draws an icon, usually from the skin's sprite bank
/** \param element: Pointer to the element which wishes to draw this icon.
This parameter is usually not used by IGUISkin, but can be used for example
by more complex implementations to find out how to draw the part exactly.
\param icon: Specifies the icon to be drawn.
\param position: The position to draw the icon
\param starttime: The time at the start of the animation
\param currenttime: The present time, used to calculate the frame number
\param loop: Whether the animation should loop or not
\param clip: Clip area. */
virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
const core::position2di position,
u32 starttime=0, u32 currenttime=0,
bool loop=false, const core::rect<s32>* clip=0) override;
//! draws a 2d rectangle.
/** \param element: Pointer to the element which wishes to draw this icon.
This parameter is usually not used by IGUISkin, but can be used for example
by more complex implementations to find out how to draw the part exactly.
\param color: Color of the rectangle to draw. The alpha component specifies how
transparent the rectangle will be.
\param pos: Position of the rectangle.
\param clip: Pointer to rectangle against which the rectangle will be clipped.
If the pointer is null, no clipping will be performed. */
virtual void draw2DRectangle(IGUIElement *element, const video::SColor &color,
const core::rect<s32> &pos, const core::rect<s32> *clip = 0) override;
//! get the type of this skin
EGUI_SKIN_TYPE getType() const override;
//! draws a 2d rectangle.
/** \param element: Pointer to the element which wishes to draw this icon.
This parameter is usually not used by IGUISkin, but can be used for example
by more complex implementations to find out how to draw the part exactly.
\param color: Color of the rectangle to draw. The alpha component specifies how
transparent the rectangle will be.
\param pos: Position of the rectangle.
\param clip: Pointer to rectangle against which the rectangle will be clipped.
If the pointer is null, no clipping will be performed. */
virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color,
const core::rect<s32>& pos, const core::rect<s32>* clip = 0) override;
//! get the type of this skin
EGUI_SKIN_TYPE getType() const override;
private:
video::SColor Colors[EGDC_COUNT];
s32 Sizes[EGDS_COUNT];
u32 Icons[EGDI_COUNT];
IGUIFont* Fonts[EGDF_COUNT];
IGUISpriteBank* SpriteBank;
core::stringw Texts[EGDT_COUNT];
video::IVideoDriver* Driver;
bool UseGradient;
EGUI_SKIN_TYPE Type;
};
private:
video::SColor Colors[EGDC_COUNT];
s32 Sizes[EGDS_COUNT];
u32 Icons[EGDI_COUNT];
IGUIFont *Fonts[EGDF_COUNT];
IGUISpriteBank *SpriteBank;
core::stringw Texts[EGDT_COUNT];
video::IVideoDriver *Driver;
bool UseGradient;
EGUI_SKIN_TYPE Type;
};
} // end namespace gui
} // end namespace irr

View File

@ -13,22 +13,20 @@ namespace irr
namespace gui
{
CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) :
Environment(env), Driver(0)
CGUISpriteBank::CGUISpriteBank(IGUIEnvironment *env) :
Environment(env), Driver(0)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUISpriteBank");
#endif
#endif
if (Environment)
{
if (Environment) {
Driver = Environment->getVideoDriver();
if (Driver)
Driver->grab();
}
}
CGUISpriteBank::~CGUISpriteBank()
{
clear();
@ -38,26 +36,22 @@ CGUISpriteBank::~CGUISpriteBank()
Driver->drop();
}
core::array< core::rect<s32> >& CGUISpriteBank::getPositions()
core::array<core::rect<s32>> &CGUISpriteBank::getPositions()
{
return Rectangles;
}
core::array< SGUISprite >& CGUISpriteBank::getSprites()
core::array<SGUISprite> &CGUISpriteBank::getSprites()
{
return Sprites;
}
u32 CGUISpriteBank::getTextureCount() const
{
return Textures.size();
}
video::ITexture* CGUISpriteBank::getTexture(u32 index) const
video::ITexture *CGUISpriteBank::getTexture(u32 index) const
{
if (index < Textures.size())
return Textures[index];
@ -65,8 +59,7 @@ video::ITexture* CGUISpriteBank::getTexture(u32 index) const
return 0;
}
void CGUISpriteBank::addTexture(video::ITexture* texture)
void CGUISpriteBank::addTexture(video::ITexture *texture)
{
if (texture)
texture->grab();
@ -74,8 +67,7 @@ void CGUISpriteBank::addTexture(video::ITexture* texture)
Textures.push_back(texture);
}
void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture)
void CGUISpriteBank::setTexture(u32 index, video::ITexture *texture)
{
while (index >= Textures.size())
Textures.push_back(0);
@ -89,13 +81,11 @@ void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture)
Textures[index] = texture;
}
//! clear everything
void CGUISpriteBank::clear()
{
// drop textures
for (u32 i=0; i<Textures.size(); ++i)
{
for (u32 i = 0; i < Textures.size(); ++i) {
if (Textures[i])
Textures[i]->drop();
}
@ -105,16 +95,16 @@ void CGUISpriteBank::clear()
}
//! Add the texture and use it for a single non-animated sprite.
s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture)
s32 CGUISpriteBank::addTextureAsSprite(video::ITexture *texture)
{
if ( !texture )
if (!texture)
return -1;
addTexture(texture);
u32 textureIndex = getTextureCount() - 1;
u32 rectangleIndex = Rectangles.size();
Rectangles.push_back( core::rect<s32>(0,0, texture->getOriginalSize().Width, texture->getOriginalSize().Height) );
Rectangles.push_back(core::rect<s32>(0, 0, texture->getOriginalSize().Width, texture->getOriginalSize().Height));
SGUISprite sprite;
sprite.frameTime = 0;
@ -122,27 +112,26 @@ s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture)
SGUISpriteFrame frame;
frame.textureNumber = textureIndex;
frame.rectNumber = rectangleIndex;
sprite.Frames.push_back( frame );
sprite.Frames.push_back(frame);
Sprites.push_back( sprite );
Sprites.push_back(sprite);
return Sprites.size() - 1;
}
// get FrameNr for time. return true on exisiting frame
inline bool CGUISpriteBank::getFrameNr(u32& frame,u32 index, u32 time, bool loop) const
inline bool CGUISpriteBank::getFrameNr(u32 &frame, u32 index, u32 time, bool loop) const
{
frame = 0;
if (index >= Sprites.size())
return false;
const SGUISprite& sprite = Sprites[index];
const SGUISprite &sprite = Sprites[index];
const u32 frameSize = sprite.Frames.size();
if (frameSize < 1)
return false;
if (sprite.frameTime)
{
if (sprite.frameTime) {
u32 f = (time / sprite.frameTime);
if (loop)
frame = f % frameSize;
@ -153,15 +142,15 @@ inline bool CGUISpriteBank::getFrameNr(u32& frame,u32 index, u32 time, bool loop
}
//! draws a sprite in 2d with scale and color
void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos,
const core::rect<s32>* clip, const video::SColor& color,
void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di &pos,
const core::rect<s32> *clip, const video::SColor &color,
u32 starttime, u32 currenttime, bool loop, bool center)
{
u32 frame = 0;
if (!getFrameNr(frame, index, currenttime - starttime, loop))
return;
const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);
const video::ITexture *tex = getTexture(Sprites[index].Frames[frame].textureNumber);
if (!tex)
return;
@ -169,24 +158,23 @@ void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos,
if (rn >= Rectangles.size())
return;
const core::rect<s32>& r = Rectangles[rn];
const core::rect<s32> &r = Rectangles[rn];
core::position2di p(pos);
if (center)
{
if (center) {
p -= r.getSize() / 2;
}
Driver->draw2DImage(tex, p, r, clip, color, true);
}
void CGUISpriteBank::draw2DSprite(u32 index, const core::rect<s32>& destRect,
const core::rect<s32>* clip, const video::SColor * const colors,
void CGUISpriteBank::draw2DSprite(u32 index, const core::rect<s32> &destRect,
const core::rect<s32> *clip, const video::SColor *const colors,
u32 timeTicks, bool loop)
{
u32 frame = 0;
if (!getFrameNr(frame,index, timeTicks, loop))
if (!getFrameNr(frame, index, timeTicks, loop))
return;
const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);
const video::ITexture *tex = getTexture(Sprites[index].Frames[frame].textureNumber);
if (!tex)
return;
@ -197,27 +185,25 @@ void CGUISpriteBank::draw2DSprite(u32 index, const core::rect<s32>& destRect,
Driver->draw2DImage(tex, destRect, Rectangles[rn], clip, colors, true);
}
void CGUISpriteBank::draw2DSpriteBatch( const core::array<u32>& indices,
const core::array<core::position2di>& pos,
const core::rect<s32>* clip,
const video::SColor& color,
u32 starttime, u32 currenttime,
bool loop, bool center)
void CGUISpriteBank::draw2DSpriteBatch(const core::array<u32> &indices,
const core::array<core::position2di> &pos,
const core::rect<s32> *clip,
const video::SColor &color,
u32 starttime, u32 currenttime,
bool loop, bool center)
{
const irr::u32 drawCount = core::min_<u32>(indices.size(), pos.size());
if (!getTextureCount())
return;
core::array<SDrawBatch> drawBatches(getTextureCount());
for (u32 i=0; i < Textures.size(); ++i)
{
for (u32 i = 0; i < Textures.size(); ++i) {
drawBatches.push_back(SDrawBatch());
drawBatches[i].positions.reallocate(drawCount);
drawBatches[i].sourceRects.reallocate(drawCount);
}
for (u32 i = 0; i < drawCount; ++i)
{
for (u32 i = 0; i < drawCount; ++i) {
const u32 index = indices[i];
// work out frame number
@ -226,38 +212,33 @@ void CGUISpriteBank::draw2DSpriteBatch( const core::array<u32>& indices,
return;
const u32 texNum = Sprites[index].Frames[frame].textureNumber;
if (texNum >= drawBatches.size())
{
if (texNum >= drawBatches.size()) {
continue;
}
SDrawBatch& currentBatch = drawBatches[texNum];
SDrawBatch &currentBatch = drawBatches[texNum];
const u32 rn = Sprites[index].Frames[frame].rectNumber;
if (rn >= Rectangles.size())
return;
const core::rect<s32>& r = Rectangles[rn];
const core::rect<s32> &r = Rectangles[rn];
if (center)
{
if (center) {
core::position2di p = pos[i];
p -= r.getSize() / 2;
currentBatch.positions.push_back(p);
currentBatch.sourceRects.push_back(r);
}
else
{
} else {
currentBatch.positions.push_back(pos[i]);
currentBatch.sourceRects.push_back(r);
}
}
for(u32 i = 0;i < drawBatches.size();i++)
{
if(!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty())
for (u32 i = 0; i < drawBatches.size(); i++) {
if (!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty())
Driver->draw2DImageBatch(getTexture(i), drawBatches[i].positions,
drawBatches[i].sourceRects, clip, color, true);
drawBatches[i].sourceRects, clip, color, true);
}
}

View File

@ -11,59 +11,57 @@ namespace irr
namespace video
{
class IVideoDriver;
class ITexture;
class IVideoDriver;
class ITexture;
}
namespace gui
{
class IGUIEnvironment;
class IGUIEnvironment;
//! Sprite bank interface.
class CGUISpriteBank : public IGUISpriteBank
{
public:
CGUISpriteBank(IGUIEnvironment* env);
CGUISpriteBank(IGUIEnvironment *env);
virtual ~CGUISpriteBank();
core::array< core::rect<s32> >& getPositions() override;
core::array< SGUISprite >& getSprites() override;
core::array<core::rect<s32>> &getPositions() override;
core::array<SGUISprite> &getSprites() override;
u32 getTextureCount() const override;
video::ITexture* getTexture(u32 index) const override;
void addTexture(video::ITexture* texture) override;
void setTexture(u32 index, video::ITexture* texture) override;
video::ITexture *getTexture(u32 index) const override;
void addTexture(video::ITexture *texture) override;
void setTexture(u32 index, video::ITexture *texture) override;
//! Add the texture and use it for a single non-animated sprite.
s32 addTextureAsSprite(video::ITexture* texture) override;
s32 addTextureAsSprite(video::ITexture *texture) override;
//! clears sprites, rectangles and textures
void clear() override;
//! Draws a sprite in 2d with position and color
virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect<s32>* clip=0,
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false) override;
virtual void draw2DSprite(u32 index, const core::position2di &pos, const core::rect<s32> *clip = 0,
const video::SColor &color = video::SColor(255, 255, 255, 255),
u32 starttime = 0, u32 currenttime = 0, bool loop = true, bool center = false) override;
//! Draws a sprite in 2d with destination rectangle and colors
virtual void draw2DSprite(u32 index, const core::rect<s32>& destRect,
const core::rect<s32>* clip=0,
const video::SColor * const colors=0,
virtual void draw2DSprite(u32 index, const core::rect<s32> &destRect,
const core::rect<s32> *clip = 0,
const video::SColor *const colors = 0,
u32 timeTicks = 0,
bool loop=true) override;
bool loop = true) override;
//! Draws a sprite batch in 2d using an array of positions and a color
virtual void draw2DSpriteBatch(const core::array<u32>& indices, const core::array<core::position2di>& pos,
const core::rect<s32>* clip=0,
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0,
bool loop=true, bool center=false) override;
virtual void draw2DSpriteBatch(const core::array<u32> &indices, const core::array<core::position2di> &pos,
const core::rect<s32> *clip = 0,
const video::SColor &color = video::SColor(255, 255, 255, 255),
u32 starttime = 0, u32 currenttime = 0,
bool loop = true, bool center = false) override;
protected:
bool getFrameNr(u32& frameNr, u32 index, u32 time, bool loop) const;
bool getFrameNr(u32 &frameNr, u32 index, u32 time, bool loop) const;
struct SDrawBatch
{
@ -73,11 +71,10 @@ protected:
};
core::array<SGUISprite> Sprites;
core::array< core::rect<s32> > Rectangles;
core::array<video::ITexture*> Textures;
IGUIEnvironment* Environment;
video::IVideoDriver* Driver;
core::array<core::rect<s32>> Rectangles;
core::array<video::ITexture *> Textures;
IGUIEnvironment *Environment;
video::IVideoDriver *Driver;
};
} // end namespace gui

View File

@ -16,29 +16,27 @@ namespace gui
{
//! constructor
CGUIStaticText::CGUIStaticText(const wchar_t* text, bool border,
IGUIEnvironment* environment, IGUIElement* parent,
s32 id, const core::rect<s32>& rectangle,
bool background)
: IGUIStaticText(environment, parent, id, rectangle),
HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background),
RestrainTextInside(true), RightToLeft(false),
OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)),
OverrideFont(0), LastBreakFont(0)
CGUIStaticText::CGUIStaticText(const wchar_t *text, bool border,
IGUIEnvironment *environment, IGUIElement *parent,
s32 id, const core::rect<s32> &rectangle,
bool background) :
IGUIStaticText(environment, parent, id, rectangle),
HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background),
RestrainTextInside(true), RightToLeft(false),
OverrideColor(video::SColor(101, 255, 255, 255)), BGColor(video::SColor(101, 210, 210, 210)),
OverrideFont(0), LastBreakFont(0)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUIStaticText");
#endif
#endif
Text = text;
if (environment && environment->getSkin())
{
if (environment && environment->getSkin()) {
BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
}
}
//! destructor
CGUIStaticText::~CGUIStaticText()
{
@ -46,25 +44,23 @@ CGUIStaticText::~CGUIStaticText()
OverrideFont->drop();
}
//! draws the element and its children
void CGUIStaticText::draw()
{
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (!skin)
return;
video::IVideoDriver* driver = Environment->getVideoDriver();
video::IVideoDriver *driver = Environment->getVideoDriver();
core::rect<s32> frameRect(AbsoluteRect);
// draw background
if (Background)
{
if ( !OverrideBGColorEnabled ) // skin-colors can change
if (Background) {
if (!OverrideBGColorEnabled) // skin-colors can change
BGColor = skin->getColor(gui::EGDC_3D_FACE);
driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect);
@ -72,64 +68,51 @@ void CGUIStaticText::draw()
// draw the border
if (Border)
{
if (Border) {
skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
}
// draw the text
if (Text.size())
{
IGUIFont* font = getActiveFont();
if (Text.size()) {
IGUIFont *font = getActiveFont();
if (font)
{
if (!WordWrap)
{
if (VAlign == EGUIA_LOWERRIGHT)
{
if (font) {
if (!WordWrap) {
if (VAlign == EGUIA_LOWERRIGHT) {
frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y -
font->getDimension(L"A").Height - font->getKerningHeight();
font->getDimension(L"A").Height - font->getKerningHeight();
}
if (HAlign == EGUIA_LOWERRIGHT)
{
if (HAlign == EGUIA_LOWERRIGHT) {
frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
font->getDimension(Text.c_str()).Width;
font->getDimension(Text.c_str()).Width;
}
font->draw(Text.c_str(), frameRect,
getActiveColor(),
HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
}
else
{
getActiveColor(),
HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
} else {
if (font != LastBreakFont)
breakText();
core::rect<s32> r = frameRect;
s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
s32 totalHeight = height * BrokenText.size();
if (VAlign == EGUIA_CENTER)
{
if (VAlign == EGUIA_CENTER) {
r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2);
}
else if (VAlign == EGUIA_LOWERRIGHT)
{
} else if (VAlign == EGUIA_LOWERRIGHT) {
r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight;
}
for (u32 i=0; i<BrokenText.size(); ++i)
{
if (HAlign == EGUIA_LOWERRIGHT)
{
for (u32 i = 0; i < BrokenText.size(); ++i) {
if (HAlign == EGUIA_LOWERRIGHT) {
r.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
font->getDimension(BrokenText[i].c_str()).Width;
font->getDimension(BrokenText[i].c_str()).Width;
}
font->draw(BrokenText[i].c_str(), r,
getActiveColor(),
HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
getActiveColor(),
HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
r.LowerRightCorner.Y += height;
r.UpperLeftCorner.Y += height;
@ -141,9 +124,8 @@ void CGUIStaticText::draw()
IGUIElement::draw();
}
//! Sets another skin independent font.
void CGUIStaticText::setOverrideFont(IGUIFont* font)
void CGUIStaticText::setOverrideFont(IGUIFont *font)
{
if (OverrideFont == font)
return;
@ -160,17 +142,17 @@ void CGUIStaticText::setOverrideFont(IGUIFont* font)
}
//! Gets the override font (if any)
IGUIFont * CGUIStaticText::getOverrideFont() const
IGUIFont *CGUIStaticText::getOverrideFont() const
{
return OverrideFont;
}
//! Get the font which is used right now for drawing
IGUIFont* CGUIStaticText::getActiveFont() const
IGUIFont *CGUIStaticText::getActiveFont() const
{
if ( OverrideFont )
if (OverrideFont)
return OverrideFont;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (skin)
return skin->getFont();
return 0;
@ -183,7 +165,6 @@ void CGUIStaticText::setOverrideColor(video::SColor color)
OverrideColorEnabled = true;
}
//! Sets another color for the text.
void CGUIStaticText::setBackgroundColor(video::SColor color)
{
@ -192,72 +173,62 @@ void CGUIStaticText::setBackgroundColor(video::SColor color)
Background = true;
}
//! Sets whether to draw the background
void CGUIStaticText::setDrawBackground(bool draw)
{
Background = draw;
}
//! Gets the background color
video::SColor CGUIStaticText::getBackgroundColor() const
{
return BGColor;
}
//! Checks if background drawing is enabled
bool CGUIStaticText::isDrawBackgroundEnabled() const
{
return Background;
}
//! Sets whether to draw the border
void CGUIStaticText::setDrawBorder(bool draw)
{
Border = draw;
}
//! Checks if border drawing is enabled
bool CGUIStaticText::isDrawBorderEnabled() const
{
return Border;
}
void CGUIStaticText::setTextRestrainedInside(bool restrainTextInside)
{
RestrainTextInside = restrainTextInside;
}
bool CGUIStaticText::isTextRestrainedInside() const
{
return RestrainTextInside;
}
void CGUIStaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
{
HAlign = horizontal;
VAlign = vertical;
}
video::SColor CGUIStaticText::getOverrideColor() const
{
return OverrideColor;
}
irr::video::SColor CGUIStaticText::getActiveColor() const
{
if ( OverrideColorEnabled )
if (OverrideColorEnabled)
return OverrideColor;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (skin)
return OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT);
return OverrideColor;
@ -270,13 +241,11 @@ void CGUIStaticText::enableOverrideColor(bool enable)
OverrideColorEnabled = enable;
}
bool CGUIStaticText::isOverrideColorEnabled() const
{
return OverrideColorEnabled;
}
//! Enables or disables word wrap for using the static text as
//! multiline text control.
void CGUIStaticText::setWordWrap(bool enable)
@ -285,29 +254,24 @@ void CGUIStaticText::setWordWrap(bool enable)
breakText();
}
bool CGUIStaticText::isWordWrapEnabled() const
{
return WordWrap;
}
void CGUIStaticText::setRightToLeft(bool rtl)
{
if (RightToLeft != rtl)
{
if (RightToLeft != rtl) {
RightToLeft = rtl;
breakText();
}
}
bool CGUIStaticText::isRightToLeft() const
{
return RightToLeft;
}
//! Breaks the single text line.
void CGUIStaticText::breakText()
{
@ -316,8 +280,8 @@ void CGUIStaticText::breakText()
BrokenText.clear();
IGUISkin* skin = Environment->getSkin();
IGUIFont* font = getActiveFont();
IGUISkin *skin = Environment->getSkin();
IGUIFont *font = getActiveFont();
if (!font)
return;
@ -330,70 +294,60 @@ void CGUIStaticText::breakText()
s32 length = 0;
s32 elWidth = RelativeRect.getWidth();
if (Border)
elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
elWidth -= 2 * skin->getSize(EGDS_TEXT_DISTANCE_X);
wchar_t c;
// We have to deal with right-to-left and left-to-right differently
// However, most parts of the following code is the same, it's just
// some order and boundaries which change.
if (!RightToLeft)
{
if (!RightToLeft) {
// regular (left-to-right)
for (s32 i=0; i<size; ++i)
{
for (s32 i = 0; i < size; ++i) {
c = Text[i];
bool lineBreak = false;
if (c == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if (Text[i+1] == L'\n') // Windows breaks
if (Text[i + 1] == L'\n') // Windows breaks
{
Text.erase(i+1);
Text.erase(i + 1);
--size;
}
c = '\0';
}
else if (c == L'\n') // Unix breaks
} else if (c == L'\n') // Unix breaks
{
lineBreak = true;
c = '\0';
}
bool isWhitespace = (c == L' ' || c == 0);
if ( !isWhitespace )
{
if (!isWhitespace) {
// part of a word
word += c;
}
if ( isWhitespace || i == (size-1))
{
if (word.size())
{
if (isWhitespace || i == (size - 1)) {
if (word.size()) {
// here comes the next whitespace, look if
// we must break the last word to the next line.
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
const s32 wordlgth = font->getDimension(word.c_str()).Width;
if (wordlgth > elWidth)
{
if (wordlgth > elWidth) {
// This word is too long to fit in the available space, look for
// the Unicode Soft HYphen (SHY / 00AD) character for a place to
// break the word at
int where = word.findFirst( wchar_t(0x00AD) );
if (where != -1)
{
core::stringw first = word.subString(0, where);
int where = word.findFirst(wchar_t(0x00AD));
if (where != -1) {
core::stringw first = word.subString(0, where);
core::stringw second = word.subString(where, word.size() - where);
BrokenText.push_back(line + first + L"-");
const s32 secondLength = font->getDimension(second.c_str()).Width;
length = secondLength;
line = second;
}
else
{
} else {
// No soft hyphen found, so there's nothing more we can do
// break to next line
if (length)
@ -401,16 +355,12 @@ void CGUIStaticText::breakText()
length = wordlgth;
line = word;
}
}
else if (length && (length + wordlgth + whitelgth > elWidth))
{
} else if (length && (length + wordlgth + whitelgth > elWidth)) {
// break to next line
BrokenText.push_back(line);
length = wordlgth;
line = word;
}
else
{
} else {
// add word to line
line += whitespace;
line += word;
@ -421,14 +371,12 @@ void CGUIStaticText::breakText()
whitespace = L"";
}
if ( isWhitespace )
{
if (isWhitespace) {
whitespace += c;
}
// compute line break
if (lineBreak)
{
if (lineBreak) {
line += whitespace;
line += word;
BrokenText.push_back(line);
@ -443,49 +391,40 @@ void CGUIStaticText::breakText()
line += whitespace;
line += word;
BrokenText.push_back(line);
}
else
{
} else {
// right-to-left
for (s32 i=size; i>=0; --i)
{
for (s32 i = size; i >= 0; --i) {
c = Text[i];
bool lineBreak = false;
if (c == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if ((i>0) && Text[i-1] == L'\n') // Windows breaks
if ((i > 0) && Text[i - 1] == L'\n') // Windows breaks
{
Text.erase(i-1);
Text.erase(i - 1);
--size;
}
c = '\0';
}
else if (c == L'\n') // Unix breaks
} else if (c == L'\n') // Unix breaks
{
lineBreak = true;
c = '\0';
}
if (c==L' ' || c==0 || i==0)
{
if (word.size())
{
if (c == L' ' || c == 0 || i == 0) {
if (word.size()) {
// here comes the next whitespace, look if
// we must break the last word to the next line.
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
const s32 wordlgth = font->getDimension(word.c_str()).Width;
if (length && (length + wordlgth + whitelgth > elWidth))
{
if (length && (length + wordlgth + whitelgth > elWidth)) {
// break to next line
BrokenText.push_back(line);
length = wordlgth;
line = word;
}
else
{
} else {
// add word to line
line = whitespace + line;
line = word + line;
@ -500,8 +439,7 @@ void CGUIStaticText::breakText()
whitespace = core::stringw(&c, 1) + whitespace;
// compute line break
if (lineBreak)
{
if (lineBreak) {
line = whitespace + line;
line = word + line;
BrokenText.push_back(line);
@ -510,9 +448,7 @@ void CGUIStaticText::breakText()
whitespace = L"";
length = 0;
}
}
else
{
} else {
// yippee this is a word..
word = core::stringw(&c, 1) + word;
}
@ -524,36 +460,30 @@ void CGUIStaticText::breakText()
}
}
//! Sets the new caption of this element.
void CGUIStaticText::setText(const wchar_t* text)
void CGUIStaticText::setText(const wchar_t *text)
{
IGUIElement::setText(text);
breakText();
}
void CGUIStaticText::updateAbsolutePosition()
{
IGUIElement::updateAbsolutePosition();
breakText();
}
//! Returns the height of the text in pixels when it is drawn.
s32 CGUIStaticText::getTextHeight() const
{
IGUIFont* font = getActiveFont();
IGUIFont *font = getActiveFont();
if (!font)
return 0;
if (WordWrap)
{
if (WordWrap) {
s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
return height* BrokenText.size();
}
else
{
return height * BrokenText.size();
} else {
// TODO: Text can have multiple lines which are not in BrokenText
// This is likely not correct. But as I have no time for further
// investigation I just fix it for now by return the true height here.
@ -561,33 +491,27 @@ s32 CGUIStaticText::getTextHeight() const
}
}
s32 CGUIStaticText::getTextWidth() const
{
IGUIFont * font = getActiveFont();
if(!font)
IGUIFont *font = getActiveFont();
if (!font)
return 0;
if(WordWrap)
{
if (WordWrap) {
s32 widest = 0;
for(u32 line = 0; line < BrokenText.size(); ++line)
{
for (u32 line = 0; line < BrokenText.size(); ++line) {
s32 width = font->getDimension(BrokenText[line].c_str()).Width;
if(width > widest)
if (width > widest)
widest = width;
}
return widest;
}
else
{
} else {
return font->getDimension(Text.c_str()).Width;
}
}
} // end namespace gui
} // end namespace irr

View File

@ -11,123 +11,121 @@ namespace irr
{
namespace gui
{
class CGUIStaticText : public IGUIStaticText
{
public:
//! constructor
CGUIStaticText(const wchar_t* text, bool border, IGUIEnvironment* environment,
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
class CGUIStaticText : public IGUIStaticText
{
public:
//! constructor
CGUIStaticText(const wchar_t *text, bool border, IGUIEnvironment *environment,
IGUIElement *parent, s32 id, const core::rect<s32> &rectangle,
bool background = false);
//! destructor
virtual ~CGUIStaticText();
//! destructor
virtual ~CGUIStaticText();
//! draws the element and its children
void draw() override;
//! draws the element and its children
void draw() override;
//! Sets another skin independent font.
void setOverrideFont(IGUIFont* font=0) override;
//! Sets another skin independent font.
void setOverrideFont(IGUIFont *font = 0) override;
//! Gets the override font (if any)
IGUIFont* getOverrideFont() const override;
//! Gets the override font (if any)
IGUIFont *getOverrideFont() const override;
//! Get the font which is used right now for drawing
IGUIFont* getActiveFont() const override;
//! Get the font which is used right now for drawing
IGUIFont *getActiveFont() const override;
//! Sets another color for the text.
void setOverrideColor(video::SColor color) override;
//! Sets another color for the text.
void setOverrideColor(video::SColor color) override;
//! Sets another color for the background.
void setBackgroundColor(video::SColor color) override;
//! Sets another color for the background.
void setBackgroundColor(video::SColor color) override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Sets whether to draw the background
void setDrawBackground(bool draw) override;
//! Gets the background color
video::SColor getBackgroundColor() const override;
//! Gets the background color
video::SColor getBackgroundColor() const override;
//! Checks if background drawing is enabled
bool isDrawBackgroundEnabled() const override;
//! Checks if background drawing is enabled
bool isDrawBackgroundEnabled() const override;
//! Sets whether to draw the border
void setDrawBorder(bool draw) override;
//! Sets whether to draw the border
void setDrawBorder(bool draw) override;
//! Checks if border drawing is enabled
bool isDrawBorderEnabled() const override;
//! Checks if border drawing is enabled
bool isDrawBorderEnabled() const override;
//! Sets alignment mode for text
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
//! Sets alignment mode for text
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
//! Gets the override color
video::SColor getOverrideColor() const override;
//! Gets the override color
video::SColor getOverrideColor() const override;
//! Gets the currently used text color
video::SColor getActiveColor() const override;
//! Gets the currently used text color
video::SColor getActiveColor() const override;
//! Sets if the static text should use the override color or the
//! color in the gui skin.
void enableOverrideColor(bool enable) override;
//! Sets if the static text should use the override color or the
//! color in the gui skin.
void enableOverrideColor(bool enable) override;
//! Checks if an override color is enabled
bool isOverrideColorEnabled() const override;
//! Checks if an override color is enabled
bool isOverrideColorEnabled() const override;
//! Set whether the text in this label should be clipped if it goes outside bounds
void setTextRestrainedInside(bool restrainedInside) override;
//! Set whether the text in this label should be clipped if it goes outside bounds
void setTextRestrainedInside(bool restrainedInside) override;
//! Checks if the text in this label should be clipped if it goes outside bounds
bool isTextRestrainedInside() const override;
//! Checks if the text in this label should be clipped if it goes outside bounds
bool isTextRestrainedInside() const override;
//! Enables or disables word wrap for using the static text as
//! multiline text control.
void setWordWrap(bool enable) override;
//! Enables or disables word wrap for using the static text as
//! multiline text control.
void setWordWrap(bool enable) override;
//! Checks if word wrap is enabled
bool isWordWrapEnabled() const override;
//! Checks if word wrap is enabled
bool isWordWrapEnabled() const override;
//! Sets the new caption of this element.
void setText(const wchar_t* text) override;
//! Sets the new caption of this element.
void setText(const wchar_t *text) override;
//! Returns the height of the text in pixels when it is drawn.
s32 getTextHeight() const override;
//! Returns the height of the text in pixels when it is drawn.
s32 getTextHeight() const override;
//! Returns the width of the current text, in the current font
s32 getTextWidth() const override;
//! Returns the width of the current text, in the current font
s32 getTextWidth() const override;
//! Updates the absolute position, splits text if word wrap is enabled
void updateAbsolutePosition() override;
//! Updates the absolute position, splits text if word wrap is enabled
void updateAbsolutePosition() override;
//! Set whether the string should be interpreted as right-to-left (RTL) text
/** \note This component does not implement the Unicode bidi standard, the
text of the component should be already RTL if you call this. The
main difference when RTL is enabled is that the linebreaks for multiline
elements are performed starting from the end.
*/
void setRightToLeft(bool rtl) override;
//! Set whether the string should be interpreted as right-to-left (RTL) text
/** \note This component does not implement the Unicode bidi standard, the
text of the component should be already RTL if you call this. The
main difference when RTL is enabled is that the linebreaks for multiline
elements are performed starting from the end.
*/
void setRightToLeft(bool rtl) override;
//! Checks if the text should be interpreted as right-to-left text
bool isRightToLeft() const override;
//! Checks if the text should be interpreted as right-to-left text
bool isRightToLeft() const override;
private:
private:
//! Breaks the single text line.
void breakText();
//! Breaks the single text line.
void breakText();
EGUI_ALIGNMENT HAlign, VAlign;
bool Border;
bool OverrideColorEnabled;
bool OverrideBGColorEnabled;
bool WordWrap;
bool Background;
bool RestrainTextInside;
bool RightToLeft;
EGUI_ALIGNMENT HAlign, VAlign;
bool Border;
bool OverrideColorEnabled;
bool OverrideBGColorEnabled;
bool WordWrap;
bool Background;
bool RestrainTextInside;
bool RightToLeft;
video::SColor OverrideColor, BGColor;
gui::IGUIFont *OverrideFont;
gui::IGUIFont *LastBreakFont; // stored because: if skin changes, line break must be recalculated.
video::SColor OverrideColor, BGColor;
gui::IGUIFont* OverrideFont;
gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated.
core::array< core::stringw > BrokenText;
};
core::array<core::stringw> BrokenText;
};
} // end namespace gui
} // end namespace irr

View File

@ -22,18 +22,18 @@ namespace gui
// ------------------------------------------------------------------
//! constructor
CGUITab::CGUITab(IGUIEnvironment* environment,
IGUIElement* parent, const core::rect<s32>& rectangle,
s32 id)
: IGUITab(environment, parent, id, rectangle),
BackColor(0,0,0,0), OverrideTextColorEnabled(false), TextColor(255,0,0,0),
CGUITab::CGUITab(IGUIEnvironment *environment,
IGUIElement *parent, const core::rect<s32> &rectangle,
s32 id) :
IGUITab(environment, parent, id, rectangle),
BackColor(0, 0, 0, 0), OverrideTextColorEnabled(false), TextColor(255, 0, 0, 0),
DrawBackground(false)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUITab");
#endif
#endif
const IGUISkin* const skin = environment->getSkin();
const IGUISkin *const skin = environment->getSkin();
if (skin)
TextColor = skin->getColor(EGDC_BUTTON_TEXT);
}
@ -52,21 +52,18 @@ void CGUITab::draw()
IGUIElement::draw();
}
//! sets if the tab should draw its background
void CGUITab::setDrawBackground(bool draw)
{
DrawBackground = draw;
}
//! sets the color of the background, if it should be drawn.
void CGUITab::setBackgroundColor(video::SColor c)
{
BackColor = c;
}
//! sets the color of the text
void CGUITab::setTextColor(video::SColor c)
{
@ -74,10 +71,9 @@ void CGUITab::setTextColor(video::SColor c)
TextColor = c;
}
video::SColor CGUITab::getTextColor() const
{
if ( OverrideTextColorEnabled )
if (OverrideTextColorEnabled)
return TextColor;
else
return Environment->getSkin()->getColor(EGDC_BUTTON_TEXT);
@ -89,45 +85,42 @@ bool CGUITab::isDrawingBackground() const
return DrawBackground;
}
//! returns the color of the background
video::SColor CGUITab::getBackgroundColor() const
{
return BackColor;
}
// ------------------------------------------------------------------
// Tabcontrol
// ------------------------------------------------------------------
//! constructor
CGUITabControl::CGUITabControl(IGUIEnvironment* environment,
IGUIElement* parent, const core::rect<s32>& rectangle,
bool fillbackground, bool border, s32 id)
: IGUITabControl(environment, parent, id, rectangle), ActiveTabIndex(-1),
Border(border), FillBackground(fillbackground), ScrollControl(false), TabHeight(0), VerticalAlignment(EGUIA_UPPERLEFT),
UpButton(0), DownButton(0), TabMaxWidth(0), CurrentScrollTabIndex(0), TabExtraWidth(20)
CGUITabControl::CGUITabControl(IGUIEnvironment *environment,
IGUIElement *parent, const core::rect<s32> &rectangle,
bool fillbackground, bool border, s32 id) :
IGUITabControl(environment, parent, id, rectangle),
ActiveTabIndex(-1),
Border(border), FillBackground(fillbackground), ScrollControl(false), TabHeight(0), VerticalAlignment(EGUIA_UPPERLEFT),
UpButton(0), DownButton(0), TabMaxWidth(0), CurrentScrollTabIndex(0), TabExtraWidth(20)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CGUITabControl");
#endif
#endif
IGUISkin* skin = Environment->getSkin();
IGUISpriteBank* sprites = 0;
IGUISkin *skin = Environment->getSkin();
IGUISpriteBank *sprites = 0;
TabHeight = 32;
if (skin)
{
if (skin) {
sprites = skin->getSpriteBank();
TabHeight = skin->getSize(gui::EGDS_BUTTON_HEIGHT) + 2;
}
UpButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
UpButton = Environment->addButton(core::rect<s32>(0, 0, 10, 10), this);
if (UpButton)
{
if (UpButton) {
UpButton->setSpriteBank(sprites);
UpButton->setVisible(false);
UpButton->setSubElement(true);
@ -136,10 +129,9 @@ CGUITabControl::CGUITabControl(IGUIEnvironment* environment,
UpButton->grab();
}
DownButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
DownButton = Environment->addButton(core::rect<s32>(0, 0, 10, 10), this);
if (DownButton)
{
if (DownButton) {
DownButton->setSpriteBank(sprites);
DownButton->setVisible(false);
DownButton->setSubElement(true);
@ -155,8 +147,7 @@ CGUITabControl::CGUITabControl(IGUIEnvironment* environment,
//! destructor
CGUITabControl::~CGUITabControl()
{
for (u32 i=0; i<Tabs.size(); ++i)
{
for (u32 i = 0; i < Tabs.size(); ++i) {
if (Tabs[i])
Tabs[i]->drop();
}
@ -170,20 +161,17 @@ CGUITabControl::~CGUITabControl()
void CGUITabControl::refreshSprites()
{
video::SColor color(255,255,255,255);
IGUISkin* skin = Environment->getSkin();
if (skin)
{
video::SColor color(255, 255, 255, 255);
IGUISkin *skin = Environment->getSkin();
if (skin) {
color = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
if (UpButton)
{
if (UpButton) {
UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), color);
UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), color);
}
if (DownButton)
{
if (DownButton) {
DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), color);
DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), color);
}
@ -191,18 +179,17 @@ void CGUITabControl::refreshSprites()
}
//! Adds a tab
IGUITab* CGUITabControl::addTab(const wchar_t* caption, s32 id)
IGUITab *CGUITabControl::addTab(const wchar_t *caption, s32 id)
{
CGUITab* tab = new CGUITab(Environment, this, calcTabPos(), id);
CGUITab *tab = new CGUITab(Environment, this, calcTabPos(), id);
tab->setText(caption);
tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
tab->setVisible(false);
Tabs.push_back(tab); // no grab as new already creates a reference
Tabs.push_back(tab); // no grab as new already creates a reference
if (ActiveTabIndex == -1)
{
ActiveTabIndex = Tabs.size()-1;
if (ActiveTabIndex == -1) {
ActiveTabIndex = Tabs.size() - 1;
tab->setVisible(true);
}
@ -211,33 +198,29 @@ IGUITab* CGUITabControl::addTab(const wchar_t* caption, s32 id)
return tab;
}
//! adds a tab which has been created elsewhere
s32 CGUITabControl::addTab(IGUITab* tab)
s32 CGUITabControl::addTab(IGUITab *tab)
{
return insertTab( Tabs.size(), tab, false);
return insertTab(Tabs.size(), tab, false);
}
//! Insert the tab at the given index
IGUITab* CGUITabControl::insertTab(s32 idx, const wchar_t* caption, s32 id)
IGUITab *CGUITabControl::insertTab(s32 idx, const wchar_t *caption, s32 id)
{
if ( idx < 0 || idx > (s32)Tabs.size() ) // idx == Tabs.size() is indeed OK here as core::array can handle that
if (idx < 0 || idx > (s32)Tabs.size()) // idx == Tabs.size() is indeed OK here as core::array can handle that
return NULL;
CGUITab* tab = new CGUITab(Environment, this, calcTabPos(), id);
CGUITab *tab = new CGUITab(Environment, this, calcTabPos(), id);
tab->setText(caption);
tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
tab->setVisible(false);
Tabs.insert(tab, (u32)idx);
if (ActiveTabIndex == -1)
{
if (ActiveTabIndex == -1) {
ActiveTabIndex = (u32)idx;
tab->setVisible(true);
}
else if ( idx <= ActiveTabIndex )
{
} else if (idx <= ActiveTabIndex) {
++ActiveTabIndex;
setVisibleTab(ActiveTabIndex);
}
@ -247,51 +230,44 @@ IGUITab* CGUITabControl::insertTab(s32 idx, const wchar_t* caption, s32 id)
return tab;
}
s32 CGUITabControl::insertTab(s32 idx, IGUITab* tab, bool serializationMode)
s32 CGUITabControl::insertTab(s32 idx, IGUITab *tab, bool serializationMode)
{
if (!tab)
return -1;
if ( idx > (s32)Tabs.size() && !serializationMode ) // idx == Tabs.size() is indeed OK here as core::array can handle that
if (idx > (s32)Tabs.size() && !serializationMode) // idx == Tabs.size() is indeed OK here as core::array can handle that
return -1;
// Not allowing to add same tab twice as it would make things complicated (serialization or setting active visible)
if ( getTabIndex(tab) >= 0 )
if (getTabIndex(tab) >= 0)
return -1;
if ( idx < 0 )
if (idx < 0)
idx = (s32)Tabs.size();
if ( tab->getParent() != this )
if (tab->getParent() != this)
this->addChildToEnd(tab);
tab->setVisible(false);
tab->grab();
if ( serializationMode)
{
while ( idx >= (s32)Tabs.size() )
{
if (serializationMode) {
while (idx >= (s32)Tabs.size()) {
Tabs.push_back(0);
}
Tabs[idx] = tab;
if ( idx == ActiveTabIndex) // in serialization that can happen for any index
if (idx == ActiveTabIndex) // in serialization that can happen for any index
{
setVisibleTab(ActiveTabIndex);
tab->setVisible(true);
}
}
else
{
} else {
Tabs.insert(tab, (u32)idx);
if (ActiveTabIndex == -1)
{
if (ActiveTabIndex == -1) {
ActiveTabIndex = idx;
setVisibleTab(ActiveTabIndex);
}
else if ( idx <= ActiveTabIndex)
{
} else if (idx <= ActiveTabIndex) {
++ActiveTabIndex;
setVisibleTab(ActiveTabIndex);
}
@ -303,10 +279,10 @@ s32 CGUITabControl::insertTab(s32 idx, IGUITab* tab, bool serializationMode)
}
//! Removes a child.
void CGUITabControl::removeChild(IGUIElement* child)
void CGUITabControl::removeChild(IGUIElement *child)
{
s32 idx = getTabIndex(child);
if ( idx >= 0 )
if (idx >= 0)
removeTabButNotChild(idx);
// remove real element
@ -315,11 +291,10 @@ void CGUITabControl::removeChild(IGUIElement* child)
recalculateScrollBar();
}
//! Removes a tab from the tabcontrol
void CGUITabControl::removeTab(s32 idx)
{
if ( idx < 0 || idx >= (s32)Tabs.size() )
if (idx < 0 || idx >= (s32)Tabs.size())
return;
removeChild(Tabs[(u32)idx]);
@ -327,20 +302,17 @@ void CGUITabControl::removeTab(s32 idx)
void CGUITabControl::removeTabButNotChild(s32 idx)
{
if ( idx < 0 || idx >= (s32)Tabs.size() )
if (idx < 0 || idx >= (s32)Tabs.size())
return;
Tabs[(u32)idx]->drop();
Tabs.erase((u32)idx);
if ( idx < ActiveTabIndex )
{
if (idx < ActiveTabIndex) {
--ActiveTabIndex;
setVisibleTab(ActiveTabIndex);
}
else if ( idx == ActiveTabIndex )
{
if ( (u32)idx == Tabs.size() )
} else if (idx == ActiveTabIndex) {
if ((u32)idx == Tabs.size())
--ActiveTabIndex;
setVisibleTab(ActiveTabIndex);
}
@ -349,10 +321,8 @@ void CGUITabControl::removeTabButNotChild(s32 idx)
//! Clears the tabcontrol removing all tabs
void CGUITabControl::clear()
{
for (u32 i=0; i<Tabs.size(); ++i)
{
if (Tabs[i])
{
for (u32 i = 0; i < Tabs.size(); ++i) {
if (Tabs[i]) {
IGUIElement::removeChild(Tabs[i]);
Tabs[i]->drop();
}
@ -368,9 +338,8 @@ s32 CGUITabControl::getTabCount() const
return Tabs.size();
}
//! Returns a tab based on zero based index
IGUITab* CGUITabControl::getTab(s32 idx) const
IGUITab *CGUITabControl::getTab(s32 idx) const
{
if (idx < 0 || (u32)idx >= Tabs.size())
return 0;
@ -378,45 +347,35 @@ IGUITab* CGUITabControl::getTab(s32 idx) const
return Tabs[idx];
}
//! called if an event happened.
bool CGUITabControl::OnEvent(const SEvent& event)
bool CGUITabControl::OnEvent(const SEvent &event)
{
if (isEnabled())
{
switch(event.EventType)
{
if (isEnabled()) {
switch (event.EventType) {
case EET_GUI_EVENT:
switch(event.GUIEvent.EventType)
{
switch (event.GUIEvent.EventType) {
case EGET_BUTTON_CLICKED:
if (event.GUIEvent.Caller == UpButton)
{
if (event.GUIEvent.Caller == UpButton) {
scrollLeft();
return true;
}
else if (event.GUIEvent.Caller == DownButton)
{
} else if (event.GUIEvent.Caller == DownButton) {
scrollRight();
return true;
}
break;
break;
default:
break;
break;
}
break;
case EET_MOUSE_INPUT_EVENT:
switch(event.MouseInput.Event)
{
//case EMIE_LMOUSE_PRESSED_DOWN:
switch (event.MouseInput.Event) {
// case EMIE_LMOUSE_PRESSED_DOWN:
// // todo: dragging tabs around
// return true;
case EMIE_LMOUSE_LEFT_UP:
{
case EMIE_LMOUSE_LEFT_UP: {
s32 idx = getTabAt(event.MouseInput.X, event.MouseInput.Y);
if ( idx >= 0 )
{
if (idx >= 0) {
setActiveTab(idx);
return true;
}
@ -434,32 +393,29 @@ bool CGUITabControl::OnEvent(const SEvent& event)
return IGUIElement::OnEvent(event);
}
void CGUITabControl::scrollLeft()
{
if ( CurrentScrollTabIndex > 0 )
if (CurrentScrollTabIndex > 0)
--CurrentScrollTabIndex;
recalculateScrollBar();
}
void CGUITabControl::scrollRight()
{
if ( CurrentScrollTabIndex < (s32)(Tabs.size()) - 1 )
{
if ( needScrollControl(CurrentScrollTabIndex, true) )
if (CurrentScrollTabIndex < (s32)(Tabs.size()) - 1) {
if (needScrollControl(CurrentScrollTabIndex, true))
++CurrentScrollTabIndex;
}
recalculateScrollBar();
}
s32 CGUITabControl::calcTabWidth(IGUIFont* font, const wchar_t* text) const
s32 CGUITabControl::calcTabWidth(IGUIFont *font, const wchar_t *text) const
{
if ( !font )
if (!font)
return 0;
s32 len = font->getDimension(text).Width + TabExtraWidth;
if ( TabMaxWidth > 0 && len > TabMaxWidth )
if (TabMaxWidth > 0 && len > TabMaxWidth)
len = TabMaxWidth;
return len;
@ -467,14 +423,14 @@ s32 CGUITabControl::calcTabWidth(IGUIFont* font, const wchar_t* text) const
bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl, s32 *pos_rightmost)
{
if ( startIndex < 0 )
if (startIndex < 0)
startIndex = 0;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (!skin)
return false;
IGUIFont* font = skin->getFont();
IGUIFont *font = skin->getFont();
if (Tabs.empty())
return false;
@ -483,20 +439,16 @@ bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl, s
return false;
s32 pos = AbsoluteRect.UpperLeftCorner.X + 2;
const s32 pos_right = withScrollControl ?
UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 :
AbsoluteRect.LowerRightCorner.X;
const s32 pos_right = withScrollControl ? UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 : AbsoluteRect.LowerRightCorner.X;
for (s32 i = startIndex; i < (s32)Tabs.size(); ++i)
{
for (s32 i = startIndex; i < (s32)Tabs.size(); ++i) {
// get Text
const wchar_t* text = 0;
if (Tabs[i])
{
const wchar_t *text = 0;
if (Tabs[i]) {
text = Tabs[i]->getText();
// get text length
s32 len = calcTabWidth(font, text); // always without withScrollControl here or len would be shortened
s32 len = calcTabWidth(font, text); // always without withScrollControl here or len would be shortened
pos += len;
}
@ -509,7 +461,6 @@ bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl, s
return false;
}
s32 CGUITabControl::calculateScrollIndexFromActive()
{
if (!ScrollControl || Tabs.empty())
@ -566,27 +517,21 @@ core::rect<s32> CGUITabControl::calcTabPos()
core::rect<s32> r;
r.UpperLeftCorner.X = 0;
r.LowerRightCorner.X = AbsoluteRect.getWidth();
if ( Border )
{
if (Border) {
++r.UpperLeftCorner.X;
--r.LowerRightCorner.X;
}
if ( VerticalAlignment == EGUIA_UPPERLEFT )
{
r.UpperLeftCorner.Y = TabHeight+2;
r.LowerRightCorner.Y = AbsoluteRect.getHeight()-1;
if ( Border )
{
if (VerticalAlignment == EGUIA_UPPERLEFT) {
r.UpperLeftCorner.Y = TabHeight + 2;
r.LowerRightCorner.Y = AbsoluteRect.getHeight() - 1;
if (Border) {
--r.LowerRightCorner.Y;
}
}
else
{
} else {
r.UpperLeftCorner.Y = 0;
r.LowerRightCorner.Y = AbsoluteRect.getHeight()-(TabHeight+2);
if ( Border )
{
r.LowerRightCorner.Y = AbsoluteRect.getHeight() - (TabHeight + 2);
if (Border) {
++r.UpperLeftCorner.Y;
}
}
@ -594,19 +539,18 @@ core::rect<s32> CGUITabControl::calcTabPos()
return r;
}
//! draws the element and its children
void CGUITabControl::draw()
{
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
if (!skin)
return;
IGUIFont* font = skin->getFont();
video::IVideoDriver* driver = Environment->getVideoDriver();
IGUIFont *font = skin->getFont();
video::IVideoDriver *driver = Environment->getVideoDriver();
core::rect<s32> frameRect(AbsoluteRect);
@ -618,13 +562,10 @@ void CGUITabControl::draw()
return;
// tab button bar can be above or below the tabs
if ( VerticalAlignment == EGUIA_UPPERLEFT )
{
if (VerticalAlignment == EGUIA_UPPERLEFT) {
frameRect.UpperLeftCorner.Y += 2;
frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
}
else
{
} else {
frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight - 1;
frameRect.LowerRightCorner.Y -= 2;
}
@ -639,14 +580,13 @@ void CGUITabControl::draw()
s32 left = 0;
s32 right = 0;
//const wchar_t* activetext = 0;
// const wchar_t* activetext = 0;
IGUITab *activeTab = 0;
// Draw all tab-buttons except the active one
for (u32 i = CurrentScrollTabIndex; i < Tabs.size() && !needRightScroll; ++i)
{
for (u32 i = CurrentScrollTabIndex; i < Tabs.size() && !needRightScroll; ++i) {
// get Text
const wchar_t* text = 0;
const wchar_t *text = 0;
if (Tabs[i])
text = Tabs[i]->getText();
@ -666,44 +606,39 @@ void CGUITabControl::draw()
pos += len;
if ((s32)i == ActiveTabIndex)
{
if ((s32)i == ActiveTabIndex) {
// for active button just remember values
left = frameRect.UpperLeftCorner.X;
right = frameRect.LowerRightCorner.X;
//activetext = text;
// activetext = text;
activeTab = Tabs[i];
}
else
{
} else {
skin->draw3DTabButton(this, false, frameRect, &AbsoluteClippingRect, VerticalAlignment);
// draw text
core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
textClipRect.clipAgainst(AbsoluteClippingRect);
font->draw(text, frameRect, Tabs[i]->getTextColor(),
true, true, &textClipRect);
true, true, &textClipRect);
}
}
// Draw active tab button
// Drawn later than other buttons because it draw over the buttons before/after it.
if (left != 0 && right != 0 && activeTab != 0)
{
if (left != 0 && right != 0 && activeTab != 0) {
// draw upper highlight frame
if ( VerticalAlignment == EGUIA_UPPERLEFT )
{
frameRect.UpperLeftCorner.X = left-2;
frameRect.LowerRightCorner.X = right+2;
if (VerticalAlignment == EGUIA_UPPERLEFT) {
frameRect.UpperLeftCorner.X = left - 2;
frameRect.LowerRightCorner.X = right + 2;
frameRect.UpperLeftCorner.Y -= 2;
skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
// draw text
core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
textClipRect.clipAgainst(AbsoluteClippingRect);
font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
true, true, &textClipRect);
true, true, &textClipRect);
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = left - 1;
@ -714,18 +649,16 @@ void CGUITabControl::draw()
tr.UpperLeftCorner.X = right;
tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
}
else
{
frameRect.UpperLeftCorner.X = left-2;
frameRect.LowerRightCorner.X = right+2;
} else {
frameRect.UpperLeftCorner.X = left - 2;
frameRect.LowerRightCorner.X = right + 2;
frameRect.LowerRightCorner.Y += 2;
skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
// draw text
font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
true, true, &frameRect);
true, true, &frameRect);
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = left - 1;
@ -737,9 +670,7 @@ void CGUITabControl::draw()
tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
}
}
else
{
} else {
// No active tab
// Draw a line separating button bar from tab area
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
@ -747,12 +678,9 @@ void CGUITabControl::draw()
tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
if ( VerticalAlignment == EGUIA_UPPERLEFT )
{
if (VerticalAlignment == EGUIA_UPPERLEFT) {
driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
}
else
{
} else {
tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
@ -763,20 +691,19 @@ void CGUITabControl::draw()
skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment);
// enable scrollcontrols on need
if ( UpButton )
if (UpButton)
UpButton->setEnabled(needLeftScroll);
if ( DownButton )
if (DownButton)
DownButton->setEnabled(needRightScroll);
refreshSprites();
IGUIElement::draw();
}
//! Set the height of the tabs
void CGUITabControl::setTabHeight( s32 height )
void CGUITabControl::setTabHeight(s32 height)
{
if ( height < 0 )
if (height < 0)
height = 0;
TabHeight = height;
@ -785,7 +712,6 @@ void CGUITabControl::setTabHeight( s32 height )
recalculateScrollBar();
}
//! Get the height of the tabs
s32 CGUITabControl::getTabHeight() const
{
@ -793,7 +719,7 @@ s32 CGUITabControl::getTabHeight() const
}
//! set the maximal width of a tab. Per default width is 0 which means "no width restriction".
void CGUITabControl::setTabMaxWidth(s32 width )
void CGUITabControl::setTabMaxWidth(s32 width)
{
TabMaxWidth = width;
}
@ -804,11 +730,10 @@ s32 CGUITabControl::getTabMaxWidth() const
return TabMaxWidth;
}
//! Set the extra width added to tabs on each side of the text
void CGUITabControl::setTabExtraWidth( s32 extraWidth )
void CGUITabControl::setTabExtraWidth(s32 extraWidth)
{
if ( extraWidth < 0 )
if (extraWidth < 0)
extraWidth = 0;
TabExtraWidth = extraWidth;
@ -816,14 +741,12 @@ void CGUITabControl::setTabExtraWidth( s32 extraWidth )
recalculateScrollBar();
}
//! Get the extra width added to tabs on each side of the text
s32 CGUITabControl::getTabExtraWidth() const
{
return TabExtraWidth;
}
void CGUITabControl::recalculateScrollBar()
{
// Down: to right, Up: to left
@ -832,23 +755,20 @@ void CGUITabControl::recalculateScrollBar()
ScrollControl = needScrollControl() || CurrentScrollTabIndex > 0;
if (ScrollControl)
{
UpButton->setVisible( true );
DownButton->setVisible( true );
}
else
{
UpButton->setVisible( false );
DownButton->setVisible( false );
if (ScrollControl) {
UpButton->setVisible(true);
DownButton->setVisible(true);
} else {
UpButton->setVisible(false);
DownButton->setVisible(false);
}
bringToFront( UpButton );
bringToFront( DownButton );
bringToFront(UpButton);
bringToFront(DownButton);
}
//! Set the alignment of the tabs
void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment )
void CGUITabControl::setTabVerticalAlignment(EGUI_ALIGNMENT alignment)
{
VerticalAlignment = alignment;
@ -856,45 +776,40 @@ void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment )
recalculateScrollBar();
core::rect<s32> r(calcTabPos());
for ( u32 i=0; i<Tabs.size(); ++i )
{
for (u32 i = 0; i < Tabs.size(); ++i) {
Tabs[i]->setRelativePosition(r);
}
}
void CGUITabControl::recalculateScrollButtonPlacement()
{
IGUISkin* skin = Environment->getSkin();
IGUISkin *skin = Environment->getSkin();
s32 ButtonSize = 16;
s32 ButtonHeight = TabHeight - 2;
if ( ButtonHeight < 0 )
if (ButtonHeight < 0)
ButtonHeight = TabHeight;
if (skin)
{
if (skin) {
ButtonSize = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
if (ButtonSize > TabHeight)
ButtonSize = TabHeight;
}
s32 ButtonX = RelativeRect.getWidth() - (s32)(2.5f*(f32)ButtonSize) - 1;
s32 ButtonX = RelativeRect.getWidth() - (s32)(2.5f * (f32)ButtonSize) - 1;
s32 ButtonY = 0;
if (VerticalAlignment == EGUIA_UPPERLEFT)
{
if (VerticalAlignment == EGUIA_UPPERLEFT) {
ButtonY = 2 + (TabHeight / 2) - (ButtonHeight / 2);
UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
}
else
{
} else {
ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonHeight / 2) - 2;
UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
}
UpButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
UpButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX + ButtonSize, ButtonY + ButtonHeight));
ButtonX += ButtonSize + 1;
DownButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
DownButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX + ButtonSize, ButtonY + ButtonHeight));
}
//! Get the alignment of the tabs
@ -903,22 +818,18 @@ EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const
return VerticalAlignment;
}
s32 CGUITabControl::getTabAt(s32 xpos, s32 ypos) const
{
core::position2di p(xpos, ypos);
IGUISkin* skin = Environment->getSkin();
IGUIFont* font = skin->getFont();
IGUISkin *skin = Environment->getSkin();
IGUIFont *font = skin->getFont();
core::rect<s32> frameRect(AbsoluteRect);
if ( VerticalAlignment == EGUIA_UPPERLEFT )
{
if (VerticalAlignment == EGUIA_UPPERLEFT) {
frameRect.UpperLeftCorner.Y += 2;
frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
}
else
{
} else {
frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight;
}
@ -928,10 +839,9 @@ s32 CGUITabControl::getTabAt(s32 xpos, s32 ypos) const
return -1;
bool abort = false;
for (s32 i = CurrentScrollTabIndex; i < (s32)Tabs.size() && !abort; ++i)
{
for (s32 i = CurrentScrollTabIndex; i < (s32)Tabs.size() && !abort; ++i) {
// get Text
const wchar_t* text = 0;
const wchar_t *text = 0;
if (Tabs[i])
text = Tabs[i]->getText();
@ -951,11 +861,9 @@ s32 CGUITabControl::getTabAt(s32 xpos, s32 ypos) const
pos += len;
if (frameRect.isPointInside(p))
{
if (frameRect.isPointInside(p)) {
return i;
}
}
return -1;
}
@ -966,7 +874,6 @@ s32 CGUITabControl::getActiveTab() const
return ActiveTabIndex;
}
//! Brings a tab to front.
bool CGUITabControl::setActiveTab(s32 idx)
{
@ -979,8 +886,7 @@ bool CGUITabControl::setActiveTab(s32 idx)
setVisibleTab(ActiveTabIndex);
if (changed && Parent)
{
if (changed && Parent) {
SEvent event;
event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this;
@ -999,12 +905,11 @@ bool CGUITabControl::setActiveTab(s32 idx)
void CGUITabControl::setVisibleTab(s32 idx)
{
for (u32 i=0; i<Tabs.size(); ++i)
for (u32 i = 0; i < Tabs.size(); ++i)
if (Tabs[i])
Tabs[i]->setVisible( (s32)i == idx );
Tabs[i]->setVisible((s32)i == idx);
}
bool CGUITabControl::setActiveTab(IGUITab *tab)
{
return setActiveTab(getTabIndex(tab));
@ -1012,7 +917,7 @@ bool CGUITabControl::setActiveTab(IGUITab *tab)
s32 CGUITabControl::getTabIndex(const IGUIElement *tab) const
{
for (u32 i=0; i<Tabs.size(); ++i)
for (u32 i = 0; i < Tabs.size(); ++i)
if (Tabs[i] == tab)
return (s32)i;
@ -1026,6 +931,5 @@ void CGUITabControl::updateAbsolutePosition()
recalculateScrollBar();
}
} // end namespace irr
} // end namespace gui

View File

@ -12,170 +12,164 @@ namespace irr
{
namespace gui
{
class CGUITabControl;
class IGUIButton;
class CGUITabControl;
class IGUIButton;
// A tab, onto which other gui elements could be added.
class CGUITab : public IGUITab
{
public:
//! constructor
CGUITab(IGUIEnvironment* environment,
IGUIElement* parent, const core::rect<s32>& rectangle,
// A tab, onto which other gui elements could be added.
class CGUITab : public IGUITab
{
public:
//! constructor
CGUITab(IGUIEnvironment *environment,
IGUIElement *parent, const core::rect<s32> &rectangle,
s32 id);
//! draws the element and its children
void draw() override;
//! draws the element and its children
void draw() override;
//! sets if the tab should draw its background
void setDrawBackground(bool draw=true) override;
//! sets if the tab should draw its background
void setDrawBackground(bool draw = true) override;
//! sets the color of the background, if it should be drawn.
void setBackgroundColor(video::SColor c) override;
//! sets the color of the background, if it should be drawn.
void setBackgroundColor(video::SColor c) override;
//! sets the color of the text
void setTextColor(video::SColor c) override;
//! sets the color of the text
void setTextColor(video::SColor c) override;
//! returns true if the tab is drawing its background, false if not
bool isDrawingBackground() const override;
//! returns true if the tab is drawing its background, false if not
bool isDrawingBackground() const override;
//! returns the color of the background
video::SColor getBackgroundColor() const override;
//! returns the color of the background
video::SColor getBackgroundColor() const override;
video::SColor getTextColor() const override;
video::SColor getTextColor() const override;
private:
private:
video::SColor BackColor;
bool OverrideTextColorEnabled;
video::SColor TextColor;
bool DrawBackground;
};
video::SColor BackColor;
bool OverrideTextColorEnabled;
video::SColor TextColor;
bool DrawBackground;
};
//! A standard tab control
class CGUITabControl : public IGUITabControl
{
public:
//! destructor
CGUITabControl(IGUIEnvironment *environment,
IGUIElement *parent, const core::rect<s32> &rectangle,
bool fillbackground = true, bool border = true, s32 id = -1);
//! destructor
virtual ~CGUITabControl();
//! A standard tab control
class CGUITabControl : public IGUITabControl
{
public:
//! Adds a tab
IGUITab *addTab(const wchar_t *caption, s32 id = -1) override;
//! destructor
CGUITabControl(IGUIEnvironment* environment,
IGUIElement* parent, const core::rect<s32>& rectangle,
bool fillbackground=true, bool border=true, s32 id=-1);
//! Adds an existing tab
s32 addTab(IGUITab *tab) override;
//! destructor
virtual ~CGUITabControl();
//! Insert the tab at the given index
IGUITab *insertTab(s32 idx, const wchar_t *caption, s32 id = -1) override;
//! Adds a tab
IGUITab* addTab(const wchar_t* caption, s32 id=-1) override;
//! Insert an existing tab
/** Note that it will also add the tab as a child of this TabControl.
\return Index of added tab (should be same as the one passed) or -1 for failure*/
s32 insertTab(s32 idx, IGUITab *tab, bool serializationMode) override;
//! Adds an existing tab
s32 addTab(IGUITab* tab) override;
//! Removes a tab from the tabcontrol
void removeTab(s32 idx) override;
//! Insert the tab at the given index
IGUITab* insertTab(s32 idx, const wchar_t* caption, s32 id=-1) override;
//! Clears the tabcontrol removing all tabs
void clear() override;
//! Insert an existing tab
/** Note that it will also add the tab as a child of this TabControl.
\return Index of added tab (should be same as the one passed) or -1 for failure*/
s32 insertTab(s32 idx, IGUITab* tab, bool serializationMode) override;
//! Returns amount of tabs in the tabcontrol
s32 getTabCount() const override;
//! Removes a tab from the tabcontrol
void removeTab(s32 idx) override;
//! Returns a tab based on zero based index
IGUITab *getTab(s32 idx) const override;
//! Clears the tabcontrol removing all tabs
void clear() override;
//! Brings a tab to front.
bool setActiveTab(s32 idx) override;
//! Returns amount of tabs in the tabcontrol
s32 getTabCount() const override;
//! Brings a tab to front.
bool setActiveTab(IGUITab *tab) override;
//! Returns a tab based on zero based index
IGUITab* getTab(s32 idx) const override;
//! For given given tab find it's zero-based index (or -1 for not found)
s32 getTabIndex(const IGUIElement *tab) const override;
//! Brings a tab to front.
bool setActiveTab(s32 idx) override;
//! Returns which tab is currently active
s32 getActiveTab() const override;
//! Brings a tab to front.
bool setActiveTab(IGUITab *tab) override;
//! get the the id of the tab at the given absolute coordinates
s32 getTabAt(s32 xpos, s32 ypos) const override;
//! For given given tab find it's zero-based index (or -1 for not found)
s32 getTabIndex(const IGUIElement *tab) const override;
//! called if an event happened.
bool OnEvent(const SEvent &event) override;
//! Returns which tab is currently active
s32 getActiveTab() const override;
//! draws the element and its children
void draw() override;
//! get the the id of the tab at the given absolute coordinates
s32 getTabAt(s32 xpos, s32 ypos) const override;
//! Removes a child.
void removeChild(IGUIElement *child) override;
//! called if an event happened.
bool OnEvent(const SEvent& event) override;
//! Set the height of the tabs
void setTabHeight(s32 height) override;
//! draws the element and its children
void draw() override;
//! Get the height of the tabs
s32 getTabHeight() const override;
//! Removes a child.
void removeChild(IGUIElement* child) override;
//! set the maximal width of a tab. Per default width is 0 which means "no width restriction".
void setTabMaxWidth(s32 width) override;
//! Set the height of the tabs
void setTabHeight( s32 height ) override;
//! get the maximal width of a tab
s32 getTabMaxWidth() const override;
//! Get the height of the tabs
s32 getTabHeight() const override;
//! Set the alignment of the tabs
//! note: EGUIA_CENTER is not an option
void setTabVerticalAlignment(gui::EGUI_ALIGNMENT alignment) override;
//! set the maximal width of a tab. Per default width is 0 which means "no width restriction".
void setTabMaxWidth(s32 width ) override;
//! Get the alignment of the tabs
gui::EGUI_ALIGNMENT getTabVerticalAlignment() const override;
//! get the maximal width of a tab
s32 getTabMaxWidth() const override;
//! Set the extra width added to tabs on each side of the text
void setTabExtraWidth(s32 extraWidth) override;
//! Set the alignment of the tabs
//! note: EGUIA_CENTER is not an option
void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ) override;
//! Get the extra width added to tabs on each side of the text
s32 getTabExtraWidth() const override;
//! Get the alignment of the tabs
gui::EGUI_ALIGNMENT getTabVerticalAlignment() const override;
//! Update the position of the element, decides scroll button status
void updateAbsolutePosition() override;
//! Set the extra width added to tabs on each side of the text
void setTabExtraWidth( s32 extraWidth ) override;
private:
void scrollLeft();
void scrollRight();
//! Indicates whether the tabs overflow in X direction
bool needScrollControl(s32 startIndex = 0, bool withScrollControl = false, s32 *pos_rightmost = nullptr);
//! Left index calculation based on the selected tab
s32 calculateScrollIndexFromActive();
s32 calcTabWidth(IGUIFont *font, const wchar_t *text) const;
core::rect<s32> calcTabPos();
void setVisibleTab(s32 idx);
void removeTabButNotChild(s32 idx);
//! Get the extra width added to tabs on each side of the text
s32 getTabExtraWidth() const override;
//! Update the position of the element, decides scroll button status
void updateAbsolutePosition() override;
private:
void scrollLeft();
void scrollRight();
//! Indicates whether the tabs overflow in X direction
bool needScrollControl( s32 startIndex=0, bool withScrollControl=false, s32 *pos_rightmost=nullptr );
//! Left index calculation based on the selected tab
s32 calculateScrollIndexFromActive();
s32 calcTabWidth(IGUIFont* font, const wchar_t* text) const;
core::rect<s32> calcTabPos();
void setVisibleTab(s32 idx);
void removeTabButNotChild(s32 idx);
void recalculateScrollButtonPlacement();
void recalculateScrollBar();
void refreshSprites();
core::array<IGUITab*> Tabs;
s32 ActiveTabIndex;
bool Border;
bool FillBackground;
bool ScrollControl;
s32 TabHeight;
gui::EGUI_ALIGNMENT VerticalAlignment;
IGUIButton* UpButton;
IGUIButton* DownButton;
s32 TabMaxWidth;
s32 CurrentScrollTabIndex;
s32 TabExtraWidth;
};
void recalculateScrollButtonPlacement();
void recalculateScrollBar();
void refreshSprites();
core::array<IGUITab *> Tabs;
s32 ActiveTabIndex;
bool Border;
bool FillBackground;
bool ScrollControl;
s32 TabHeight;
gui::EGUI_ALIGNMENT VerticalAlignment;
IGUIButton *UpButton;
IGUIButton *DownButton;
s32 TabMaxWidth;
s32 CurrentScrollTabIndex;
s32 TabExtraWidth;
};
} // end namespace gui
} // end namespace irr

View File

@ -15,100 +15,89 @@ namespace video
{
//! Constructor from raw data
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, void* data,
bool ownForeignMemory, bool deleteMemory) : IImage(format, size, deleteMemory)
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32> &size, void *data,
bool ownForeignMemory, bool deleteMemory) :
IImage(format, size, deleteMemory)
{
if (ownForeignMemory)
{
Data = (u8*)data;
}
else
{
if (ownForeignMemory) {
Data = (u8 *)data;
} else {
const u32 dataSize = getDataSizeFromFormat(Format, Size.Width, Size.Height);
const u32 allocSize = align_next(dataSize, 16);
// allocate as u32 to ensure enough alignment when casted
Data = reinterpret_cast<u8*>(new u32[allocSize / 4]);
Data = reinterpret_cast<u8 *>(new u32[allocSize / 4]);
memcpy(Data, data, dataSize);
DeleteMemory = true;
}
}
//! Constructor of empty image
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) : IImage(format, size, true)
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32> &size) :
IImage(format, size, true)
{
const u32 dataSize = getDataSizeFromFormat(Format, Size.Width, Size.Height);
const u32 allocSize = align_next(dataSize, 16);
Data = reinterpret_cast<u8*>(new u32[allocSize / 4]);
Data = reinterpret_cast<u8 *>(new u32[allocSize / 4]);
DeleteMemory = true;
}
//! sets a pixel
void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend)
{
if (x >= Size.Width || y >= Size.Height)
return;
switch(Format)
{
case ECF_A1R5G5B5:
{
u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 ));
*dest = video::A8R8G8B8toA1R5G5B5( color.color );
} break;
switch (Format) {
case ECF_A1R5G5B5: {
u16 *dest = (u16 *)(Data + (y * Pitch) + (x << 1));
*dest = video::A8R8G8B8toA1R5G5B5(color.color);
} break;
case ECF_R5G6B5:
{
u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 ));
*dest = video::A8R8G8B8toR5G6B5( color.color );
} break;
case ECF_R5G6B5: {
u16 *dest = (u16 *)(Data + (y * Pitch) + (x << 1));
*dest = video::A8R8G8B8toR5G6B5(color.color);
} break;
case ECF_R8G8B8:
{
u8* dest = Data + ( y * Pitch ) + ( x * 3 );
dest[0] = (u8)color.getRed();
dest[1] = (u8)color.getGreen();
dest[2] = (u8)color.getBlue();
} break;
case ECF_R8G8B8: {
u8 *dest = Data + (y * Pitch) + (x * 3);
dest[0] = (u8)color.getRed();
dest[1] = (u8)color.getGreen();
dest[2] = (u8)color.getBlue();
} break;
case ECF_A8R8G8B8:
{
u32 * dest = (u32*) (Data + ( y * Pitch ) + ( x << 2 ));
*dest = blend ? PixelBlend32 ( *dest, color.color ) : color.color;
} break;
case ECF_A8R8G8B8: {
u32 *dest = (u32 *)(Data + (y * Pitch) + (x << 2));
*dest = blend ? PixelBlend32(*dest, color.color) : color.color;
} break;
case ECF_UNKNOWN:
os::Printer::log("IImage::setPixel unknown format.", ELL_WARNING);
return;
case ECF_UNKNOWN:
os::Printer::log("IImage::setPixel unknown format.", ELL_WARNING);
return;
default:
break;
default:
break;
}
}
//! returns a pixel
SColor CImage::getPixel(u32 x, u32 y) const
{
if (x >= Size.Width || y >= Size.Height)
return SColor(0);
switch(Format)
{
switch (Format) {
case ECF_A1R5G5B5:
return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
return A1R5G5B5toA8R8G8B8(((u16 *)Data)[y * Size.Width + x]);
case ECF_R5G6B5:
return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
return R5G6B5toA8R8G8B8(((u16 *)Data)[y * Size.Width + x]);
case ECF_A8R8G8B8:
return ((u32*)Data)[y*Size.Width + x];
case ECF_R8G8B8:
{
u8* p = Data+(y*3)*Size.Width + (x*3);
return SColor(255,p[0],p[1],p[2]);
}
return ((u32 *)Data)[y * Size.Width + x];
case ECF_R8G8B8: {
u8 *p = Data + (y * 3) * Size.Width + (x * 3);
return SColor(255, p[0], p[1], p[2]);
}
case ECF_UNKNOWN:
os::Printer::log("IImage::getPixel unknown format.", ELL_WARNING);
@ -121,32 +110,26 @@ SColor CImage::getPixel(u32 x, u32 y) const
return SColor(0);
}
//! copies this surface into another at given position
void CImage::copyTo(IImage* target, const core::position2d<s32>& pos)
void CImage::copyTo(IImage *target, const core::position2d<s32> &pos)
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
return;
}
if (!Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0)
&& target && pos.X == 0 && pos.Y == 0 &&
CColorConverter::canConvertFormat(Format, target->getColorFormat()))
{
if (!Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0) && target && pos.X == 0 && pos.Y == 0 &&
CColorConverter::canConvertFormat(Format, target->getColorFormat())) {
// No fast blitting, but copyToScaling uses other color conversions and might work
irr::core::dimension2du dim(target->getDimension());
copyToScaling(target->getData(), dim.Width, dim.Height, target->getColorFormat(), target->getPitch());
}
}
//! copies this surface partially into another at given position
void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect)
void CImage::copyTo(IImage *target, const core::position2d<s32> &pos, const core::rect<s32> &sourceRect, const core::rect<s32> *clipRect)
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
return;
}
@ -154,27 +137,23 @@ void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core
Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0);
}
//! copies this surface into another, using the alpha mask, a cliprect and a color to add with
void CImage::copyToWithAlpha(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const SColor &color, const core::rect<s32>* clipRect, bool combineAlpha)
void CImage::copyToWithAlpha(IImage *target, const core::position2d<s32> &pos, const core::rect<s32> &sourceRect, const SColor &color, const core::rect<s32> *clipRect, bool combineAlpha)
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::copyToWithAlpha method doesn't work with compressed images.", ELL_WARNING);
return;
}
eBlitter op = combineAlpha ? BLITTER_TEXTURE_COMBINE_ALPHA :
color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND : BLITTER_TEXTURE_ALPHA_COLOR_BLEND;
Blit(op,target, clipRect, &pos, this, &sourceRect, color.color);
eBlitter op = combineAlpha ? BLITTER_TEXTURE_COMBINE_ALPHA : color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND
: BLITTER_TEXTURE_ALPHA_COLOR_BLEND;
Blit(op, target, clipRect, &pos, this, &sourceRect, color.color);
}
//! copies this surface into another, if it has the exact same size and format.
bool CImage::copyToNoScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch) const
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::copyToNoScaling method doesn't work with compressed images.", ELL_WARNING);
return false;
}
@ -182,29 +161,25 @@ bool CImage::copyToNoScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT
if (!target || !width || !height || !Size.Width || !Size.Height)
return false;
const u32 bpp=getBitsPerPixelFromFormat(format)/8;
if (0==pitch)
pitch = width*bpp;
const u32 bpp = getBitsPerPixelFromFormat(format) / 8;
if (0 == pitch)
pitch = width * bpp;
if (!(Format==format && Size.Width==width && Size.Height==height))
if (!(Format == format && Size.Width == width && Size.Height == height))
return false;
if (pitch==Pitch)
{
memcpy(target, Data, (size_t)height*pitch);
}
else
{
u8* tgtpos = (u8*) target;
u8* srcpos = Data;
const u32 bwidth = width*bpp;
const u32 rest = pitch-bwidth;
for (u32 y=0; y<height; ++y)
{
if (pitch == Pitch) {
memcpy(target, Data, (size_t)height * pitch);
} else {
u8 *tgtpos = (u8 *)target;
u8 *srcpos = Data;
const u32 bwidth = width * bpp;
const u32 rest = pitch - bwidth;
for (u32 y = 0; y < height; ++y) {
// copy scanline
memcpy(tgtpos, srcpos, bwidth);
// clear pitch
memset(tgtpos+bwidth, 0, rest);
memset(tgtpos + bwidth, 0, rest);
tgtpos += pitch;
srcpos += Pitch;
}
@ -213,13 +188,11 @@ bool CImage::copyToNoScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT
return true;
}
//! copies this surface into another, scaling it to the target image size
// note: this is very very slow.
void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch)
void CImage::copyToScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch)
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
return;
}
@ -227,9 +200,9 @@ void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT fo
if (!target || !width || !height || !Size.Width || !Size.Height)
return;
const u32 bpp=getBitsPerPixelFromFormat(format)/8;
if (0==pitch)
pitch = width*bpp;
const u32 bpp = getBitsPerPixelFromFormat(format) / 8;
if (0 == pitch)
pitch = width * bpp;
if (copyToNoScaling(target, width, height, format, pitch))
return;
@ -247,42 +220,36 @@ void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT fo
f32 sourceXStart = 0.f, sourceYStart = 0.f;
if (width % Size.Width == 0)
sourceXStep = (f32)(Size.Width) / (f32)(width);
else
{
sourceXStep = width > 1 ? (f32)(Size.Width-1) / (f32)(width-1) : 0.f;
sourceXStart = 0.5f; // for rounding to nearest pixel
else {
sourceXStep = width > 1 ? (f32)(Size.Width - 1) / (f32)(width - 1) : 0.f;
sourceXStart = 0.5f; // for rounding to nearest pixel
}
if (height % Size.Height == 0)
sourceYStep = (f32)(Size.Height) / (f32)(height);
else
{
sourceYStep = height > 1 ? (f32)(Size.Height-1) / (f32)(height-1) : 0.f;
sourceYStart = 0.5f; // for rounding to nearest pixel
else {
sourceYStep = height > 1 ? (f32)(Size.Height - 1) / (f32)(height - 1) : 0.f;
sourceYStart = 0.5f; // for rounding to nearest pixel
}
s32 yval=0, syval=0;
s32 yval = 0, syval = 0;
f32 sy = sourceYStart;
for (u32 y=0; y<height; ++y)
{
for (u32 y = 0; y < height; ++y) {
f32 sx = sourceXStart;
for (u32 x=0; x<width; ++x)
{
CColorConverter::convert_viaFormat(Data+ syval + ((s32)sx)*BytesPerPixel, Format, 1, ((u8*)target)+ yval + (x*bpp), format);
sx+=sourceXStep;
for (u32 x = 0; x < width; ++x) {
CColorConverter::convert_viaFormat(Data + syval + ((s32)sx) * BytesPerPixel, Format, 1, ((u8 *)target) + yval + (x * bpp), format);
sx += sourceXStep;
}
sy+=sourceYStep;
syval=(s32)(sy)*Pitch;
yval+=pitch;
sy += sourceYStep;
syval = (s32)(sy)*Pitch;
yval += pitch;
}
}
//! copies this surface into another, scaling it to the target image size
// note: this is very very slow.
void CImage::copyToScaling(IImage* target)
void CImage::copyToScaling(IImage *target)
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
return;
}
@ -290,10 +257,9 @@ void CImage::copyToScaling(IImage* target)
if (!target)
return;
const core::dimension2d<u32>& targetSize = target->getDimension();
const core::dimension2d<u32> &targetSize = target->getDimension();
if (targetSize==Size)
{
if (targetSize == Size) {
copyTo(target);
return;
}
@ -301,90 +267,78 @@ void CImage::copyToScaling(IImage* target)
copyToScaling(target->getData(), targetSize.Width, targetSize.Height, target->getColorFormat());
}
//! copies this surface into another, scaling it to fit it.
void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend)
void CImage::copyToScalingBoxFilter(IImage *target, s32 bias, bool blend)
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::copyToScalingBoxFilter method doesn't work with compressed images.", ELL_WARNING);
return;
}
const core::dimension2d<u32> destSize = target->getDimension();
const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width;
const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height;
const f32 sourceXStep = (f32)Size.Width / (f32)destSize.Width;
const f32 sourceYStep = (f32)Size.Height / (f32)destSize.Height;
s32 fx = core::ceil32( sourceXStep );
s32 fy = core::ceil32( sourceYStep );
s32 fx = core::ceil32(sourceXStep);
s32 fy = core::ceil32(sourceYStep);
f32 sx;
f32 sy;
sy = 0.f;
for ( u32 y = 0; y != destSize.Height; ++y )
{
for (u32 y = 0; y != destSize.Height; ++y) {
sx = 0.f;
for ( u32 x = 0; x != destSize.Width; ++x )
{
target->setPixel( x, y,
getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ), blend );
for (u32 x = 0; x != destSize.Width; ++x) {
target->setPixel(x, y,
getPixelBox(core::floor32(sx), core::floor32(sy), fx, fy, bias), blend);
sx += sourceXStep;
}
sy += sourceYStep;
}
}
//! fills the surface with given color
void CImage::fill(const SColor &color)
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::fill method doesn't work with compressed images.", ELL_WARNING);
return;
}
u32 c;
switch ( Format )
{
case ECF_A1R5G5B5:
c = color.toA1R5G5B5();
c |= c << 16;
break;
case ECF_R5G6B5:
c = video::A8R8G8B8toR5G6B5( color.color );
c |= c << 16;
break;
case ECF_A8R8G8B8:
c = color.color;
break;
case ECF_R8G8B8:
{
u8 rgb[3];
CColorConverter::convert_A8R8G8B8toR8G8B8(&color, 1, rgb);
const u32 size = getImageDataSizeInBytes();
for (u32 i=0; i<size; i+=3)
{
memcpy(Data+i, rgb, 3);
}
return;
}
switch (Format) {
case ECF_A1R5G5B5:
c = color.toA1R5G5B5();
c |= c << 16;
break;
default:
case ECF_R5G6B5:
c = video::A8R8G8B8toR5G6B5(color.color);
c |= c << 16;
break;
case ECF_A8R8G8B8:
c = color.color;
break;
case ECF_R8G8B8: {
u8 rgb[3];
CColorConverter::convert_A8R8G8B8toR8G8B8(&color, 1, rgb);
const u32 size = getImageDataSizeInBytes();
for (u32 i = 0; i < size; i += 3) {
memcpy(Data + i, rgb, 3);
}
return;
} break;
default:
// TODO: Handle other formats
return;
return;
}
memset32( Data, c, getImageDataSizeInBytes() );
memset32(Data, c, getImageDataSizeInBytes());
}
//! get a filtered pixel
inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const
inline SColor CImage::getPixelBox(s32 x, s32 y, s32 fx, s32 fy, s32 bias) const
{
if (IImage::isCompressedFormat(Format))
{
if (IImage::isCompressedFormat(Format)) {
os::Printer::log("IImage::getPixelBox method doesn't work with compressed images.", ELL_WARNING);
return SColor(0);
}
@ -392,34 +346,28 @@ inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) cons
SColor c;
s32 a = 0, r = 0, g = 0, b = 0;
for ( s32 dx = 0; dx != fx; ++dx )
{
for ( s32 dy = 0; dy != fy; ++dy )
{
c = getPixel( core::s32_min ( x + dx, Size.Width - 1 ) ,
core::s32_min ( y + dy, Size.Height - 1 )
);
for (s32 dx = 0; dx != fx; ++dx) {
for (s32 dy = 0; dy != fy; ++dy) {
c = getPixel(core::s32_min(x + dx, Size.Width - 1),
core::s32_min(y + dy, Size.Height - 1));
a += c.getAlpha();
r += c.getRed();
g += c.getGreen();
b += c.getBlue();
}
}
s32 sdiv = s32_log2_s32(fx * fy);
a = core::s32_clamp( ( a >> sdiv ) + bias, 0, 255 );
r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 );
g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 );
b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 );
a = core::s32_clamp((a >> sdiv) + bias, 0, 255);
r = core::s32_clamp((r >> sdiv) + bias, 0, 255);
g = core::s32_clamp((g >> sdiv) + bias, 0, 255);
b = core::s32_clamp((b >> sdiv) + bias, 0, 255);
c.set( a, r, g, b );
c.set(a, r, g, b);
return c;
}
} // end namespace video
} // end namespace irr

View File

@ -24,51 +24,50 @@ inline bool checkImageDimensions(u32 width, u32 height)
class CImage : public IImage
{
public:
//! constructor from raw image data
/** \param useForeignMemory: If true, the image will use the data pointer
directly and own it from now on, which means it will also try to delete [] the
data when the image will be destructed. If false, the memory will by copied. */
CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, void* data,
bool ownForeignMemory = true, bool deleteMemory = true);
CImage(ECOLOR_FORMAT format, const core::dimension2d<u32> &size, void *data,
bool ownForeignMemory = true, bool deleteMemory = true);
//! constructor for empty image
CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size);
CImage(ECOLOR_FORMAT format, const core::dimension2d<u32> &size);
//! returns a pixel
SColor getPixel(u32 x, u32 y) const override;
//! sets a pixel
void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) override;
void setPixel(u32 x, u32 y, const SColor &color, bool blend = false) override;
//! copies this surface into another, if it has the exact same size and format.
bool copyToNoScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch=0) const override;
bool copyToNoScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch = 0) const override;
//! copies this surface into another, scaling it to fit.
void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch=0) override;
void copyToScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch = 0) override;
//! copies this surface into another, scaling it to fit.
void copyToScaling(IImage* target) override;
void copyToScaling(IImage *target) override;
//! copies this surface into another
void copyTo(IImage* target, const core::position2d<s32>& pos=core::position2d<s32>(0,0)) override;
void copyTo(IImage *target, const core::position2d<s32> &pos = core::position2d<s32>(0, 0)) override;
//! copies this surface into another
void copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect=0) override;
void copyTo(IImage *target, const core::position2d<s32> &pos, const core::rect<s32> &sourceRect, const core::rect<s32> *clipRect = 0) override;
//! copies this surface into another, using the alpha mask, an cliprect and a color to add with
virtual void copyToWithAlpha(IImage* target, const core::position2d<s32>& pos,
const core::rect<s32>& sourceRect, const SColor &color,
const core::rect<s32>* clipRect = 0, bool combineAlpha=false) override;
virtual void copyToWithAlpha(IImage *target, const core::position2d<s32> &pos,
const core::rect<s32> &sourceRect, const SColor &color,
const core::rect<s32> *clipRect = 0, bool combineAlpha = false) override;
//! copies this surface into another, scaling it to fit, applying a box filter
void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) override;
void copyToScalingBoxFilter(IImage *target, s32 bias = 0, bool blend = false) override;
//! fills the surface with given color
void fill(const SColor &color) override;
private:
inline SColor getPixelBox ( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const;
inline SColor getPixelBox(s32 x, s32 y, s32 fx, s32 fy, s32 bias) const;
};
} // end namespace video

View File

@ -16,26 +16,23 @@ namespace irr
namespace video
{
//! constructor
CImageLoaderBMP::CImageLoaderBMP()
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CImageLoaderBMP");
#endif
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderBMP::isALoadableFileExtension(const io::path& filename) const
bool CImageLoaderBMP::isALoadableFileExtension(const io::path &filename) const
{
return core::hasFileExtension ( filename, "bmp" );
return core::hasFileExtension(filename, "bmp");
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderBMP::isALoadableFileFormat(io::IReadFile* file) const
bool CImageLoaderBMP::isALoadableFileFormat(io::IReadFile *file) const
{
u16 headerID;
file->read(&headerID, sizeof(u16));
@ -49,71 +46,75 @@ bool CImageLoaderBMP::isALoadableFileFormat(io::IReadFile* file) const
static inline bool overflowCheck(const void *base, size_t offset, const void *end)
{
auto baseI = reinterpret_cast<uintptr_t>(base),
endI = reinterpret_cast<uintptr_t>(end);
endI = reinterpret_cast<uintptr_t>(end);
return baseI > endI || offset >= (endI - baseI);
}
// check whether &p[0] to &p[_off - 1] can be accessed
#define CHECKP(_off) if ((_off) < 0 || overflowCheck(p, _off, pEnd)) goto exit
#define CHECKP(_off) \
if ((_off) < 0 || overflowCheck(p, _off, pEnd)) \
goto exit
// same for d
#define CHECKD(_off) if ((_off) < 0 || overflowCheck(d, _off, destEnd)) goto exit
#define CHECKD(_off) \
if ((_off) < 0 || overflowCheck(d, _off, destEnd)) \
goto exit
void CImageLoaderBMP::decompress8BitRLE(u8*& bmpData, s32 size, s32 width, s32 height, s32 pitch) const
void CImageLoaderBMP::decompress8BitRLE(u8 *&bmpData, s32 size, s32 width, s32 height, s32 pitch) const
{
u8* p = bmpData;
const u8* pEnd = bmpData + size;
u8* newBmp = new u8[(width+pitch)*height];
u8* d = newBmp;
const u8* destEnd = newBmp + (width+pitch)*height;
u8 *p = bmpData;
const u8 *pEnd = bmpData + size;
u8 *newBmp = new u8[(width + pitch) * height];
u8 *d = newBmp;
const u8 *destEnd = newBmp + (width + pitch) * height;
s32 line = 0;
while (p < pEnd && d < destEnd)
{
if (*p == 0)
{
++p; CHECKP(1);
while (p < pEnd && d < destEnd) {
if (*p == 0) {
++p;
CHECKP(1);
switch(*p)
{
switch (*p) {
case 0: // end of line
++p;
++line;
d = newBmp + (line*(width+pitch));
d = newBmp + (line * (width + pitch));
break;
case 1: // end of bmp
goto exit;
case 2:
++p; CHECKP(2);
d += (u8)*p; ++p; // delta
d += ((u8)*p)*(width+pitch); ++p;
++p;
CHECKP(2);
d += (u8)*p;
++p; // delta
d += ((u8)*p) * (width + pitch);
++p;
break;
default:
{
// absolute mode
s32 count = (u8)*p; ++p;
s32 readAdditional = ((2-(count%2))%2);
default: {
// absolute mode
s32 count = (u8)*p;
++p;
s32 readAdditional = ((2 - (count % 2)) % 2);
CHECKP(count); CHECKD(count);
for (s32 i=0; i<count; ++i)
{
*d = *p;
++p;
++d;
}
CHECKP(readAdditional);
for (s32 i=0; i<readAdditional; ++i)
++p;
CHECKP(count);
CHECKD(count);
for (s32 i = 0; i < count; ++i) {
*d = *p;
++p;
++d;
}
CHECKP(readAdditional);
for (s32 i = 0; i < readAdditional; ++i)
++p;
}
}
else
{
s32 count = (u8)*p; ++p;
}
} else {
s32 count = (u8)*p;
++p;
CHECKP(1);
u8 color = *p; ++p;
u8 color = *p;
++p;
CHECKD(count);
for (s32 i=0; i<count; ++i)
{
for (s32 i = 0; i < count; ++i) {
*d = color;
++d;
}
@ -121,7 +122,7 @@ void CImageLoaderBMP::decompress8BitRLE(u8*& bmpData, s32 size, s32 width, s32 h
}
exit:
delete [] bmpData;
delete[] bmpData;
bmpData = newBmp;
}
@ -135,97 +136,91 @@ static inline u32 shiftedCount(s32 count, s32 shift)
return ret;
}
void CImageLoaderBMP::decompress4BitRLE(u8*& bmpData, s32 size, s32 width, s32 height, s32 pitch) const
void CImageLoaderBMP::decompress4BitRLE(u8 *&bmpData, s32 size, s32 width, s32 height, s32 pitch) const
{
const s32 lineWidth = (width+1)/2+pitch;
u8* p = bmpData;
const u8* pEnd = bmpData + size;
u8* newBmp = new u8[lineWidth*height];
u8* d = newBmp;
const u8* destEnd = newBmp + lineWidth*height;
const s32 lineWidth = (width + 1) / 2 + pitch;
u8 *p = bmpData;
const u8 *pEnd = bmpData + size;
u8 *newBmp = new u8[lineWidth * height];
u8 *d = newBmp;
const u8 *destEnd = newBmp + lineWidth * height;
s32 line = 0;
s32 shift = 4;
while (p < pEnd && d < destEnd)
{
if (*p == 0)
{
++p; CHECKP(1);
while (p < pEnd && d < destEnd) {
if (*p == 0) {
++p;
CHECKP(1);
switch(*p)
{
switch (*p) {
case 0: // end of line
++p;
++line;
d = newBmp + (line*lineWidth);
d = newBmp + (line * lineWidth);
shift = 4;
break;
case 1: // end of bmp
goto exit;
case 2:
{
++p; CHECKP(2);
s32 x = (u8)*p; ++p;
s32 y = (u8)*p; ++p;
d += x/2 + y*lineWidth;
shift = x%2==0 ? 4 : 0;
}
break;
default:
{
// absolute mode
s32 count = (u8)*p; ++p;
s32 readAdditional = ((2-((count)%2))%2);
s32 readShift = 4;
CHECKP(shiftedCount(count, readShift));
CHECKD(shiftedCount(count, shift));
for (s32 i=0; i<count; ++i)
{
s32 color = (((u8)*p) >> readShift) & 0x0f;
readShift -= 4;
if (readShift < 0)
{
++*p; // <- bug?
readShift = 4;
}
u8 mask = 0x0f << shift;
*d = (*d & (~mask)) | ((color << shift) & mask);
shift -= 4;
if (shift < 0)
{
shift = 4;
++d;
}
case 2: {
++p;
CHECKP(2);
s32 x = (u8)*p;
++p;
s32 y = (u8)*p;
++p;
d += x / 2 + y * lineWidth;
shift = x % 2 == 0 ? 4 : 0;
} break;
default: {
// absolute mode
s32 count = (u8)*p;
++p;
s32 readAdditional = ((2 - ((count) % 2)) % 2);
s32 readShift = 4;
CHECKP(shiftedCount(count, readShift));
CHECKD(shiftedCount(count, shift));
for (s32 i = 0; i < count; ++i) {
s32 color = (((u8)*p) >> readShift) & 0x0f;
readShift -= 4;
if (readShift < 0) {
++*p; // <- bug?
readShift = 4;
}
CHECKP(readAdditional);
for (s32 i=0; i<readAdditional; ++i)
++p;
u8 mask = 0x0f << shift;
*d = (*d & (~mask)) | ((color << shift) & mask);
shift -= 4;
if (shift < 0) {
shift = 4;
++d;
}
}
CHECKP(readAdditional);
for (s32 i = 0; i < readAdditional; ++i)
++p;
}
}
else
{
s32 count = (u8)*p; ++p;
}
} else {
s32 count = (u8)*p;
++p;
CHECKP(1);
s32 color1 = (u8)*p; color1 = color1 & 0x0f;
s32 color2 = (u8)*p; color2 = (color2 >> 4) & 0x0f;
s32 color1 = (u8)*p;
color1 = color1 & 0x0f;
s32 color2 = (u8)*p;
color2 = (color2 >> 4) & 0x0f;
++p;
CHECKD(shiftedCount(count, shift));
for (s32 i=0; i<count; ++i)
{
for (s32 i = 0; i < count; ++i) {
u8 mask = 0x0f << shift;
u8 toSet = (shift==0 ? color1 : color2) << shift;
u8 toSet = (shift == 0 ? color1 : color2) << shift;
*d = (*d & (~mask)) | (toSet & mask);
shift -= 4;
if (shift < 0)
{
if (shift < 0) {
shift = 4;
++d;
}
@ -234,7 +229,7 @@ void CImageLoaderBMP::decompress4BitRLE(u8*& bmpData, s32 size, s32 width, s32 h
}
exit:
delete [] bmpData;
delete[] bmpData;
bmpData = newBmp;
}
@ -243,7 +238,7 @@ exit:
#undef CHECKD
//! creates a surface from the file
IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const
IImage *CImageLoaderBMP::loadImage(io::IReadFile *file) const
{
SBMPHeader header;
@ -279,14 +274,13 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const
return 0;
}
if (header.BPP > 32 || !checkImageDimensions(header.Width, header.Height))
{
if (header.BPP > 32 || !checkImageDimensions(header.Width, header.Height)) {
os::Printer::log("Rejecting BMP with unreasonable size or BPP.", ELL_ERROR);
return 0;
}
// adjust bitmap data size to dword boundary
header.BitmapDataSize += (4-(header.BitmapDataSize%4))%4;
header.BitmapDataSize += (4 - (header.BitmapDataSize % 4)) % 4;
// read palette
@ -295,23 +289,21 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const
s32 paletteSize = (header.BitmapDataOffset - pos) / 4;
paletteSize = core::clamp(paletteSize, 0, paletteAllocSize);
s32* paletteData = 0;
if (paletteSize)
{
s32 *paletteData = 0;
if (paletteSize) {
// always allocate an 8-bit palette to ensure enough space
paletteData = new s32[paletteAllocSize];
memset(paletteData, 0, paletteAllocSize * sizeof(s32));
file->read(paletteData, paletteSize * sizeof(s32));
#ifdef __BIG_ENDIAN__
for (s32 i=0; i<paletteSize; ++i)
for (s32 i = 0; i < paletteSize; ++i)
paletteData[i] = os::Byteswap::byteswap(paletteData[i]);
#endif
}
// read image data
if (!header.BitmapDataSize)
{
if (!header.BitmapDataSize) {
// okay, lets guess the size
// some tools simply don't set it
header.BitmapDataSize = static_cast<u32>(file->getSize()) - header.BitmapDataOffset;
@ -324,35 +316,33 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const
f32 t = (header.Width) * (header.BPP / 8.0f);
widthInBytes = (s32)t;
t -= widthInBytes;
if (t!=0.0f)
if (t != 0.0f)
++widthInBytes;
}
const s32 lineSize = widthInBytes + ((4-(widthInBytes%4)))%4;
const s32 lineSize = widthInBytes + ((4 - (widthInBytes % 4))) % 4;
pitch = lineSize - widthInBytes;
u8* bmpData = new u8[header.BitmapDataSize];
u8 *bmpData = new u8[header.BitmapDataSize];
file->read(bmpData, header.BitmapDataSize);
// decompress data if needed
switch(header.Compression)
{
switch (header.Compression) {
case 1: // 8 bit rle
decompress8BitRLE(bmpData, header.BitmapDataSize, header.Width, header.Height, pitch);
header.BitmapDataSize = (header.Width + pitch) * header.Height;
break;
case 2: // 4 bit rle
decompress4BitRLE(bmpData, header.BitmapDataSize, header.Width, header.Height, pitch);
header.BitmapDataSize = ((header.Width+1)/2 + pitch) * header.Height;
header.BitmapDataSize = ((header.Width + 1) / 2 + pitch) * header.Height;
break;
}
if (header.BitmapDataSize < lineSize * header.Height)
{
if (header.BitmapDataSize < lineSize * header.Height) {
os::Printer::log("Bitmap data is cut off.", ELL_ERROR);
delete [] paletteData;
delete [] bmpData;
delete[] paletteData;
delete[] bmpData;
return 0;
}
@ -361,56 +351,53 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const
dim.Width = header.Width;
dim.Height = header.Height;
IImage* image = 0;
switch(header.BPP)
{
IImage *image = 0;
switch (header.BPP) {
case 1:
image = new CImage(ECF_A1R5G5B5, dim);
if (image)
CColorConverter::convert1BitTo16Bit(bmpData, (s16*)image->getData(), header.Width, header.Height, pitch, true);
CColorConverter::convert1BitTo16Bit(bmpData, (s16 *)image->getData(), header.Width, header.Height, pitch, true);
break;
case 4:
image = new CImage(ECF_A1R5G5B5, dim);
if (image)
CColorConverter::convert4BitTo16Bit(bmpData, (s16*)image->getData(), header.Width, header.Height, paletteData, pitch, true);
CColorConverter::convert4BitTo16Bit(bmpData, (s16 *)image->getData(), header.Width, header.Height, paletteData, pitch, true);
break;
case 8:
image = new CImage(ECF_A1R5G5B5, dim);
if (image)
CColorConverter::convert8BitTo16Bit(bmpData, (s16*)image->getData(), header.Width, header.Height, paletteData, pitch, true);
CColorConverter::convert8BitTo16Bit(bmpData, (s16 *)image->getData(), header.Width, header.Height, paletteData, pitch, true);
break;
case 16:
image = new CImage(ECF_A1R5G5B5, dim);
if (image)
CColorConverter::convert16BitTo16Bit((s16*)bmpData, (s16*)image->getData(), header.Width, header.Height, pitch, true);
CColorConverter::convert16BitTo16Bit((s16 *)bmpData, (s16 *)image->getData(), header.Width, header.Height, pitch, true);
break;
case 24:
image = new CImage(ECF_R8G8B8, dim);
if (image)
CColorConverter::convert24BitTo24Bit(bmpData, (u8*)image->getData(), header.Width, header.Height, pitch, true, true);
CColorConverter::convert24BitTo24Bit(bmpData, (u8 *)image->getData(), header.Width, header.Height, pitch, true, true);
break;
case 32: // thx to Reinhard Ostermeier
image = new CImage(ECF_A8R8G8B8, dim);
if (image)
CColorConverter::convert32BitTo32Bit((s32*)bmpData, (s32*)image->getData(), header.Width, header.Height, pitch, true);
CColorConverter::convert32BitTo32Bit((s32 *)bmpData, (s32 *)image->getData(), header.Width, header.Height, pitch, true);
break;
};
// clean up
delete [] paletteData;
delete [] bmpData;
delete[] paletteData;
delete[] bmpData;
return image;
}
//! creates a loader which is able to load windows bitmaps
IImageLoader* createImageLoaderBMP()
IImageLoader *createImageLoaderBMP()
{
return new CImageLoaderBMP;
}
} // end namespace video
} // end namespace irr

View File

@ -6,7 +6,6 @@
#include "IImageLoader.h"
namespace irr
{
namespace video
@ -15,40 +14,40 @@ namespace video
// byte-align structures
#include "irrpack.h"
struct SBMPHeader
{
u16 Id; // BM - Windows 3.1x, 95, NT, 98, 2000, ME, XP
// BA - OS/2 Bitmap Array
// CI - OS/2 Color Icon
// CP - OS/2 Color Pointer
// IC - OS/2 Icon
// PT - OS/2 Pointer
u32 FileSize;
u32 Reserved;
u32 BitmapDataOffset;
u32 BitmapHeaderSize; // should be 28h for windows bitmaps or
// 0Ch for OS/2 1.x or F0h for OS/2 2.x
u32 Width;
u32 Height;
u16 Planes;
u16 BPP; // 1: Monochrome bitmap
// 4: 16 color bitmap
// 8: 256 color bitmap
// 16: 16bit (high color) bitmap
// 24: 24bit (true color) bitmap
// 32: 32bit (true color) bitmap
struct SBMPHeader
{
u16 Id; // BM - Windows 3.1x, 95, NT, 98, 2000, ME, XP
// BA - OS/2 Bitmap Array
// CI - OS/2 Color Icon
// CP - OS/2 Color Pointer
// IC - OS/2 Icon
// PT - OS/2 Pointer
u32 FileSize;
u32 Reserved;
u32 BitmapDataOffset;
u32 BitmapHeaderSize; // should be 28h for windows bitmaps or
// 0Ch for OS/2 1.x or F0h for OS/2 2.x
u32 Width;
u32 Height;
u16 Planes;
u16 BPP; // 1: Monochrome bitmap
// 4: 16 color bitmap
// 8: 256 color bitmap
// 16: 16bit (high color) bitmap
// 24: 24bit (true color) bitmap
// 32: 32bit (true color) bitmap
u32 Compression; // 0: none (Also identified by BI_RGB)
// 1: RLE 8-bit / pixel (Also identified by BI_RLE4)
// 2: RLE 4-bit / pixel (Also identified by BI_RLE8)
// 3: Bitfields (Also identified by BI_BITFIELDS)
u32 Compression; // 0: none (Also identified by BI_RGB)
// 1: RLE 8-bit / pixel (Also identified by BI_RLE4)
// 2: RLE 4-bit / pixel (Also identified by BI_RLE8)
// 3: Bitfields (Also identified by BI_BITFIELDS)
u32 BitmapDataSize; // Size of the bitmap data in bytes. This number must be rounded to the next 4 byte boundary.
u32 PixelPerMeterX;
u32 PixelPerMeterY;
u32 Colors;
u32 ImportantColors;
} PACK_STRUCT;
u32 BitmapDataSize; // Size of the bitmap data in bytes. This number must be rounded to the next 4 byte boundary.
u32 PixelPerMeterX;
u32 PixelPerMeterY;
u32 Colors;
u32 ImportantColors;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
@ -59,27 +58,24 @@ namespace video
class CImageLoaderBMP : public IImageLoader
{
public:
//! constructor
CImageLoaderBMP();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool isALoadableFileExtension(const io::path& filename) const override;
bool isALoadableFileExtension(const io::path &filename) const override;
//! returns true if the file maybe is able to be loaded by this class
bool isALoadableFileFormat(io::IReadFile* file) const override;
bool isALoadableFileFormat(io::IReadFile *file) const override;
//! creates a surface from the file
IImage* loadImage(io::IReadFile* file) const override;
IImage *loadImage(io::IReadFile *file) const override;
private:
void decompress8BitRLE(u8 *&BmpData, s32 size, s32 width, s32 height, s32 pitch) const;
void decompress8BitRLE(u8*& BmpData, s32 size, s32 width, s32 height, s32 pitch) const;
void decompress4BitRLE(u8*& BmpData, s32 size, s32 width, s32 height, s32 pitch) const;
void decompress4BitRLE(u8 *&BmpData, s32 size, s32 width, s32 height, s32 pitch) const;
};
} // end namespace video
} // end namespace irr

View File

@ -17,25 +17,21 @@ namespace video
//! constructor
CImageLoaderJPG::CImageLoaderJPG()
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CImageLoaderJPG");
#endif
#endif
}
//! destructor
CImageLoaderJPG::~CImageLoaderJPG()
{
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderJPG::isALoadableFileExtension(const io::path& filename) const
bool CImageLoaderJPG::isALoadableFileExtension(const io::path &filename) const
{
return core::hasFileExtension ( filename, "jpg", "jpeg" );
return core::hasFileExtension(filename, "jpg", "jpeg");
}
// struct for handling jpeg errors
@ -48,58 +44,49 @@ struct irr_jpeg_error_mgr
jmp_buf setjmp_buffer;
// for having access to the filename when printing the error messages
core::stringc* filename;
core::stringc *filename;
};
void CImageLoaderJPG::init_source (j_decompress_ptr cinfo)
void CImageLoaderJPG::init_source(j_decompress_ptr cinfo)
{
// DO NOTHING
}
boolean CImageLoaderJPG::fill_input_buffer (j_decompress_ptr cinfo)
boolean CImageLoaderJPG::fill_input_buffer(j_decompress_ptr cinfo)
{
// DO NOTHING
return TRUE;
}
void CImageLoaderJPG::skip_input_data (j_decompress_ptr cinfo, long count)
void CImageLoaderJPG::skip_input_data(j_decompress_ptr cinfo, long count)
{
jpeg_source_mgr * src = cinfo->src;
if(count > 0)
{
jpeg_source_mgr *src = cinfo->src;
if (count > 0) {
src->bytes_in_buffer -= count;
src->next_input_byte += count;
}
}
void CImageLoaderJPG::term_source (j_decompress_ptr cinfo)
void CImageLoaderJPG::term_source(j_decompress_ptr cinfo)
{
// DO NOTHING
}
void CImageLoaderJPG::error_exit (j_common_ptr cinfo)
void CImageLoaderJPG::error_exit(j_common_ptr cinfo)
{
// unfortunately we need to use a goto rather than throwing an exception
// as gcc crashes under linux crashes when using throw from within
// extern c code
// Always display the message
(*cinfo->err->output_message) (cinfo);
(*cinfo->err->output_message)(cinfo);
// cinfo->err really points to a irr_error_mgr struct
irr_jpeg_error_mgr *myerr = (irr_jpeg_error_mgr*) cinfo->err;
irr_jpeg_error_mgr *myerr = (irr_jpeg_error_mgr *)cinfo->err;
longjmp(myerr->setjmp_buffer, 1);
}
void CImageLoaderJPG::output_message(j_common_ptr cinfo)
{
// display the error message.
@ -107,13 +94,13 @@ void CImageLoaderJPG::output_message(j_common_ptr cinfo)
(*cinfo->err->format_message)(cinfo, temp1);
core::stringc errMsg("JPEG FATAL ERROR in ");
irr_jpeg_error_mgr* myerr = (irr_jpeg_error_mgr*)cinfo->err;
irr_jpeg_error_mgr *myerr = (irr_jpeg_error_mgr *)cinfo->err;
errMsg += *myerr->filename;
os::Printer::log(errMsg.c_str(),temp1, ELL_ERROR);
os::Printer::log(errMsg.c_str(), temp1, ELL_ERROR);
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const
bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile *file) const
{
if (!(file && file->seek(0)))
return false;
@ -123,25 +110,25 @@ bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const
}
//! creates a surface from the file
IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
IImage *CImageLoaderJPG::loadImage(io::IReadFile *file) const
{
if (!file)
return 0;
core::stringc filename = file->getFileName();
u8 **rowPtr=0;
u8* input = new u8[file->getSize()];
u8 **rowPtr = 0;
u8 *input = new u8[file->getSize()];
file->read(input, file->getSize());
// allocate and initialize JPEG decompression object
struct jpeg_decompress_struct cinfo;
struct irr_jpeg_error_mgr jerr;
//We have to set up the error handler first, in case the initialization
//step fails. (Unlikely, but it could happen if you are out of memory.)
//This routine fills in the contents of struct jerr, and returns jerr's
//address which we place into the link field in cinfo.
// We have to set up the error handler first, in case the initialization
// step fails. (Unlikely, but it could happen if you are out of memory.)
// This routine fills in the contents of struct jerr, and returns jerr's
// address which we place into the link field in cinfo.
cinfo.err = jpeg_std_error(&jerr.pub);
cinfo.err->error_exit = error_exit;
@ -151,15 +138,14 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
// compatibility fudge:
// we need to use setjmp/longjmp for error handling as gcc-linux
// crashes when throwing within external c code
if (setjmp(jerr.setjmp_buffer))
{
if (setjmp(jerr.setjmp_buffer)) {
// If we get here, the JPEG code has signaled an error.
// We need to clean up the JPEG object and return.
jpeg_destroy_decompress(&cinfo);
delete [] input;
delete [] rowPtr;
delete[] input;
delete[] rowPtr;
// return null pointer
return 0;
@ -173,7 +159,7 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
// Set up data pointer
jsrc.bytes_in_buffer = file->getSize();
jsrc.next_input_byte = (JOCTET*)input;
jsrc.next_input_byte = (JOCTET *)input;
cinfo.src = &jsrc;
jsrc.init_source = init_source;
@ -190,20 +176,17 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
// read file parameters with jpeg_read_header()
jpeg_read_header(&cinfo, TRUE);
bool useCMYK=false;
if (cinfo.jpeg_color_space==JCS_CMYK)
{
cinfo.out_color_space=JCS_CMYK;
cinfo.out_color_components=4;
useCMYK=true;
bool useCMYK = false;
if (cinfo.jpeg_color_space == JCS_CMYK) {
cinfo.out_color_space = JCS_CMYK;
cinfo.out_color_components = 4;
useCMYK = true;
} else {
cinfo.out_color_space = JCS_RGB;
cinfo.out_color_components = 3;
}
else
{
cinfo.out_color_space=JCS_RGB;
cinfo.out_color_components=3;
}
cinfo.output_gamma=2.2;
cinfo.do_fancy_upsampling=FALSE;
cinfo.output_gamma = 2.2;
cinfo.do_fancy_upsampling = FALSE;
// reject unreasonable sizes
if (!checkImageDimensions(cinfo.image_width, cinfo.image_height))
@ -218,22 +201,22 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
u32 height = cinfo.image_height;
// Allocate memory for buffer
u8* output = new u8[rowspan * height];
u8 *output = new u8[rowspan * height];
// Here we use the library's state variable cinfo.output_scanline as the
// loop counter, so that we don't have to keep track ourselves.
// Create array of row pointers for lib
rowPtr = new u8* [height];
rowPtr = new u8 *[height];
for( u32 i = 0; i < height; i++ )
rowPtr[i] = &output[ i * rowspan ];
for (u32 i = 0; i < height; i++)
rowPtr[i] = &output[i * rowspan];
u32 rowsRead = 0;
while( cinfo.output_scanline < cinfo.output_height )
rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead );
while (cinfo.output_scanline < cinfo.output_height)
rowsRead += jpeg_read_scanlines(&cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead);
delete [] rowPtr;
delete[] rowPtr;
// Finish decompression
jpeg_finish_decompress(&cinfo);
@ -243,41 +226,35 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
jpeg_destroy_decompress(&cinfo);
// convert image
IImage* image = 0;
if (useCMYK)
{
IImage *image = 0;
if (useCMYK) {
image = new CImage(ECF_R8G8B8,
core::dimension2d<u32>(width, height));
const u32 size = 3*width*height;
u8* data = (u8*)image->getData();
if (data)
{
for (u32 i=0,j=0; i<size; i+=3, j+=4)
{
const u32 size = 3 * width * height;
u8 *data = (u8 *)image->getData();
if (data) {
for (u32 i = 0, j = 0; i < size; i += 3, j += 4) {
// Also works without K, but has more contrast with K multiplied in
// data[i+0] = output[j+2];
// data[i+1] = output[j+1];
// data[i+2] = output[j+0];
data[i+0] = (char)(output[j+2]*(output[j+3]/255.f));
data[i+1] = (char)(output[j+1]*(output[j+3]/255.f));
data[i+2] = (char)(output[j+0]*(output[j+3]/255.f));
// data[i+0] = output[j+2];
// data[i+1] = output[j+1];
// data[i+2] = output[j+0];
data[i + 0] = (char)(output[j + 2] * (output[j + 3] / 255.f));
data[i + 1] = (char)(output[j + 1] * (output[j + 3] / 255.f));
data[i + 2] = (char)(output[j + 0] * (output[j + 3] / 255.f));
}
}
delete [] output;
}
else
delete[] output;
} else
image = new CImage(ECF_R8G8B8,
core::dimension2d<u32>(width, height), output);
delete [] input;
delete[] input;
return image;
}
//! creates a loader which is able to load jpeg images
IImageLoader* createImageLoaderJPG()
IImageLoader *createImageLoaderJPG()
{
return new CImageLoaderJPG();
}

View File

@ -6,22 +6,19 @@
#include "IImageLoader.h"
#include <cstdio> // required for jpeglib.h
#include <cstdio> // required for jpeglib.h
#include <jpeglib.h> // use system lib
#include <setjmp.h>
namespace irr
{
namespace video
{
//! Surface Loader for JPG images
class CImageLoaderJPG : public IImageLoader
{
public:
//! constructor
CImageLoaderJPG();
@ -30,13 +27,13 @@ public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool isALoadableFileExtension(const io::path& filename) const override;
bool isALoadableFileExtension(const io::path &filename) const override;
//! returns true if the file maybe is able to be loaded by this class
bool isALoadableFileFormat(io::IReadFile* file) const override;
bool isALoadableFileFormat(io::IReadFile *file) const override;
//! creates a surface from the file
IImage* loadImage(io::IReadFile* file) const override;
IImage *loadImage(io::IReadFile *file) const override;
private:
// several methods used via function pointers by jpeglib
@ -49,7 +46,7 @@ private:
default behavior. Note that if you continue processing, you should
clean up the JPEG object with jpeg_abort() or jpeg_destroy().
*/
static void error_exit (j_common_ptr cinfo);
static void error_exit(j_common_ptr cinfo);
/* output error messages via Irrlicht logger. */
static void output_message(j_common_ptr cinfo);
@ -58,7 +55,7 @@ private:
data is actually read. Unlike init_destination(), it may leave
bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
will occur immediately). */
static void init_source (j_decompress_ptr cinfo);
static void init_source(j_decompress_ptr cinfo);
/* This is called whenever bytes_in_buffer has reached zero and more
data is wanted. In typical applications, it should read fresh data
@ -69,7 +66,7 @@ private:
least one more byte. bytes_in_buffer MUST be set to a positive value
if TRUE is returned. A FALSE return should only be used when I/O
suspension is desired (this mode is discussed in the next section). */
static boolean fill_input_buffer (j_decompress_ptr cinfo);
static boolean fill_input_buffer(j_decompress_ptr cinfo);
/* Skip num_bytes worth of data. The buffer pointer and count should
be advanced over num_bytes input bytes, refilling the buffer as
@ -79,13 +76,12 @@ private:
but it's not clear that being smart is worth much trouble; large
skips are uncommon. bytes_in_buffer may be zero on return.
A zero or negative skip count should be treated as a no-op. */
static void skip_input_data (j_decompress_ptr cinfo, long num_bytes);
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
/* Terminate source --- called by jpeg_finish_decompress() after all
data has been read. Often a no-op. */
static void term_source (j_decompress_ptr cinfo);
static void term_source(j_decompress_ptr cinfo);
};
} // end namespace video
} // end namespace irr

View File

@ -34,25 +34,23 @@ void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t l
png_size_t check;
// changed by zola {
io::IReadFile* file=(io::IReadFile*)png_get_io_ptr(png_ptr);
check=(png_size_t) file->read((void*)data, length);
io::IReadFile *file = (io::IReadFile *)png_get_io_ptr(png_ptr);
check = (png_size_t)file->read((void *)data, length);
// }
if (check != length)
png_error(png_ptr, "Read Error");
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderPng::isALoadableFileExtension(const io::path& filename) const
bool CImageLoaderPng::isALoadableFileExtension(const io::path &filename) const
{
return core::hasFileExtension ( filename, "png" );
return core::hasFileExtension(filename, "png");
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderPng::isALoadableFileFormat(io::IReadFile* file) const
bool CImageLoaderPng::isALoadableFileFormat(io::IReadFile *file) const
{
if (!file)
return false;
@ -66,54 +64,48 @@ bool CImageLoaderPng::isALoadableFileFormat(io::IReadFile* file) const
return !png_sig_cmp(buffer, 0, 8);
}
// load in the image data
IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
IImage *CImageLoaderPng::loadImage(io::IReadFile *file) const
{
if (!file)
return 0;
//Used to point to image rows
u8** RowPointers = 0;
// Used to point to image rows
u8 **RowPointers = 0;
png_byte buffer[8];
// Read the first few bytes of the PNG file
if( file->read(buffer, 8) != 8 )
{
if (file->read(buffer, 8) != 8) {
os::Printer::log("LOAD PNG: can't read file (filesize < 8)", file->getFileName(), ELL_ERROR);
return 0;
}
// Check if it really is a PNG file
if( png_sig_cmp(buffer, 0, 8) )
{
if (png_sig_cmp(buffer, 0, 8)) {
os::Printer::log("LOAD PNG: not really a png (wrong signature)", file->getFileName(), ELL_ERROR);
return 0;
}
// Allocate the png read struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn);
if (!png_ptr)
{
NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn);
if (!png_ptr) {
os::Printer::log("LOAD PNG: Internal PNG create read struct failure", file->getFileName(), ELL_ERROR);
return 0;
}
// Allocate the png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
if (!info_ptr) {
os::Printer::log("LOAD PNG: Internal PNG create info struct failure", file->getFileName(), ELL_ERROR);
png_destroy_read_struct(&png_ptr, NULL, NULL);
return 0;
}
// for proper error handling
if (setjmp(png_jmpbuf(png_ptr)))
{
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
delete [] RowPointers;
delete[] RowPointers;
return 0;
}
@ -130,26 +122,25 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
s32 ColorType;
{
// Use temporary variables to avoid passing cast pointers
png_uint_32 w,h;
png_uint_32 w, h;
// Extract info
png_get_IHDR(png_ptr, info_ptr,
&w, &h,
&BitDepth, &ColorType, NULL, NULL, NULL);
Width=w;
Height=h;
&w, &h,
&BitDepth, &ColorType, NULL, NULL, NULL);
Width = w;
Height = h;
}
if (!checkImageDimensions(Width, Height))
png_cpexcept_error(png_ptr, "Unreasonable size");
// Convert palette color to true color
if (ColorType==PNG_COLOR_TYPE_PALETTE)
if (ColorType == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
// Convert low bit colors to 8 bit colors
if (BitDepth < 8)
{
if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
if (BitDepth < 8) {
if (ColorType == PNG_COLOR_TYPE_GRAY || ColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_expand_gray_1_2_4_to_8(png_ptr);
else
png_set_packing(png_ptr);
@ -163,7 +154,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
png_set_strip_16(png_ptr);
// Convert gray color to true color
if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
if (ColorType == PNG_COLOR_TYPE_GRAY || ColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
int intent;
@ -171,8 +162,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
if (png_get_sRGB(png_ptr, info_ptr, &intent))
png_set_gamma(png_ptr, screen_gamma, 0.45455);
else
{
else {
double image_gamma;
if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
png_set_gamma(png_ptr, screen_gamma, image_gamma);
@ -185,18 +175,17 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
png_read_update_info(png_ptr, info_ptr);
{
// Use temporary variables to avoid passing cast pointers
png_uint_32 w,h;
png_uint_32 w, h;
// Extract info
png_get_IHDR(png_ptr, info_ptr,
&w, &h,
&BitDepth, &ColorType, NULL, NULL, NULL);
Width=w;
Height=h;
&w, &h,
&BitDepth, &ColorType, NULL, NULL, NULL);
Width = w;
Height = h;
}
// Convert RGBA to BGRA
if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
{
if (ColorType == PNG_COLOR_TYPE_RGB_ALPHA) {
#ifdef __BIG_ENDIAN__
png_set_swap_alpha(png_ptr);
#else
@ -205,13 +194,12 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
}
// Create the image structure to be filled by png data
video::IImage* image = 0;
if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
video::IImage *image = 0;
if (ColorType == PNG_COLOR_TYPE_RGB_ALPHA)
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(Width, Height));
else
image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(Width, Height));
if (!image)
{
if (!image) {
os::Printer::log("LOAD PNG: Internal PNG create image struct failure", file->getFileName(), ELL_ERROR);
png_destroy_read_struct(&png_ptr, NULL, NULL);
return 0;
@ -219,8 +207,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
// Create array of pointers to rows in image data
RowPointers = new png_bytep[Height];
if (!RowPointers)
{
if (!RowPointers) {
os::Printer::log("LOAD PNG: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR);
png_destroy_read_struct(&png_ptr, NULL, NULL);
delete image;
@ -228,18 +215,16 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
}
// Fill array of pointers to rows in image data
unsigned char* data = (unsigned char*)image->getData();
for (u32 i=0; i<Height; ++i)
{
RowPointers[i]=data;
unsigned char *data = (unsigned char *)image->getData();
for (u32 i = 0; i < Height; ++i) {
RowPointers[i] = data;
data += image->getPitch();
}
// for proper error handling
if (setjmp(png_jmpbuf(png_ptr)))
{
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
delete [] RowPointers;
delete[] RowPointers;
delete image;
return 0;
}
@ -248,18 +233,16 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
png_read_image(png_ptr, RowPointers);
png_read_end(png_ptr, NULL);
delete [] RowPointers;
png_destroy_read_struct(&png_ptr,&info_ptr, 0); // Clean up memory
delete[] RowPointers;
png_destroy_read_struct(&png_ptr, &info_ptr, 0); // Clean up memory
return image;
}
IImageLoader* createImageLoaderPNG()
IImageLoader *createImageLoaderPNG()
{
return new CImageLoaderPng();
}
}// end namespace irr
}//end namespace video
} // end namespace irr
} // end namespace video

View File

@ -19,18 +19,16 @@ namespace video
class CImageLoaderPng : public IImageLoader
{
public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".png")
bool isALoadableFileExtension(const io::path& filename) const override;
bool isALoadableFileExtension(const io::path &filename) const override;
//! returns true if the file maybe is able to be loaded by this class
bool isALoadableFileFormat(io::IReadFile* file) const override;
bool isALoadableFileFormat(io::IReadFile *file) const override;
//! creates a surface from the file
IImage* loadImage(io::IReadFile* file) const override;
IImage *loadImage(io::IReadFile *file) const override;
};
} // end namespace video
} // end namespace irr

View File

@ -17,72 +17,58 @@ namespace irr
namespace video
{
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderTGA::isALoadableFileExtension(const io::path& filename) const
bool CImageLoaderTGA::isALoadableFileExtension(const io::path &filename) const
{
return core::hasFileExtension ( filename, "tga" );
return core::hasFileExtension(filename, "tga");
}
//! loads a compressed tga.
u8 *CImageLoaderTGA::loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const
u8 *CImageLoaderTGA::loadCompressedImage(io::IReadFile *file, const STGAHeader &header) const
{
// This was written and sent in by Jon Pry, thank you very much!
// I only changed the formatting a little bit.
const u32 bytesPerPixel = header.PixelDepth/8;
const u32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel;
u8* data = new u8[imageSize];
const u32 bytesPerPixel = header.PixelDepth / 8;
const u32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel;
u8 *data = new u8[imageSize];
u32 currentByte = 0;
while(currentByte < imageSize)
{
while (currentByte < imageSize) {
u8 chunkheader = 0;
file->read(&chunkheader, sizeof(u8)); // Read The Chunk's Header
if(chunkheader < 128) // If The Chunk Is A 'RAW' Chunk
if (chunkheader < 128) // If The Chunk Is A 'RAW' Chunk
{
chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels
const u32 bytesToRead = bytesPerPixel * chunkheader;
if ( currentByte+bytesToRead <= imageSize )
{
if (currentByte + bytesToRead <= imageSize) {
file->read(&data[currentByte], bytesToRead);
currentByte += bytesToRead;
}
else
{
} else {
os::Printer::log("Compressed TGA file RAW chunk tries writing beyond buffer", file->getFileName(), ELL_WARNING);
break;
}
}
else
{
} else {
// thnx to neojzs for some fixes with this code
// If It's An RLE Header
chunkheader -= 127; // Subtract 127 To Get Rid Of The ID Bit
u32 dataOffset = currentByte;
if ( dataOffset+bytesPerPixel < imageSize )
{
if (dataOffset + bytesPerPixel < imageSize) {
file->read(&data[dataOffset], bytesPerPixel);
currentByte += bytesPerPixel;
}
else
{
} else {
os::Printer::log("Compressed TGA file RLE headertries writing beyond buffer", file->getFileName(), ELL_WARNING);
break;
}
for(u32 counter = 1; counter < chunkheader; counter++)
{
if ( currentByte + bytesPerPixel <= imageSize )
{
for(u32 elementCounter=0; elementCounter < bytesPerPixel; elementCounter++)
{
for (u32 counter = 1; counter < chunkheader; counter++) {
if (currentByte + bytesPerPixel <= imageSize) {
for (u32 elementCounter = 0; elementCounter < bytesPerPixel; elementCounter++) {
data[currentByte + elementCounter] = data[dataOffset + elementCounter];
}
}
@ -95,25 +81,21 @@ u8 *CImageLoaderTGA::loadCompressedImage(io::IReadFile *file, const STGAHeader&
return data;
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile* file) const
bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile *file) const
{
if (!file)
return false;
STGAFooter footer;
memset(&footer, 0, sizeof(STGAFooter));
file->seek(file->getSize()-sizeof(STGAFooter));
file->seek(file->getSize() - sizeof(STGAFooter));
file->read(&footer, sizeof(STGAFooter));
return (!strcmp(footer.Signature,"TRUEVISION-XFILE.")); // very old tgas are refused.
return (!strcmp(footer.Signature, "TRUEVISION-XFILE.")); // very old tgas are refused.
}
//! creates a surface from the file
IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
IImage *CImageLoaderTGA::loadImage(io::IReadFile *file) const
{
STGAHeader header;
u32 *palette = 0;
@ -126,8 +108,7 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight);
#endif
if (!checkImageDimensions(header.ImageWidth, header.ImageHeight))
{
if (!checkImageDimensions(header.ImageWidth, header.ImageHeight)) {
os::Printer::log("Image dimensions too large in file", file->getFileName(), ELL_ERROR);
return 0;
}
@ -136,149 +117,132 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
if (header.IdLength)
file->seek(header.IdLength, true);
if (header.ColorMapType)
{
if (header.ColorMapType) {
// Create 32 bit palette
// `core::max_()` is not used here because it takes its inputs as references. Since `header` is packed, use the macro `MAX()` instead:
const irr::u16 paletteSize = MAX((u16)256u, header.ColorMapLength); // ColorMapLength can lie, but so far we only use palette for 8-bit, so ensure it has 256 entries
palette = new u32[paletteSize];
if( paletteSize > header.ColorMapLength )
{
if (paletteSize > header.ColorMapLength) {
// To catch images using palette colors with invalid indices
const irr::u32 errorCol = irr::video::SColor(255,255, 0, 205).color; // bright magenta
for ( irr::u16 i = header.ColorMapLength; i< paletteSize; ++i )
const irr::u32 errorCol = irr::video::SColor(255, 255, 0, 205).color; // bright magenta
for (irr::u16 i = header.ColorMapLength; i < paletteSize; ++i)
palette[i] = errorCol;
}
// read color map
u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength];
file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength);
u8 *colorMap = new u8[header.ColorMapEntrySize / 8 * header.ColorMapLength];
file->read(colorMap, header.ColorMapEntrySize / 8 * header.ColorMapLength);
// convert to 32-bit palette
switch ( header.ColorMapEntrySize )
{
case 16:
CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
case 24:
CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
case 32:
CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
switch (header.ColorMapEntrySize) {
case 16:
CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
case 24:
CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
case 32:
CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
}
delete [] colorMap;
delete[] colorMap;
}
// read image
u8* data = 0;
u8 *data = 0;
if ( header.ImageType == 1 || // Uncompressed, color-mapped images.
if (header.ImageType == 1 || // Uncompressed, color-mapped images.
header.ImageType == 2 || // Uncompressed, RGB images
header.ImageType == 3 // Uncompressed, black and white images
)
{
const s32 imageSize = header.ImageHeight * header.ImageWidth * (header.PixelDepth/8);
header.ImageType == 3 // Uncompressed, black and white images
) {
const s32 imageSize = header.ImageHeight * header.ImageWidth * (header.PixelDepth / 8);
data = new u8[imageSize];
file->read(data, imageSize);
}
else
if(header.ImageType == 10)
{
file->read(data, imageSize);
} else if (header.ImageType == 10) {
// Runlength encoded RGB images
data = loadCompressedImage(file, header);
}
else
{
} else {
os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR);
delete [] palette;
delete[] palette;
return 0;
}
IImage* image = 0;
IImage *image = 0;
switch(header.PixelDepth)
{
case 8:
switch (header.PixelDepth) {
case 8: {
if (header.ImageType == 3) // grey image
{
if (header.ImageType==3) // grey image
{
image = new CImage(ECF_R8G8B8,
image = new CImage(ECF_R8G8B8,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert8BitTo24Bit((u8 *)data,
(u8 *)image->getData(),
header.ImageWidth, header.ImageHeight,
0, 0, (header.ImageDescriptor & 0x20) == 0);
} else {
switch (header.ColorMapEntrySize) {
case 16:
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert8BitTo24Bit((u8*)data,
(u8*)image->getData(),
header.ImageWidth,header.ImageHeight,
0, 0, (header.ImageDescriptor&0x20)==0);
}
else
{
switch ( header.ColorMapEntrySize )
{
case 16:
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if ( image )
CColorConverter::convert8BitTo16Bit((u8*)data,
(s16*)image->getData(),
header.ImageWidth,header.ImageHeight,
(s32*) palette, 0,
(header.ImageDescriptor&0x20)==0);
break;
// Note: 24 bit with palette would need a 24 bit palette, too lazy doing that now (textures will prefer 32-bit later anyway)
default:
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if ( image )
CColorConverter::convert8BitTo32Bit((u8*)data,
(u8*)image->getData(),
header.ImageWidth,header.ImageHeight,
(u8*) palette, 0,
(header.ImageDescriptor&0x20)==0);
break;
}
CColorConverter::convert8BitTo16Bit((u8 *)data,
(s16 *)image->getData(),
header.ImageWidth, header.ImageHeight,
(s32 *)palette, 0,
(header.ImageDescriptor & 0x20) == 0);
break;
// Note: 24 bit with palette would need a 24 bit palette, too lazy doing that now (textures will prefer 32-bit later anyway)
default:
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert8BitTo32Bit((u8 *)data,
(u8 *)image->getData(),
header.ImageWidth, header.ImageHeight,
(u8 *)palette, 0,
(header.ImageDescriptor & 0x20) == 0);
break;
}
}
break;
} break;
case 16:
image = new CImage(ECF_A1R5G5B5,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert16BitTo16Bit((s16*)data,
(s16*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
CColorConverter::convert16BitTo16Bit((s16 *)data,
(s16 *)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor & 0x20) == 0);
break;
case 24:
image = new CImage(ECF_R8G8B8,
image = new CImage(ECF_R8G8B8,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert24BitTo24Bit(
(u8*)data, (u8*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true);
if (image)
CColorConverter::convert24BitTo24Bit(
(u8 *)data, (u8 *)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor & 0x20) == 0, true);
break;
case 32:
image = new CImage(ECF_A8R8G8B8,
image = new CImage(ECF_A8R8G8B8,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert32BitTo32Bit((s32*)data,
(s32*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
if (image)
CColorConverter::convert32BitTo32Bit((s32 *)data,
(s32 *)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor & 0x20) == 0);
break;
default:
os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR);
break;
}
delete [] data;
delete [] palette;
delete[] data;
delete[] palette;
return image;
}
//! creates a loader which is able to load tgas
IImageLoader* createImageLoaderTGA()
IImageLoader *createImageLoaderTGA()
{
return new CImageLoaderTGA();
}
} // end namespace video
} // end namespace irr

View File

@ -6,7 +6,6 @@
#include "IImageLoader.h"
namespace irr
{
namespace video
@ -15,28 +14,29 @@ namespace video
// byte-align structures
#include "irrpack.h"
// these structs are also used in the TGA writer
struct STGAHeader{
u8 IdLength;
u8 ColorMapType;
u8 ImageType;
u8 FirstEntryIndex[2];
u16 ColorMapLength;
u8 ColorMapEntrySize;
u8 XOrigin[2];
u8 YOrigin[2];
u16 ImageWidth;
u16 ImageHeight;
u8 PixelDepth;
u8 ImageDescriptor;
} PACK_STRUCT;
// these structs are also used in the TGA writer
struct STGAHeader
{
u8 IdLength;
u8 ColorMapType;
u8 ImageType;
u8 FirstEntryIndex[2];
u16 ColorMapLength;
u8 ColorMapEntrySize;
u8 XOrigin[2];
u8 YOrigin[2];
u16 ImageWidth;
u16 ImageHeight;
u8 PixelDepth;
u8 ImageDescriptor;
} PACK_STRUCT;
struct STGAFooter
{
u32 ExtensionOffset;
u32 DeveloperOffset;
c8 Signature[18];
} PACK_STRUCT;
struct STGAFooter
{
u32 ExtensionOffset;
u32 DeveloperOffset;
c8 Signature[18];
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
@ -47,21 +47,19 @@ namespace video
class CImageLoaderTGA : public IImageLoader
{
public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool isALoadableFileExtension(const io::path& filename) const override;
bool isALoadableFileExtension(const io::path &filename) const override;
//! returns true if the file maybe is able to be loaded by this class
bool isALoadableFileFormat(io::IReadFile* file) const override;
bool isALoadableFileFormat(io::IReadFile *file) const override;
//! creates a surface from the file
IImage* loadImage(io::IReadFile* file) const override;
IImage *loadImage(io::IReadFile *file) const override;
private:
//! loads a compressed tga. Was written and sent in by Jon Pry, thank you very much!
u8* loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const;
u8 *loadCompressedImage(io::IReadFile *file, const STGAHeader &header) const;
};
} // end namespace video

View File

@ -11,13 +11,11 @@
#include "os.h"
#include <cstdio> // required for jpeglib.h
extern "C"
{
#include <jpeglib.h>
#include <jerror.h>
extern "C" {
#include <jpeglib.h>
#include <jerror.h>
}
namespace irr
{
namespace video
@ -27,33 +25,30 @@ namespace video
#define OUTPUT_BUF_SIZE 4096
typedef struct
{
struct jpeg_destination_mgr pub;/* public fields */
struct jpeg_destination_mgr pub; /* public fields */
io::IWriteFile* file; /* target file */
JOCTET buffer[OUTPUT_BUF_SIZE]; /* image buffer */
io::IWriteFile *file; /* target file */
JOCTET buffer[OUTPUT_BUF_SIZE]; /* image buffer */
} mem_destination_mgr;
typedef mem_destination_mgr * mem_dest_ptr;
typedef mem_destination_mgr *mem_dest_ptr;
// init
static void jpeg_init_destination(j_compress_ptr cinfo)
{
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest;
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
// flush to disk and reset buffer
static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo)
{
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest;
// for now just exit upon file error
if (dest->file->write(dest->buffer, OUTPUT_BUF_SIZE) != OUTPUT_BUF_SIZE)
ERREXIT (cinfo, JERR_FILE_WRITE);
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
@ -61,29 +56,25 @@ static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo)
return TRUE;
}
static void jpeg_term_destination(j_compress_ptr cinfo)
{
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest;
const size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
// for now just exit upon file error
if (dest->file->write(dest->buffer, datacount) != datacount)
ERREXIT (cinfo, JERR_FILE_WRITE);
ERREXIT(cinfo, JERR_FILE_WRITE);
}
// set up buffer data
static void jpeg_file_dest(j_compress_ptr cinfo, io::IWriteFile* file)
static void jpeg_file_dest(j_compress_ptr cinfo, io::IWriteFile *file)
{
if (cinfo->dest == NULL)
{ /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
JPOOL_PERMANENT,
sizeof(mem_destination_mgr));
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr)cinfo,
JPOOL_PERMANENT,
sizeof(mem_destination_mgr));
}
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; /* for casting */
mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest; /* for casting */
/* Initialize method pointers */
dest->pub.init_destination = jpeg_init_destination;
@ -94,33 +85,31 @@ static void jpeg_file_dest(j_compress_ptr cinfo, io::IWriteFile* file)
dest->file = file;
}
/* write_JPEG_memory: store JPEG compressed image into memory.
*/
static bool writeJPEGFile(io::IWriteFile* file, IImage* image, u32 quality)
*/
static bool writeJPEGFile(io::IWriteFile *file, IImage *image, u32 quality)
{
void (*format)(const void*, s32, void*) = 0;
switch( image->getColorFormat () )
{
case ECF_R8G8B8:
format = CColorConverter::convert_R8G8B8toR8G8B8;
break;
case ECF_A8R8G8B8:
format = CColorConverter::convert_A8R8G8B8toR8G8B8;
break;
case ECF_A1R5G5B5:
format = CColorConverter::convert_A1R5G5B5toB8G8R8;
break;
case ECF_R5G6B5:
format = CColorConverter::convert_R5G6B5toR8G8B8;
break;
default:
os::Printer::log("writeJPEGFile does not support image format", ColorFormatNames[image->getColorFormat()], ELL_WARNING);
break;
void (*format)(const void *, s32, void *) = 0;
switch (image->getColorFormat()) {
case ECF_R8G8B8:
format = CColorConverter::convert_R8G8B8toR8G8B8;
break;
case ECF_A8R8G8B8:
format = CColorConverter::convert_A8R8G8B8toR8G8B8;
break;
case ECF_A1R5G5B5:
format = CColorConverter::convert_A1R5G5B5toB8G8R8;
break;
case ECF_R5G6B5:
format = CColorConverter::convert_R5G6B5toR8G8B8;
break;
default:
os::Printer::log("writeJPEGFile does not support image format", ColorFormatNames[image->getColorFormat()], ELL_WARNING);
break;
}
// couldn't find a color converter
if ( 0 == format )
if (0 == format)
return false;
const core::dimension2du dim = image->getDimension();
@ -138,31 +127,29 @@ static bool writeJPEGFile(io::IWriteFile* file, IImage* image, u32 quality)
jpeg_set_defaults(&cinfo);
if ( 0 == quality )
if (0 == quality)
quality = 75;
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
u8 * dest = new u8[dim.Width*3];
u8 *dest = new u8[dim.Width * 3];
if (dest)
{
if (dest) {
const u32 pitch = image->getPitch();
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
row_pointer[0] = dest;
u8* src = (u8*)image->getData();
u8 *src = (u8 *)image->getData();
while (cinfo.next_scanline < cinfo.image_height)
{
while (cinfo.next_scanline < cinfo.image_height) {
// convert next line
format( src, dim.Width, dest );
format(src, dim.Width, dest);
src += pitch;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
delete [] dest;
delete[] dest;
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
@ -174,18 +161,15 @@ static bool writeJPEGFile(io::IWriteFile* file, IImage* image, u32 quality)
return (dest != 0);
}
} // namespace video
} // namespace irr
namespace irr
{
namespace video
{
IImageWriter* createImageWriterJPG()
IImageWriter *createImageWriterJPG()
{
return new CImageWriterJPG;
}
@ -197,13 +181,11 @@ CImageWriterJPG::CImageWriterJPG()
#endif
}
bool CImageWriterJPG::isAWriteableFileExtension(const io::path& filename) const
bool CImageWriterJPG::isAWriteableFileExtension(const io::path &filename) const
{
return core::hasFileExtension ( filename, "jpg", "jpeg" );
return core::hasFileExtension(filename, "jpg", "jpeg");
}
bool CImageWriterJPG::writeImage(io::IWriteFile *file, IImage *image, u32 quality) const
{
return writeJPEGFile(file, image, quality);

View File

@ -18,7 +18,7 @@ public:
CImageWriterJPG();
//! return true if this writer can write a file with the given extension
bool isAWriteableFileExtension(const io::path& filename) const override;
bool isAWriteableFileExtension(const io::path &filename) const override;
//! write image to file
bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const override;

View File

@ -17,7 +17,7 @@ namespace irr
namespace video
{
IImageWriter* createImageWriterPNG()
IImageWriter *createImageWriterPNG()
{
return new CImageWriterPNG;
}
@ -40,8 +40,8 @@ void PNGAPI user_write_data_fcn(png_structp png_ptr, png_bytep data, png_size_t
{
png_size_t check;
io::IWriteFile* file=(io::IWriteFile*)png_get_io_ptr(png_ptr);
check=(png_size_t) file->write((const void*)data, length);
io::IWriteFile *file = (io::IWriteFile *)png_get_io_ptr(png_ptr);
check = (png_size_t)file->write((const void *)data, length);
if (check != length)
png_error(png_ptr, "Write Error");
@ -54,37 +54,34 @@ CImageWriterPNG::CImageWriterPNG()
#endif
}
bool CImageWriterPNG::isAWriteableFileExtension(const io::path& filename) const
bool CImageWriterPNG::isAWriteableFileExtension(const io::path &filename) const
{
return core::hasFileExtension ( filename, "png" );
return core::hasFileExtension(filename, "png");
}
bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) const
bool CImageWriterPNG::writeImage(io::IWriteFile *file, IImage *image, u32 param) const
{
if (!file || !image)
return false;
// Allocate the png write struct
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warning);
if (!png_ptr)
{
NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warning);
if (!png_ptr) {
os::Printer::log("PNGWriter: Internal PNG create write struct failure", file->getFileName(), ELL_ERROR);
return false;
}
// Allocate the png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
if (!info_ptr) {
os::Printer::log("PNGWriter: Internal PNG create info struct failure", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, NULL);
return false;
}
// for proper error handling
if (setjmp(png_jmpbuf(png_ptr)))
{
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return false;
}
@ -92,107 +89,99 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
png_set_write_fn(png_ptr, file, user_write_data_fcn, NULL);
// Set info
switch(image->getColorFormat())
{
case ECF_A8R8G8B8:
case ECF_A1R5G5B5:
png_set_IHDR(png_ptr, info_ptr,
switch (image->getColorFormat()) {
case ECF_A8R8G8B8:
case ECF_A1R5G5B5:
png_set_IHDR(png_ptr, info_ptr,
image->getDimension().Width, image->getDimension().Height,
8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
break;
default:
png_set_IHDR(png_ptr, info_ptr,
default:
png_set_IHDR(png_ptr, info_ptr,
image->getDimension().Width, image->getDimension().Height,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
}
s32 lineWidth = image->getDimension().Width;
switch(image->getColorFormat())
{
switch (image->getColorFormat()) {
case ECF_R8G8B8:
case ECF_R5G6B5:
lineWidth*=3;
lineWidth *= 3;
break;
case ECF_A8R8G8B8:
case ECF_A1R5G5B5:
lineWidth*=4;
lineWidth *= 4;
break;
// TODO: Error handling in case of unsupported color format
default:
break;
}
u8* tmpImage = new u8[image->getDimension().Height*lineWidth];
if (!tmpImage)
{
u8 *tmpImage = new u8[image->getDimension().Height * lineWidth];
if (!tmpImage) {
os::Printer::log("PNGWriter: Internal PNG create image failure", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, &info_ptr);
return false;
}
u8* data = (u8*)image->getData();
switch(image->getColorFormat())
{
u8 *data = (u8 *)image->getData();
switch (image->getColorFormat()) {
case ECF_R8G8B8:
CColorConverter::convert_R8G8B8toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
CColorConverter::convert_R8G8B8toR8G8B8(data, image->getDimension().Height * image->getDimension().Width, tmpImage);
break;
case ECF_A8R8G8B8:
CColorConverter::convert_A8R8G8B8toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
CColorConverter::convert_A8R8G8B8toA8R8G8B8(data, image->getDimension().Height * image->getDimension().Width, tmpImage);
break;
case ECF_R5G6B5:
CColorConverter::convert_R5G6B5toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
CColorConverter::convert_R5G6B5toR8G8B8(data, image->getDimension().Height * image->getDimension().Width, tmpImage);
break;
case ECF_A1R5G5B5:
CColorConverter::convert_A1R5G5B5toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
CColorConverter::convert_A1R5G5B5toA8R8G8B8(data, image->getDimension().Height * image->getDimension().Width, tmpImage);
break;
// TODO: Error handling in case of unsupported color format
default:
os::Printer::log("CImageWriterPNG does not support image format", ColorFormatNames[image->getColorFormat()], ELL_WARNING);
png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] tmpImage;
delete[] tmpImage;
return false;
}
// Create array of pointers to rows in image data
//Used to point to image rows
u8** RowPointers = new png_bytep[image->getDimension().Height];
if (!RowPointers)
{
// Used to point to image rows
u8 **RowPointers = new png_bytep[image->getDimension().Height];
if (!RowPointers) {
os::Printer::log("PNGWriter: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] tmpImage;
delete[] tmpImage;
return false;
}
data=tmpImage;
data = tmpImage;
// Fill array of pointers to rows in image data
for (u32 i=0; i<image->getDimension().Height; ++i)
{
RowPointers[i]=data;
for (u32 i = 0; i < image->getDimension().Height; ++i) {
RowPointers[i] = data;
data += lineWidth;
}
// for proper error handling
if (setjmp(png_jmpbuf(png_ptr)))
{
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] RowPointers;
delete [] tmpImage;
delete[] RowPointers;
delete[] tmpImage;
return false;
}
png_set_rows(png_ptr, info_ptr, RowPointers);
if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5)
if (image->getColorFormat() == ECF_A8R8G8B8 || image->getColorFormat() == ECF_A1R5G5B5)
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL);
else
{
else {
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
}
delete [] RowPointers;
delete [] tmpImage;
delete[] RowPointers;
delete[] tmpImage;
png_destroy_write_struct(&png_ptr, &info_ptr);
return true;
}

View File

@ -18,7 +18,7 @@ public:
CImageWriterPNG();
//! return true if this writer can write a file with the given extension
bool isAWriteableFileExtension(const io::path& filename) const override;
bool isAWriteableFileExtension(const io::path &filename) const override;
//! write image to file
bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const override;

File diff suppressed because it is too large Load Diff

View File

@ -29,204 +29,197 @@
namespace irr
{
class CIrrDeviceLinux : public CIrrDeviceStub
class CIrrDeviceLinux : public CIrrDeviceStub
{
public:
//! constructor
CIrrDeviceLinux(const SIrrlichtCreationParameters &param);
//! destructor
virtual ~CIrrDeviceLinux();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht
void yield() override;
//! Pause execution and let other processes to run for a specified amount of time.
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t *text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! returns if window has focus.
bool isWindowFocused() const override;
//! returns if window is minimized.
bool isWindowMinimized() const override;
//! returns last state from maximizeWindow() and restoreWindow()
bool isWindowMaximized() const override;
//! returns color format of the window.
video::ECOLOR_FORMAT getColorFormat() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize = false) override;
//! Resize the render window.
void setWindowSize(const irr::core::dimension2d<u32> &size) override;
//! Minimizes the window.
void minimizeWindow() override;
//! Maximizes the window.
void maximizeWindow() override;
//! Restores the window size.
void restoreWindow() override;
//! Get the position of this window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> &joystickInfo) override;
//! gets text from the clipboard
//! \return Returns 0 if no string is in there, otherwise utf-8 text.
virtual const c8 *getTextFromClipboard() const;
//! gets text from the primary selection
//! \return Returns 0 if no string is in there, otherwise utf-8 text.
virtual const c8 *getTextFromPrimarySelection() const;
//! copies text to the clipboard
//! This sets the clipboard selection and _not_ the primary selection.
//! @param text The text in utf-8
virtual void copyToClipboard(const c8 *text) const;
//! copies text to the primary selection
//! This sets the primary selection which you have on X on the middle mouse button.
//! @param text The text in utf-8
virtual void copyToPrimarySelection(const c8 *text) const;
//! Remove all messages pending in the system message loop
void clearSystemMessages() override;
//! Get the device type
E_DEVICE_TYPE getType() const override
{
return EIDT_X11;
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
#ifdef _IRR_COMPILE_WITH_X11_
// convert an Irrlicht texture to a X11 cursor
Cursor TextureToCursor(irr::video::ITexture *tex, const core::rect<s32> &sourceRect, const core::position2d<s32> &hotspot);
Cursor TextureToMonochromeCursor(irr::video::ITexture *tex, const core::rect<s32> &sourceRect, const core::position2d<s32> &hotspot);
#ifdef _IRR_LINUX_XCURSOR_
Cursor TextureToARGBCursor(irr::video::ITexture *tex, const core::rect<s32> &sourceRect, const core::position2d<s32> &hotspot);
#endif
#endif
private:
//! create the driver
void createDriver();
bool createWindow();
void createKeyMap();
void pollJoysticks();
void initXAtoms();
void initXInput2();
bool switchToFullscreen();
void setupTopLevelXorgWindow();
#ifdef _IRR_COMPILE_WITH_X11_
bool createInputContext();
void destroyInputContext();
EKEY_CODE getKeyCode(XEvent &event);
const c8 *getTextFromSelection(Atom selection, core::stringc &text_buffer) const;
bool becomeSelectionOwner(Atom selection) const;
#endif
//! Implementation of the linux cursor control
class CCursorControl : public gui::ICursorControl
{
public:
CCursorControl(CIrrDeviceLinux *dev, bool null);
//! constructor
CIrrDeviceLinux(const SIrrlichtCreationParameters& param);
~CCursorControl();
//! destructor
virtual ~CIrrDeviceLinux();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht
void yield() override;
//! Pause execution and let other processes to run for a specified amount of time.
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t* text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! returns if window has focus.
bool isWindowFocused() const override;
//! returns if window is minimized.
bool isWindowMinimized() const override;
//! returns last state from maximizeWindow() and restoreWindow()
bool isWindowMaximized() const override;
//! returns color format of the window.
video::ECOLOR_FORMAT getColorFormat() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize=false) override;
//! Resize the render window.
void setWindowSize(const irr::core::dimension2d<u32>& size) override;
//! Minimizes the window.
void minimizeWindow() override;
//! Maximizes the window.
void maximizeWindow() override;
//! Restores the window size.
void restoreWindow() override;
//! Get the position of this window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
//! gets text from the clipboard
//! \return Returns 0 if no string is in there, otherwise utf-8 text.
virtual const c8 *getTextFromClipboard() const;
//! gets text from the primary selection
//! \return Returns 0 if no string is in there, otherwise utf-8 text.
virtual const c8 *getTextFromPrimarySelection() const;
//! copies text to the clipboard
//! This sets the clipboard selection and _not_ the primary selection.
//! @param text The text in utf-8
virtual void copyToClipboard(const c8 *text) const;
//! copies text to the primary selection
//! This sets the primary selection which you have on X on the middle mouse button.
//! @param text The text in utf-8
virtual void copyToPrimarySelection(const c8 *text) const;
//! Remove all messages pending in the system message loop
void clearSystemMessages() override;
//! Get the device type
E_DEVICE_TYPE getType() const override
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
return EIDT_X11;
if (visible == IsVisible)
return;
IsVisible = visible;
#ifdef _IRR_COMPILE_WITH_X11_
if (!Null) {
if (!IsVisible)
XDefineCursor(Device->XDisplay, Device->XWindow, InvisCursor);
else
XUndefineCursor(Device->XDisplay, Device->XWindow);
}
#endif
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
#ifdef _IRR_COMPILE_WITH_X11_
// convert an Irrlicht texture to a X11 cursor
Cursor TextureToCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
Cursor TextureToMonochromeCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
#ifdef _IRR_LINUX_XCURSOR_
Cursor TextureToARGBCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
#endif
#endif
private:
//! create the driver
void createDriver();
bool createWindow();
void createKeyMap();
void pollJoysticks();
void initXAtoms();
void initXInput2();
bool switchToFullscreen();
void setupTopLevelXorgWindow();
#ifdef _IRR_COMPILE_WITH_X11_
bool createInputContext();
void destroyInputContext();
EKEY_CODE getKeyCode(XEvent &event);
const c8 *getTextFromSelection(Atom selection, core::stringc &text_buffer) const;
bool becomeSelectionOwner(Atom selection) const;
#endif
//! Implementation of the linux cursor control
class CCursorControl : public gui::ICursorControl
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
public:
return IsVisible;
}
CCursorControl(CIrrDeviceLinux* dev, bool null);
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
~CCursorControl();
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
setPosition((s32)(x * Device->Width), (s32)(y * Device->Height));
}
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
if (visible==IsVisible)
return;
IsVisible = visible;
#ifdef _IRR_COMPILE_WITH_X11_
if (!Null)
{
if ( !IsVisible )
XDefineCursor( Device->XDisplay, Device->XWindow, InvisCursor );
else
XUndefineCursor( Device->XDisplay, Device->XWindow );
}
#endif
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
return IsVisible;
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
#ifdef _IRR_COMPILE_WITH_X11_
if (!Null)
{
if (UseReferenceRect)
{
if (!Null) {
if (UseReferenceRect) {
// NOTE: XIWarpPointer works when X11 has set a coordinate transformation matrix for the mouse unlike XWarpPointer
// which runs into a bug mentioned here: https://gitlab.freedesktop.org/xorg/xserver/-/issues/600
// So also workaround for Irrlicht bug #450
#ifdef _IRR_LINUX_X11_XINPUT2_
if ( DeviceId != 0)
{
XIWarpPointer(Device->XDisplay,
if (DeviceId != 0) {
XIWarpPointer(Device->XDisplay,
DeviceId,
None,
Device->XWindow, 0, 0,
@ -234,249 +227,242 @@ namespace irr
Device->Height,
ReferenceRect.UpperLeftCorner.X + x,
ReferenceRect.UpperLeftCorner.Y + y);
}
else
} else
#endif
{
XWarpPointer(Device->XDisplay,
None,
Device->XWindow, 0, 0,
Device->Width,
Device->Height,
ReferenceRect.UpperLeftCorner.X + x,
ReferenceRect.UpperLeftCorner.Y + y);
}
}
else
{
XWarpPointer(Device->XDisplay,
None,
Device->XWindow, 0, 0,
Device->Width,
Device->Height,
ReferenceRect.UpperLeftCorner.X + x,
ReferenceRect.UpperLeftCorner.Y + y);
}
} else {
#ifdef _IRR_LINUX_X11_XINPUT2_
if ( DeviceId != 0)
{
XIWarpPointer(Device->XDisplay,
if (DeviceId != 0) {
XIWarpPointer(Device->XDisplay,
DeviceId,
None,
Device->XWindow, 0, 0,
Device->Width,
Device->Height, x, y);
}
else
} else
#endif
{
XWarpPointer(Device->XDisplay,
{
XWarpPointer(Device->XDisplay,
None,
Device->XWindow, 0, 0,
Device->Width,
Device->Height, x, y);
}
}
XFlush(Device->XDisplay);
}
XFlush(Device->XDisplay);
}
#endif
CursorPos.X = x;
CursorPos.Y = y;
}
CursorPos.X = x;
CursorPos.Y = y;
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32>& getPosition(bool updateCursor) override
{
if ( updateCursor )
updateCursorPos();
return CursorPos;
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32> &getPosition(bool updateCursor) override
{
if (updateCursor)
updateCursorPos();
return CursorPos;
}
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if ( updateCursor )
updateCursorPos();
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if (updateCursor)
updateCursorPos();
if (!UseReferenceRect)
{
return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
if (!UseReferenceRect) {
return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
CursorPos.Y / (f32)Device->Height);
}
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
}
void setReferenceRect(core::rect<s32>* rect=0) override
{
if (rect)
{
ReferenceRect = *rect;
UseReferenceRect = true;
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
}
// prevent division through zero and uneven sizes
void setReferenceRect(core::rect<s32> *rect = 0) override
{
if (rect) {
ReferenceRect = *rect;
UseReferenceRect = true;
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
ReferenceRect.LowerRightCorner.Y += 1;
// prevent division through zero and uneven sizes
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
ReferenceRect.LowerRightCorner.X += 1;
}
else
UseReferenceRect = false;
}
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight() % 2)
ReferenceRect.LowerRightCorner.Y += 1;
//! Sets the active cursor icon
void setActiveIcon(gui::ECURSOR_ICON iconId) override;
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth() % 2)
ReferenceRect.LowerRightCorner.X += 1;
} else
UseReferenceRect = false;
}
//! Gets the currently active icon
gui::ECURSOR_ICON getActiveIcon() const override
{
return ActiveIcon;
}
//! Sets the active cursor icon
void setActiveIcon(gui::ECURSOR_ICON iconId) override;
//! Add a custom sprite as cursor icon.
gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) override;
//! Gets the currently active icon
gui::ECURSOR_ICON getActiveIcon() const override
{
return ActiveIcon;
}
//! replace the given cursor icon.
void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) override;
//! Add a custom sprite as cursor icon.
gui::ECURSOR_ICON addIcon(const gui::SCursorSprite &icon) override;
//! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
core::dimension2di getSupportedIconSize() const override;
//! replace the given cursor icon.
void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite &icon) override;
//! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
core::dimension2di getSupportedIconSize() const override;
#ifdef _IRR_COMPILE_WITH_X11_
//! Set platform specific behavior flags.
void setPlatformBehavior(gui::ECURSOR_PLATFORM_BEHAVIOR behavior) override {PlatformBehavior = behavior; }
//! Set platform specific behavior flags.
void setPlatformBehavior(gui::ECURSOR_PLATFORM_BEHAVIOR behavior) override { PlatformBehavior = behavior; }
//! Return platform specific behavior.
gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const override { return PlatformBehavior; }
//! Return platform specific behavior.
gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const override { return PlatformBehavior; }
void update();
void clearCursors();
void update();
void clearCursors();
#endif
private:
void updateCursorPos()
{
private:
void updateCursorPos()
{
#ifdef _IRR_COMPILE_WITH_X11_
if (Null)
if (Null)
return;
if (PlatformBehavior & gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped()) {
u32 now = os::Timer::getTime();
if (now <= LastQuery)
return;
LastQuery = now;
}
if ( PlatformBehavior&gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped() )
{
u32 now = os::Timer::getTime();
if (now <= LastQuery)
return;
LastQuery = now;
}
Window tmp;
int itmp1, itmp2;
unsigned int maskreturn;
XQueryPointer(Device->XDisplay, Device->XWindow,
Window tmp;
int itmp1, itmp2;
unsigned int maskreturn;
XQueryPointer(Device->XDisplay, Device->XWindow,
&tmp, &tmp,
&itmp1, &itmp2,
&CursorPos.X, &CursorPos.Y, &maskreturn);
#endif
}
}
CIrrDeviceLinux* Device;
core::position2d<s32> CursorPos;
core::rect<s32> ReferenceRect;
CIrrDeviceLinux *Device;
core::position2d<s32> CursorPos;
core::rect<s32> ReferenceRect;
#ifdef _IRR_COMPILE_WITH_X11_
gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior;
u32 LastQuery;
Cursor InvisCursor;
gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior;
u32 LastQuery;
Cursor InvisCursor;
#ifdef _IRR_LINUX_X11_XINPUT2_
int DeviceId;
int DeviceId;
#endif
struct CursorFrameX11
{
CursorFrameX11() : IconHW(0) {}
CursorFrameX11(Cursor icon) : IconHW(icon) {}
Cursor IconHW; // hardware cursor
};
struct CursorX11
{
CursorX11() {}
explicit CursorX11(Cursor iconHw, u32 frameTime=0) : FrameTime(frameTime)
{
Frames.push_back( CursorFrameX11(iconHw) );
}
core::array<CursorFrameX11> Frames;
u32 FrameTime;
};
core::array<CursorX11> Cursors;
void initCursors();
#endif
bool IsVisible;
bool Null;
bool UseReferenceRect;
gui::ECURSOR_ICON ActiveIcon;
u32 ActiveIconStartTime;
};
friend class CCursorControl;
#ifdef _IRR_COMPILE_WITH_X11_
friend class COpenGLDriver;
Display *XDisplay;
XVisualInfo* VisualInfo;
int Screennr;
Window XWindow;
XSetWindowAttributes WndAttributes;
XSizeHints* StdHints;
XIM XInputMethod;
XIC XInputContext;
bool HasNetWM;
// text is utf-8
mutable core::stringc Clipboard;
mutable core::stringc PrimarySelection;
#endif
#if defined(_IRR_LINUX_X11_XINPUT2_)
int currentTouchedCount;
#endif
u32 Width, Height;
bool WindowHasFocus;
bool WindowMinimized;
bool WindowMaximized;
bool ExternalWindow;
int AutorepeatSupport;
struct SKeyMap
struct CursorFrameX11
{
SKeyMap() {}
SKeyMap(s32 x11, s32 win32)
: X11Key(x11), Win32Key(win32)
{
}
CursorFrameX11() :
IconHW(0) {}
CursorFrameX11(Cursor icon) :
IconHW(icon) {}
KeySym X11Key;
s32 Win32Key;
bool operator<(const SKeyMap& o) const
{
return X11Key<o.X11Key;
}
Cursor IconHW; // hardware cursor
};
core::array<SKeyMap> KeyMap;
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
struct JoystickInfo
struct CursorX11
{
int fd;
int axes;
int buttons;
SEvent persistentData;
JoystickInfo() : fd(-1), axes(0), buttons(0) { }
CursorX11() {}
explicit CursorX11(Cursor iconHw, u32 frameTime = 0) :
FrameTime(frameTime)
{
Frames.push_back(CursorFrameX11(iconHw));
}
core::array<CursorFrameX11> Frames;
u32 FrameTime;
};
core::array<JoystickInfo> ActiveJoysticks;
core::array<CursorX11> Cursors;
void initCursors();
#endif
bool IsVisible;
bool Null;
bool UseReferenceRect;
gui::ECURSOR_ICON ActiveIcon;
u32 ActiveIconStartTime;
};
friend class CCursorControl;
#ifdef _IRR_COMPILE_WITH_X11_
friend class COpenGLDriver;
Display *XDisplay;
XVisualInfo *VisualInfo;
int Screennr;
Window XWindow;
XSetWindowAttributes WndAttributes;
XSizeHints *StdHints;
XIM XInputMethod;
XIC XInputContext;
bool HasNetWM;
// text is utf-8
mutable core::stringc Clipboard;
mutable core::stringc PrimarySelection;
#endif
#if defined(_IRR_LINUX_X11_XINPUT2_)
int currentTouchedCount;
#endif
u32 Width, Height;
bool WindowHasFocus;
bool WindowMinimized;
bool WindowMaximized;
bool ExternalWindow;
int AutorepeatSupport;
struct SKeyMap
{
SKeyMap() {}
SKeyMap(s32 x11, s32 win32) :
X11Key(x11), Win32Key(win32)
{
}
KeySym X11Key;
s32 Win32Key;
bool operator<(const SKeyMap &o) const
{
return X11Key < o.X11Key;
}
};
core::array<SKeyMap> KeyMap;
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
struct JoystickInfo
{
int fd;
int axes;
int buttons;
SEvent persistentData;
JoystickInfo() :
fd(-1), axes(0), buttons(0) {}
};
core::array<JoystickInfo> ActiveJoysticks;
#endif
};
} // end namespace irr

View File

@ -19,12 +19,12 @@
namespace irr
{
class CIrrDeviceMacOSX;
class CIrrDeviceMacOSX;
}
@interface CIrrDelegateOSX : NSObject <NSApplicationDelegate, NSWindowDelegate>
- (id)initWithDevice:(irr::CIrrDeviceMacOSX*)device;
- (id)initWithDevice:(irr::CIrrDeviceMacOSX *)device;
- (void)terminate:(id)sender;
- (BOOL)isQuit;
@ -32,217 +32,206 @@ namespace irr
namespace irr
{
class CIrrDeviceMacOSX : public CIrrDeviceStub
class CIrrDeviceMacOSX : public CIrrDeviceStub
{
public:
//! constructor
CIrrDeviceMacOSX(const SIrrlichtCreationParameters &params);
//! destructor
virtual ~CIrrDeviceMacOSX();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht
void yield() override;
//! Pause execution and let other processes to run for a specified amount of time.
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t *text) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! Checks if the Irrlicht window has focus
bool isWindowFocused() const override;
//! Checks if the Irrlicht window is minimized
bool isWindowMinimized() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize) override;
//! Returns true if the window is resizable, false if not
virtual bool isResizable() const;
//! Minimizes the window if possible
void minimizeWindow() override;
//! Maximizes the window if possible.
void maximizeWindow() override;
//! Restore the window to normal size if possible.
void restoreWindow() override;
//! Get the position of this window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> &joystickInfo) override;
//! Get the device type
E_DEVICE_TYPE getType() const override
{
return EIDT_OSX;
}
void setMouseLocation(int x, int y);
void setResize(int width, int height);
void setCursorVisible(bool visible);
void setWindow(NSWindow *window);
private:
//! create the driver
void createDriver();
//! Implementation of the macos x cursor control
class CCursorControl : public gui::ICursorControl
{
public:
//! constructor
CIrrDeviceMacOSX(const SIrrlichtCreationParameters& params);
//! destructor
virtual ~CIrrDeviceMacOSX();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht
void yield() override;
//! Pause execution and let other processes to run for a specified amount of time.
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t* text) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! Checks if the Irrlicht window has focus
bool isWindowFocused() const override;
//! Checks if the Irrlicht window is minimized
bool isWindowMinimized() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize) override;
//! Returns true if the window is resizable, false if not
virtual bool isResizable() const;
//! Minimizes the window if possible
void minimizeWindow() override;
//! Maximizes the window if possible.
void maximizeWindow() override;
//! Restore the window to normal size if possible.
void restoreWindow() override;
//! Get the position of this window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
//! Get the device type
E_DEVICE_TYPE getType() const override
CCursorControl(const core::dimension2d<u32> &wsize, CIrrDeviceMacOSX *device) :
WindowSize(wsize), InvWindowSize(0.0f, 0.0f), Device(device), IsVisible(true), UseReferenceRect(false)
{
return EIDT_OSX;
CursorPos.X = CursorPos.Y = 0;
if (WindowSize.Width != 0)
InvWindowSize.Width = 1.0f / WindowSize.Width;
if (WindowSize.Height != 0)
InvWindowSize.Height = 1.0f / WindowSize.Height;
}
void setMouseLocation(int x, int y);
void setResize(int width, int height);
void setCursorVisible(bool visible);
void setWindow(NSWindow* window);
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
IsVisible = visible;
Device->setCursorVisible(visible);
}
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
return IsVisible;
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
setPosition((s32)(x * WindowSize.Width), (s32)(y * WindowSize.Height));
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
if (CursorPos.X != pos.X || CursorPos.Y != pos.Y)
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
if (UseReferenceRect) {
Device->setMouseLocation(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y);
} else {
Device->setMouseLocation(x, y);
}
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32> &getPosition(bool updateCursor) override
{
return CursorPos;
}
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if (!UseReferenceRect) {
return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
CursorPos.Y * InvWindowSize.Height);
}
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
}
//! Sets an absolute reference rect for calculating the cursor position.
void setReferenceRect(core::rect<s32> *rect = 0) override
{
if (rect) {
ReferenceRect = *rect;
UseReferenceRect = true;
// prevent division through zero and uneven sizes
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight() % 2)
ReferenceRect.LowerRightCorner.Y += 1;
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth() % 2)
ReferenceRect.LowerRightCorner.X += 1;
} else
UseReferenceRect = false;
}
//! Updates the internal cursor position
void updateInternalCursorPosition(int x, int y)
{
CursorPos.X = x;
CursorPos.Y = y;
}
private:
//! create the driver
void createDriver();
//! Implementation of the macos x cursor control
class CCursorControl : public gui::ICursorControl
{
public:
CCursorControl(const core::dimension2d<u32>& wsize, CIrrDeviceMacOSX *device)
: WindowSize(wsize), InvWindowSize(0.0f, 0.0f), Device(device), IsVisible(true), UseReferenceRect(false)
{
CursorPos.X = CursorPos.Y = 0;
if (WindowSize.Width!=0)
InvWindowSize.Width = 1.0f / WindowSize.Width;
if (WindowSize.Height!=0)
InvWindowSize.Height = 1.0f / WindowSize.Height;
}
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
IsVisible = visible;
Device->setCursorVisible(visible);
}
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
return IsVisible;
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height));
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
if (CursorPos.X != pos.X || CursorPos.Y != pos.Y)
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
if (UseReferenceRect)
{
Device->setMouseLocation(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y);
}
else
{
Device->setMouseLocation(x,y);
}
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32>& getPosition(bool updateCursor) override
{
return CursorPos;
}
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if (!UseReferenceRect)
{
return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
CursorPos.Y * InvWindowSize.Height);
}
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
}
//! Sets an absolute reference rect for calculating the cursor position.
void setReferenceRect(core::rect<s32>* rect=0) override
{
if (rect)
{
ReferenceRect = *rect;
UseReferenceRect = true;
// prevent division through zero and uneven sizes
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
ReferenceRect.LowerRightCorner.Y += 1;
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
ReferenceRect.LowerRightCorner.X += 1;
}
else
UseReferenceRect = false;
}
//! Updates the internal cursor position
void updateInternalCursorPosition(int x,int y)
{
CursorPos.X = x;
CursorPos.Y = y;
}
private:
core::position2d<s32> CursorPos;
core::dimension2d<s32> WindowSize;
core::dimension2d<float> InvWindowSize;
core::rect<s32> ReferenceRect;
CIrrDeviceMacOSX *Device;
bool IsVisible;
bool UseReferenceRect;
};
bool createWindow();
void initKeycodes();
void storeMouseLocation();
void postMouseEvent(void *event, irr::SEvent &ievent);
void postKeyEvent(void *event, irr::SEvent &ievent, bool pressed);
void pollJoysticks();
NSWindow* Window;
CGDirectDisplayID Display;
std::map<int,int> KeyCodes;
int DeviceWidth;
int DeviceHeight;
int ScreenWidth;
int ScreenHeight;
u32 MouseButtonStates;
bool IsFullscreen;
bool IsActive;
bool IsShiftDown;
bool IsControlDown;
bool IsResizable;
core::position2d<s32> CursorPos;
core::dimension2d<s32> WindowSize;
core::dimension2d<float> InvWindowSize;
core::rect<s32> ReferenceRect;
CIrrDeviceMacOSX *Device;
bool IsVisible;
bool UseReferenceRect;
};
bool createWindow();
void initKeycodes();
void storeMouseLocation();
void postMouseEvent(void *event, irr::SEvent &ievent);
void postKeyEvent(void *event, irr::SEvent &ievent, bool pressed);
void pollJoysticks();
NSWindow *Window;
CGDirectDisplayID Display;
std::map<int, int> KeyCodes;
int DeviceWidth;
int DeviceHeight;
int ScreenWidth;
int ScreenHeight;
u32 MouseButtonStates;
bool IsFullscreen;
bool IsActive;
bool IsShiftDown;
bool IsControlDown;
bool IsResizable;
};
} // end namespace irr

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -28,306 +28,299 @@
namespace irr
{
class CIrrDeviceSDL : public CIrrDeviceStub
class CIrrDeviceSDL : public CIrrDeviceStub
{
public:
//! constructor
CIrrDeviceSDL(const SIrrlichtCreationParameters &param);
//! destructor
virtual ~CIrrDeviceSDL();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! pause execution temporarily
void yield() override;
//! pause execution for a specified time
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t *text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! returns if window has focus.
bool isWindowFocused() const override;
//! returns if window is minimized.
bool isWindowMinimized() const override;
//! returns color format of the window.
video::ECOLOR_FORMAT getColorFormat() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize = false) override;
//! Minimizes the window.
void minimizeWindow() override;
//! Maximizes the window.
void maximizeWindow() override;
//! Restores the window size.
void restoreWindow() override;
//! Checks if the window is maximized.
bool isWindowMaximized() const override;
//! Checks if the Irrlicht window is running in fullscreen mode
/** \return True if window is fullscreen. */
bool isFullscreen() const override;
//! Get the position of this window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> &joystickInfo) override;
//! Get the device type
E_DEVICE_TYPE getType() const override
{
return EIDT_SDL;
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
void SwapWindow();
//! Implementation of the linux cursor control
class CCursorControl : public gui::ICursorControl
{
public:
//! constructor
CIrrDeviceSDL(const SIrrlichtCreationParameters& param);
//! destructor
virtual ~CIrrDeviceSDL();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! pause execution temporarily
void yield() override;
//! pause execution for a specified time
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t* text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! returns if window has focus.
bool isWindowFocused() const override;
//! returns if window is minimized.
bool isWindowMinimized() const override;
//! returns color format of the window.
video::ECOLOR_FORMAT getColorFormat() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize=false) override;
//! Minimizes the window.
void minimizeWindow() override;
//! Maximizes the window.
void maximizeWindow() override;
//! Restores the window size.
void restoreWindow() override;
//! Checks if the window is maximized.
bool isWindowMaximized() const override;
//! Checks if the Irrlicht window is running in fullscreen mode
/** \return True if window is fullscreen. */
bool isFullscreen() const override;
//! Get the position of this window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
//! Get the device type
E_DEVICE_TYPE getType() const override
CCursorControl(CIrrDeviceSDL *dev) :
Device(dev), IsVisible(true)
{
return EIDT_SDL;
initCursors();
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
void SwapWindow();
//! Implementation of the linux cursor control
class CCursorControl : public gui::ICursorControl
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
public:
CCursorControl(CIrrDeviceSDL* dev)
: Device(dev), IsVisible(true)
{
initCursors();
IsVisible = visible;
if (visible)
SDL_ShowCursor(SDL_ENABLE);
else {
SDL_ShowCursor(SDL_DISABLE);
}
}
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
IsVisible = visible;
if ( visible )
SDL_ShowCursor( SDL_ENABLE );
else
{
SDL_ShowCursor( SDL_DISABLE );
}
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
return IsVisible;
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
setPosition((s32)(x * Device->Width), (s32)(y * Device->Height));
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
SDL_WarpMouseInWindow(Device->Window, x, y);
if (SDL_GetRelativeMouseMode()) {
// There won't be an event for this warp (details on libsdl-org/SDL/issues/6034)
Device->MouseX = x;
Device->MouseY = y;
}
}
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
return IsVisible;
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32> &getPosition(bool updateCursor) override
{
if (updateCursor)
updateCursorPos();
return CursorPos;
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
SDL_WarpMouseInWindow(Device->Window, x, y);
if (SDL_GetRelativeMouseMode()) {
// There won't be an event for this warp (details on libsdl-org/SDL/issues/6034)
Device->MouseX = x;
Device->MouseY = y;
}
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32>& getPosition(bool updateCursor) override
{
if ( updateCursor )
updateCursorPos();
return CursorPos;
}
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if ( updateCursor )
updateCursorPos();
return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if (updateCursor)
updateCursorPos();
return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
CursorPos.Y / (f32)Device->Height);
}
void setReferenceRect(core::rect<s32> *rect = 0) override
{
}
virtual void setRelativeMode(bool relative) _IRR_OVERRIDE_
{
// Only change it when necessary, as it flushes mouse motion when enabled
if (relative != SDL_GetRelativeMouseMode()) {
if (relative)
SDL_SetRelativeMouseMode(SDL_TRUE);
else
SDL_SetRelativeMouseMode(SDL_FALSE);
}
}
void setReferenceRect(core::rect<s32>* rect=0) override
{
void setActiveIcon(gui::ECURSOR_ICON iconId) override
{
ActiveIcon = iconId;
if (iconId > Cursors.size() || !Cursors[iconId]) {
iconId = gui::ECI_NORMAL;
if (iconId > Cursors.size() || !Cursors[iconId])
return;
}
SDL_SetCursor(Cursors[iconId].get());
}
virtual void setRelativeMode(bool relative) _IRR_OVERRIDE_
{
// Only change it when necessary, as it flushes mouse motion when enabled
if ( relative != SDL_GetRelativeMouseMode()) {
if ( relative )
SDL_SetRelativeMouseMode( SDL_TRUE );
else
SDL_SetRelativeMouseMode( SDL_FALSE );
}
}
void setActiveIcon(gui::ECURSOR_ICON iconId) override
{
ActiveIcon = iconId;
if (iconId > Cursors.size() || !Cursors[iconId]) {
iconId = gui::ECI_NORMAL;
if (iconId > Cursors.size() || !Cursors[iconId])
return;
}
SDL_SetCursor(Cursors[iconId].get());
}
gui::ECURSOR_ICON getActiveIcon() const override
{
return ActiveIcon;
}
private:
void updateCursorPos()
{
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
EmscriptenPointerlockChangeEvent pointerlockStatus; // let's hope that test is not expensive ...
if ( emscripten_get_pointerlock_status(&pointerlockStatus) == EMSCRIPTEN_RESULT_SUCCESS )
{
if ( pointerlockStatus.isActive )
{
CursorPos.X += Device->MouseXRel;
CursorPos.Y += Device->MouseYRel;
Device->MouseXRel = 0;
Device->MouseYRel = 0;
}
else
{
CursorPos.X = Device->MouseX;
CursorPos.Y = Device->MouseY;
}
}
#else
CursorPos.X = Device->MouseX;
CursorPos.Y = Device->MouseY;
if (CursorPos.X < 0)
CursorPos.X = 0;
if (CursorPos.X > (s32)Device->Width)
CursorPos.X = Device->Width;
if (CursorPos.Y < 0)
CursorPos.Y = 0;
if (CursorPos.Y > (s32)Device->Height)
CursorPos.Y = Device->Height;
#endif
}
void initCursors();
CIrrDeviceSDL* Device;
core::position2d<s32> CursorPos;
bool IsVisible;
struct CursorDeleter {
void operator()(SDL_Cursor *ptr) {
if (ptr)
SDL_FreeCursor(ptr);
}
};
std::vector<std::unique_ptr<SDL_Cursor, CursorDeleter>> Cursors;
gui::ECURSOR_ICON ActiveIcon = gui::ECURSOR_ICON::ECI_NORMAL;
};
gui::ECURSOR_ICON getActiveIcon() const override
{
return ActiveIcon;
}
private:
void updateCursorPos()
{
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
static EM_BOOL MouseUpDownCallback(int eventType, const EmscriptenMouseEvent * event, void* userData);
EmscriptenPointerlockChangeEvent pointerlockStatus; // let's hope that test is not expensive ...
if (emscripten_get_pointerlock_status(&pointerlockStatus) == EMSCRIPTEN_RESULT_SUCCESS) {
if (pointerlockStatus.isActive) {
CursorPos.X += Device->MouseXRel;
CursorPos.Y += Device->MouseYRel;
Device->MouseXRel = 0;
Device->MouseYRel = 0;
} else {
CursorPos.X = Device->MouseX;
CursorPos.Y = Device->MouseY;
}
}
#else
CursorPos.X = Device->MouseX;
CursorPos.Y = Device->MouseY;
if (CursorPos.X < 0)
CursorPos.X = 0;
if (CursorPos.X > (s32)Device->Width)
CursorPos.X = Device->Width;
if (CursorPos.Y < 0)
CursorPos.Y = 0;
if (CursorPos.Y > (s32)Device->Height)
CursorPos.Y = Device->Height;
#endif
}
void initCursors();
CIrrDeviceSDL *Device;
core::position2d<s32> CursorPos;
bool IsVisible;
struct CursorDeleter
{
void operator()(SDL_Cursor *ptr)
{
if (ptr)
SDL_FreeCursor(ptr);
}
};
std::vector<std::unique_ptr<SDL_Cursor, CursorDeleter>> Cursors;
gui::ECURSOR_ICON ActiveIcon = gui::ECURSOR_ICON::ECI_NORMAL;
};
private:
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
static EM_BOOL MouseUpDownCallback(int eventType, const EmscriptenMouseEvent *event, void *userData);
static EM_BOOL MouseEnterCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
static EM_BOOL MouseLeaveCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
#endif
// Check if a key is a known special character with no side effects on text boxes.
static bool keyIsKnownSpecial(EKEY_CODE key);
// Check if a key is a known special character with no side effects on text boxes.
static bool keyIsKnownSpecial(EKEY_CODE key);
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
void resetReceiveTextInputEvents();
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
void resetReceiveTextInputEvents();
//! create the driver
void createDriver();
//! create the driver
void createDriver();
bool createWindow();
bool createWindow();
void createKeyMap();
void createKeyMap();
void logAttributes();
SDL_GLContext Context;
SDL_Window *Window;
int SDL_Flags;
void logAttributes();
SDL_GLContext Context;
SDL_Window *Window;
int SDL_Flags;
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
core::array<SDL_Joystick*> Joysticks;
core::array<SDL_Joystick *> Joysticks;
#endif
s32 MouseX, MouseY;
s32 MouseXRel, MouseYRel;
u32 MouseButtonStates;
s32 MouseX, MouseY;
s32 MouseXRel, MouseYRel;
u32 MouseButtonStates;
u32 Width, Height;
u32 Width, Height;
bool Resizable;
bool Resizable;
core::rect<s32> lastElemPos;
core::rect<s32> lastElemPos;
struct SKeyMap
struct SKeyMap
{
SKeyMap() {}
SKeyMap(s32 x11, s32 win32) :
SDLKey(x11), Win32Key(win32)
{
SKeyMap() {}
SKeyMap(s32 x11, s32 win32)
: SDLKey(x11), Win32Key(win32)
{
}
}
s32 SDLKey;
s32 Win32Key;
s32 SDLKey;
s32 Win32Key;
bool operator<(const SKeyMap& o) const
{
return SDLKey<o.SDLKey;
}
};
core::array<SKeyMap> KeyMap;
SDL_SysWMinfo Info;
s32 CurrentTouchCount;
bool operator<(const SKeyMap &o) const
{
return SDLKey < o.SDLKey;
}
};
core::array<SKeyMap> KeyMap;
SDL_SysWMinfo Info;
s32 CurrentTouchCount;
};
} // end namespace irr
#endif // _IRR_COMPILE_WITH_SDL_DEVICE_

View File

@ -17,22 +17,19 @@
namespace irr
{
//! constructor
CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params)
: IrrlichtDevice(), VideoDriver(0), GUIEnvironment(0), SceneManager(0),
Timer(0), CursorControl(0), UserReceiver(params.EventReceiver),
Logger(0), Operator(0), FileSystem(0),
InputReceivingSceneManager(0), ContextManager(0),
CreationParams(params), Close(false)
CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters &params) :
IrrlichtDevice(), VideoDriver(0), GUIEnvironment(0), SceneManager(0),
Timer(0), CursorControl(0), UserReceiver(params.EventReceiver),
Logger(0), Operator(0), FileSystem(0),
InputReceivingSceneManager(0), ContextManager(0),
CreationParams(params), Close(false)
{
Timer = new CTimer();
if (os::Printer::Logger)
{
if (os::Printer::Logger) {
os::Printer::Logger->grab();
Logger = (CLogger*)os::Printer::Logger;
Logger = (CLogger *)os::Printer::Logger;
Logger->setReceiver(UserReceiver);
}
else
{
} else {
Logger = new CLogger(UserReceiver);
os::Printer::Logger = Logger;
}
@ -49,7 +46,6 @@ CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params)
checkVersion(params.SDK_version_do_not_use);
}
CIrrDeviceStub::~CIrrDeviceStub()
{
if (GUIEnvironment)
@ -64,7 +60,7 @@ CIrrDeviceStub::~CIrrDeviceStub()
if (ContextManager)
ContextManager->drop();
if ( FileSystem )
if (FileSystem)
FileSystem->drop();
if (InputReceivingSceneManager)
@ -85,7 +81,6 @@ CIrrDeviceStub::~CIrrDeviceStub()
os::Printer::Logger = 0;
}
void CIrrDeviceStub::createGUIAndScene()
{
// create gui environment
@ -97,76 +92,65 @@ void CIrrDeviceStub::createGUIAndScene()
setEventReceiver(UserReceiver);
}
//! returns the video driver
video::IVideoDriver* CIrrDeviceStub::getVideoDriver()
video::IVideoDriver *CIrrDeviceStub::getVideoDriver()
{
return VideoDriver;
}
//! return file system
io::IFileSystem* CIrrDeviceStub::getFileSystem()
io::IFileSystem *CIrrDeviceStub::getFileSystem()
{
return FileSystem;
}
//! returns the gui environment
gui::IGUIEnvironment* CIrrDeviceStub::getGUIEnvironment()
gui::IGUIEnvironment *CIrrDeviceStub::getGUIEnvironment()
{
return GUIEnvironment;
}
//! returns the scene manager
scene::ISceneManager* CIrrDeviceStub::getSceneManager()
scene::ISceneManager *CIrrDeviceStub::getSceneManager()
{
return SceneManager;
}
//! \return Returns a pointer to the ITimer object. With it the
//! current Time can be received.
ITimer* CIrrDeviceStub::getTimer()
ITimer *CIrrDeviceStub::getTimer()
{
return Timer;
}
//! Sets the window icon.
bool CIrrDeviceStub::setWindowIcon(const video::IImage *img)
{
return false;
}
//! Returns the version of the engine.
const char* CIrrDeviceStub::getVersion() const
const char *CIrrDeviceStub::getVersion() const
{
return IRRLICHT_SDK_VERSION;
}
//! \return Returns a pointer to the mouse cursor control interface.
gui::ICursorControl* CIrrDeviceStub::getCursorControl()
gui::ICursorControl *CIrrDeviceStub::getCursorControl()
{
return CursorControl;
}
//! return the context manager
video::IContextManager* CIrrDeviceStub::getContextManager()
video::IContextManager *CIrrDeviceStub::getContextManager()
{
return ContextManager;
}
//! checks version of sdk and prints warning if there might be a problem
bool CIrrDeviceStub::checkVersion(const char* version)
bool CIrrDeviceStub::checkVersion(const char *version)
{
if (strcmp(getVersion(), version))
{
if (strcmp(getVersion(), version)) {
core::stringc w;
w = "Warning: The library version of the Irrlicht Engine (";
w += getVersion();
@ -181,25 +165,16 @@ bool CIrrDeviceStub::checkVersion(const char* version)
return true;
}
//! Compares to the last call of this function to return double and triple clicks.
u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent )
u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent)
{
const s32 MAX_MOUSEMOVE = 3;
irr::u32 clickTime = getTimer()->getRealTime();
if ( (clickTime-MouseMultiClicks.LastClickTime) < MouseMultiClicks.DoubleClickTime
&& core::abs_(MouseMultiClicks.LastClick.X - mouseX ) <= MAX_MOUSEMOVE
&& core::abs_(MouseMultiClicks.LastClick.Y - mouseY ) <= MAX_MOUSEMOVE
&& MouseMultiClicks.CountSuccessiveClicks < 3
&& MouseMultiClicks.LastMouseInputEvent == inputEvent
)
{
if ((clickTime - MouseMultiClicks.LastClickTime) < MouseMultiClicks.DoubleClickTime && core::abs_(MouseMultiClicks.LastClick.X - mouseX) <= MAX_MOUSEMOVE && core::abs_(MouseMultiClicks.LastClick.Y - mouseY) <= MAX_MOUSEMOVE && MouseMultiClicks.CountSuccessiveClicks < 3 && MouseMultiClicks.LastMouseInputEvent == inputEvent) {
++MouseMultiClicks.CountSuccessiveClicks;
}
else
{
} else {
MouseMultiClicks.CountSuccessiveClicks = 1;
}
@ -211,9 +186,8 @@ u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_E
return MouseMultiClicks.CountSuccessiveClicks;
}
//! send the event to the right receiver
bool CIrrDeviceStub::postEventFromUser(const SEvent& event)
bool CIrrDeviceStub::postEventFromUser(const SEvent &event)
{
bool absorbed = false;
@ -223,7 +197,7 @@ bool CIrrDeviceStub::postEventFromUser(const SEvent& event)
if (!absorbed && GUIEnvironment)
absorbed = GUIEnvironment->postEventFromUser(event);
scene::ISceneManager* inputReceiver = InputReceivingSceneManager;
scene::ISceneManager *inputReceiver = InputReceivingSceneManager;
if (!inputReceiver)
inputReceiver = SceneManager;
@ -233,9 +207,8 @@ bool CIrrDeviceStub::postEventFromUser(const SEvent& event)
return absorbed;
}
//! Sets a new event receiver to receive events
void CIrrDeviceStub::setEventReceiver(IEventReceiver* receiver)
void CIrrDeviceStub::setEventReceiver(IEventReceiver *receiver)
{
UserReceiver = receiver;
Logger->setReceiver(receiver);
@ -243,30 +216,26 @@ void CIrrDeviceStub::setEventReceiver(IEventReceiver* receiver)
GUIEnvironment->setUserEventReceiver(receiver);
}
//! Returns poinhter to the current event receiver. Returns 0 if there is none.
IEventReceiver* CIrrDeviceStub::getEventReceiver()
IEventReceiver *CIrrDeviceStub::getEventReceiver()
{
return UserReceiver;
}
//! \return Returns a pointer to the logger.
ILogger* CIrrDeviceStub::getLogger()
ILogger *CIrrDeviceStub::getLogger()
{
return Logger;
}
//! Returns the operation system opertator object.
IOSOperator* CIrrDeviceStub::getOSOperator()
IOSOperator *CIrrDeviceStub::getOSOperator()
{
return Operator;
}
//! Sets the input receiving scene manager.
void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneManager)
void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager *sceneManager)
{
if (sceneManager)
sceneManager->grab();
@ -276,21 +245,18 @@ void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneMa
InputReceivingSceneManager = sceneManager;
}
//! Checks if the window is maximized.
bool CIrrDeviceStub::isWindowMaximized() const
{
return false;
}
//! Checks if the window is running in fullscreen mode
bool CIrrDeviceStub::isFullscreen() const
{
return CreationParams.Fullscreen;
}
//! returns color format
video::ECOLOR_FORMAT CIrrDeviceStub::getColorFormat() const
{
@ -298,7 +264,7 @@ video::ECOLOR_FORMAT CIrrDeviceStub::getColorFormat() const
}
//! No-op in this implementation
bool CIrrDeviceStub::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
bool CIrrDeviceStub::activateJoysticks(core::array<SJoystickInfo> &joystickInfo)
{
return false;
}
@ -306,77 +272,77 @@ bool CIrrDeviceStub::activateJoysticks(core::array<SJoystickInfo> & joystickInfo
//! No-op in this implementation
bool CIrrDeviceStub::activateAccelerometer(float updateInterval)
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::deactivateAccelerometer()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::isAccelerometerActive()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::isAccelerometerAvailable()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::activateGyroscope(float updateInterval)
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::deactivateGyroscope()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::isGyroscopeActive()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::isGyroscopeAvailable()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::activateDeviceMotion(float updateInterval)
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::deactivateDeviceMotion()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::isDeviceMotionActive()
{
return false;
return false;
}
//! No-op in this implementation
bool CIrrDeviceStub::isDeviceMotionAvailable()
{
return false;
return false;
}
//! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behavior.
void CIrrDeviceStub::setDoubleClickTime( u32 timeMs )
void CIrrDeviceStub::setDoubleClickTime(u32 timeMs)
{
MouseMultiClicks.DoubleClickTime = timeMs;
}
@ -407,6 +373,4 @@ bool CIrrDeviceStub::acceptsIME()
return elem && elem->acceptsIME();
}
} // end namespace irr

View File

@ -10,198 +10,195 @@
namespace irr
{
// lots of prototypes:
class ILogger;
class CLogger;
// lots of prototypes:
class ILogger;
class CLogger;
namespace gui
namespace gui
{
class IGUIEnvironment;
IGUIEnvironment *createGUIEnvironment(io::IFileSystem *fs,
video::IVideoDriver *Driver, IOSOperator *op);
}
namespace scene
{
ISceneManager *createSceneManager(video::IVideoDriver *driver, gui::ICursorControl *cc);
}
namespace io
{
IFileSystem *createFileSystem();
}
namespace video
{
IVideoDriver *createNullDriver(io::IFileSystem *io, const core::dimension2d<u32> &screenSize);
}
//! Stub for an Irrlicht Device implementation
class CIrrDeviceStub : public IrrlichtDevice
{
public:
//! constructor
CIrrDeviceStub(const SIrrlichtCreationParameters &param);
//! destructor
virtual ~CIrrDeviceStub();
//! returns the video driver
video::IVideoDriver *getVideoDriver() override;
//! return file system
io::IFileSystem *getFileSystem() override;
//! returns the gui environment
gui::IGUIEnvironment *getGUIEnvironment() override;
//! returns the scene manager
scene::ISceneManager *getSceneManager() override;
//! \return Returns a pointer to the mouse cursor control interface.
gui::ICursorControl *getCursorControl() override;
//! return the context manager
video::IContextManager *getContextManager() override;
//! Returns a pointer to the ITimer object. With it the current Time can be received.
ITimer *getTimer() override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! Returns the version of the engine.
const char *getVersion() const override;
//! send the event to the right receiver
bool postEventFromUser(const SEvent &event) override;
//! Sets a new event receiver to receive events
void setEventReceiver(IEventReceiver *receiver) override;
//! Returns pointer to the current event receiver. Returns 0 if there is none.
IEventReceiver *getEventReceiver() override;
//! Sets the input receiving scene manager.
/** If set to null, the main scene manager (returned by GetSceneManager()) will receive the input */
void setInputReceivingSceneManager(scene::ISceneManager *sceneManager) override;
//! Returns a pointer to the logger.
ILogger *getLogger() override;
//! Returns the operation system opertator object.
IOSOperator *getOSOperator() override;
//! Checks if the window is maximized.
bool isWindowMaximized() const override;
//! Checks if the window is running in fullscreen mode.
bool isFullscreen() const override;
//! get color format of the current window
video::ECOLOR_FORMAT getColorFormat() const override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> &joystickInfo) override;
//! Activate accelerometer.
bool activateAccelerometer(float updateInterval = 0.016666f) override;
//! Deactivate accelerometer.
bool deactivateAccelerometer() override;
//! Is accelerometer active.
bool isAccelerometerActive() override;
//! Is accelerometer available.
bool isAccelerometerAvailable() override;
//! Activate gyroscope.
bool activateGyroscope(float updateInterval = 0.016666f) override;
//! Deactivate gyroscope.
bool deactivateGyroscope() override;
//! Is gyroscope active.
bool isGyroscopeActive() override;
//! Is gyroscope available.
bool isGyroscopeAvailable() override;
//! Activate device motion.
bool activateDeviceMotion(float updateInterval = 0.016666f) override;
//! Deactivate device motion.
bool deactivateDeviceMotion() override;
//! Is device motion active.
bool isDeviceMotionActive() override;
//! Is device motion available.
bool isDeviceMotionAvailable() override;
//! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behavior.
//! When set to 0 no double- and tripleclicks will be generated.
void setDoubleClickTime(u32 timeMs) override;
//! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse.
u32 getDoubleClickTime() const override;
//! Remove all messages pending in the system message loop
void clearSystemMessages() override;
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
//! Resize the render window.
void setWindowSize(const irr::core::dimension2d<u32> &size) override {}
protected:
void createGUIAndScene();
//! checks version of SDK and prints warning if there might be a problem
bool checkVersion(const char *version);
//! Compares to the last call of this function to return double and triple clicks.
/** Needed for win32 device event handling
\return Returns only 1,2 or 3. A 4th click will start with 1 again.
*/
virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent);
//! Checks whether the input device should take input from the IME
bool acceptsIME();
video::IVideoDriver *VideoDriver;
gui::IGUIEnvironment *GUIEnvironment;
scene::ISceneManager *SceneManager;
ITimer *Timer;
gui::ICursorControl *CursorControl;
IEventReceiver *UserReceiver;
CLogger *Logger;
IOSOperator *Operator;
io::IFileSystem *FileSystem;
scene::ISceneManager *InputReceivingSceneManager;
struct SMouseMultiClicks
{
class IGUIEnvironment;
IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs,
video::IVideoDriver* Driver, IOSOperator* op);
}
namespace scene
{
ISceneManager* createSceneManager(video::IVideoDriver* driver, gui::ICursorControl* cc);
}
namespace io
{
IFileSystem* createFileSystem();
}
namespace video
{
IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize);
}
//! Stub for an Irrlicht Device implementation
class CIrrDeviceStub : public IrrlichtDevice
{
public:
//! constructor
CIrrDeviceStub(const SIrrlichtCreationParameters& param);
//! destructor
virtual ~CIrrDeviceStub();
//! returns the video driver
video::IVideoDriver* getVideoDriver() override;
//! return file system
io::IFileSystem* getFileSystem() override;
//! returns the gui environment
gui::IGUIEnvironment* getGUIEnvironment() override;
//! returns the scene manager
scene::ISceneManager* getSceneManager() override;
//! \return Returns a pointer to the mouse cursor control interface.
gui::ICursorControl* getCursorControl() override;
//! return the context manager
video::IContextManager* getContextManager() override;
//! Returns a pointer to the ITimer object. With it the current Time can be received.
ITimer* getTimer() override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! Returns the version of the engine.
const char* getVersion() const override;
//! send the event to the right receiver
bool postEventFromUser(const SEvent& event) override;
//! Sets a new event receiver to receive events
void setEventReceiver(IEventReceiver* receiver) override;
//! Returns pointer to the current event receiver. Returns 0 if there is none.
IEventReceiver* getEventReceiver() override;
//! Sets the input receiving scene manager.
/** If set to null, the main scene manager (returned by GetSceneManager()) will receive the input */
void setInputReceivingSceneManager(scene::ISceneManager* sceneManager) override;
//! Returns a pointer to the logger.
ILogger* getLogger() override;
//! Returns the operation system opertator object.
IOSOperator* getOSOperator() override;
//! Checks if the window is maximized.
bool isWindowMaximized() const override;
//! Checks if the window is running in fullscreen mode.
bool isFullscreen() const override;
//! get color format of the current window
video::ECOLOR_FORMAT getColorFormat() const override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
//! Activate accelerometer.
bool activateAccelerometer(float updateInterval = 0.016666f) override;
//! Deactivate accelerometer.
bool deactivateAccelerometer() override;
//! Is accelerometer active.
bool isAccelerometerActive() override;
//! Is accelerometer available.
bool isAccelerometerAvailable() override;
//! Activate gyroscope.
bool activateGyroscope(float updateInterval = 0.016666f) override;
//! Deactivate gyroscope.
bool deactivateGyroscope() override;
//! Is gyroscope active.
bool isGyroscopeActive() override;
//! Is gyroscope available.
bool isGyroscopeAvailable() override;
//! Activate device motion.
bool activateDeviceMotion(float updateInterval = 0.016666f) override;
//! Deactivate device motion.
bool deactivateDeviceMotion() override;
//! Is device motion active.
bool isDeviceMotionActive() override;
//! Is device motion available.
bool isDeviceMotionAvailable() override;
//! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behavior.
//! When set to 0 no double- and tripleclicks will be generated.
void setDoubleClickTime( u32 timeMs ) override;
//! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse.
u32 getDoubleClickTime() const override;
//! Remove all messages pending in the system message loop
void clearSystemMessages() override;
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
//! Resize the render window.
void setWindowSize(const irr::core::dimension2d<u32>& size) override {}
protected:
void createGUIAndScene();
//! checks version of SDK and prints warning if there might be a problem
bool checkVersion(const char* version);
//! Compares to the last call of this function to return double and triple clicks.
/** Needed for win32 device event handling
\return Returns only 1,2 or 3. A 4th click will start with 1 again.
*/
virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent);
//! Checks whether the input device should take input from the IME
bool acceptsIME();
video::IVideoDriver* VideoDriver;
gui::IGUIEnvironment* GUIEnvironment;
scene::ISceneManager* SceneManager;
ITimer* Timer;
gui::ICursorControl* CursorControl;
IEventReceiver* UserReceiver;
CLogger* Logger;
IOSOperator* Operator;
io::IFileSystem* FileSystem;
scene::ISceneManager* InputReceivingSceneManager;
struct SMouseMultiClicks
SMouseMultiClicks() :
DoubleClickTime(500), CountSuccessiveClicks(0), LastClickTime(0), LastMouseInputEvent(EMIE_COUNT)
{
SMouseMultiClicks()
: DoubleClickTime(500), CountSuccessiveClicks(0), LastClickTime(0), LastMouseInputEvent(EMIE_COUNT)
{}
}
u32 DoubleClickTime;
u32 CountSuccessiveClicks;
u32 LastClickTime;
core::position2di LastClick;
EMOUSE_INPUT_EVENT LastMouseInputEvent;
};
SMouseMultiClicks MouseMultiClicks;
video::IContextManager* ContextManager;
SIrrlichtCreationParameters CreationParams;
bool Close;
u32 DoubleClickTime;
u32 CountSuccessiveClicks;
u32 LastClickTime;
core::position2di LastClick;
EMOUSE_INPUT_EVENT LastMouseInputEvent;
};
SMouseMultiClicks MouseMultiClicks;
video::IContextManager *ContextManager;
SIrrlichtCreationParameters CreationParams;
bool Close;
};
} // end namespace irr

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,8 @@
#pragma once
#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
#include "CIrrDeviceStub.h"
#include "IrrlichtDevice.h"
@ -20,410 +20,386 @@
namespace irr
{
struct SJoystickWin32Control;
struct SJoystickWin32Control;
class CIrrDeviceWin32 : public CIrrDeviceStub
{
class CIrrDeviceWin32 : public CIrrDeviceStub
{
friend struct SJoystickWin32Control;
public:
//! constructor
CIrrDeviceWin32(const SIrrlichtCreationParameters &params);
//! destructor
virtual ~CIrrDeviceWin32();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht
void yield() override;
//! Pause execution and let other processes to run for a specified amount of time.
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t *text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! returns if window has focus
bool isWindowFocused() const override;
//! returns if window is minimized
bool isWindowMinimized() const override;
//! returns last state from maximizeWindow() and restoreWindow()
bool isWindowMaximized() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Notifies the device, that it has been resized
/** Must be publis as it is called from free function (event handler) */
void OnResized();
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize = false) override;
//! Resize the render window.
void setWindowSize(const irr::core::dimension2d<u32> &size) override;
//! Minimizes the window.
void minimizeWindow() override;
//! Maximizes the window.
void maximizeWindow() override;
//! Restores the window size.
void restoreWindow() override;
//! Get the position of the window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> &joystickInfo) override;
//! Remove all messages pending in the system message loop
void clearSystemMessages() override;
//! Get the device type
E_DEVICE_TYPE getType() const override
{
return EIDT_WIN32;
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
//! Compares to the last call of this function to return double and triple clicks.
//! \return Returns only 1,2 or 3. A 4th click will start with 1 again.
u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent) override
{
// we just have to make it public
return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent);
}
//! Switch to fullscreen
bool switchToFullScreen();
// convert an Irrlicht texture to a windows cursor
HCURSOR TextureToCursor(HWND hwnd, irr::video::ITexture *tex, const core::rect<s32> &sourceRect, const core::position2d<s32> &hotspot);
//! Implementation of the win32 cursor control
class CCursorControl : public gui::ICursorControl
{
public:
CCursorControl(CIrrDeviceWin32 *device, const core::dimension2d<u32> &wsize, HWND hwnd, bool fullscreen);
~CCursorControl();
//! constructor
CIrrDeviceWin32(const SIrrlichtCreationParameters& params);
//! destructor
virtual ~CIrrDeviceWin32();
//! runs the device. Returns false if device wants to be deleted
bool run() override;
//! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht
void yield() override;
//! Pause execution and let other processes to run for a specified amount of time.
void sleep(u32 timeMs, bool pauseTimer) override;
//! sets the caption of the window
void setWindowCaption(const wchar_t* text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
//! returns if window has focus
bool isWindowFocused() const override;
//! returns if window is minimized
bool isWindowMinimized() const override;
//! returns last state from maximizeWindow() and restoreWindow()
bool isWindowMaximized() const override;
//! notifies the device that it should close itself
void closeDevice() override;
//! Notifies the device, that it has been resized
/** Must be publis as it is called from free function (event handler) */
void OnResized();
//! Sets if the window should be resizable in windowed mode.
void setResizable(bool resize=false) override;
//! Resize the render window.
void setWindowSize(const irr::core::dimension2d<u32>& size) override;
//! Minimizes the window.
void minimizeWindow() override;
//! Maximizes the window.
void maximizeWindow() override;
//! Restores the window size.
void restoreWindow() override;
//! Get the position of the window on screen
core::position2di getWindowPosition() override;
//! Activate any joysticks, and generate events for them.
bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
//! Remove all messages pending in the system message loop
void clearSystemMessages() override;
//! Get the device type
E_DEVICE_TYPE getType() const override
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
return EIDT_WIN32;
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
//! Compares to the last call of this function to return double and triple clicks.
//! \return Returns only 1,2 or 3. A 4th click will start with 1 again.
u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) override
{
// we just have to make it public
return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent );
}
//! Switch to fullscreen
bool switchToFullScreen();
// convert an Irrlicht texture to a windows cursor
HCURSOR TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
//! Implementation of the win32 cursor control
class CCursorControl : public gui::ICursorControl
{
public:
CCursorControl(CIrrDeviceWin32* device, const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen);
~CCursorControl();
//! Changes the visible state of the mouse cursor.
void setVisible(bool visible) override
{
CURSORINFO info;
info.cbSize = sizeof(CURSORINFO);
BOOL gotCursorInfo = GetCursorInfo(&info);
while ( gotCursorInfo )
{
CURSORINFO info;
info.cbSize = sizeof(CURSORINFO);
BOOL gotCursorInfo = GetCursorInfo(&info);
while (gotCursorInfo) {
#ifdef CURSOR_SUPPRESSED
// Since Windows 8 the cursor can be suppressed by a touch interface
if (visible && info.flags == CURSOR_SUPPRESSED)
{
break;
}
// Since Windows 8 the cursor can be suppressed by a touch interface
if (visible && info.flags == CURSOR_SUPPRESSED) {
break;
}
#endif
if ( (visible && info.flags == CURSOR_SHOWING) || // visible
(!visible && info.flags == 0 ) ) // hidden
{
break;
}
// this only increases an internal
// display counter in windows, so it
// might have to be called some more
const int showResult = ShowCursor(visible);
// if result has correct sign we can
// stop here as well
if (( !visible && showResult < 0 ) ||
if ((visible && info.flags == CURSOR_SHOWING) || // visible
(!visible && info.flags == 0)) // hidden
{
break;
}
// this only increases an internal
// display counter in windows, so it
// might have to be called some more
const int showResult = ShowCursor(visible);
// if result has correct sign we can
// stop here as well
if ((!visible && showResult < 0) ||
(visible && showResult >= 0))
break;
// yes, it really must be set each time
info.cbSize = sizeof(CURSORINFO);
gotCursorInfo = GetCursorInfo(&info);
break;
// yes, it really must be set each time
info.cbSize = sizeof(CURSORINFO);
gotCursorInfo = GetCursorInfo(&info);
#ifdef CURSOR_SUPPRESSED
// Not sure if a cursor which we tried to hide still can be suppressed.
// I have no touch-display for testing this and MSDN doesn't describe it.
// But adding this check shouldn't hurt and might prevent an endless loop.
if (!visible && info.flags == CURSOR_SUPPRESSED)
{
break;
}
// Not sure if a cursor which we tried to hide still can be suppressed.
// I have no touch-display for testing this and MSDN doesn't describe it.
// But adding this check shouldn't hurt and might prevent an endless loop.
if (!visible && info.flags == CURSOR_SUPPRESSED) {
break;
}
#endif
}
IsVisible = visible;
}
IsVisible = visible;
}
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
return IsVisible;
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
if (!UseReferenceRect)
setPosition(core::round32(x * WindowSize.Width), core::round32(y * WindowSize.Height));
else
setPosition(core::round32(x * ReferenceRect.getWidth()), core::round32(y * ReferenceRect.getHeight()));
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
if (UseReferenceRect) {
SetCursorPos(ReferenceRect.UpperLeftCorner.X + x,
ReferenceRect.UpperLeftCorner.Y + y);
} else {
RECT rect;
if (GetWindowRect(HWnd, &rect))
SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY);
}
//! Returns if the cursor is currently visible.
bool isVisible() const override
{
return IsVisible;
}
CursorPos.X = x;
CursorPos.Y = y;
}
//! Sets the new position of the cursor.
void setPosition(const core::position2d<f32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32> &getPosition(bool updateCursor) override
{
if (updateCursor)
updateInternalCursorPosition();
return CursorPos;
}
//! Sets the new position of the cursor.
void setPosition(f32 x, f32 y) override
{
if (!UseReferenceRect)
setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height));
else
setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight()));
}
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if (updateCursor)
updateInternalCursorPosition();
//! Sets the new position of the cursor.
void setPosition(const core::position2d<s32> &pos) override
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
if (UseReferenceRect)
{
SetCursorPos(ReferenceRect.UpperLeftCorner.X + x,
ReferenceRect.UpperLeftCorner.Y + y);
}
else
{
RECT rect;
if (GetWindowRect(HWnd, &rect))
SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY);
}
CursorPos.X = x;
CursorPos.Y = y;
}
//! Returns the current position of the mouse cursor.
const core::position2d<s32>& getPosition(bool updateCursor) override
{
if ( updateCursor )
updateInternalCursorPosition();
return CursorPos;
}
//! Returns the current position of the mouse cursor.
core::position2d<f32> getRelativePosition(bool updateCursor) override
{
if ( updateCursor )
updateInternalCursorPosition();
if (!UseReferenceRect)
{
return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
if (!UseReferenceRect) {
return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
CursorPos.Y * InvWindowSize.Height);
}
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
}
//! Sets an absolute reference rect for calculating the cursor position.
void setReferenceRect(core::rect<s32>* rect=0) override
{
if (rect)
{
ReferenceRect = *rect;
UseReferenceRect = true;
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
}
// prevent division through zero and uneven sizes
//! Sets an absolute reference rect for calculating the cursor position.
void setReferenceRect(core::rect<s32> *rect = 0) override
{
if (rect) {
ReferenceRect = *rect;
UseReferenceRect = true;
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
ReferenceRect.LowerRightCorner.Y += 1;
// prevent division through zero and uneven sizes
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
ReferenceRect.LowerRightCorner.X += 1;
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight() % 2)
ReferenceRect.LowerRightCorner.Y += 1;
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth() % 2)
ReferenceRect.LowerRightCorner.X += 1;
} else
UseReferenceRect = false;
}
/** Used to notify the cursor that the window was resized. */
void OnResize(const core::dimension2d<u32> &size)
{
WindowSize = size;
if (size.Width != 0)
InvWindowSize.Width = 1.0f / size.Width;
else
InvWindowSize.Width = 0.f;
if (size.Height != 0)
InvWindowSize.Height = 1.0f / size.Height;
else
InvWindowSize.Height = 0.f;
}
/** Used to notify the cursor that the window resizable settings changed. */
void updateBorderSize(bool fullscreen, bool resizable)
{
if (!fullscreen) {
s32 paddingBorder = 0;
#ifdef SM_CXPADDEDBORDER
paddingBorder = GetSystemMetrics(SM_CXPADDEDBORDER);
#endif
if (resizable) {
BorderX = GetSystemMetrics(SM_CXSIZEFRAME) + paddingBorder;
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) + paddingBorder;
} else {
BorderX = GetSystemMetrics(SM_CXDLGFRAME) + paddingBorder;
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME) + paddingBorder;
}
else
UseReferenceRect = false;
} else {
BorderX = BorderY = 0;
}
}
/** Used to notify the cursor that the window was resized. */
void OnResize(const core::dimension2d<u32>& size)
{
WindowSize = size;
if (size.Width!=0)
InvWindowSize.Width = 1.0f / size.Width;
else
InvWindowSize.Width = 0.f;
//! Sets the active cursor icon
void setActiveIcon(gui::ECURSOR_ICON iconId) override;
if (size.Height!=0)
InvWindowSize.Height = 1.0f / size.Height;
else
InvWindowSize.Height = 0.f;
}
//! Gets the currently active icon
gui::ECURSOR_ICON getActiveIcon() const override
{
return ActiveIcon;
}
/** Used to notify the cursor that the window resizable settings changed. */
void updateBorderSize(bool fullscreen, bool resizable)
{
if (!fullscreen)
{
s32 paddingBorder = 0;
#ifdef SM_CXPADDEDBORDER
paddingBorder = GetSystemMetrics(SM_CXPADDEDBORDER);
#endif
//! Add a custom sprite as cursor icon.
gui::ECURSOR_ICON addIcon(const gui::SCursorSprite &icon) override;
if (resizable)
{
BorderX = GetSystemMetrics(SM_CXSIZEFRAME) + paddingBorder;
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) + paddingBorder;
}
else
{
BorderX = GetSystemMetrics(SM_CXDLGFRAME) + paddingBorder;
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME) + paddingBorder;
}
}
else
{
BorderX = BorderY = 0;
}
}
//! replace the given cursor icon.
void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite &icon) override;
//! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
core::dimension2di getSupportedIconSize() const override;
//! Sets the active cursor icon
void setActiveIcon(gui::ECURSOR_ICON iconId) override;
//! Gets the currently active icon
gui::ECURSOR_ICON getActiveIcon() const override
{
return ActiveIcon;
}
//! Add a custom sprite as cursor icon.
gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) override;
//! replace the given cursor icon.
void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) override;
//! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
core::dimension2di getSupportedIconSize() const override;
void update();
private:
//! Updates the internal cursor position
void updateInternalCursorPosition()
{
POINT p;
if (!GetCursorPos(&p))
{
DWORD xy = GetMessagePos();
p.x = GET_X_LPARAM(xy);
p.y = GET_Y_LPARAM(xy);
}
if (UseReferenceRect)
{
CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X;
CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y;
}
else
{
RECT rect;
if (GetWindowRect(HWnd, &rect))
{
CursorPos.X = p.x-rect.left-BorderX;
CursorPos.Y = p.y-rect.top-BorderY;
}
else
{
// window seems not to be existent, so set cursor to
// a negative value
CursorPos.X = -1;
CursorPos.Y = -1;
}
}
}
CIrrDeviceWin32* Device;
core::position2d<s32> CursorPos;
core::dimension2d<u32> WindowSize;
core::dimension2d<f32> InvWindowSize;
HWND HWnd;
s32 BorderX, BorderY;
core::rect<s32> ReferenceRect;
bool UseReferenceRect;
bool IsVisible;
struct CursorFrameW32
{
CursorFrameW32() : IconHW(0) {}
CursorFrameW32(HCURSOR icon) : IconHW(icon) {}
HCURSOR IconHW; // hardware cursor
};
struct CursorW32
{
CursorW32() {}
explicit CursorW32(HCURSOR iconHw, u32 frameTime=0) : FrameTime(frameTime)
{
Frames.push_back( CursorFrameW32(iconHw) );
}
core::array<CursorFrameW32> Frames;
u32 FrameTime;
};
core::array<CursorW32> Cursors;
gui::ECURSOR_ICON ActiveIcon;
u32 ActiveIconStartTime;
void initCursors();
};
//! returns the win32 cursor control
CCursorControl* getWin32CursorControl();
void update();
private:
//! Updates the internal cursor position
void updateInternalCursorPosition()
{
POINT p;
if (!GetCursorPos(&p)) {
DWORD xy = GetMessagePos();
p.x = GET_X_LPARAM(xy);
p.y = GET_Y_LPARAM(xy);
}
//! create the driver
void createDriver();
//! Process system events
void handleSystemMessages();
void getWindowsVersion(core::stringc& version);
void resizeIfNecessary();
DWORD getWindowStyle(bool fullscreen, bool resizable) const;
if (UseReferenceRect) {
CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X;
CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y;
} else {
RECT rect;
if (GetWindowRect(HWnd, &rect)) {
CursorPos.X = p.x - rect.left - BorderX;
CursorPos.Y = p.y - rect.top - BorderY;
} else {
// window seems not to be existent, so set cursor to
// a negative value
CursorPos.X = -1;
CursorPos.Y = -1;
}
}
}
CIrrDeviceWin32 *Device;
core::position2d<s32> CursorPos;
core::dimension2d<u32> WindowSize;
core::dimension2d<f32> InvWindowSize;
HWND HWnd;
bool Resized;
bool ExternalWindow;
CCursorControl* Win32CursorControl;
s32 BorderX, BorderY;
core::rect<s32> ReferenceRect;
bool UseReferenceRect;
bool IsVisible;
SJoystickWin32Control* JoyControl;
struct CursorFrameW32
{
CursorFrameW32() :
IconHW(0) {}
CursorFrameW32(HCURSOR icon) :
IconHW(icon) {}
bool WindowMaximized;
HCURSOR IconHW; // hardware cursor
};
struct CursorW32
{
CursorW32() {}
explicit CursorW32(HCURSOR iconHw, u32 frameTime = 0) :
FrameTime(frameTime)
{
Frames.push_back(CursorFrameW32(iconHw));
}
core::array<CursorFrameW32> Frames;
u32 FrameTime;
};
core::array<CursorW32> Cursors;
gui::ECURSOR_ICON ActiveIcon;
u32 ActiveIconStartTime;
void initCursors();
};
//! returns the win32 cursor control
CCursorControl *getWin32CursorControl();
private:
//! create the driver
void createDriver();
//! Process system events
void handleSystemMessages();
void getWindowsVersion(core::stringc &version);
void resizeIfNecessary();
DWORD getWindowStyle(bool fullscreen, bool resizable) const;
HWND HWnd;
bool Resized;
bool ExternalWindow;
CCursorControl *Win32CursorControl;
SJoystickWin32Control *JoyControl;
bool WindowMaximized;
};
} // end namespace irr
#endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_
#endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_

View File

@ -11,34 +11,31 @@ namespace irr
namespace io
{
CLimitReadFile::CLimitReadFile(IReadFile* alreadyOpenedFile, long pos,
long areaSize, const io::path& name)
: Filename(name), AreaStart(0), AreaEnd(0), Pos(0),
File(alreadyOpenedFile)
CLimitReadFile::CLimitReadFile(IReadFile *alreadyOpenedFile, long pos,
long areaSize, const io::path &name) :
Filename(name),
AreaStart(0), AreaEnd(0), Pos(0),
File(alreadyOpenedFile)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CLimitReadFile");
#endif
#endif
if (File)
{
if (File) {
File->grab();
AreaStart = pos;
AreaEnd = AreaStart + areaSize;
}
}
CLimitReadFile::~CLimitReadFile()
{
if (File)
File->drop();
}
//! returns how much was read
size_t CLimitReadFile::read(void* buffer, size_t sizeToRead)
size_t CLimitReadFile::read(void *buffer, size_t sizeToRead)
{
if (0 == File)
return 0;
@ -65,23 +62,19 @@ size_t CLimitReadFile::read(void* buffer, size_t sizeToRead)
#endif
}
//! changes position in file, returns true if successful
bool CLimitReadFile::seek(long finalPos, bool relativeMovement)
{
#if 1
Pos = core::s32_clamp(finalPos + (relativeMovement ? Pos : 0 ), 0, AreaEnd - AreaStart);
Pos = core::s32_clamp(finalPos + (relativeMovement ? Pos : 0), 0, AreaEnd - AreaStart);
return true;
#else
const long pos = File->getPos();
if (relativeMovement)
{
if (relativeMovement) {
if (pos + finalPos > AreaEnd)
finalPos = AreaEnd - pos;
}
else
{
} else {
finalPos += AreaStart;
if (finalPos > AreaEnd)
return false;
@ -91,14 +84,12 @@ bool CLimitReadFile::seek(long finalPos, bool relativeMovement)
#endif
}
//! returns size of file
long CLimitReadFile::getSize() const
{
return AreaEnd - AreaStart;
}
//! returns where in the file we are.
long CLimitReadFile::getPos() const
{
@ -109,20 +100,16 @@ long CLimitReadFile::getPos() const
#endif
}
//! returns name of file
const io::path& CLimitReadFile::getFileName() const
const io::path &CLimitReadFile::getFileName() const
{
return Filename;
}
IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize)
IReadFile *createLimitReadFile(const io::path &fileName, IReadFile *alreadyOpenedFile, long pos, long areaSize)
{
return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName);
}
} // end namespace io
} // end namespace irr

View File

@ -9,56 +9,54 @@
namespace irr
{
class CUnicodeConverter;
class CUnicodeConverter;
namespace io
{
/*! this is a read file, which is limited to some boundaries,
so that it may only start from a certain file position
and may only read until a certain file position.
This can be useful, for example for reading uncompressed files
in an archive (zip, tar).
!*/
class CLimitReadFile : public IReadFile
/*! this is a read file, which is limited to some boundaries,
so that it may only start from a certain file position
and may only read until a certain file position.
This can be useful, for example for reading uncompressed files
in an archive (zip, tar).
!*/
class CLimitReadFile : public IReadFile
{
public:
CLimitReadFile(IReadFile *alreadyOpenedFile, long pos, long areaSize, const io::path &name);
virtual ~CLimitReadFile();
//! returns how much was read
size_t read(void *buffer, size_t sizeToRead) override;
//! changes position in file, returns true if successful
//! if relativeMovement==true, the pos is changed relative to current pos,
//! otherwise from begin of file
bool seek(long finalPos, bool relativeMovement = false) override;
//! returns size of file
long getSize() const override;
//! returns where in the file we are.
long getPos() const override;
//! returns name of file
const io::path &getFileName() const override;
//! Get the type of the class implementing this interface
EREAD_FILE_TYPE getType() const override
{
public:
return ERFT_LIMIT_READ_FILE;
}
CLimitReadFile(IReadFile* alreadyOpenedFile, long pos, long areaSize, const io::path& name);
virtual ~CLimitReadFile();
//! returns how much was read
size_t read(void* buffer, size_t sizeToRead) override;
//! changes position in file, returns true if successful
//! if relativeMovement==true, the pos is changed relative to current pos,
//! otherwise from begin of file
bool seek(long finalPos, bool relativeMovement = false) override;
//! returns size of file
long getSize() const override;
//! returns where in the file we are.
long getPos() const override;
//! returns name of file
const io::path& getFileName() const override;
//! Get the type of the class implementing this interface
EREAD_FILE_TYPE getType() const override
{
return ERFT_LIMIT_READ_FILE;
}
private:
io::path Filename;
long AreaStart;
long AreaEnd;
long Pos;
IReadFile* File;
};
private:
io::path Filename;
long AreaStart;
long AreaEnd;
long Pos;
IReadFile *File;
};
} // end namespace io
} // end namespace irr

View File

@ -7,64 +7,60 @@
namespace irr
{
CLogger::CLogger(IEventReceiver* r)
: LogLevel(ELL_INFORMATION), Receiver(r)
{
#ifdef _DEBUG
setDebugName("CLogger");
#endif
}
CLogger::CLogger(IEventReceiver *r) :
LogLevel(ELL_INFORMATION), Receiver(r)
{
#ifdef _DEBUG
setDebugName("CLogger");
#endif
}
//! Returns the current set log level.
ELOG_LEVEL CLogger::getLogLevel() const
{
return LogLevel;
}
//! Returns the current set log level.
ELOG_LEVEL CLogger::getLogLevel() const
{
return LogLevel;
}
//! Sets a new log level.
void CLogger::setLogLevel(ELOG_LEVEL ll)
{
LogLevel = ll;
}
//! Sets a new log level.
void CLogger::setLogLevel(ELOG_LEVEL ll)
{
LogLevel = ll;
}
//! Prints out a text into the log
void CLogger::log(const c8* text, ELOG_LEVEL ll)
{
if (ll < LogLevel)
//! Prints out a text into the log
void CLogger::log(const c8 *text, ELOG_LEVEL ll)
{
if (ll < LogLevel)
return;
if (Receiver) {
SEvent event;
event.EventType = EET_LOG_TEXT_EVENT;
event.LogEvent.Text = text;
event.LogEvent.Level = ll;
if (Receiver->OnEvent(event))
return;
if (Receiver)
{
SEvent event;
event.EventType = EET_LOG_TEXT_EVENT;
event.LogEvent.Text = text;
event.LogEvent.Level = ll;
if (Receiver->OnEvent(event))
return;
}
os::Printer::print(text);
}
os::Printer::print(text);
}
//! Prints out a text into the log
void CLogger::log(const c8* text, const c8* hint, ELOG_LEVEL ll)
{
if (ll < LogLevel)
return;
//! Prints out a text into the log
void CLogger::log(const c8 *text, const c8 *hint, ELOG_LEVEL ll)
{
if (ll < LogLevel)
return;
core::stringc s = text;
s += ": ";
s += hint;
log (s.c_str(), ll);
}
//! Sets a new event receiver
void CLogger::setReceiver(IEventReceiver* r)
{
Receiver = r;
}
core::stringc s = text;
s += ": ";
s += hint;
log(s.c_str(), ll);
}
//! Sets a new event receiver
void CLogger::setReceiver(IEventReceiver *r)
{
Receiver = r;
}
} // end namespace irr

View File

@ -16,8 +16,7 @@ namespace irr
class CLogger : public ILogger
{
public:
CLogger(IEventReceiver* r);
CLogger(IEventReceiver *r);
//! Returns the current set log level.
ELOG_LEVEL getLogLevel() const override;
@ -26,18 +25,17 @@ public:
void setLogLevel(ELOG_LEVEL ll) override;
//! Prints out a text into the log
void log(const c8* text, ELOG_LEVEL ll=ELL_INFORMATION) override;
void log(const c8 *text, ELOG_LEVEL ll = ELL_INFORMATION) override;
//! Prints out a text into the log
void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION) override;
void log(const c8 *text, const c8 *hint, ELOG_LEVEL ll = ELL_INFORMATION) override;
//! Sets a new event receiver
void setReceiver(IEventReceiver* r);
void setReceiver(IEventReceiver *r);
private:
ELOG_LEVEL LogLevel;
IEventReceiver* Receiver;
IEventReceiver *Receiver;
};
} // end namespace

View File

@ -10,25 +10,22 @@ namespace irr
namespace io
{
CMemoryReadFile::CMemoryReadFile(const void* memory, long len, const io::path& fileName, bool d)
: Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d)
CMemoryReadFile::CMemoryReadFile(const void *memory, long len, const io::path &fileName, bool d) :
Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CMemoryReadFile");
#endif
#endif
}
CMemoryReadFile::~CMemoryReadFile()
{
if (deleteMemoryWhenDropped)
delete [] (c8*)Buffer;
delete[] (c8 *)Buffer;
}
//! returns how much was read
size_t CMemoryReadFile::read(void* buffer, size_t sizeToRead)
size_t CMemoryReadFile::read(void *buffer, size_t sizeToRead)
{
long amount = static_cast<long>(sizeToRead);
if (Pos + amount > Len)
@ -37,7 +34,7 @@ size_t CMemoryReadFile::read(void* buffer, size_t sizeToRead)
if (amount <= 0)
return 0;
c8* p = (c8*)Buffer;
c8 *p = (c8 *)Buffer;
memcpy(buffer, p + Pos, amount);
Pos += amount;
@ -50,15 +47,12 @@ size_t CMemoryReadFile::read(void* buffer, size_t sizeToRead)
//! otherwise from begin of file
bool CMemoryReadFile::seek(long finalPos, bool relativeMovement)
{
if (relativeMovement)
{
if (relativeMovement) {
if (Pos + finalPos < 0 || Pos + finalPos > Len)
return false;
Pos += finalPos;
}
else
{
} else {
if (finalPos < 0 || finalPos > Len)
return false;
@ -68,46 +62,40 @@ bool CMemoryReadFile::seek(long finalPos, bool relativeMovement)
return true;
}
//! returns size of file
long CMemoryReadFile::getSize() const
{
return Len;
}
//! returns where in the file we are.
long CMemoryReadFile::getPos() const
{
return Pos;
}
//! returns name of file
const io::path& CMemoryReadFile::getFileName() const
const io::path &CMemoryReadFile::getFileName() const
{
return Filename;
}
CMemoryWriteFile::CMemoryWriteFile(void* memory, long len, const io::path& fileName, bool d)
: Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d)
CMemoryWriteFile::CMemoryWriteFile(void *memory, long len, const io::path &fileName, bool d) :
Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d)
{
#ifdef _DEBUG
#ifdef _DEBUG
setDebugName("CMemoryWriteFile");
#endif
#endif
}
CMemoryWriteFile::~CMemoryWriteFile()
{
if (deleteMemoryWhenDropped)
delete [] (c8*)Buffer;
delete[] (c8 *)Buffer;
}
//! returns how much was written
size_t CMemoryWriteFile::write(const void* buffer, size_t sizeToWrite)
size_t CMemoryWriteFile::write(const void *buffer, size_t sizeToWrite)
{
long amount = (long)sizeToWrite;
if (Pos + amount > Len)
@ -116,7 +104,7 @@ size_t CMemoryWriteFile::write(const void* buffer, size_t sizeToWrite)
if (amount <= 0)
return 0;
c8* p = (c8*)Buffer;
c8 *p = (c8 *)Buffer;
memcpy(p + Pos, buffer, amount);
Pos += amount;
@ -124,22 +112,17 @@ size_t CMemoryWriteFile::write(const void* buffer, size_t sizeToWrite)
return (size_t)amount;
}
//! changes position in file, returns true if successful
//! if relativeMovement==true, the pos is changed relative to current pos,
//! otherwise from begin of file
bool CMemoryWriteFile::seek(long finalPos, bool relativeMovement)
{
if (relativeMovement)
{
if (relativeMovement) {
if (Pos + finalPos < 0 || Pos + finalPos > Len)
return false;
Pos += finalPos;
}
else
{
} else {
if (finalPos < 0 || finalPos > Len)
return false;
@ -149,16 +132,14 @@ bool CMemoryWriteFile::seek(long finalPos, bool relativeMovement)
return true;
}
//! returns where in the file we are.
long CMemoryWriteFile::getPos() const
{
return Pos;
}
//! returns name of file
const io::path& CMemoryWriteFile::getFileName() const
const io::path &CMemoryWriteFile::getFileName() const
{
return Filename;
}
@ -168,20 +149,17 @@ bool CMemoryWriteFile::flush()
return true; // no buffering, so nothing to do
}
IReadFile* createMemoryReadFile(const void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped)
IReadFile *createMemoryReadFile(const void *memory, long size, const io::path &fileName, bool deleteMemoryWhenDropped)
{
CMemoryReadFile* file = new CMemoryReadFile(memory, size, fileName, deleteMemoryWhenDropped);
CMemoryReadFile *file = new CMemoryReadFile(memory, size, fileName, deleteMemoryWhenDropped);
return file;
}
IWriteFile* createMemoryWriteFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped)
IWriteFile *createMemoryWriteFile(void *memory, long size, const io::path &fileName, bool deleteMemoryWhenDropped)
{
CMemoryWriteFile* file = new CMemoryWriteFile(memory, size, fileName, deleteMemoryWhenDropped);
CMemoryWriteFile *file = new CMemoryWriteFile(memory, size, fileName, deleteMemoryWhenDropped);
return file;
}
} // end namespace io
} // end namespace irr

View File

@ -14,90 +14,86 @@ namespace irr
namespace io
{
/*!
Class for reading from memory.
*/
class CMemoryReadFile : public IMemoryReadFile
/*!
Class for reading from memory.
*/
class CMemoryReadFile : public IMemoryReadFile
{
public:
//! Constructor
CMemoryReadFile(const void *memory, long len, const io::path &fileName, bool deleteMemoryWhenDropped);
//! Destructor
virtual ~CMemoryReadFile();
//! returns how much was read
size_t read(void *buffer, size_t sizeToRead) override;
//! changes position in file, returns true if successful
bool seek(long finalPos, bool relativeMovement = false) override;
//! returns size of file
long getSize() const override;
//! returns where in the file we are.
long getPos() const override;
//! returns name of file
const io::path &getFileName() const override;
//! Get the type of the class implementing this interface
EREAD_FILE_TYPE getType() const override
{
public:
return ERFT_MEMORY_READ_FILE;
}
//! Constructor
CMemoryReadFile(const void* memory, long len, const io::path& fileName, bool deleteMemoryWhenDropped);
//! Destructor
virtual ~CMemoryReadFile();
//! returns how much was read
size_t read(void* buffer, size_t sizeToRead) override;
//! changes position in file, returns true if successful
bool seek(long finalPos, bool relativeMovement = false) override;
//! returns size of file
long getSize() const override;
//! returns where in the file we are.
long getPos() const override;
//! returns name of file
const io::path& getFileName() const override;
//! Get the type of the class implementing this interface
EREAD_FILE_TYPE getType() const override
{
return ERFT_MEMORY_READ_FILE;
}
//! Get direct access to internal buffer
const void *getBuffer() const override
{
return Buffer;
}
private:
const void *Buffer;
long Len;
long Pos;
io::path Filename;
bool deleteMemoryWhenDropped;
};
/*!
Class for writing to memory.
*/
class CMemoryWriteFile : public IWriteFile
//! Get direct access to internal buffer
const void *getBuffer() const override
{
public:
return Buffer;
}
//! Constructor
CMemoryWriteFile(void* memory, long len, const io::path& fileName, bool deleteMemoryWhenDropped);
private:
const void *Buffer;
long Len;
long Pos;
io::path Filename;
bool deleteMemoryWhenDropped;
};
//! Destructor
virtual ~CMemoryWriteFile();
/*!
Class for writing to memory.
*/
class CMemoryWriteFile : public IWriteFile
{
public:
//! Constructor
CMemoryWriteFile(void *memory, long len, const io::path &fileName, bool deleteMemoryWhenDropped);
//! returns how much was written
size_t write(const void* buffer, size_t sizeToWrite) override;
//! Destructor
virtual ~CMemoryWriteFile();
//! changes position in file, returns true if successful
bool seek(long finalPos, bool relativeMovement = false) override;
//! returns how much was written
size_t write(const void *buffer, size_t sizeToWrite) override;
//! returns where in the file we are.
long getPos() const override;
//! changes position in file, returns true if successful
bool seek(long finalPos, bool relativeMovement = false) override;
//! returns name of file
const io::path& getFileName() const override;
//! returns where in the file we are.
long getPos() const override;
bool flush() override;
//! returns name of file
const io::path &getFileName() const override;
private:
bool flush() override;
void *Buffer;
long Len;
long Pos;
io::path Filename;
bool deleteMemoryWhenDropped;
};
private:
void *Buffer;
long Len;
long Pos;
io::path Filename;
bool deleteMemoryWhenDropped;
};
} // end namespace io
} // end namespace irr

View File

@ -13,34 +13,29 @@ namespace scene
static const io::SNamedPath emptyNamedPath;
CMeshCache::~CMeshCache()
{
clear();
}
//! adds a mesh to the list
void CMeshCache::addMesh(const io::path& filename, IAnimatedMesh* mesh)
void CMeshCache::addMesh(const io::path &filename, IAnimatedMesh *mesh)
{
mesh->grab();
MeshEntry e ( filename );
MeshEntry e(filename);
e.Mesh = mesh;
Meshes.push_back(e);
}
//! Removes a mesh from the cache.
void CMeshCache::removeMesh(const IMesh* const mesh)
void CMeshCache::removeMesh(const IMesh *const mesh)
{
if ( !mesh )
if (!mesh)
return;
for (u32 i=0; i<Meshes.size(); ++i)
{
if (Meshes[i].Mesh == mesh || (Meshes[i].Mesh && Meshes[i].Mesh->getMesh(0) == mesh))
{
for (u32 i = 0; i < Meshes.size(); ++i) {
if (Meshes[i].Mesh == mesh || (Meshes[i].Mesh && Meshes[i].Mesh->getMesh(0) == mesh)) {
Meshes[i].Mesh->drop();
Meshes.erase(i);
return;
@ -48,19 +43,16 @@ void CMeshCache::removeMesh(const IMesh* const mesh)
}
}
//! Returns amount of loaded meshes
u32 CMeshCache::getMeshCount() const
{
return Meshes.size();
}
//! Returns current number of the mesh
s32 CMeshCache::getMeshIndex(const IMesh* const mesh) const
s32 CMeshCache::getMeshIndex(const IMesh *const mesh) const
{
for (u32 i=0; i<Meshes.size(); ++i)
{
for (u32 i = 0; i < Meshes.size(); ++i) {
if (Meshes[i].Mesh == mesh || (Meshes[i].Mesh && Meshes[i].Mesh->getMesh(0) == mesh))
return (s32)i;
}
@ -68,9 +60,8 @@ s32 CMeshCache::getMeshIndex(const IMesh* const mesh) const
return -1;
}
//! Returns a mesh based on its index number
IAnimatedMesh* CMeshCache::getMeshByIndex(u32 number)
IAnimatedMesh *CMeshCache::getMeshByIndex(u32 number)
{
if (number >= Meshes.size())
return 0;
@ -78,18 +69,16 @@ IAnimatedMesh* CMeshCache::getMeshByIndex(u32 number)
return Meshes[number].Mesh;
}
//! Returns a mesh based on its name.
IAnimatedMesh* CMeshCache::getMeshByName(const io::path& name)
IAnimatedMesh *CMeshCache::getMeshByName(const io::path &name)
{
MeshEntry e ( name );
MeshEntry e(name);
s32 id = Meshes.binary_search(e);
return (id != -1) ? Meshes[id].Mesh : 0;
}
//! Get the name of a loaded mesh, based on its index.
const io::SNamedPath& CMeshCache::getMeshName(u32 index) const
const io::SNamedPath &CMeshCache::getMeshName(u32 index) const
{
if (index >= Meshes.size())
return emptyNamedPath;
@ -97,15 +86,13 @@ const io::SNamedPath& CMeshCache::getMeshName(u32 index) const
return Meshes[index].NamedPath;
}
//! Get the name of a loaded mesh, if there is any.
const io::SNamedPath& CMeshCache::getMeshName(const IMesh* const mesh) const
const io::SNamedPath &CMeshCache::getMeshName(const IMesh *const mesh) const
{
if (!mesh)
return emptyNamedPath;
for (u32 i=0; i<Meshes.size(); ++i)
{
for (u32 i = 0; i < Meshes.size(); ++i) {
if (Meshes[i].Mesh == mesh || (Meshes[i].Mesh && Meshes[i].Mesh->getMesh(0) == mesh))
return Meshes[i].NamedPath;
}
@ -114,7 +101,7 @@ const io::SNamedPath& CMeshCache::getMeshName(const IMesh* const mesh) const
}
//! Renames a loaded mesh.
bool CMeshCache::renameMesh(u32 index, const io::path& name)
bool CMeshCache::renameMesh(u32 index, const io::path &name)
{
if (index >= Meshes.size())
return false;
@ -124,14 +111,11 @@ bool CMeshCache::renameMesh(u32 index, const io::path& name)
return true;
}
//! Renames a loaded mesh.
bool CMeshCache::renameMesh(const IMesh* const mesh, const io::path& name)
bool CMeshCache::renameMesh(const IMesh *const mesh, const io::path &name)
{
for (u32 i=0; i<Meshes.size(); ++i)
{
if (Meshes[i].Mesh == mesh || (Meshes[i].Mesh && Meshes[i].Mesh->getMesh(0) == mesh))
{
for (u32 i = 0; i < Meshes.size(); ++i) {
if (Meshes[i].Mesh == mesh || (Meshes[i].Mesh && Meshes[i].Mesh->getMesh(0) == mesh)) {
Meshes[i].NamedPath.setPath(name);
Meshes.sort();
return true;
@ -141,18 +125,16 @@ bool CMeshCache::renameMesh(const IMesh* const mesh, const io::path& name)
return false;
}
//! returns if a mesh already was loaded
bool CMeshCache::isMeshLoaded(const io::path& name)
bool CMeshCache::isMeshLoaded(const io::path &name)
{
return getMeshByName(name) != 0;
}
//! Clears the whole mesh cache, removing all meshes.
void CMeshCache::clear()
{
for (u32 i=0; i<Meshes.size(); ++i)
for (u32 i = 0; i < Meshes.size(); ++i)
Meshes[i].Mesh->drop();
Meshes.clear();
@ -161,10 +143,8 @@ void CMeshCache::clear()
//! Clears all meshes that are held in the mesh cache but not used anywhere else.
void CMeshCache::clearUnusedMeshes()
{
for (u32 i=0; i<Meshes.size(); ++i)
{
if (Meshes[i].Mesh->getReferenceCount() == 1)
{
for (u32 i = 0; i < Meshes.size(); ++i) {
if (Meshes[i].Mesh->getReferenceCount() == 1) {
Meshes[i].Mesh->drop();
Meshes.erase(i);
--i;
@ -172,7 +152,5 @@ void CMeshCache::clearUnusedMeshes()
}
}
} // end namespace scene
} // end namespace irr

Some files were not shown because too many files have changed in this diff Show More