Cleanup line endings (#245)
The exact commands to make this commit were: git reset --hard origin/master find -type f | # list all regular files grep -E '\.(h|cpp|fsh|vsh|mm)|LICENSE$' | # filter for text files xargs -n 1 -P $(nproc) sed -i 's:\s*$::' # for each file, trim trailing whitespace including the CR git commit -a
This commit is contained in:
@@ -1,109 +1,109 @@
|
||||
// Copyright (C) 2002-2011 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
#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 <android_native_app_glue.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <android/log.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
CAndroidAssetReader *reader = new CAndroidAssetReader(AssetManager, filename);
|
||||
|
||||
if(reader->isOpen())
|
||||
return reader;
|
||||
|
||||
reader->drop();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//! opens a file by index
|
||||
IReadFile* CAndroidAssetFileArchive::createAndOpenFile(u32 index)
|
||||
{
|
||||
const io::path& filename(getFullFileName(index));
|
||||
if ( filename.empty() )
|
||||
return 0;
|
||||
|
||||
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);
|
||||
|
||||
// os::Printer::log("addDirectoryToFileList:", dirname.c_str(), ELL_DEBUG);
|
||||
if (findFile(dirname, true) >= 0 )
|
||||
return; // was already added
|
||||
|
||||
AAssetDir *dir = AAssetManager_openDir(AssetManager, core::stringc(dirname).c_str());
|
||||
if(!dir)
|
||||
return;
|
||||
|
||||
// add directory itself
|
||||
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;
|
||||
|
||||
// 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());
|
||||
// os::Printer::log("addItem:", full_filename.c_str(), ELL_DEBUG);
|
||||
}
|
||||
AAssetDir_close(dir);
|
||||
}
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
// Copyright (C) 2002-2011 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
#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 <android_native_app_glue.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <android/log.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
CAndroidAssetReader *reader = new CAndroidAssetReader(AssetManager, filename);
|
||||
|
||||
if(reader->isOpen())
|
||||
return reader;
|
||||
|
||||
reader->drop();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//! opens a file by index
|
||||
IReadFile* CAndroidAssetFileArchive::createAndOpenFile(u32 index)
|
||||
{
|
||||
const io::path& filename(getFullFileName(index));
|
||||
if ( filename.empty() )
|
||||
return 0;
|
||||
|
||||
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);
|
||||
|
||||
// os::Printer::log("addDirectoryToFileList:", dirname.c_str(), ELL_DEBUG);
|
||||
if (findFile(dirname, true) >= 0 )
|
||||
return; // was already added
|
||||
|
||||
AAssetDir *dir = AAssetManager_openDir(AssetManager, core::stringc(dirname).c_str());
|
||||
if(!dir)
|
||||
return;
|
||||
|
||||
// add directory itself
|
||||
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;
|
||||
|
||||
// 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());
|
||||
// os::Printer::log("addItem:", full_filename.c_str(), ELL_DEBUG);
|
||||
}
|
||||
AAssetDir_close(dir);
|
||||
}
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
// Copyright (C) 2012 Joerg Henrichs
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "IFileArchive.h"
|
||||
#include "CFileList.h"
|
||||
|
||||
#include <android/native_activity.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
/*!
|
||||
Android asset file system written August 2012 by J.Henrichs (later reworked by others).
|
||||
*/
|
||||
class CAndroidAssetFileArchive : public virtual IFileArchive,
|
||||
virtual CFileList
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAndroidAssetFileArchive(AAssetManager *assetManager, bool ignoreCase, bool ignorePaths);
|
||||
|
||||
//! destructor
|
||||
virtual ~CAndroidAssetFileArchive();
|
||||
|
||||
//! opens a file by file name
|
||||
virtual IReadFile* createAndOpenFile(const io::path& filename);
|
||||
|
||||
//! opens a file by index
|
||||
virtual IReadFile* createAndOpenFile(u32 index);
|
||||
|
||||
//! returns the list of files
|
||||
virtual const IFileList* getFileList() 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);
|
||||
|
||||
//! return the name (id) of the file Archive
|
||||
const io::path& getArchiveName() const override {return Path;}
|
||||
|
||||
protected:
|
||||
//! Android's asset manager
|
||||
AAssetManager *AssetManager;
|
||||
|
||||
}; // CAndroidAssetFileArchive
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
// Copyright (C) 2012 Joerg Henrichs
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "IFileArchive.h"
|
||||
#include "CFileList.h"
|
||||
|
||||
#include <android/native_activity.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
/*!
|
||||
Android asset file system written August 2012 by J.Henrichs (later reworked by others).
|
||||
*/
|
||||
class CAndroidAssetFileArchive : public virtual IFileArchive,
|
||||
virtual CFileList
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAndroidAssetFileArchive(AAssetManager *assetManager, bool ignoreCase, bool ignorePaths);
|
||||
|
||||
//! destructor
|
||||
virtual ~CAndroidAssetFileArchive();
|
||||
|
||||
//! opens a file by file name
|
||||
virtual IReadFile* createAndOpenFile(const io::path& filename);
|
||||
|
||||
//! opens a file by index
|
||||
virtual IReadFile* createAndOpenFile(u32 index);
|
||||
|
||||
//! returns the list of files
|
||||
virtual const IFileList* getFileList() 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);
|
||||
|
||||
//! return the name (id) of the file Archive
|
||||
const io::path& getArchiveName() const override {return Path;}
|
||||
|
||||
protected:
|
||||
//! Android's asset manager
|
||||
AAssetManager *AssetManager;
|
||||
|
||||
}; // CAndroidAssetFileArchive
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
// Copyright (C) 2002-2011 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
#include "CAndroidAssetReader.h"
|
||||
|
||||
#include "CReadFile.h"
|
||||
#include "coreutil.h"
|
||||
#include "CAndroidAssetReader.h"
|
||||
#include "CIrrDeviceAndroid.h"
|
||||
|
||||
#include <android_native_app_glue.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
CAndroidAssetReader::CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename)
|
||||
: AssetManager(assetManager), Filename(filename)
|
||||
{
|
||||
Asset = AAssetManager_open(AssetManager,
|
||||
core::stringc(filename).c_str(),
|
||||
AASSET_MODE_RANDOM);
|
||||
|
||||
}
|
||||
|
||||
CAndroidAssetReader::~CAndroidAssetReader()
|
||||
{
|
||||
if(Asset)
|
||||
AAsset_close(Asset);
|
||||
}
|
||||
|
||||
size_t CAndroidAssetReader::read(void* buffer, size_t sizeToRead)
|
||||
{
|
||||
int readBytes = AAsset_read(Asset, buffer, sizeToRead);
|
||||
if ( readBytes >= 0 )
|
||||
return size_t(readBytes);
|
||||
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);
|
||||
|
||||
return status+1;
|
||||
}
|
||||
|
||||
long CAndroidAssetReader::getSize() const
|
||||
{
|
||||
return AAsset_getLength(Asset);
|
||||
}
|
||||
|
||||
long CAndroidAssetReader::getPos() const
|
||||
{
|
||||
return AAsset_getLength(Asset) - AAsset_getRemainingLength(Asset);
|
||||
}
|
||||
|
||||
const io::path& CAndroidAssetReader::getFileName() const
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
// Copyright (C) 2002-2011 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
#include "CAndroidAssetReader.h"
|
||||
|
||||
#include "CReadFile.h"
|
||||
#include "coreutil.h"
|
||||
#include "CAndroidAssetReader.h"
|
||||
#include "CIrrDeviceAndroid.h"
|
||||
|
||||
#include <android_native_app_glue.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
CAndroidAssetReader::CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename)
|
||||
: AssetManager(assetManager), Filename(filename)
|
||||
{
|
||||
Asset = AAssetManager_open(AssetManager,
|
||||
core::stringc(filename).c_str(),
|
||||
AASSET_MODE_RANDOM);
|
||||
|
||||
}
|
||||
|
||||
CAndroidAssetReader::~CAndroidAssetReader()
|
||||
{
|
||||
if(Asset)
|
||||
AAsset_close(Asset);
|
||||
}
|
||||
|
||||
size_t CAndroidAssetReader::read(void* buffer, size_t sizeToRead)
|
||||
{
|
||||
int readBytes = AAsset_read(Asset, buffer, sizeToRead);
|
||||
if ( readBytes >= 0 )
|
||||
return size_t(readBytes);
|
||||
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);
|
||||
|
||||
return status+1;
|
||||
}
|
||||
|
||||
long CAndroidAssetReader::getSize() const
|
||||
{
|
||||
return AAsset_getLength(Asset);
|
||||
}
|
||||
|
||||
long CAndroidAssetReader::getPos() const
|
||||
{
|
||||
return AAsset_getLength(Asset) - AAsset_getRemainingLength(Asset);
|
||||
}
|
||||
|
||||
const io::path& CAndroidAssetReader::getFileName() const
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
@@ -1,69 +1,69 @@
|
||||
// Copyright (C) 2012 Joerg Henrichs
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
|
||||
#include "IReadFile.h"
|
||||
|
||||
struct AAssetManager;
|
||||
struct AAsset;
|
||||
struct ANativeActivity;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class CAndroidAssetReader : public virtual IReadFile
|
||||
{
|
||||
public:
|
||||
CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename);
|
||||
|
||||
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);
|
||||
|
||||
//! 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 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;
|
||||
|
||||
/** Return true if the file could be opened. */
|
||||
bool isOpen() const { return Asset!=NULL; }
|
||||
|
||||
private:
|
||||
//! Android's asset manager
|
||||
AAssetManager *AssetManager;
|
||||
|
||||
// An asset, i.e. file
|
||||
AAsset *Asset;
|
||||
path Filename;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
// Copyright (C) 2012 Joerg Henrichs
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
|
||||
#include "IReadFile.h"
|
||||
|
||||
struct AAssetManager;
|
||||
struct AAsset;
|
||||
struct ANativeActivity;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class CAndroidAssetReader : public virtual IReadFile
|
||||
{
|
||||
public:
|
||||
CAndroidAssetReader(AAssetManager *assetManager, const io::path &filename);
|
||||
|
||||
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);
|
||||
|
||||
//! 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 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;
|
||||
|
||||
/** Return true if the file could be opened. */
|
||||
bool isOpen() const { return Asset!=NULL; }
|
||||
|
||||
private:
|
||||
//! Android's asset manager
|
||||
AAssetManager *AssetManager;
|
||||
|
||||
// An asset, i.e. file
|
||||
AAsset *Asset;
|
||||
path Filename;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,101 +1,101 @@
|
||||
// Copyright (C) 2002-2011 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
#include <android/sensor.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
class CIrrDeviceAndroid : public CIrrDeviceStub
|
||||
{
|
||||
public:
|
||||
CIrrDeviceAndroid(const SIrrlichtCreationParameters& param);
|
||||
|
||||
virtual ~CIrrDeviceAndroid();
|
||||
|
||||
virtual bool run();
|
||||
|
||||
virtual void yield();
|
||||
|
||||
virtual void sleep(u32 timeMs, bool pauseTimer = false);
|
||||
|
||||
virtual void setWindowCaption(const wchar_t* text);
|
||||
|
||||
virtual bool isWindowActive() const;
|
||||
|
||||
virtual bool isWindowFocused() const;
|
||||
|
||||
virtual bool isWindowMinimized() const;
|
||||
|
||||
virtual void closeDevice();
|
||||
|
||||
virtual void setResizable(bool resize = false);
|
||||
|
||||
virtual void minimizeWindow();
|
||||
|
||||
virtual void maximizeWindow();
|
||||
|
||||
virtual void restoreWindow();
|
||||
|
||||
virtual core::position2di getWindowPosition();
|
||||
|
||||
virtual E_DEVICE_TYPE getType() const;
|
||||
|
||||
virtual bool activateAccelerometer(float updateInterval);
|
||||
|
||||
virtual bool deactivateAccelerometer();
|
||||
|
||||
virtual bool isAccelerometerActive();
|
||||
|
||||
virtual bool isAccelerometerAvailable();
|
||||
|
||||
virtual bool activateGyroscope(float updateInterval);
|
||||
|
||||
virtual bool deactivateGyroscope();
|
||||
|
||||
virtual bool isGyroscopeActive();
|
||||
|
||||
virtual bool isGyroscopeAvailable();
|
||||
|
||||
private:
|
||||
|
||||
static void handleAndroidCommand(android_app* app, int32_t cmd);
|
||||
|
||||
static s32 handleInput(android_app* app, AInputEvent* event);
|
||||
|
||||
void createDriver();
|
||||
|
||||
void createKeyMap();
|
||||
|
||||
video::SExposedVideoData& getExposedVideoData();
|
||||
|
||||
android_app* Android;
|
||||
ASensorManager* SensorManager;
|
||||
ASensorEventQueue* SensorEventQueue;
|
||||
const ASensor* Accelerometer;
|
||||
const ASensor* Gyroscope;
|
||||
|
||||
bool Focused;
|
||||
bool Initialized;
|
||||
bool Paused;
|
||||
|
||||
JNIEnv* JNIEnvAttachedToVM;
|
||||
|
||||
video::SExposedVideoData ExposedVideoData;
|
||||
|
||||
core::array<EKEY_CODE> KeyMap;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
// Copyright (C) 2002-2011 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
#include <android/sensor.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
class CIrrDeviceAndroid : public CIrrDeviceStub
|
||||
{
|
||||
public:
|
||||
CIrrDeviceAndroid(const SIrrlichtCreationParameters& param);
|
||||
|
||||
virtual ~CIrrDeviceAndroid();
|
||||
|
||||
virtual bool run();
|
||||
|
||||
virtual void yield();
|
||||
|
||||
virtual void sleep(u32 timeMs, bool pauseTimer = false);
|
||||
|
||||
virtual void setWindowCaption(const wchar_t* text);
|
||||
|
||||
virtual bool isWindowActive() const;
|
||||
|
||||
virtual bool isWindowFocused() const;
|
||||
|
||||
virtual bool isWindowMinimized() const;
|
||||
|
||||
virtual void closeDevice();
|
||||
|
||||
virtual void setResizable(bool resize = false);
|
||||
|
||||
virtual void minimizeWindow();
|
||||
|
||||
virtual void maximizeWindow();
|
||||
|
||||
virtual void restoreWindow();
|
||||
|
||||
virtual core::position2di getWindowPosition();
|
||||
|
||||
virtual E_DEVICE_TYPE getType() const;
|
||||
|
||||
virtual bool activateAccelerometer(float updateInterval);
|
||||
|
||||
virtual bool deactivateAccelerometer();
|
||||
|
||||
virtual bool isAccelerometerActive();
|
||||
|
||||
virtual bool isAccelerometerAvailable();
|
||||
|
||||
virtual bool activateGyroscope(float updateInterval);
|
||||
|
||||
virtual bool deactivateGyroscope();
|
||||
|
||||
virtual bool isGyroscopeActive();
|
||||
|
||||
virtual bool isGyroscopeAvailable();
|
||||
|
||||
private:
|
||||
|
||||
static void handleAndroidCommand(android_app* app, int32_t cmd);
|
||||
|
||||
static s32 handleInput(android_app* app, AInputEvent* event);
|
||||
|
||||
void createDriver();
|
||||
|
||||
void createKeyMap();
|
||||
|
||||
video::SExposedVideoData& getExposedVideoData();
|
||||
|
||||
android_app* Android;
|
||||
ASensorManager* SensorManager;
|
||||
ASensorEventQueue* SensorEventQueue;
|
||||
const ASensor* Accelerometer;
|
||||
const ASensor* Gyroscope;
|
||||
|
||||
bool Focused;
|
||||
bool Initialized;
|
||||
bool Paused;
|
||||
|
||||
JNIEnv* JNIEnvAttachedToVM;
|
||||
|
||||
video::SExposedVideoData ExposedVideoData;
|
||||
|
||||
core::array<EKEY_CODE> KeyMap;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CKeyEventWrapper.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace jni
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Class_KeyEvent = reinterpret_cast<jclass>(JniEnv->NewGlobalRef(localClass));
|
||||
}
|
||||
|
||||
Method_constructor = JniEnv->GetMethodID(Class_KeyEvent, "<init>", "(II)V");
|
||||
Method_getUnicodeChar = JniEnv->GetMethodID(Class_KeyEvent, "getUnicodeChar", "(I)I");
|
||||
}
|
||||
|
||||
if ( Class_KeyEvent && Method_constructor )
|
||||
{
|
||||
JniKeyEvent = JniEnv->NewObject(Class_KeyEvent, Method_constructor, action, code);
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("CKeyEventWrapper didn't find JNI classes/methods", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CKeyEventWrapper::~CKeyEventWrapper()
|
||||
{
|
||||
JniEnv->DeleteLocalRef(JniKeyEvent);
|
||||
}
|
||||
|
||||
int CKeyEventWrapper::getUnicodeChar(int metaState)
|
||||
{
|
||||
return JniEnv->CallIntMethod(JniKeyEvent, Method_getUnicodeChar, metaState);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CKeyEventWrapper.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace jni
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Class_KeyEvent = reinterpret_cast<jclass>(JniEnv->NewGlobalRef(localClass));
|
||||
}
|
||||
|
||||
Method_constructor = JniEnv->GetMethodID(Class_KeyEvent, "<init>", "(II)V");
|
||||
Method_getUnicodeChar = JniEnv->GetMethodID(Class_KeyEvent, "getUnicodeChar", "(I)I");
|
||||
}
|
||||
|
||||
if ( Class_KeyEvent && Method_constructor )
|
||||
{
|
||||
JniKeyEvent = JniEnv->NewObject(Class_KeyEvent, Method_constructor, action, code);
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("CKeyEventWrapper didn't find JNI classes/methods", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CKeyEventWrapper::~CKeyEventWrapper()
|
||||
{
|
||||
JniEnv->DeleteLocalRef(JniKeyEvent);
|
||||
}
|
||||
|
||||
int CKeyEventWrapper::getUnicodeChar(int metaState)
|
||||
{
|
||||
return JniEnv->CallIntMethod(JniKeyEvent, Method_getUnicodeChar, metaState);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
struct android_app;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace jni
|
||||
{
|
||||
|
||||
//! Minimal JNI wrapper class around android.view.KeyEvent
|
||||
//! NOTE: Only functions we actually use in the engine are wrapped
|
||||
//! This is currently not written to support multithreading - meaning threads are not attached/detached to the Java VM (to be discussed)
|
||||
class CKeyEventWrapper
|
||||
{
|
||||
public:
|
||||
CKeyEventWrapper(JNIEnv* jniEnv, int action, int code);
|
||||
~CKeyEventWrapper();
|
||||
|
||||
int getUnicodeChar(int metaState);
|
||||
|
||||
private:
|
||||
static jclass Class_KeyEvent;
|
||||
static jmethodID Method_getUnicodeChar;
|
||||
static jmethodID Method_constructor;
|
||||
JNIEnv* JniEnv;
|
||||
jobject JniKeyEvent; // this object in java
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
} // namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
struct android_app;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace jni
|
||||
{
|
||||
|
||||
//! Minimal JNI wrapper class around android.view.KeyEvent
|
||||
//! NOTE: Only functions we actually use in the engine are wrapped
|
||||
//! This is currently not written to support multithreading - meaning threads are not attached/detached to the Java VM (to be discussed)
|
||||
class CKeyEventWrapper
|
||||
{
|
||||
public:
|
||||
CKeyEventWrapper(JNIEnv* jniEnv, int action, int code);
|
||||
~CKeyEventWrapper();
|
||||
|
||||
int getUnicodeChar(int metaState);
|
||||
|
||||
private:
|
||||
static jclass Class_KeyEvent;
|
||||
static jmethodID Method_getUnicodeChar;
|
||||
static jmethodID Method_constructor;
|
||||
JNIEnv* JniEnv;
|
||||
jobject JniKeyEvent; // this object in java
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
} // namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,181 +1,181 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
|
||||
#include "matrix4.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class IDummyTransformationSceneNode;
|
||||
|
||||
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));
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshSceneNode();
|
||||
|
||||
//! sets the current frame. from now on the animation is played from this frame.
|
||||
void setCurrentFrame(f32 frame) override;
|
||||
|
||||
//! frame
|
||||
void OnRegisterSceneNode() override;
|
||||
|
||||
//! OnAnimate() is called just before rendering the whole scene.
|
||||
void OnAnimate(u32 timeMs) override;
|
||||
|
||||
//! renders the node.
|
||||
void render() 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! same as getJointNode(const c8* jointName), but based on id
|
||||
IBoneSceneNode* getJointNode(u32 jointID) 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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; }
|
||||
|
||||
//! 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;
|
||||
|
||||
//! updates the joint positions of this mesh
|
||||
void animateJoints(bool CalculateAbsolutePositions=true) override;
|
||||
|
||||
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
||||
void setRenderFromIdentity( bool On ) 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;
|
||||
|
||||
private:
|
||||
|
||||
//! Get a static mesh for the current frame of this animated mesh
|
||||
IMesh* getMeshForCurrentFrame();
|
||||
|
||||
void buildFrameNr(u32 timeMs);
|
||||
void checkJoints();
|
||||
void beginTransition();
|
||||
|
||||
core::array<video::SMaterial> Materials;
|
||||
core::aabbox3d<f32> Box;
|
||||
IAnimatedMesh* Mesh;
|
||||
|
||||
s32 StartFrame;
|
||||
s32 EndFrame;
|
||||
f32 FramesPerSecond;
|
||||
f32 CurrentFrameNr;
|
||||
|
||||
u32 LastTimeMs;
|
||||
u32 TransitionTime; //Transition time in millisecs
|
||||
f32 Transiting; //is mesh transiting (plus cache of TransitionTime)
|
||||
f32 TransitingBlend; //0-1, calculated on buildFrameNr
|
||||
|
||||
//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;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
|
||||
#include "matrix4.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class IDummyTransformationSceneNode;
|
||||
|
||||
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));
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshSceneNode();
|
||||
|
||||
//! sets the current frame. from now on the animation is played from this frame.
|
||||
void setCurrentFrame(f32 frame) override;
|
||||
|
||||
//! frame
|
||||
void OnRegisterSceneNode() override;
|
||||
|
||||
//! OnAnimate() is called just before rendering the whole scene.
|
||||
void OnAnimate(u32 timeMs) override;
|
||||
|
||||
//! renders the node.
|
||||
void render() 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! same as getJointNode(const c8* jointName), but based on id
|
||||
IBoneSceneNode* getJointNode(u32 jointID) 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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; }
|
||||
|
||||
//! 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;
|
||||
|
||||
//! updates the joint positions of this mesh
|
||||
void animateJoints(bool CalculateAbsolutePositions=true) override;
|
||||
|
||||
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
||||
void setRenderFromIdentity( bool On ) 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;
|
||||
|
||||
private:
|
||||
|
||||
//! Get a static mesh for the current frame of this animated mesh
|
||||
IMesh* getMeshForCurrentFrame();
|
||||
|
||||
void buildFrameNr(u32 timeMs);
|
||||
void checkJoints();
|
||||
void beginTransition();
|
||||
|
||||
core::array<video::SMaterial> Materials;
|
||||
core::aabbox3d<f32> Box;
|
||||
IAnimatedMesh* Mesh;
|
||||
|
||||
s32 StartFrame;
|
||||
s32 EndFrame;
|
||||
f32 FramesPerSecond;
|
||||
f32 CurrentFrameNr;
|
||||
|
||||
u32 LastTimeMs;
|
||||
u32 TransitionTime; //Transition time in millisecs
|
||||
f32 Transiting; //is mesh transiting (plus cache of TransitionTime)
|
||||
f32 TransitingBlend; //0-1, calculated on buildFrameNr
|
||||
|
||||
//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;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,162 +1,162 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CAttributes.h"
|
||||
#include "fast_atof.h"
|
||||
#include "ITexture.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
/*
|
||||
Basic types, check documentation in IAttribute.h to see how they generally work.
|
||||
*/
|
||||
|
||||
// Attribute implemented for boolean values
|
||||
class CBoolAttribute : public IAttribute
|
||||
{
|
||||
public:
|
||||
|
||||
CBoolAttribute(const char* name, bool value)
|
||||
{
|
||||
Name = name;
|
||||
setBool(value);
|
||||
}
|
||||
|
||||
s32 getInt() const override
|
||||
{
|
||||
return BoolValue ? 1 : 0;
|
||||
}
|
||||
|
||||
f32 getFloat() const override
|
||||
{
|
||||
return BoolValue ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
bool getBool() const override
|
||||
{
|
||||
return BoolValue;
|
||||
}
|
||||
|
||||
void setInt(s32 intValue) override
|
||||
{
|
||||
BoolValue = (intValue != 0);
|
||||
}
|
||||
|
||||
void setFloat(f32 floatValue) override
|
||||
{
|
||||
BoolValue = (floatValue != 0);
|
||||
}
|
||||
|
||||
void setBool(bool boolValue) override
|
||||
{
|
||||
BoolValue = boolValue;
|
||||
}
|
||||
|
||||
E_ATTRIBUTE_TYPE getType() const override
|
||||
{
|
||||
return EAT_BOOL;
|
||||
}
|
||||
|
||||
const wchar_t* getTypeString() const override
|
||||
{
|
||||
return L"bool";
|
||||
}
|
||||
|
||||
bool BoolValue;
|
||||
};
|
||||
|
||||
// Attribute implemented for integers
|
||||
class CIntAttribute : public IAttribute
|
||||
{
|
||||
public:
|
||||
|
||||
CIntAttribute(const char* name, s32 value)
|
||||
{
|
||||
Name = name;
|
||||
setInt(value);
|
||||
}
|
||||
|
||||
s32 getInt() const override
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
f32 getFloat() const override
|
||||
{
|
||||
return (f32)Value;
|
||||
}
|
||||
|
||||
void setInt(s32 intValue) override
|
||||
{
|
||||
Value = intValue;
|
||||
}
|
||||
|
||||
void setFloat(f32 floatValue) override
|
||||
{
|
||||
Value = (s32)floatValue;
|
||||
};
|
||||
|
||||
E_ATTRIBUTE_TYPE getType() const override
|
||||
{
|
||||
return EAT_INT;
|
||||
}
|
||||
|
||||
const wchar_t* getTypeString() const override
|
||||
{
|
||||
return L"int";
|
||||
}
|
||||
|
||||
s32 Value;
|
||||
};
|
||||
|
||||
// Attribute implemented for floats
|
||||
class CFloatAttribute : public IAttribute
|
||||
{
|
||||
public:
|
||||
|
||||
CFloatAttribute(const char* name, f32 value)
|
||||
{
|
||||
Name = name;
|
||||
setFloat(value);
|
||||
}
|
||||
|
||||
s32 getInt() const override
|
||||
{
|
||||
return (s32)Value;
|
||||
}
|
||||
|
||||
f32 getFloat() const override
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
void setInt(s32 intValue) override
|
||||
{
|
||||
Value = (f32)intValue;
|
||||
}
|
||||
|
||||
void setFloat(f32 floatValue) override
|
||||
{
|
||||
Value = floatValue;
|
||||
}
|
||||
|
||||
E_ATTRIBUTE_TYPE getType() const override
|
||||
{
|
||||
return EAT_FLOAT;
|
||||
}
|
||||
|
||||
const wchar_t* getTypeString() const override
|
||||
{
|
||||
return L"float";
|
||||
}
|
||||
|
||||
f32 Value;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CAttributes.h"
|
||||
#include "fast_atof.h"
|
||||
#include "ITexture.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
/*
|
||||
Basic types, check documentation in IAttribute.h to see how they generally work.
|
||||
*/
|
||||
|
||||
// Attribute implemented for boolean values
|
||||
class CBoolAttribute : public IAttribute
|
||||
{
|
||||
public:
|
||||
|
||||
CBoolAttribute(const char* name, bool value)
|
||||
{
|
||||
Name = name;
|
||||
setBool(value);
|
||||
}
|
||||
|
||||
s32 getInt() const override
|
||||
{
|
||||
return BoolValue ? 1 : 0;
|
||||
}
|
||||
|
||||
f32 getFloat() const override
|
||||
{
|
||||
return BoolValue ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
bool getBool() const override
|
||||
{
|
||||
return BoolValue;
|
||||
}
|
||||
|
||||
void setInt(s32 intValue) override
|
||||
{
|
||||
BoolValue = (intValue != 0);
|
||||
}
|
||||
|
||||
void setFloat(f32 floatValue) override
|
||||
{
|
||||
BoolValue = (floatValue != 0);
|
||||
}
|
||||
|
||||
void setBool(bool boolValue) override
|
||||
{
|
||||
BoolValue = boolValue;
|
||||
}
|
||||
|
||||
E_ATTRIBUTE_TYPE getType() const override
|
||||
{
|
||||
return EAT_BOOL;
|
||||
}
|
||||
|
||||
const wchar_t* getTypeString() const override
|
||||
{
|
||||
return L"bool";
|
||||
}
|
||||
|
||||
bool BoolValue;
|
||||
};
|
||||
|
||||
// Attribute implemented for integers
|
||||
class CIntAttribute : public IAttribute
|
||||
{
|
||||
public:
|
||||
|
||||
CIntAttribute(const char* name, s32 value)
|
||||
{
|
||||
Name = name;
|
||||
setInt(value);
|
||||
}
|
||||
|
||||
s32 getInt() const override
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
f32 getFloat() const override
|
||||
{
|
||||
return (f32)Value;
|
||||
}
|
||||
|
||||
void setInt(s32 intValue) override
|
||||
{
|
||||
Value = intValue;
|
||||
}
|
||||
|
||||
void setFloat(f32 floatValue) override
|
||||
{
|
||||
Value = (s32)floatValue;
|
||||
};
|
||||
|
||||
E_ATTRIBUTE_TYPE getType() const override
|
||||
{
|
||||
return EAT_INT;
|
||||
}
|
||||
|
||||
const wchar_t* getTypeString() const override
|
||||
{
|
||||
return L"int";
|
||||
}
|
||||
|
||||
s32 Value;
|
||||
};
|
||||
|
||||
// Attribute implemented for floats
|
||||
class CFloatAttribute : public IAttribute
|
||||
{
|
||||
public:
|
||||
|
||||
CFloatAttribute(const char* name, f32 value)
|
||||
{
|
||||
Name = name;
|
||||
setFloat(value);
|
||||
}
|
||||
|
||||
s32 getInt() const override
|
||||
{
|
||||
return (s32)Value;
|
||||
}
|
||||
|
||||
f32 getFloat() const override
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
void setInt(s32 intValue) override
|
||||
{
|
||||
Value = (f32)intValue;
|
||||
}
|
||||
|
||||
void setFloat(f32 floatValue) override
|
||||
{
|
||||
Value = floatValue;
|
||||
}
|
||||
|
||||
E_ATTRIBUTE_TYPE getType() const override
|
||||
{
|
||||
return EAT_FLOAT;
|
||||
}
|
||||
|
||||
const wchar_t* getTypeString() const override
|
||||
{
|
||||
return L"float";
|
||||
}
|
||||
|
||||
f32 Value;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,274 +1,274 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CAttributes.h"
|
||||
#include "CAttributeImpl.h"
|
||||
#include "ITexture.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
CAttributes::CAttributes(video::IVideoDriver* driver)
|
||||
: Driver(driver)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CAttributes");
|
||||
#endif
|
||||
|
||||
if (Driver)
|
||||
Driver->grab();
|
||||
}
|
||||
|
||||
CAttributes::~CAttributes()
|
||||
{
|
||||
clear();
|
||||
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Removes all attributes
|
||||
void CAttributes::clear()
|
||||
{
|
||||
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
|
||||
{
|
||||
for (u32 i=0; i<Attributes.size(); ++i)
|
||||
if (Attributes[i]->Name == attributeName)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
IAttribute* CAttributes::getAttributeP(const c8* attributeName) const
|
||||
{
|
||||
for (u32 i=0; i<Attributes.size(); ++i)
|
||||
if (Attributes[i]->Name == attributeName)
|
||||
return Attributes[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets a attribute as boolean value
|
||||
void CAttributes::setAttribute(const c8* attributeName, bool value)
|
||||
{
|
||||
IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
att->setBool(value);
|
||||
else
|
||||
{
|
||||
Attributes.push_back(new CBoolAttribute(attributeName, value));
|
||||
}
|
||||
}
|
||||
|
||||
//! Gets a attribute as boolean 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
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getBool();
|
||||
else
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Sets a attribute as integer value
|
||||
void CAttributes::setAttribute(const c8* attributeName, s32 value)
|
||||
{
|
||||
IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
att->setInt(value);
|
||||
else
|
||||
{
|
||||
Attributes.push_back(new CIntAttribute(attributeName, value));
|
||||
}
|
||||
}
|
||||
|
||||
//! Gets a attribute as integer 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
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getInt();
|
||||
else
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Sets a attribute as float value
|
||||
void CAttributes::setAttribute(const c8* attributeName, f32 value)
|
||||
{
|
||||
IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
att->setFloat(value);
|
||||
else
|
||||
Attributes.push_back(new CFloatAttribute(attributeName, value));
|
||||
}
|
||||
|
||||
//! Gets a attribute as integer 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
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getFloat();
|
||||
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Returns amount of string attributes set in this scene manager.
|
||||
u32 CAttributes::getAttributeCount() const
|
||||
{
|
||||
return Attributes.size();
|
||||
}
|
||||
|
||||
//! Returns string attribute name by index.
|
||||
//! \param index: Index value, must be between 0 and getStringAttributeCount()-1.
|
||||
const c8* CAttributes::getAttributeName(s32 index) const
|
||||
{
|
||||
if ((u32)index >= Attributes.size())
|
||||
return 0;
|
||||
|
||||
return Attributes[index]->Name.c_str();
|
||||
}
|
||||
|
||||
//! Returns the type of an attribute
|
||||
E_ATTRIBUTE_TYPE CAttributes::getAttributeType(const c8* attributeName) const
|
||||
{
|
||||
E_ATTRIBUTE_TYPE ret = EAT_UNKNOWN;
|
||||
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
ret = att->getType();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Returns attribute type by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
E_ATTRIBUTE_TYPE CAttributes::getAttributeType(s32 index) const
|
||||
{
|
||||
if ((u32)index >= Attributes.size())
|
||||
return EAT_UNKNOWN;
|
||||
|
||||
return Attributes[index]->getType();
|
||||
}
|
||||
|
||||
//! Returns the type of an attribute
|
||||
const wchar_t* CAttributes::getAttributeTypeString(const c8* attributeName, const wchar_t* defaultNotFound) const
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getTypeString();
|
||||
else
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Returns attribute type string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
const wchar_t* CAttributes::getAttributeTypeString(s32 index, const wchar_t* defaultNotFound) const
|
||||
{
|
||||
if ((u32)index >= Attributes.size())
|
||||
return defaultNotFound;
|
||||
|
||||
return Attributes[index]->getTypeString();
|
||||
}
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
s32 CAttributes::getAttributeAsInt(s32 index) const
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
return Attributes[index]->getInt();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
f32 CAttributes::getAttributeAsFloat(s32 index) const
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
return Attributes[index]->getFloat();
|
||||
else
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
bool CAttributes::getAttributeAsBool(s32 index) const
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if ((u32)index < Attributes.size())
|
||||
ret = Attributes[index]->getBool();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Adds an attribute as integer
|
||||
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)
|
||||
{
|
||||
Attributes.push_back(new CFloatAttribute(attributeName, value));
|
||||
}
|
||||
|
||||
//! Adds an attribute as bool
|
||||
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
|
||||
{
|
||||
return getAttributeP(attributeName) != 0;
|
||||
}
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
void CAttributes::setAttribute(s32 index, bool value)
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
Attributes[index]->setBool(value);
|
||||
}
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
void CAttributes::setAttribute(s32 index, s32 value)
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
Attributes[index]->setInt(value);
|
||||
}
|
||||
|
||||
//! Sets a attribute as float value
|
||||
void CAttributes::setAttribute(s32 index, f32 value)
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
Attributes[index]->setFloat(value);
|
||||
}
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CAttributes.h"
|
||||
#include "CAttributeImpl.h"
|
||||
#include "ITexture.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
CAttributes::CAttributes(video::IVideoDriver* driver)
|
||||
: Driver(driver)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CAttributes");
|
||||
#endif
|
||||
|
||||
if (Driver)
|
||||
Driver->grab();
|
||||
}
|
||||
|
||||
CAttributes::~CAttributes()
|
||||
{
|
||||
clear();
|
||||
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Removes all attributes
|
||||
void CAttributes::clear()
|
||||
{
|
||||
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
|
||||
{
|
||||
for (u32 i=0; i<Attributes.size(); ++i)
|
||||
if (Attributes[i]->Name == attributeName)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
IAttribute* CAttributes::getAttributeP(const c8* attributeName) const
|
||||
{
|
||||
for (u32 i=0; i<Attributes.size(); ++i)
|
||||
if (Attributes[i]->Name == attributeName)
|
||||
return Attributes[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets a attribute as boolean value
|
||||
void CAttributes::setAttribute(const c8* attributeName, bool value)
|
||||
{
|
||||
IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
att->setBool(value);
|
||||
else
|
||||
{
|
||||
Attributes.push_back(new CBoolAttribute(attributeName, value));
|
||||
}
|
||||
}
|
||||
|
||||
//! Gets a attribute as boolean 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
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getBool();
|
||||
else
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Sets a attribute as integer value
|
||||
void CAttributes::setAttribute(const c8* attributeName, s32 value)
|
||||
{
|
||||
IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
att->setInt(value);
|
||||
else
|
||||
{
|
||||
Attributes.push_back(new CIntAttribute(attributeName, value));
|
||||
}
|
||||
}
|
||||
|
||||
//! Gets a attribute as integer 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
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getInt();
|
||||
else
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Sets a attribute as float value
|
||||
void CAttributes::setAttribute(const c8* attributeName, f32 value)
|
||||
{
|
||||
IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
att->setFloat(value);
|
||||
else
|
||||
Attributes.push_back(new CFloatAttribute(attributeName, value));
|
||||
}
|
||||
|
||||
//! Gets a attribute as integer 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
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getFloat();
|
||||
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Returns amount of string attributes set in this scene manager.
|
||||
u32 CAttributes::getAttributeCount() const
|
||||
{
|
||||
return Attributes.size();
|
||||
}
|
||||
|
||||
//! Returns string attribute name by index.
|
||||
//! \param index: Index value, must be between 0 and getStringAttributeCount()-1.
|
||||
const c8* CAttributes::getAttributeName(s32 index) const
|
||||
{
|
||||
if ((u32)index >= Attributes.size())
|
||||
return 0;
|
||||
|
||||
return Attributes[index]->Name.c_str();
|
||||
}
|
||||
|
||||
//! Returns the type of an attribute
|
||||
E_ATTRIBUTE_TYPE CAttributes::getAttributeType(const c8* attributeName) const
|
||||
{
|
||||
E_ATTRIBUTE_TYPE ret = EAT_UNKNOWN;
|
||||
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
ret = att->getType();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Returns attribute type by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
E_ATTRIBUTE_TYPE CAttributes::getAttributeType(s32 index) const
|
||||
{
|
||||
if ((u32)index >= Attributes.size())
|
||||
return EAT_UNKNOWN;
|
||||
|
||||
return Attributes[index]->getType();
|
||||
}
|
||||
|
||||
//! Returns the type of an attribute
|
||||
const wchar_t* CAttributes::getAttributeTypeString(const c8* attributeName, const wchar_t* defaultNotFound) const
|
||||
{
|
||||
const IAttribute* att = getAttributeP(attributeName);
|
||||
if (att)
|
||||
return att->getTypeString();
|
||||
else
|
||||
return defaultNotFound;
|
||||
}
|
||||
|
||||
//! Returns attribute type string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
const wchar_t* CAttributes::getAttributeTypeString(s32 index, const wchar_t* defaultNotFound) const
|
||||
{
|
||||
if ((u32)index >= Attributes.size())
|
||||
return defaultNotFound;
|
||||
|
||||
return Attributes[index]->getTypeString();
|
||||
}
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
s32 CAttributes::getAttributeAsInt(s32 index) const
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
return Attributes[index]->getInt();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
f32 CAttributes::getAttributeAsFloat(s32 index) const
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
return Attributes[index]->getFloat();
|
||||
else
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
bool CAttributes::getAttributeAsBool(s32 index) const
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if ((u32)index < Attributes.size())
|
||||
ret = Attributes[index]->getBool();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Adds an attribute as integer
|
||||
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)
|
||||
{
|
||||
Attributes.push_back(new CFloatAttribute(attributeName, value));
|
||||
}
|
||||
|
||||
//! Adds an attribute as bool
|
||||
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
|
||||
{
|
||||
return getAttributeP(attributeName) != 0;
|
||||
}
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
void CAttributes::setAttribute(s32 index, bool value)
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
Attributes[index]->setBool(value);
|
||||
}
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
void CAttributes::setAttribute(s32 index, s32 value)
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
Attributes[index]->setInt(value);
|
||||
}
|
||||
|
||||
//! Sets a attribute as float value
|
||||
void CAttributes::setAttribute(s32 index, f32 value)
|
||||
{
|
||||
if ((u32)index < Attributes.size())
|
||||
Attributes[index]->setFloat(value);
|
||||
}
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IAttributes.h"
|
||||
#include "IAttribute.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class ITexture;
|
||||
class IVideoDriver;
|
||||
}
|
||||
namespace io
|
||||
{
|
||||
|
||||
|
||||
//! Implementation of the IAttributes interface
|
||||
class CAttributes : public IAttributes
|
||||
{
|
||||
public:
|
||||
|
||||
CAttributes(video::IVideoDriver* driver=0);
|
||||
~CAttributes();
|
||||
|
||||
//! Returns amount of attributes in this collection of attributes.
|
||||
u32 getAttributeCount() const override;
|
||||
|
||||
//! Returns attribute name by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
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;
|
||||
|
||||
//! 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 the type string of the attribute
|
||||
//! \param attributeName: String for the attribute type
|
||||
//! \param defaultNotFound Value returned when attributeName was not found
|
||||
const wchar_t* getAttributeTypeString(const c8* attributeName, const wchar_t* defaultNotFound = L"unknown") const override;
|
||||
|
||||
//! Returns the type string of the attribute by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
const wchar_t* getAttributeTypeString(s32 index, const wchar_t* defaultNotFound = L"unknown") const override;
|
||||
|
||||
//! Returns if an attribute with a name exists
|
||||
bool existsAttribute(const c8* attributeName) const override;
|
||||
|
||||
//! Returns attribute index from name, -1 if not found
|
||||
s32 findAttribute(const c8* attributeName) const override;
|
||||
|
||||
//! Removes all attributes
|
||||
void clear() override;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Integer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as integer
|
||||
void addInt(const c8* attributeName, s32 value) override;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
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;
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
s32 getAttributeAsInt(s32 index) const override;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
void setAttribute(s32 index, s32 value) override;
|
||||
|
||||
/*
|
||||
|
||||
Float Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as float
|
||||
void addFloat(const c8* attributeName, f32 value) override;
|
||||
|
||||
//! Sets a attribute as float value
|
||||
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;
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
f32 getAttributeAsFloat(s32 index) const override;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
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;
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
bool getAttributeAsBool(s32 index) const override;
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
void setAttribute(s32 index, bool value) override;
|
||||
|
||||
protected:
|
||||
|
||||
core::array<IAttribute*> Attributes;
|
||||
|
||||
IAttribute* getAttributeP(const c8* attributeName) const;
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IAttributes.h"
|
||||
#include "IAttribute.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class ITexture;
|
||||
class IVideoDriver;
|
||||
}
|
||||
namespace io
|
||||
{
|
||||
|
||||
|
||||
//! Implementation of the IAttributes interface
|
||||
class CAttributes : public IAttributes
|
||||
{
|
||||
public:
|
||||
|
||||
CAttributes(video::IVideoDriver* driver=0);
|
||||
~CAttributes();
|
||||
|
||||
//! Returns amount of attributes in this collection of attributes.
|
||||
u32 getAttributeCount() const override;
|
||||
|
||||
//! Returns attribute name by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
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;
|
||||
|
||||
//! 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 the type string of the attribute
|
||||
//! \param attributeName: String for the attribute type
|
||||
//! \param defaultNotFound Value returned when attributeName was not found
|
||||
const wchar_t* getAttributeTypeString(const c8* attributeName, const wchar_t* defaultNotFound = L"unknown") const override;
|
||||
|
||||
//! Returns the type string of the attribute by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
const wchar_t* getAttributeTypeString(s32 index, const wchar_t* defaultNotFound = L"unknown") const override;
|
||||
|
||||
//! Returns if an attribute with a name exists
|
||||
bool existsAttribute(const c8* attributeName) const override;
|
||||
|
||||
//! Returns attribute index from name, -1 if not found
|
||||
s32 findAttribute(const c8* attributeName) const override;
|
||||
|
||||
//! Removes all attributes
|
||||
void clear() override;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Integer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as integer
|
||||
void addInt(const c8* attributeName, s32 value) override;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
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;
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
s32 getAttributeAsInt(s32 index) const override;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
void setAttribute(s32 index, s32 value) override;
|
||||
|
||||
/*
|
||||
|
||||
Float Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as float
|
||||
void addFloat(const c8* attributeName, f32 value) override;
|
||||
|
||||
//! Sets a attribute as float value
|
||||
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;
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
f32 getAttributeAsFloat(s32 index) const override;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
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;
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
bool getAttributeAsBool(s32 index) const override;
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
void setAttribute(s32 index, bool value) override;
|
||||
|
||||
protected:
|
||||
|
||||
core::array<IAttribute*> Attributes;
|
||||
|
||||
IAttribute* getAttributeP(const c8* attributeName) const;
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,83 +1,83 @@
|
||||
// Copyright (C) 2006-2012 Luke Hoschke
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// B3D Mesh loader
|
||||
// File format designed by Mark Sibly for the Blitz3D engine and has been
|
||||
// declared public domain
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SB3DStructs.h"
|
||||
#include "IReadFile.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Meshloader for B3D format
|
||||
class CB3DMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
|
||||
bool load();
|
||||
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 readChunkANIM();
|
||||
bool readChunkTEXS();
|
||||
bool readChunkBRUS();
|
||||
|
||||
void readString(core::stringc& newstring);
|
||||
void readFloats(f32* vec, u32 count);
|
||||
|
||||
core::array<SB3dChunk> B3dStack;
|
||||
|
||||
core::array<SB3dMaterial> Materials;
|
||||
core::array<SB3dTexture> Textures;
|
||||
|
||||
core::array<s32> AnimatedVertices_VertexID;
|
||||
|
||||
core::array<s32> AnimatedVertices_BufferID;
|
||||
|
||||
core::array<video::S3DVertex2TCoords> BaseVertices;
|
||||
|
||||
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
|
||||
u32 VerticesStart;
|
||||
|
||||
bool NormalsInFile;
|
||||
bool HasVertexColors;
|
||||
bool ShowWarning;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2006-2012 Luke Hoschke
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// B3D Mesh loader
|
||||
// File format designed by Mark Sibly for the Blitz3D engine and has been
|
||||
// declared public domain
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "SB3DStructs.h"
|
||||
#include "IReadFile.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Meshloader for B3D format
|
||||
class CB3DMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
|
||||
bool load();
|
||||
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 readChunkANIM();
|
||||
bool readChunkTEXS();
|
||||
bool readChunkBRUS();
|
||||
|
||||
void readString(core::stringc& newstring);
|
||||
void readFloats(f32* vec, u32 count);
|
||||
|
||||
core::array<SB3dChunk> B3dStack;
|
||||
|
||||
core::array<SB3dMaterial> Materials;
|
||||
core::array<SB3dTexture> Textures;
|
||||
|
||||
core::array<s32> AnimatedVertices_VertexID;
|
||||
|
||||
core::array<s32> AnimatedVertices_BufferID;
|
||||
|
||||
core::array<video::S3DVertex2TCoords> BaseVertices;
|
||||
|
||||
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
|
||||
u32 VerticesStart;
|
||||
|
||||
bool NormalsInFile;
|
||||
bool HasVertexColors;
|
||||
bool ShowWarning;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,51 +1,51 @@
|
||||
// Copyright (C) 2014 Lauri Kasanen
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// Modified version with rigging/skinning support
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IMeshWriter.h"
|
||||
#include "IWriteFile.h"
|
||||
#include "SB3DStructs.h"
|
||||
#include "ISkinnedMesh.h"
|
||||
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! class to write B3D mesh files
|
||||
class CB3DMeshWriter : public IMeshWriter
|
||||
{
|
||||
public:
|
||||
|
||||
CB3DMeshWriter();
|
||||
|
||||
//! Returns the type of the mesh writer
|
||||
EMESH_WRITER_TYPE getType() const override;
|
||||
|
||||
//! writes a mesh
|
||||
bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) override;
|
||||
|
||||
private:
|
||||
void writeJointChunk(io::IWriteFile* file, ISkinnedMesh* mesh , ISkinnedMesh::SJoint* joint, f32 animationSpeedMultiplier);
|
||||
u32 getJointChunkSize(const ISkinnedMesh* mesh, ISkinnedMesh::SJoint* joint);
|
||||
core::array<ISkinnedMesh::SJoint*> getRootJoints(const ISkinnedMesh* mesh);
|
||||
|
||||
u32 getUVlayerCount(const IMesh *mesh);
|
||||
ISkinnedMesh* getSkinned (IMesh *mesh);
|
||||
|
||||
inline void writeVector2(io::IWriteFile* file, const core::vector2df& vec);
|
||||
inline void writeVector3(io::IWriteFile* file, const core::vector3df& vec);
|
||||
inline void writeQuaternion(io::IWriteFile* file, const core::quaternion& quat);
|
||||
inline void writeColor(io::IWriteFile* file, const video::SColorf& color);
|
||||
void writeSizeFrom(io::IWriteFile* file, const u32 from, const u32 adressToWrite);
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
// Copyright (C) 2014 Lauri Kasanen
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// Modified version with rigging/skinning support
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IMeshWriter.h"
|
||||
#include "IWriteFile.h"
|
||||
#include "SB3DStructs.h"
|
||||
#include "ISkinnedMesh.h"
|
||||
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! class to write B3D mesh files
|
||||
class CB3DMeshWriter : public IMeshWriter
|
||||
{
|
||||
public:
|
||||
|
||||
CB3DMeshWriter();
|
||||
|
||||
//! Returns the type of the mesh writer
|
||||
EMESH_WRITER_TYPE getType() const override;
|
||||
|
||||
//! writes a mesh
|
||||
bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) override;
|
||||
|
||||
private:
|
||||
void writeJointChunk(io::IWriteFile* file, ISkinnedMesh* mesh , ISkinnedMesh::SJoint* joint, f32 animationSpeedMultiplier);
|
||||
u32 getJointChunkSize(const ISkinnedMesh* mesh, ISkinnedMesh::SJoint* joint);
|
||||
core::array<ISkinnedMesh::SJoint*> getRootJoints(const ISkinnedMesh* mesh);
|
||||
|
||||
u32 getUVlayerCount(const IMesh *mesh);
|
||||
ISkinnedMesh* getSkinned (IMesh *mesh);
|
||||
|
||||
inline void writeVector2(io::IWriteFile* file, const core::vector2df& vec);
|
||||
inline void writeVector3(io::IWriteFile* file, const core::vector3df& vec);
|
||||
inline void writeQuaternion(io::IWriteFile* file, const core::quaternion& quat);
|
||||
inline void writeColor(io::IWriteFile* file, const video::SColorf& color);
|
||||
void writeSizeFrom(io::IWriteFile* file, const u32 from, const u32 adressToWrite);
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
|
||||
@@ -1,281 +1,281 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CBillboardSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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())
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBillboardSceneNode");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
|
||||
Buffer->Vertices.set_used(4);
|
||||
Buffer->Indices.set_used(6);
|
||||
|
||||
Buffer->Indices[0] = 0;
|
||||
Buffer->Indices[1] = 2;
|
||||
Buffer->Indices[2] = 1;
|
||||
Buffer->Indices[3] = 0;
|
||||
Buffer->Indices[4] = 3;
|
||||
Buffer->Indices[5] = 2;
|
||||
|
||||
Buffer->Vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
Buffer->Vertices[0].Color = colorBottom;
|
||||
|
||||
Buffer->Vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
Buffer->Vertices[1].Color = colorTop;
|
||||
|
||||
Buffer->Vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
Buffer->Vertices[2].Color = colorTop;
|
||||
|
||||
Buffer->Vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
Buffer->Vertices[3].Color = colorBottom;
|
||||
}
|
||||
|
||||
CBillboardSceneNode::~CBillboardSceneNode()
|
||||
{
|
||||
Buffer->drop();
|
||||
}
|
||||
|
||||
//! pre render event
|
||||
void CBillboardSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CBillboardSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
||||
|
||||
if (!camera || !driver)
|
||||
return;
|
||||
|
||||
// make billboard look to camera
|
||||
updateMesh(camera);
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
driver->setMaterial(Buffer->Material);
|
||||
driver->drawMeshBuffer(Buffer);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
|
||||
{
|
||||
// billboard looks toward camera
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
|
||||
core::vector3df campos = camera->getAbsolutePosition();
|
||||
core::vector3df target = camera->getTarget();
|
||||
core::vector3df up = camera->getUpVector();
|
||||
core::vector3df view = target - campos;
|
||||
view.normalize();
|
||||
|
||||
core::vector3df horizontal = up.crossProduct(view);
|
||||
if ( horizontal.getLength() == 0 )
|
||||
{
|
||||
horizontal.set(up.Y,up.X,up.Z);
|
||||
}
|
||||
horizontal.normalize();
|
||||
core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth;
|
||||
horizontal *= 0.5f * Size.Width;
|
||||
|
||||
// pointing down!
|
||||
core::vector3df vertical = horizontal.crossProduct(view);
|
||||
vertical.normalize();
|
||||
vertical *= 0.5f * Size.Height;
|
||||
|
||||
view *= -1.0f;
|
||||
|
||||
core::array<video::S3DVertex>& vertices = Buffer->Vertices;
|
||||
|
||||
for (s32 i=0; i<4; ++i)
|
||||
vertices[i].Normal = view;
|
||||
|
||||
/* Vertices are:
|
||||
2--1
|
||||
|\ |
|
||||
| \|
|
||||
3--0
|
||||
*/
|
||||
vertices[0].Pos = pos + horizontal + vertical;
|
||||
vertices[1].Pos = pos + topHorizontal - vertical;
|
||||
vertices[2].Pos = pos - topHorizontal - vertical;
|
||||
vertices[3].Pos = pos - horizontal + vertical;
|
||||
|
||||
Buffer->setDirty(EBT_VERTEX);
|
||||
Buffer->recalculateBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
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)
|
||||
{
|
||||
updateMesh(camera);
|
||||
return Buffer->BoundingBox;
|
||||
}
|
||||
|
||||
void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||
{
|
||||
Size = size;
|
||||
|
||||
if (core::equals(Size.Width, 0.0f))
|
||||
Size.Width = 1.0f;
|
||||
TopEdgeWidth = Size.Width;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth)
|
||||
{
|
||||
Size.set(bottomEdgeWidth, height);
|
||||
TopEdgeWidth = topEdgeWidth;
|
||||
|
||||
if (core::equals(Size.Height, 0.0f))
|
||||
Size.Height = 1.0f;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Buffer->Vertices[0].Color = bottomColor;
|
||||
Buffer->Vertices[1].Color = topColor;
|
||||
Buffer->Vertices[2].Color = 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
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);
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CBillboardSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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())
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBillboardSceneNode");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
|
||||
Buffer->Vertices.set_used(4);
|
||||
Buffer->Indices.set_used(6);
|
||||
|
||||
Buffer->Indices[0] = 0;
|
||||
Buffer->Indices[1] = 2;
|
||||
Buffer->Indices[2] = 1;
|
||||
Buffer->Indices[3] = 0;
|
||||
Buffer->Indices[4] = 3;
|
||||
Buffer->Indices[5] = 2;
|
||||
|
||||
Buffer->Vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
Buffer->Vertices[0].Color = colorBottom;
|
||||
|
||||
Buffer->Vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
Buffer->Vertices[1].Color = colorTop;
|
||||
|
||||
Buffer->Vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
Buffer->Vertices[2].Color = colorTop;
|
||||
|
||||
Buffer->Vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
Buffer->Vertices[3].Color = colorBottom;
|
||||
}
|
||||
|
||||
CBillboardSceneNode::~CBillboardSceneNode()
|
||||
{
|
||||
Buffer->drop();
|
||||
}
|
||||
|
||||
//! pre render event
|
||||
void CBillboardSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CBillboardSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
||||
|
||||
if (!camera || !driver)
|
||||
return;
|
||||
|
||||
// make billboard look to camera
|
||||
updateMesh(camera);
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
driver->setMaterial(Buffer->Material);
|
||||
driver->drawMeshBuffer(Buffer);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
|
||||
{
|
||||
// billboard looks toward camera
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
|
||||
core::vector3df campos = camera->getAbsolutePosition();
|
||||
core::vector3df target = camera->getTarget();
|
||||
core::vector3df up = camera->getUpVector();
|
||||
core::vector3df view = target - campos;
|
||||
view.normalize();
|
||||
|
||||
core::vector3df horizontal = up.crossProduct(view);
|
||||
if ( horizontal.getLength() == 0 )
|
||||
{
|
||||
horizontal.set(up.Y,up.X,up.Z);
|
||||
}
|
||||
horizontal.normalize();
|
||||
core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth;
|
||||
horizontal *= 0.5f * Size.Width;
|
||||
|
||||
// pointing down!
|
||||
core::vector3df vertical = horizontal.crossProduct(view);
|
||||
vertical.normalize();
|
||||
vertical *= 0.5f * Size.Height;
|
||||
|
||||
view *= -1.0f;
|
||||
|
||||
core::array<video::S3DVertex>& vertices = Buffer->Vertices;
|
||||
|
||||
for (s32 i=0; i<4; ++i)
|
||||
vertices[i].Normal = view;
|
||||
|
||||
/* Vertices are:
|
||||
2--1
|
||||
|\ |
|
||||
| \|
|
||||
3--0
|
||||
*/
|
||||
vertices[0].Pos = pos + horizontal + vertical;
|
||||
vertices[1].Pos = pos + topHorizontal - vertical;
|
||||
vertices[2].Pos = pos - topHorizontal - vertical;
|
||||
vertices[3].Pos = pos - horizontal + vertical;
|
||||
|
||||
Buffer->setDirty(EBT_VERTEX);
|
||||
Buffer->recalculateBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
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)
|
||||
{
|
||||
updateMesh(camera);
|
||||
return Buffer->BoundingBox;
|
||||
}
|
||||
|
||||
void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||
{
|
||||
Size = size;
|
||||
|
||||
if (core::equals(Size.Width, 0.0f))
|
||||
Size.Width = 1.0f;
|
||||
TopEdgeWidth = Size.Width;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth)
|
||||
{
|
||||
Size.set(bottomEdgeWidth, height);
|
||||
TopEdgeWidth = topEdgeWidth;
|
||||
|
||||
if (core::equals(Size.Height, 0.0f))
|
||||
Size.Height = 1.0f;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Buffer->Vertices[0].Color = bottomColor;
|
||||
Buffer->Vertices[1].Color = topColor;
|
||||
Buffer->Vertices[2].Color = 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
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);
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,117 +1,117 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "SMeshBuffer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,
|
||||
//! which always looks to the camera.
|
||||
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));
|
||||
|
||||
virtual ~CBillboardSceneNode();
|
||||
|
||||
//! pre render event
|
||||
void OnRegisterSceneNode() override;
|
||||
|
||||
//! render
|
||||
void render() override;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& getBoundingBox() const override;
|
||||
|
||||
//! sets the size of the billboard
|
||||
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;
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Get the amount of mesh buffers.
|
||||
u32 getMeshBufferCount() const override
|
||||
{
|
||||
return Buffer ? 1 : 0;
|
||||
}
|
||||
|
||||
//! Get pointer to the mesh buffer.
|
||||
IMeshBuffer* getMeshBuffer(u32 nr) const override
|
||||
{
|
||||
if ( nr == 0 )
|
||||
return Buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Returns type of the scene node
|
||||
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;
|
||||
|
||||
protected:
|
||||
void updateMesh(const irr::scene::ICameraSceneNode* camera);
|
||||
|
||||
private:
|
||||
|
||||
//! Size.Width is the bottom edge width
|
||||
core::dimension2d<f32> Size;
|
||||
f32 TopEdgeWidth;
|
||||
|
||||
//! BoundingBox which is large enough to contain the billboard independent of the camera
|
||||
// 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. */
|
||||
core::aabbox3d<f32> BBoxSafe;
|
||||
|
||||
scene::SMeshBuffer* Buffer;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "SMeshBuffer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,
|
||||
//! which always looks to the camera.
|
||||
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));
|
||||
|
||||
virtual ~CBillboardSceneNode();
|
||||
|
||||
//! pre render event
|
||||
void OnRegisterSceneNode() override;
|
||||
|
||||
//! render
|
||||
void render() override;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& getBoundingBox() const override;
|
||||
|
||||
//! sets the size of the billboard
|
||||
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;
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Get the amount of mesh buffers.
|
||||
u32 getMeshBufferCount() const override
|
||||
{
|
||||
return Buffer ? 1 : 0;
|
||||
}
|
||||
|
||||
//! Get pointer to the mesh buffer.
|
||||
IMeshBuffer* getMeshBuffer(u32 nr) const override
|
||||
{
|
||||
if ( nr == 0 )
|
||||
return Buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Returns type of the scene node
|
||||
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;
|
||||
|
||||
protected:
|
||||
void updateMesh(const irr::scene::ICameraSceneNode* camera);
|
||||
|
||||
private:
|
||||
|
||||
//! Size.Width is the bottom edge width
|
||||
core::dimension2d<f32> Size;
|
||||
f32 TopEdgeWidth;
|
||||
|
||||
//! BoundingBox which is large enough to contain the billboard independent of the camera
|
||||
// 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. */
|
||||
core::aabbox3d<f32> BBoxSafe;
|
||||
|
||||
scene::SMeshBuffer* Buffer;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,97 +1,97 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
u32 boneIndex, const c8* boneName)
|
||||
: IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex),
|
||||
AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBoneSceneNode");
|
||||
#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)
|
||||
{
|
||||
AnimationMode = 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
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CBoneSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return core::matrix4(); // RelativeTransformation;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void CBoneSceneNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
// update absolute position
|
||||
//updateAbsolutePosition();
|
||||
|
||||
// perform the post render process on all children
|
||||
ISceneNodeList::iterator it = Children.begin();
|
||||
for (; it != Children.end(); ++it)
|
||||
(*it)->OnAnimate(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) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( this );
|
||||
}
|
||||
|
||||
|
||||
} // namespace scene
|
||||
} // namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
u32 boneIndex, const c8* boneName)
|
||||
: IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex),
|
||||
AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBoneSceneNode");
|
||||
#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)
|
||||
{
|
||||
AnimationMode = 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
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CBoneSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return core::matrix4(); // RelativeTransformation;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void CBoneSceneNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
// update absolute position
|
||||
//updateAbsolutePosition();
|
||||
|
||||
// perform the post render process on all children
|
||||
ISceneNodeList::iterator it = Children.begin();
|
||||
for (; it != Children.end(); ++it)
|
||||
(*it)->OnAnimate(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) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( this );
|
||||
}
|
||||
|
||||
|
||||
} // namespace scene
|
||||
} // namespace irr
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
// Used with SkinnedMesh and IAnimatedMeshSceneNode, for boned meshes
|
||||
|
||||
#include "IBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CBoneSceneNode : public IBoneSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id=-1, u32 boneIndex=0, const c8* boneName=0);
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 relative transformation of the scene node.
|
||||
//core::matrix4 getRelativeTransformation() const override;
|
||||
*/
|
||||
|
||||
void OnAnimate(u32 timeMs) override;
|
||||
|
||||
void updateAbsolutePositionOfAllChildren() override;
|
||||
|
||||
//! 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;
|
||||
}
|
||||
|
||||
private:
|
||||
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
|
||||
|
||||
u32 BoneIndex;
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
|
||||
E_BONE_ANIMATION_MODE AnimationMode;
|
||||
E_BONE_SKINNING_SPACE SkinningSpace;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
// Used with SkinnedMesh and IAnimatedMeshSceneNode, for boned meshes
|
||||
|
||||
#include "IBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CBoneSceneNode : public IBoneSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id=-1, u32 boneIndex=0, const c8* boneName=0);
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 relative transformation of the scene node.
|
||||
//core::matrix4 getRelativeTransformation() const override;
|
||||
*/
|
||||
|
||||
void OnAnimate(u32 timeMs) override;
|
||||
|
||||
void updateAbsolutePositionOfAllChildren() override;
|
||||
|
||||
//! 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;
|
||||
}
|
||||
|
||||
private:
|
||||
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
|
||||
|
||||
u32 BoneIndex;
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
|
||||
E_BONE_ANIMATION_MODE AnimationMode;
|
||||
E_BONE_SKINNING_SPACE SkinningSpace;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
@@ -1,350 +1,350 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CCameraSceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCameraSceneNode");
|
||||
#endif
|
||||
|
||||
// set default projection
|
||||
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 )
|
||||
Aspect = (f32)d->getCurrentRenderTargetSize().Width /
|
||||
(f32)d->getCurrentRenderTargetSize().Height;
|
||||
}
|
||||
|
||||
ViewArea.setFarNearDistance(ZFar - ZNear);
|
||||
recalculateProjectionMatrix();
|
||||
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)
|
||||
{
|
||||
IsOrthogonal = isOrthogonal;
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
Affector = affector;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the custom view matrix affector.
|
||||
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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
Target = pos;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
return Target;
|
||||
}
|
||||
|
||||
|
||||
//! sets the up vector of the camera
|
||||
//! \param pos: New upvector of the camera.
|
||||
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
|
||||
{
|
||||
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;
|
||||
recalculateProjectionMatrix();
|
||||
ViewArea.setFarNearDistance(ZFar - ZNear);
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setFarValue(f32 f)
|
||||
{
|
||||
ZFar = f;
|
||||
recalculateProjectionMatrix();
|
||||
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);
|
||||
IsOrthogonal = false;
|
||||
}
|
||||
|
||||
|
||||
//! prerender
|
||||
void CCameraSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
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) );
|
||||
}
|
||||
}
|
||||
|
||||
//! update
|
||||
void CCameraSceneNode::updateMatrices()
|
||||
{
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
core::vector3df tgtv = Target - pos;
|
||||
tgtv.normalize();
|
||||
|
||||
// if upvector and vector to the target are the same, we have a
|
||||
// problem. so solve this problem:
|
||||
core::vector3df up = UpVector;
|
||||
up.normalize();
|
||||
|
||||
f32 dp = tgtv.dotProduct(up);
|
||||
|
||||
if ( core::equals(core::abs_<f32>(dp), 1.f) )
|
||||
{
|
||||
up.X += 0.5f;
|
||||
}
|
||||
|
||||
ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up);
|
||||
ViewArea.getTransform(video::ETS_VIEW) *= Affector;
|
||||
recalculateViewArea();
|
||||
}
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CCameraSceneNode::getBoundingBox() const
|
||||
{
|
||||
return BoundingBox;
|
||||
}
|
||||
|
||||
|
||||
//! returns the view frustum.
|
||||
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.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)
|
||||
{
|
||||
ICameraSceneNode::clone(newParent, newManager);
|
||||
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CCameraSceneNode* nb = new CCameraSceneNode(newParent,
|
||||
newManager, ID, RelativeTranslation, Target);
|
||||
|
||||
nb->ISceneNode::cloneMembers(this, newManager);
|
||||
nb->ICameraSceneNode::cloneMembers(this);
|
||||
|
||||
nb->Target = Target;
|
||||
nb->UpVector = UpVector;
|
||||
nb->Fovy = Fovy;
|
||||
nb->Aspect = Aspect;
|
||||
nb->ZNear = ZNear;
|
||||
nb->ZFar = ZFar;
|
||||
nb->ViewArea = ViewArea;
|
||||
nb->Affector = Affector;
|
||||
nb->InputReceiverEnabled = InputReceiverEnabled;
|
||||
nb->TargetAndRotationAreBound = TargetAndRotationAreBound;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CCameraSceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCameraSceneNode");
|
||||
#endif
|
||||
|
||||
// set default projection
|
||||
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 )
|
||||
Aspect = (f32)d->getCurrentRenderTargetSize().Width /
|
||||
(f32)d->getCurrentRenderTargetSize().Height;
|
||||
}
|
||||
|
||||
ViewArea.setFarNearDistance(ZFar - ZNear);
|
||||
recalculateProjectionMatrix();
|
||||
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)
|
||||
{
|
||||
IsOrthogonal = isOrthogonal;
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
Affector = affector;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the custom view matrix affector.
|
||||
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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
Target = pos;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
return Target;
|
||||
}
|
||||
|
||||
|
||||
//! sets the up vector of the camera
|
||||
//! \param pos: New upvector of the camera.
|
||||
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
|
||||
{
|
||||
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;
|
||||
recalculateProjectionMatrix();
|
||||
ViewArea.setFarNearDistance(ZFar - ZNear);
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setFarValue(f32 f)
|
||||
{
|
||||
ZFar = f;
|
||||
recalculateProjectionMatrix();
|
||||
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);
|
||||
IsOrthogonal = false;
|
||||
}
|
||||
|
||||
|
||||
//! prerender
|
||||
void CCameraSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
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) );
|
||||
}
|
||||
}
|
||||
|
||||
//! update
|
||||
void CCameraSceneNode::updateMatrices()
|
||||
{
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
core::vector3df tgtv = Target - pos;
|
||||
tgtv.normalize();
|
||||
|
||||
// if upvector and vector to the target are the same, we have a
|
||||
// problem. so solve this problem:
|
||||
core::vector3df up = UpVector;
|
||||
up.normalize();
|
||||
|
||||
f32 dp = tgtv.dotProduct(up);
|
||||
|
||||
if ( core::equals(core::abs_<f32>(dp), 1.f) )
|
||||
{
|
||||
up.X += 0.5f;
|
||||
}
|
||||
|
||||
ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up);
|
||||
ViewArea.getTransform(video::ETS_VIEW) *= Affector;
|
||||
recalculateViewArea();
|
||||
}
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CCameraSceneNode::getBoundingBox() const
|
||||
{
|
||||
return BoundingBox;
|
||||
}
|
||||
|
||||
|
||||
//! returns the view frustum.
|
||||
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.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)
|
||||
{
|
||||
ICameraSceneNode::clone(newParent, newManager);
|
||||
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CCameraSceneNode* nb = new CCameraSceneNode(newParent,
|
||||
newManager, ID, RelativeTranslation, Target);
|
||||
|
||||
nb->ISceneNode::cloneMembers(this, newManager);
|
||||
nb->ICameraSceneNode::cloneMembers(this);
|
||||
|
||||
nb->Target = Target;
|
||||
nb->UpVector = UpVector;
|
||||
nb->Fovy = Fovy;
|
||||
nb->Aspect = Aspect;
|
||||
nb->ZNear = ZNear;
|
||||
nb->ZFar = ZFar;
|
||||
nb->ViewArea = ViewArea;
|
||||
nb->Affector = Affector;
|
||||
nb->InputReceiverEnabled = InputReceiverEnabled;
|
||||
nb->TargetAndRotationAreBound = TargetAndRotationAreBound;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
|
||||
@@ -1,167 +1,167 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "SViewFrustum.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
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));
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! 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 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 field of view (Default: PI / 3.5f)
|
||||
void setFOV(f32 fovy) override;
|
||||
|
||||
//! PreRender event
|
||||
void OnRegisterSceneNode() override;
|
||||
|
||||
//! Render
|
||||
void render() override;
|
||||
|
||||
//! Update
|
||||
void updateMatrices() 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;
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
protected:
|
||||
|
||||
void recalculateProjectionMatrix();
|
||||
void recalculateViewArea();
|
||||
|
||||
core::aabbox3d<f32> BoundingBox;
|
||||
|
||||
core::vector3df Target;
|
||||
core::vector3df UpVector;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "SViewFrustum.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
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));
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! 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 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 field of view (Default: PI / 3.5f)
|
||||
void setFOV(f32 fovy) override;
|
||||
|
||||
//! PreRender event
|
||||
void OnRegisterSceneNode() override;
|
||||
|
||||
//! Render
|
||||
void render() override;
|
||||
|
||||
//! Update
|
||||
void updateMatrices() 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;
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
protected:
|
||||
|
||||
void recalculateProjectionMatrix();
|
||||
void recalculateViewArea();
|
||||
|
||||
core::aabbox3d<f32> BoundingBox;
|
||||
|
||||
core::vector3df Target;
|
||||
core::vector3df UpVector;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,98 +1,98 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrTypes.h"
|
||||
#include "IImage.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
|
||||
//! Functions for converting one image format to another efficiently
|
||||
//! and hopefully correctly.
|
||||
//! Note that the format descriptions refer to the ECOLOR_FORMAT's and not to memory layout.
|
||||
//! Reasons for that go back to DX9 naming which tended to flip 32-bit and 16-bit byte orders so ARGB usually means BGRA.
|
||||
//!
|
||||
//! \param sP pointer to source pixel data
|
||||
//! \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_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_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
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrTypes.h"
|
||||
#include "IImage.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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);
|
||||
|
||||
|
||||
//! Functions for converting one image format to another efficiently
|
||||
//! and hopefully correctly.
|
||||
//! Note that the format descriptions refer to the ECOLOR_FORMAT's and not to memory layout.
|
||||
//! Reasons for that go back to DX9 naming which tended to flip 32-bit and 16-bit byte orders so ARGB usually means BGRA.
|
||||
//!
|
||||
//! \param sP pointer to source pixel data
|
||||
//! \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_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_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
|
||||
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDummyTransformationSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CDummyTransformationSceneNode::CDummyTransformationSceneNode(
|
||||
ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: IDummyTransformationSceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDummyTransformationSceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
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()
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CDummyTransformationSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CDummyTransformationSceneNode* nb = new CDummyTransformationSceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->RelativeTransformationMatrix = RelativeTransformationMatrix;
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setScale() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeScale = scale;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setRotation() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeRotation = rotation;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setPosition() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeTranslation = newpos;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDummyTransformationSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CDummyTransformationSceneNode::CDummyTransformationSceneNode(
|
||||
ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: IDummyTransformationSceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDummyTransformationSceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
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()
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CDummyTransformationSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CDummyTransformationSceneNode* nb = new CDummyTransformationSceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->RelativeTransformationMatrix = RelativeTransformationMatrix;
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setScale() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeScale = scale;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setRotation() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeRotation = rotation;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setPosition() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeTranslation = newpos;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CDummyTransformationSceneNode : public IDummyTransformationSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! does nothing.
|
||||
void render() override {}
|
||||
|
||||
//! 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;
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CDummyTransformationSceneNode : public IDummyTransformationSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! 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 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;
|
||||
|
||||
//! does nothing.
|
||||
void render() override {}
|
||||
|
||||
//! 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;
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,111 +1,111 @@
|
||||
// Copyright (C) 2013 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "SExposedVideoData.h"
|
||||
#include "IContextManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// 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
|
||||
{
|
||||
//! 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2013 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "SExposedVideoData.h"
|
||||
#include "IContextManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// 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
|
||||
{
|
||||
//! 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CEmptySceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode::CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: ISceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CEmptySceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void CEmptySceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CEmptySceneNode::render()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
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)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CEmptySceneNode* nb = new CEmptySceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CEmptySceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode::CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: ISceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CEmptySceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void CEmptySceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CEmptySceneNode::render()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
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)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CEmptySceneNode* nb = new CEmptySceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ISceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CEmptySceneNode : public ISceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
|
||||
|
||||
//! 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;
|
||||
|
||||
//! does nothing.
|
||||
void render() override;
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ISceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CEmptySceneNode : public ISceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
|
||||
|
||||
//! 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;
|
||||
|
||||
//! does nothing.
|
||||
void render() override;
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,76 +1,76 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFPSCounter.h"
|
||||
#include "irrMath.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
++FramesCounted;
|
||||
PrimitiveTotal += primitivesDrawn;
|
||||
PrimitivesCounted += primitivesDrawn;
|
||||
Primitive = primitivesDrawn;
|
||||
|
||||
const u32 milliseconds = now - StartTime;
|
||||
|
||||
if (milliseconds >= 1500 )
|
||||
{
|
||||
const f32 invMilli = core::reciprocal ( (f32) milliseconds );
|
||||
|
||||
FPS = core::ceil32 ( ( 1000 * FramesCounted ) * invMilli );
|
||||
PrimitiveAverage = core::ceil32 ( ( 1000 * PrimitivesCounted ) * invMilli );
|
||||
|
||||
FramesCounted = 0;
|
||||
PrimitivesCounted = 0;
|
||||
StartTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFPSCounter.h"
|
||||
#include "irrMath.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
++FramesCounted;
|
||||
PrimitiveTotal += primitivesDrawn;
|
||||
PrimitivesCounted += primitivesDrawn;
|
||||
Primitive = primitivesDrawn;
|
||||
|
||||
const u32 milliseconds = now - StartTime;
|
||||
|
||||
if (milliseconds >= 1500 )
|
||||
{
|
||||
const f32 invMilli = core::reciprocal ( (f32) milliseconds );
|
||||
|
||||
FPS = core::ceil32 ( ( 1000 * FramesCounted ) * invMilli );
|
||||
PrimitiveAverage = core::ceil32 ( ( 1000 * PrimitivesCounted ) * invMilli );
|
||||
|
||||
FramesCounted = 0;
|
||||
PrimitivesCounted = 0;
|
||||
StartTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
class CFPSCounter
|
||||
{
|
||||
public:
|
||||
CFPSCounter();
|
||||
|
||||
//! returns current fps
|
||||
s32 getFPS() const;
|
||||
|
||||
//! returns primitive count
|
||||
u32 getPrimitive() const;
|
||||
|
||||
//! returns average primitive count of last period
|
||||
u32 getPrimitiveAverage() const;
|
||||
|
||||
//! returns accumulated primitive count since start
|
||||
u32 getPrimitiveTotal() const;
|
||||
|
||||
//! to be called every frame
|
||||
void registerFrame(u32 now, u32 primitive);
|
||||
|
||||
private:
|
||||
|
||||
s32 FPS;
|
||||
u32 Primitive;
|
||||
u32 StartTime;
|
||||
|
||||
u32 FramesCounted;
|
||||
u32 PrimitivesCounted;
|
||||
u32 PrimitiveAverage;
|
||||
u32 PrimitiveTotal;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
class CFPSCounter
|
||||
{
|
||||
public:
|
||||
CFPSCounter();
|
||||
|
||||
//! returns current fps
|
||||
s32 getFPS() const;
|
||||
|
||||
//! returns primitive count
|
||||
u32 getPrimitive() const;
|
||||
|
||||
//! returns average primitive count of last period
|
||||
u32 getPrimitiveAverage() const;
|
||||
|
||||
//! returns accumulated primitive count since start
|
||||
u32 getPrimitiveTotal() const;
|
||||
|
||||
//! to be called every frame
|
||||
void registerFrame(u32 now, u32 primitive);
|
||||
|
||||
private:
|
||||
|
||||
s32 FPS;
|
||||
u32 Primitive;
|
||||
u32 StartTime;
|
||||
|
||||
u32 FramesCounted;
|
||||
u32 PrimitivesCounted;
|
||||
u32 PrimitiveAverage;
|
||||
u32 PrimitiveTotal;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,162 +1,162 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFileList.h"
|
||||
#include "irrArray.h"
|
||||
#include "coreutil.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
static const io::path emptyFileListEntry;
|
||||
|
||||
CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
|
||||
: IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CFileList");
|
||||
#endif
|
||||
|
||||
Path.replace('\\', '/');
|
||||
}
|
||||
|
||||
CFileList::~CFileList()
|
||||
{
|
||||
Files.clear();
|
||||
}
|
||||
|
||||
u32 CFileList::getFileCount() const
|
||||
{
|
||||
return Files.size();
|
||||
}
|
||||
|
||||
void CFileList::sort()
|
||||
{
|
||||
Files.sort();
|
||||
}
|
||||
|
||||
const io::path& CFileList::getFileName(u32 index) const
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
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
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
return Files[index].FullName;
|
||||
}
|
||||
|
||||
//! adds a file or folder
|
||||
u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id)
|
||||
{
|
||||
SFileListEntry entry;
|
||||
entry.ID = id ? id : Files.size();
|
||||
entry.Offset = offset;
|
||||
entry.Size = size;
|
||||
entry.Name = fullPath;
|
||||
entry.Name.replace('\\', '/');
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.Name.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.Name[entry.Name.size()-1] = 0;
|
||||
entry.Name.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.Name.make_lower();
|
||||
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
core::deletePathFromFilename(entry.Name);
|
||||
|
||||
if (IgnorePaths)
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
//os::Printer::log(Path.c_str(), entry.FullName);
|
||||
|
||||
Files.push_back(entry);
|
||||
|
||||
return Files.size() - 1;
|
||||
}
|
||||
|
||||
//! Returns the ID of a file in the file list, based on an index.
|
||||
u32 CFileList::getID(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].ID : 0;
|
||||
}
|
||||
|
||||
bool CFileList::isDirectory(u32 index) const
|
||||
{
|
||||
bool ret = false;
|
||||
if (index < Files.size())
|
||||
ret = Files[index].IsDirectory;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 CFileList::getFileSize(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].Size : 0;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
SFileListEntry entry;
|
||||
// we only need FullName to be set for the search
|
||||
entry.FullName = filename;
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// exchange
|
||||
entry.FullName.replace('\\', '/');
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.FullName.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.FullName[entry.FullName.size()-1] = 0;
|
||||
entry.FullName.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.FullName.make_lower();
|
||||
|
||||
if (IgnorePaths)
|
||||
core::deletePathFromFilename(entry.FullName);
|
||||
|
||||
return Files.binary_search(entry);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the base path of the file list
|
||||
const io::path& CFileList::getPath() const
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFileList.h"
|
||||
#include "irrArray.h"
|
||||
#include "coreutil.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
static const io::path emptyFileListEntry;
|
||||
|
||||
CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
|
||||
: IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CFileList");
|
||||
#endif
|
||||
|
||||
Path.replace('\\', '/');
|
||||
}
|
||||
|
||||
CFileList::~CFileList()
|
||||
{
|
||||
Files.clear();
|
||||
}
|
||||
|
||||
u32 CFileList::getFileCount() const
|
||||
{
|
||||
return Files.size();
|
||||
}
|
||||
|
||||
void CFileList::sort()
|
||||
{
|
||||
Files.sort();
|
||||
}
|
||||
|
||||
const io::path& CFileList::getFileName(u32 index) const
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
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
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
return Files[index].FullName;
|
||||
}
|
||||
|
||||
//! adds a file or folder
|
||||
u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id)
|
||||
{
|
||||
SFileListEntry entry;
|
||||
entry.ID = id ? id : Files.size();
|
||||
entry.Offset = offset;
|
||||
entry.Size = size;
|
||||
entry.Name = fullPath;
|
||||
entry.Name.replace('\\', '/');
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.Name.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.Name[entry.Name.size()-1] = 0;
|
||||
entry.Name.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.Name.make_lower();
|
||||
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
core::deletePathFromFilename(entry.Name);
|
||||
|
||||
if (IgnorePaths)
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
//os::Printer::log(Path.c_str(), entry.FullName);
|
||||
|
||||
Files.push_back(entry);
|
||||
|
||||
return Files.size() - 1;
|
||||
}
|
||||
|
||||
//! Returns the ID of a file in the file list, based on an index.
|
||||
u32 CFileList::getID(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].ID : 0;
|
||||
}
|
||||
|
||||
bool CFileList::isDirectory(u32 index) const
|
||||
{
|
||||
bool ret = false;
|
||||
if (index < Files.size())
|
||||
ret = Files[index].IsDirectory;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 CFileList::getFileSize(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].Size : 0;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
SFileListEntry entry;
|
||||
// we only need FullName to be set for the search
|
||||
entry.FullName = filename;
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// exchange
|
||||
entry.FullName.replace('\\', '/');
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.FullName.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.FullName[entry.FullName.size()-1] = 0;
|
||||
entry.FullName.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.FullName.make_lower();
|
||||
|
||||
if (IgnorePaths)
|
||||
core::deletePathFromFilename(entry.FullName);
|
||||
|
||||
return Files.binary_search(entry);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the base path of the file list
|
||||
const io::path& CFileList::getPath() const
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
|
||||
@@ -1,133 +1,133 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IFileList.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
//! An entry in a list of files, can be a folder or a file.
|
||||
struct SFileListEntry
|
||||
{
|
||||
//! The name of the file
|
||||
/** If this is a file or folder in the virtual filesystem and the archive
|
||||
was created with the ignoreCase flag then the file name will be lower case. */
|
||||
io::path Name;
|
||||
|
||||
//! The name of the file including the path
|
||||
/** If this is a file or folder in the virtual filesystem and the archive was
|
||||
created with the ignoreDirs flag then it will be the same as Name. */
|
||||
io::path FullName;
|
||||
|
||||
//! The size of the file in bytes
|
||||
u32 Size;
|
||||
|
||||
//! The ID of the file in an archive
|
||||
/** This is used to link the FileList entry to extra info held about this
|
||||
file in an archive, which can hold things like data offset and CRC. */
|
||||
u32 ID;
|
||||
|
||||
//! FileOffset inside an archive
|
||||
u32 Offset;
|
||||
|
||||
//! True if this is a folder, false if not.
|
||||
bool IsDirectory;
|
||||
|
||||
//! The == operator is provided so that CFileList can slowly search the list!
|
||||
bool operator ==(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return false;
|
||||
|
||||
return FullName.equals_ignore_case(other.FullName);
|
||||
}
|
||||
|
||||
//! The < operator is provided so that CFileList can sort and quickly search the list.
|
||||
bool operator <(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return IsDirectory;
|
||||
|
||||
return FullName.lower_ignore_case(other.FullName);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! 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);
|
||||
|
||||
//! Destructor
|
||||
virtual ~CFileList();
|
||||
|
||||
//! Add as a file or folder to the list
|
||||
/** \param fullPath The file name including path, up to the root of the file list.
|
||||
\param isDirectory True if this is a directory rather than a file.
|
||||
\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;
|
||||
|
||||
//! Sorts the file list. You should call this after adding any items to the file list
|
||||
void sort() override;
|
||||
|
||||
//! Returns the amount of files in the filelist.
|
||||
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;
|
||||
|
||||
//! Gets the full name of a file in the list, path included, based on an index.
|
||||
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;
|
||||
|
||||
//! Returns true if the file is a directory
|
||||
bool isDirectory(u32 index) const override;
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 getFileSize(u32 index) const override;
|
||||
|
||||
//! Returns the offset of a file
|
||||
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;
|
||||
|
||||
//! Returns the base path of the file list
|
||||
const io::path& getPath() const override;
|
||||
|
||||
protected:
|
||||
|
||||
//! Ignore paths when adding or searching for files
|
||||
bool IgnorePaths;
|
||||
|
||||
//! Ignore case when adding or searching for files
|
||||
bool IgnoreCase;
|
||||
|
||||
//! Path to the file list
|
||||
io::path Path;
|
||||
|
||||
//! List of files
|
||||
core::array<SFileListEntry> Files;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IFileList.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
//! An entry in a list of files, can be a folder or a file.
|
||||
struct SFileListEntry
|
||||
{
|
||||
//! The name of the file
|
||||
/** If this is a file or folder in the virtual filesystem and the archive
|
||||
was created with the ignoreCase flag then the file name will be lower case. */
|
||||
io::path Name;
|
||||
|
||||
//! The name of the file including the path
|
||||
/** If this is a file or folder in the virtual filesystem and the archive was
|
||||
created with the ignoreDirs flag then it will be the same as Name. */
|
||||
io::path FullName;
|
||||
|
||||
//! The size of the file in bytes
|
||||
u32 Size;
|
||||
|
||||
//! The ID of the file in an archive
|
||||
/** This is used to link the FileList entry to extra info held about this
|
||||
file in an archive, which can hold things like data offset and CRC. */
|
||||
u32 ID;
|
||||
|
||||
//! FileOffset inside an archive
|
||||
u32 Offset;
|
||||
|
||||
//! True if this is a folder, false if not.
|
||||
bool IsDirectory;
|
||||
|
||||
//! The == operator is provided so that CFileList can slowly search the list!
|
||||
bool operator ==(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return false;
|
||||
|
||||
return FullName.equals_ignore_case(other.FullName);
|
||||
}
|
||||
|
||||
//! The < operator is provided so that CFileList can sort and quickly search the list.
|
||||
bool operator <(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return IsDirectory;
|
||||
|
||||
return FullName.lower_ignore_case(other.FullName);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! 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);
|
||||
|
||||
//! Destructor
|
||||
virtual ~CFileList();
|
||||
|
||||
//! Add as a file or folder to the list
|
||||
/** \param fullPath The file name including path, up to the root of the file list.
|
||||
\param isDirectory True if this is a directory rather than a file.
|
||||
\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;
|
||||
|
||||
//! Sorts the file list. You should call this after adding any items to the file list
|
||||
void sort() override;
|
||||
|
||||
//! Returns the amount of files in the filelist.
|
||||
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;
|
||||
|
||||
//! Gets the full name of a file in the list, path included, based on an index.
|
||||
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;
|
||||
|
||||
//! Returns true if the file is a directory
|
||||
bool isDirectory(u32 index) const override;
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 getFileSize(u32 index) const override;
|
||||
|
||||
//! Returns the offset of a file
|
||||
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;
|
||||
|
||||
//! Returns the base path of the file list
|
||||
const io::path& getPath() const override;
|
||||
|
||||
protected:
|
||||
|
||||
//! Ignore paths when adding or searching for files
|
||||
bool IgnorePaths;
|
||||
|
||||
//! Ignore case when adding or searching for files
|
||||
bool IgnoreCase;
|
||||
|
||||
//! Path to the file list
|
||||
io::path Path;
|
||||
|
||||
//! List of files
|
||||
core::array<SFileListEntry> Files;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,141 +1,141 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IFileSystem.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class CZipReader;
|
||||
|
||||
/*!
|
||||
FileSystem which uses normal files and one zipfile
|
||||
*/
|
||||
class CFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CFileSystem();
|
||||
|
||||
//! destructor
|
||||
virtual ~CFileSystem();
|
||||
|
||||
//! opens a file for read access
|
||||
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;
|
||||
|
||||
//! Creates an IReadFile interface for accessing files inside files
|
||||
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;
|
||||
|
||||
//! Opens a file for write access.
|
||||
IWriteFile* createAndWriteFile(const io::path& filename, bool append=false) override;
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
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;
|
||||
|
||||
//! Returns the total number of archive loaders added.
|
||||
u32 getArchiveLoaderCount() const override;
|
||||
|
||||
//! Gets the archive loader by index.
|
||||
IArchiveLoader* getArchiveLoader(u32 index) const override;
|
||||
|
||||
//! gets the file archive count
|
||||
u32 getFileArchiveCount() const override;
|
||||
|
||||
//! gets an archive
|
||||
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;
|
||||
|
||||
//! Removes an archive from the file system.
|
||||
bool removeFileArchive(const IFileArchive* archive) override;
|
||||
|
||||
//! Returns the string of the current working directory
|
||||
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;
|
||||
|
||||
//! Converts a relative path to an absolute (unique) path, resolving symbolic links
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! flatten a path and file name for example: "/you/me/../." becomes "/you"
|
||||
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;
|
||||
|
||||
EFileSystemType setFileListSystem(EFileSystemType listType) override;
|
||||
|
||||
//! Creates a list of files and directories in the current working directory
|
||||
//! and returns it.
|
||||
IFileList* createFileList() override;
|
||||
|
||||
//! Creates an empty filelist
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
//! Currently used FileSystemType
|
||||
EFileSystemType FileSystemType;
|
||||
//! WorkingDirectory for Native and Virtual filesystems
|
||||
io::path WorkingDirectory [2];
|
||||
//! currently attached ArchiveLoaders
|
||||
core::array<IArchiveLoader*> ArchiveLoader;
|
||||
//! currently attached Archives
|
||||
core::array<IFileArchive*> FileArchives;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IFileSystem.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class CZipReader;
|
||||
|
||||
/*!
|
||||
FileSystem which uses normal files and one zipfile
|
||||
*/
|
||||
class CFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CFileSystem();
|
||||
|
||||
//! destructor
|
||||
virtual ~CFileSystem();
|
||||
|
||||
//! opens a file for read access
|
||||
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;
|
||||
|
||||
//! Creates an IReadFile interface for accessing files inside files
|
||||
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;
|
||||
|
||||
//! Opens a file for write access.
|
||||
IWriteFile* createAndWriteFile(const io::path& filename, bool append=false) override;
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
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;
|
||||
|
||||
//! Returns the total number of archive loaders added.
|
||||
u32 getArchiveLoaderCount() const override;
|
||||
|
||||
//! Gets the archive loader by index.
|
||||
IArchiveLoader* getArchiveLoader(u32 index) const override;
|
||||
|
||||
//! gets the file archive count
|
||||
u32 getFileArchiveCount() const override;
|
||||
|
||||
//! gets an archive
|
||||
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;
|
||||
|
||||
//! Removes an archive from the file system.
|
||||
bool removeFileArchive(const IFileArchive* archive) override;
|
||||
|
||||
//! Returns the string of the current working directory
|
||||
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;
|
||||
|
||||
//! Converts a relative path to an absolute (unique) path, resolving symbolic links
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! flatten a path and file name for example: "/you/me/../." becomes "/you"
|
||||
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;
|
||||
|
||||
EFileSystemType setFileListSystem(EFileSystemType listType) override;
|
||||
|
||||
//! Creates a list of files and directories in the current working directory
|
||||
//! and returns it.
|
||||
IFileList* createFileList() override;
|
||||
|
||||
//! Creates an empty filelist
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
//! Currently used FileSystemType
|
||||
EFileSystemType FileSystemType;
|
||||
//! WorkingDirectory for Native and Virtual filesystems
|
||||
io::path WorkingDirectory [2];
|
||||
//! currently attached ArchiveLoaders
|
||||
core::array<IArchiveLoader*> ArchiveLoader;
|
||||
//! currently attached Archives
|
||||
core::array<IFileArchive*> FileArchives;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
@@ -1,482 +1,482 @@
|
||||
// Copyright (C) 2013 Christian Stehno
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#include "CGLXManager.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GLX_MANAGER_
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#define GL_GLEXT_LEGACY 1
|
||||
#define GLX_GLXEXT_LEGACY 1
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#define GLX_GLXEXT_PROTOTYPES 1
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glxext.h>
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
CGLXManager::CGLXManager(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata, int screennr)
|
||||
: Params(params), PrimaryContext(videodata), VisualInfo(0), glxFBConfig(0), GlxWin(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGLXManager");
|
||||
#endif
|
||||
|
||||
CurrentContext.OpenGLLinux.X11Display=PrimaryContext.OpenGLLinux.X11Display;
|
||||
|
||||
int major, minor;
|
||||
Display* display = (Display*)PrimaryContext.OpenGLLinux.X11Display;
|
||||
const bool isAvailableGLX=glXQueryExtension(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);
|
||||
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXChooseFBConfig"));
|
||||
#else
|
||||
PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig=glXChooseFBConfig;
|
||||
#endif
|
||||
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,
|
||||
#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
|
||||
#elif defined(GLX_ARB_multisample)
|
||||
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
|
||||
#endif
|
||||
//#ifdef GL_ARB_framebuffer_sRGB
|
||||
// GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, Params.HandleSRGB,
|
||||
//#elif defined(GL_EXT_framebuffer_sRGB)
|
||||
// GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, Params.HandleSRGB,
|
||||
//#endif
|
||||
GLX_STEREO, Params.Stereobuffer?True:False,
|
||||
None
|
||||
};
|
||||
|
||||
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))
|
||||
{
|
||||
visualAttrBuffer[19] -= 1;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
}
|
||||
if (!configList)
|
||||
{
|
||||
visualAttrBuffer[17] = 0;
|
||||
visualAttrBuffer[19] = 0;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
if (configList)
|
||||
{
|
||||
os::Printer::log("No FSAA available.", ELL_WARNING);
|
||||
Params.AntiAlias=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reenable multisampling
|
||||
visualAttrBuffer[17] = 1;
|
||||
visualAttrBuffer[19] = Params.AntiAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next try with flipped stencil buffer value
|
||||
// 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 (Params.Stencilbuffer)
|
||||
os::Printer::log("No stencilbuffer available, disabling stencil shadows.", ELL_WARNING);
|
||||
Params.Stencilbuffer = !Params.Stencilbuffer;
|
||||
visualAttrBuffer[15]=Params.Stencilbuffer?1: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);
|
||||
}
|
||||
if (!configList)
|
||||
{
|
||||
visualAttrBuffer[17] = 0;
|
||||
visualAttrBuffer[19] = 0;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
if (configList)
|
||||
{
|
||||
os::Printer::log("No FSAA available.", ELL_WARNING);
|
||||
Params.AntiAlias=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reenable multisampling
|
||||
visualAttrBuffer[17] = 1;
|
||||
visualAttrBuffer[19] = Params.AntiAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next try without double buffer
|
||||
if (!configList && Params.Doublebuffer)
|
||||
{
|
||||
os::Printer::log("No doublebuffering available.", ELL_WARNING);
|
||||
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[19] -= 1;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
}
|
||||
if (!configList)
|
||||
{
|
||||
visualAttrBuffer[17] = 0;
|
||||
visualAttrBuffer[19] = 0;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
if (configList)
|
||||
{
|
||||
os::Printer::log("No FSAA available.", ELL_WARNING);
|
||||
Params.AntiAlias=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reenable multisampling
|
||||
visualAttrBuffer[17] = 1;
|
||||
visualAttrBuffer[19] = Params.AntiAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (configList)
|
||||
{
|
||||
glxFBConfig=configList[0];
|
||||
XFree(configList);
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
|
||||
PFNGLXGETVISUALFROMFBCONFIGPROC glxGetVisualFromFBConfig= (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXGetVisualFromFBConfig"));
|
||||
if (glxGetVisualFromFBConfig)
|
||||
VisualInfo = glxGetVisualFromFBConfig(display,(GLXFBConfig)glxFBConfig);
|
||||
#else
|
||||
VisualInfo = glXGetVisualFromFBConfig(display,(GLXFBConfig)glxFBConfig);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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
|
||||
//#ifdef GL_ARB_framebuffer_sRGB
|
||||
// Params.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB:GLX_USE_GL,
|
||||
//#elif defined(GL_EXT_framebuffer_sRGB)
|
||||
// Params.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:GLX_USE_GL,
|
||||
//#endif
|
||||
None
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
VisualInfo=glXChooseVisual(display, screennr, visualAttrBuffer);
|
||||
if (!VisualInfo && Params.Doublebuffer)
|
||||
{
|
||||
os::Printer::log("No doublebuffering available.", ELL_WARNING);
|
||||
Params.Doublebuffer=false;
|
||||
visualAttrBuffer[14] = GLX_USE_GL;
|
||||
VisualInfo=glXChooseVisual(display, screennr, visualAttrBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
os::Printer::log("No GLX support available. OpenGL driver will not work.", ELL_WARNING);
|
||||
}
|
||||
|
||||
CGLXManager::~CGLXManager()
|
||||
{
|
||||
}
|
||||
|
||||
bool CGLXManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata)
|
||||
{
|
||||
// store params
|
||||
Params=params;
|
||||
|
||||
// set display
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLXManager::terminate()
|
||||
{
|
||||
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)
|
||||
{
|
||||
os::Printer::log("Could not create GLX window.", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentContext.OpenGLLinux.GLXWindow=GlxWin;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentContext.OpenGLLinux.GLXWindow=CurrentContext.OpenGLLinux.X11Window;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLXManager::destroySurface()
|
||||
{
|
||||
if (GlxWin)
|
||||
glXDestroyWindow((Display*)CurrentContext.OpenGLLinux.X11Display, GlxWin);
|
||||
}
|
||||
|
||||
#if defined(GLX_ARB_create_context)
|
||||
static int IrrIgnoreError(Display *display, XErrorEvent *event)
|
||||
{
|
||||
char msg[256];
|
||||
XGetErrorText(display, event->error_code, msg, 256);
|
||||
os::Printer::log("Ignoring an X error", msg, ELL_DEBUG);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CGLXManager::generateContext()
|
||||
{
|
||||
GLXContext context = 0;
|
||||
|
||||
if (glxFBConfig)
|
||||
{
|
||||
if (GlxWin)
|
||||
{
|
||||
#if defined(GLX_ARB_create_context)
|
||||
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glxCreateContextAttribsARB=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB"));
|
||||
#else
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glxCreateContextAttribsARB=glXCreateContextAttribsARB;
|
||||
#endif
|
||||
|
||||
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
|
||||
};
|
||||
XErrorHandler old = XSetErrorHandler(IrrIgnoreError);
|
||||
context = glxCreateContextAttribsARB((Display*)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, NULL, True, contextAttrBuffer);
|
||||
XSetErrorHandler(old);
|
||||
// transparently fall back to legacy call
|
||||
}
|
||||
if (!context)
|
||||
#endif
|
||||
{
|
||||
// create glx 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
os::Printer::log("Could not create GLX rendering context.", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CurrentContext.OpenGLLinux.X11Context=context;
|
||||
return true;
|
||||
}
|
||||
|
||||
const SExposedVideoData& CGLXManager::getContext() const
|
||||
{
|
||||
return CurrentContext;
|
||||
}
|
||||
|
||||
bool CGLXManager::activateContext(const SExposedVideoData& videoData, bool 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))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentContext.OpenGLLinux.GLXWindow = videoData.OpenGLLinux.GLXWindow;
|
||||
CurrentContext.OpenGLLinux.X11Window = videoData.OpenGLLinux.X11Window;
|
||||
CurrentContext.OpenGLLinux.X11Display = videoData.OpenGLLinux.X11Display;
|
||||
}
|
||||
}
|
||||
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))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
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))
|
||||
{
|
||||
os::Printer::log("Render Context reset failed.");
|
||||
return false;
|
||||
}
|
||||
CurrentContext.OpenGLLinux.X11Window = 0;
|
||||
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))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentContext = PrimaryContext;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLXManager::destroyContext()
|
||||
{
|
||||
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);
|
||||
}
|
||||
glXDestroyContext((Display*)CurrentContext.OpenGLLinux.X11Display, (GLXContext)CurrentContext.OpenGLLinux.X11Context);
|
||||
}
|
||||
}
|
||||
|
||||
void* CGLXManager::getProcAddress(const std::string &procName)
|
||||
{
|
||||
return (void*)glXGetProcAddressARB(reinterpret_cast<const GLubyte*>(procName.c_str()));
|
||||
}
|
||||
|
||||
bool CGLXManager::swapBuffers()
|
||||
{
|
||||
glXSwapBuffers((Display*)CurrentContext.OpenGLLinux.X11Display, CurrentContext.OpenGLLinux.GLXWindow);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Copyright (C) 2013 Christian Stehno
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#include "CGLXManager.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GLX_MANAGER_
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#define GL_GLEXT_LEGACY 1
|
||||
#define GLX_GLXEXT_LEGACY 1
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#define GLX_GLXEXT_PROTOTYPES 1
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glxext.h>
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
CGLXManager::CGLXManager(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata, int screennr)
|
||||
: Params(params), PrimaryContext(videodata), VisualInfo(0), glxFBConfig(0), GlxWin(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGLXManager");
|
||||
#endif
|
||||
|
||||
CurrentContext.OpenGLLinux.X11Display=PrimaryContext.OpenGLLinux.X11Display;
|
||||
|
||||
int major, minor;
|
||||
Display* display = (Display*)PrimaryContext.OpenGLLinux.X11Display;
|
||||
const bool isAvailableGLX=glXQueryExtension(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);
|
||||
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXChooseFBConfig"));
|
||||
#else
|
||||
PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig=glXChooseFBConfig;
|
||||
#endif
|
||||
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,
|
||||
#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
|
||||
#elif defined(GLX_ARB_multisample)
|
||||
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
|
||||
#endif
|
||||
//#ifdef GL_ARB_framebuffer_sRGB
|
||||
// GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, Params.HandleSRGB,
|
||||
//#elif defined(GL_EXT_framebuffer_sRGB)
|
||||
// GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, Params.HandleSRGB,
|
||||
//#endif
|
||||
GLX_STEREO, Params.Stereobuffer?True:False,
|
||||
None
|
||||
};
|
||||
|
||||
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))
|
||||
{
|
||||
visualAttrBuffer[19] -= 1;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
}
|
||||
if (!configList)
|
||||
{
|
||||
visualAttrBuffer[17] = 0;
|
||||
visualAttrBuffer[19] = 0;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
if (configList)
|
||||
{
|
||||
os::Printer::log("No FSAA available.", ELL_WARNING);
|
||||
Params.AntiAlias=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reenable multisampling
|
||||
visualAttrBuffer[17] = 1;
|
||||
visualAttrBuffer[19] = Params.AntiAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next try with flipped stencil buffer value
|
||||
// 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 (Params.Stencilbuffer)
|
||||
os::Printer::log("No stencilbuffer available, disabling stencil shadows.", ELL_WARNING);
|
||||
Params.Stencilbuffer = !Params.Stencilbuffer;
|
||||
visualAttrBuffer[15]=Params.Stencilbuffer?1: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);
|
||||
}
|
||||
if (!configList)
|
||||
{
|
||||
visualAttrBuffer[17] = 0;
|
||||
visualAttrBuffer[19] = 0;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
if (configList)
|
||||
{
|
||||
os::Printer::log("No FSAA available.", ELL_WARNING);
|
||||
Params.AntiAlias=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reenable multisampling
|
||||
visualAttrBuffer[17] = 1;
|
||||
visualAttrBuffer[19] = Params.AntiAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next try without double buffer
|
||||
if (!configList && Params.Doublebuffer)
|
||||
{
|
||||
os::Printer::log("No doublebuffering available.", ELL_WARNING);
|
||||
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[19] -= 1;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
}
|
||||
if (!configList)
|
||||
{
|
||||
visualAttrBuffer[17] = 0;
|
||||
visualAttrBuffer[19] = 0;
|
||||
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
|
||||
if (configList)
|
||||
{
|
||||
os::Printer::log("No FSAA available.", ELL_WARNING);
|
||||
Params.AntiAlias=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reenable multisampling
|
||||
visualAttrBuffer[17] = 1;
|
||||
visualAttrBuffer[19] = Params.AntiAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (configList)
|
||||
{
|
||||
glxFBConfig=configList[0];
|
||||
XFree(configList);
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
|
||||
PFNGLXGETVISUALFROMFBCONFIGPROC glxGetVisualFromFBConfig= (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXGetVisualFromFBConfig"));
|
||||
if (glxGetVisualFromFBConfig)
|
||||
VisualInfo = glxGetVisualFromFBConfig(display,(GLXFBConfig)glxFBConfig);
|
||||
#else
|
||||
VisualInfo = glXGetVisualFromFBConfig(display,(GLXFBConfig)glxFBConfig);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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
|
||||
//#ifdef GL_ARB_framebuffer_sRGB
|
||||
// Params.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB:GLX_USE_GL,
|
||||
//#elif defined(GL_EXT_framebuffer_sRGB)
|
||||
// Params.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:GLX_USE_GL,
|
||||
//#endif
|
||||
None
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
VisualInfo=glXChooseVisual(display, screennr, visualAttrBuffer);
|
||||
if (!VisualInfo && Params.Doublebuffer)
|
||||
{
|
||||
os::Printer::log("No doublebuffering available.", ELL_WARNING);
|
||||
Params.Doublebuffer=false;
|
||||
visualAttrBuffer[14] = GLX_USE_GL;
|
||||
VisualInfo=glXChooseVisual(display, screennr, visualAttrBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
os::Printer::log("No GLX support available. OpenGL driver will not work.", ELL_WARNING);
|
||||
}
|
||||
|
||||
CGLXManager::~CGLXManager()
|
||||
{
|
||||
}
|
||||
|
||||
bool CGLXManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata)
|
||||
{
|
||||
// store params
|
||||
Params=params;
|
||||
|
||||
// set display
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLXManager::terminate()
|
||||
{
|
||||
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)
|
||||
{
|
||||
os::Printer::log("Could not create GLX window.", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentContext.OpenGLLinux.GLXWindow=GlxWin;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentContext.OpenGLLinux.GLXWindow=CurrentContext.OpenGLLinux.X11Window;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLXManager::destroySurface()
|
||||
{
|
||||
if (GlxWin)
|
||||
glXDestroyWindow((Display*)CurrentContext.OpenGLLinux.X11Display, GlxWin);
|
||||
}
|
||||
|
||||
#if defined(GLX_ARB_create_context)
|
||||
static int IrrIgnoreError(Display *display, XErrorEvent *event)
|
||||
{
|
||||
char msg[256];
|
||||
XGetErrorText(display, event->error_code, msg, 256);
|
||||
os::Printer::log("Ignoring an X error", msg, ELL_DEBUG);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CGLXManager::generateContext()
|
||||
{
|
||||
GLXContext context = 0;
|
||||
|
||||
if (glxFBConfig)
|
||||
{
|
||||
if (GlxWin)
|
||||
{
|
||||
#if defined(GLX_ARB_create_context)
|
||||
|
||||
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glxCreateContextAttribsARB=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB"));
|
||||
#else
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glxCreateContextAttribsARB=glXCreateContextAttribsARB;
|
||||
#endif
|
||||
|
||||
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
|
||||
};
|
||||
XErrorHandler old = XSetErrorHandler(IrrIgnoreError);
|
||||
context = glxCreateContextAttribsARB((Display*)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, NULL, True, contextAttrBuffer);
|
||||
XSetErrorHandler(old);
|
||||
// transparently fall back to legacy call
|
||||
}
|
||||
if (!context)
|
||||
#endif
|
||||
{
|
||||
// create glx 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
os::Printer::log("Could not create GLX rendering context.", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CurrentContext.OpenGLLinux.X11Context=context;
|
||||
return true;
|
||||
}
|
||||
|
||||
const SExposedVideoData& CGLXManager::getContext() const
|
||||
{
|
||||
return CurrentContext;
|
||||
}
|
||||
|
||||
bool CGLXManager::activateContext(const SExposedVideoData& videoData, bool 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))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentContext.OpenGLLinux.GLXWindow = videoData.OpenGLLinux.GLXWindow;
|
||||
CurrentContext.OpenGLLinux.X11Window = videoData.OpenGLLinux.X11Window;
|
||||
CurrentContext.OpenGLLinux.X11Display = videoData.OpenGLLinux.X11Display;
|
||||
}
|
||||
}
|
||||
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))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
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))
|
||||
{
|
||||
os::Printer::log("Render Context reset failed.");
|
||||
return false;
|
||||
}
|
||||
CurrentContext.OpenGLLinux.X11Window = 0;
|
||||
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))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentContext = PrimaryContext;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLXManager::destroyContext()
|
||||
{
|
||||
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);
|
||||
}
|
||||
glXDestroyContext((Display*)CurrentContext.OpenGLLinux.X11Display, (GLXContext)CurrentContext.OpenGLLinux.X11Context);
|
||||
}
|
||||
}
|
||||
|
||||
void* CGLXManager::getProcAddress(const std::string &procName)
|
||||
{
|
||||
return (void*)glXGetProcAddressARB(reinterpret_cast<const GLubyte*>(procName.c_str()));
|
||||
}
|
||||
|
||||
bool CGLXManager::swapBuffers()
|
||||
{
|
||||
glXSwapBuffers((Display*)CurrentContext.OpenGLLinux.X11Display, CurrentContext.OpenGLLinux.GLXWindow);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,76 +1,76 @@
|
||||
// Copyright (C) 2013 Christian Stehno
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GLX_MANAGER_
|
||||
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "SExposedVideoData.h"
|
||||
#include "IContextManager.h"
|
||||
#include "SColor.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
// we can't include glx.h here, because gl.h has incompatible types with ogl es headers and it
|
||||
// cause redefinition errors, thats why we use ugly trick with void* types and casts.
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// GLX manager.
|
||||
class CGLXManager : public IContextManager
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
CGLXManager(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata, int screennr);
|
||||
|
||||
//! Destructor
|
||||
~CGLXManager();
|
||||
|
||||
// Initialize
|
||||
bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data) override;
|
||||
|
||||
// Terminate
|
||||
void terminate() override;
|
||||
|
||||
// Create surface.
|
||||
bool generateSurface() override;
|
||||
|
||||
// Destroy surface.
|
||||
void destroySurface() override;
|
||||
|
||||
// Create context.
|
||||
bool generateContext() override;
|
||||
|
||||
// Destroy context.
|
||||
void destroyContext() 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;
|
||||
|
||||
// Get procedure address.
|
||||
void* getProcAddress(const std::string &procName) override;
|
||||
|
||||
// Swap buffers.
|
||||
bool swapBuffers() override;
|
||||
|
||||
XVisualInfo* getVisual() const {return VisualInfo;} // return XVisualInfo
|
||||
|
||||
private:
|
||||
SIrrlichtCreationParameters Params;
|
||||
SExposedVideoData PrimaryContext;
|
||||
SExposedVideoData CurrentContext;
|
||||
XVisualInfo* VisualInfo;
|
||||
void* glxFBConfig; // GLXFBConfig
|
||||
XID GlxWin; // GLXWindow
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2013 Christian Stehno
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GLX_MANAGER_
|
||||
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "SExposedVideoData.h"
|
||||
#include "IContextManager.h"
|
||||
#include "SColor.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
// we can't include glx.h here, because gl.h has incompatible types with ogl es headers and it
|
||||
// cause redefinition errors, thats why we use ugly trick with void* types and casts.
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// GLX manager.
|
||||
class CGLXManager : public IContextManager
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
CGLXManager(const SIrrlichtCreationParameters& params, const SExposedVideoData& videodata, int screennr);
|
||||
|
||||
//! Destructor
|
||||
~CGLXManager();
|
||||
|
||||
// Initialize
|
||||
bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data) override;
|
||||
|
||||
// Terminate
|
||||
void terminate() override;
|
||||
|
||||
// Create surface.
|
||||
bool generateSurface() override;
|
||||
|
||||
// Destroy surface.
|
||||
void destroySurface() override;
|
||||
|
||||
// Create context.
|
||||
bool generateContext() override;
|
||||
|
||||
// Destroy context.
|
||||
void destroyContext() 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;
|
||||
|
||||
// Get procedure address.
|
||||
void* getProcAddress(const std::string &procName) override;
|
||||
|
||||
// Swap buffers.
|
||||
bool swapBuffers() override;
|
||||
|
||||
XVisualInfo* getVisual() const {return VisualInfo;} // return XVisualInfo
|
||||
|
||||
private:
|
||||
SIrrlichtCreationParameters Params;
|
||||
SExposedVideoData PrimaryContext;
|
||||
SExposedVideoData CurrentContext;
|
||||
XVisualInfo* VisualInfo;
|
||||
void* glxFBConfig; // GLXFBConfig
|
||||
XID GlxWin; // GLXWindow
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,241 +1,241 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "ITexture.h"
|
||||
#include "SColor.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
setImage(EGBIS_IMAGE_UP, image, pos);
|
||||
}
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "ITexture.h"
|
||||
#include "SColor.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
setImage(EGBIS_IMAGE_UP, image, pos);
|
||||
}
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,227 +1,227 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUICheckBox.h"
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUICheckBox");
|
||||
#endif
|
||||
|
||||
// this element can be tabbed into
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUICheckBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(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)
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown && Pressed &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
Pressed = false;
|
||||
if (Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
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)
|
||||
{
|
||||
Pressed = true;
|
||||
CheckTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
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) ) )
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
|
||||
// draw background
|
||||
if (Background)
|
||||
{
|
||||
video::SColor bgColor = skin->getColor(gui::EGDC_3D_FACE);
|
||||
driver->draw2DRectangle(bgColor, frameRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
// draw the 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);
|
||||
}
|
||||
|
||||
const s32 height = skin->getSize(EGDS_CHECK_BOX_WIDTH);
|
||||
|
||||
// the rectangle around the "checked" area.
|
||||
core::rect<s32> checkRect(frameRect.UpperLeftCorner.X,
|
||||
((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() )
|
||||
col = Pressed ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
|
||||
skin->draw3DSunkenPane(this, skin->getColor(col),
|
||||
false, true, checkRect, &AbsoluteClippingRect);
|
||||
|
||||
// the checked icon
|
||||
if (Checked)
|
||||
{
|
||||
skin->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(),
|
||||
CheckTime, os::Timer::getTime(), false, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
// associated text
|
||||
if (Text.size())
|
||||
{
|
||||
checkRect = frameRect;
|
||||
checkRect.UpperLeftCorner.X += height + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont();
|
||||
if (font)
|
||||
{
|
||||
font->draw(Text.c_str(), checkRect,
|
||||
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! set if box is checked
|
||||
void CGUICheckBox::setChecked(bool checked)
|
||||
{
|
||||
Checked = checked;
|
||||
}
|
||||
|
||||
|
||||
//! returns if box is checked
|
||||
bool CGUICheckBox::isChecked() const
|
||||
{
|
||||
return Checked;
|
||||
}
|
||||
|
||||
//! Sets whether to draw the background
|
||||
void CGUICheckBox::setDrawBackground(bool draw)
|
||||
{
|
||||
Background = draw;
|
||||
}
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
bool CGUICheckBox::isDrawBackgroundEnabled() const
|
||||
{
|
||||
return Background;
|
||||
}
|
||||
|
||||
//! Sets whether to draw the border
|
||||
void CGUICheckBox::setDrawBorder(bool draw)
|
||||
{
|
||||
Border = draw;
|
||||
}
|
||||
|
||||
//! Checks if border drawing is enabled
|
||||
bool CGUICheckBox::isDrawBorderEnabled() const
|
||||
{
|
||||
return Border;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUICheckBox.h"
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUICheckBox");
|
||||
#endif
|
||||
|
||||
// this element can be tabbed into
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUICheckBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(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)
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown && Pressed &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
Pressed = false;
|
||||
if (Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
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)
|
||||
{
|
||||
Pressed = true;
|
||||
CheckTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
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) ) )
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
|
||||
// draw background
|
||||
if (Background)
|
||||
{
|
||||
video::SColor bgColor = skin->getColor(gui::EGDC_3D_FACE);
|
||||
driver->draw2DRectangle(bgColor, frameRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
// draw the 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);
|
||||
}
|
||||
|
||||
const s32 height = skin->getSize(EGDS_CHECK_BOX_WIDTH);
|
||||
|
||||
// the rectangle around the "checked" area.
|
||||
core::rect<s32> checkRect(frameRect.UpperLeftCorner.X,
|
||||
((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() )
|
||||
col = Pressed ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
|
||||
skin->draw3DSunkenPane(this, skin->getColor(col),
|
||||
false, true, checkRect, &AbsoluteClippingRect);
|
||||
|
||||
// the checked icon
|
||||
if (Checked)
|
||||
{
|
||||
skin->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(),
|
||||
CheckTime, os::Timer::getTime(), false, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
// associated text
|
||||
if (Text.size())
|
||||
{
|
||||
checkRect = frameRect;
|
||||
checkRect.UpperLeftCorner.X += height + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont();
|
||||
if (font)
|
||||
{
|
||||
font->draw(Text.c_str(), checkRect,
|
||||
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! set if box is checked
|
||||
void CGUICheckBox::setChecked(bool checked)
|
||||
{
|
||||
Checked = checked;
|
||||
}
|
||||
|
||||
|
||||
//! returns if box is checked
|
||||
bool CGUICheckBox::isChecked() const
|
||||
{
|
||||
return Checked;
|
||||
}
|
||||
|
||||
//! Sets whether to draw the background
|
||||
void CGUICheckBox::setDrawBackground(bool draw)
|
||||
{
|
||||
Background = draw;
|
||||
}
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
bool CGUICheckBox::isDrawBackgroundEnabled() const
|
||||
{
|
||||
return Background;
|
||||
}
|
||||
|
||||
//! Sets whether to draw the border
|
||||
void CGUICheckBox::setDrawBorder(bool draw)
|
||||
{
|
||||
Border = draw;
|
||||
}
|
||||
|
||||
//! Checks if border drawing is enabled
|
||||
bool CGUICheckBox::isDrawBorderEnabled() const
|
||||
{
|
||||
return Border;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUICheckBox.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUICheckBox : public IGUICheckBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! set if box is checked
|
||||
void setChecked(bool checked) override;
|
||||
|
||||
//! returns if box is checked
|
||||
bool isChecked() const 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
private:
|
||||
|
||||
u32 CheckTime;
|
||||
bool Pressed;
|
||||
bool Checked;
|
||||
bool Border;
|
||||
bool Background;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUICheckBox.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUICheckBox : public IGUICheckBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! set if box is checked
|
||||
void setChecked(bool checked) override;
|
||||
|
||||
//! returns if box is checked
|
||||
bool isChecked() const 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
private:
|
||||
|
||||
u32 CheckTime;
|
||||
bool Pressed;
|
||||
bool Checked;
|
||||
bool Border;
|
||||
bool Background;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,108 +1,108 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIComboBox.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIButton;
|
||||
class IGUIListBox;
|
||||
|
||||
//! 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 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 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;
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
void removeItem(u32 id) 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 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
private:
|
||||
|
||||
void openCloseMenu();
|
||||
void sendSelectionChangedEvent();
|
||||
void updateListButtonWidth(s32 width);
|
||||
|
||||
IGUIButton* ListButton;
|
||||
IGUIStaticText* SelectedText;
|
||||
IGUIListBox* ListBox;
|
||||
IGUIElement *LastFocus;
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIComboBox.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIButton;
|
||||
class IGUIListBox;
|
||||
|
||||
//! 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 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 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;
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
void removeItem(u32 id) 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 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
private:
|
||||
|
||||
void openCloseMenu();
|
||||
void sendSelectionChangedEvent();
|
||||
void updateListButtonWidth(s32 width);
|
||||
|
||||
IGUIButton* ListButton;
|
||||
IGUIStaticText* SelectedText;
|
||||
IGUIListBox* ListBox;
|
||||
IGUIElement *LastFocus;
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,198 +1,198 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "irrArray.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class CGUIEditBox : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEditBox();
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
bool isDrawBackgroundEnabled() const override;
|
||||
|
||||
//! Turns the border on or off
|
||||
void setDrawBorder(bool border) 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Sets text justification
|
||||
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Updates the absolute position, splits text if required
|
||||
void updateAbsolutePosition() 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();
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "irrArray.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class CGUIEditBox : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEditBox();
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
bool isDrawBackgroundEnabled() const override;
|
||||
|
||||
//! Turns the border on or off
|
||||
void setDrawBorder(bool border) 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Sets text justification
|
||||
void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) override;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Updates the absolute position, splits text if required
|
||||
void updateAbsolutePosition() 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();
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,228 +1,228 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIElement.h"
|
||||
#include "irrArray.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIEnvironment : public IGUIEnvironment, public IGUIElement
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEnvironment();
|
||||
|
||||
//! draws all gui elements
|
||||
void drawAll(bool useScreenSize) override;
|
||||
|
||||
//! returns the current video driver
|
||||
video::IVideoDriver* getVideoDriver() const override;
|
||||
|
||||
//! returns pointer to the filesystem
|
||||
io::IFileSystem* getFileSystem() const override;
|
||||
|
||||
//! returns a pointer to the OS operator
|
||||
IOSOperator* getOSOperator() const override;
|
||||
|
||||
//! posts an input event to the environment
|
||||
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;
|
||||
|
||||
//! removes all elements from the environment
|
||||
void clear() override;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! returns the current gui skin
|
||||
IGUISkin* getSkin() const override;
|
||||
|
||||
//! Sets a new GUI Skin
|
||||
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;
|
||||
|
||||
//! Creates the image list from the given texture.
|
||||
virtual IGUIImageList* createImageList(video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize, bool useAlphaChannel) override;
|
||||
|
||||
//! returns the font
|
||||
IGUIFont* getFont(const io::path& filename) override;
|
||||
|
||||
//! add an externally loaded font
|
||||
IGUIFont* addFont(const io::path& name, IGUIFont* font) override;
|
||||
|
||||
//! remove loaded font
|
||||
void removeFont(IGUIFont* font) override;
|
||||
|
||||
//! returns default font
|
||||
IGUIFont* getBuiltInFont() const override;
|
||||
|
||||
//! returns the sprite bank
|
||||
IGUISpriteBank* getSpriteBank(const io::path& filename) override;
|
||||
|
||||
//! returns the sprite bank
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! adds a list box
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Adds tab to the environment.
|
||||
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;
|
||||
|
||||
//! sets the focus to an element
|
||||
bool setFocus(IGUIElement* element) override;
|
||||
|
||||
//! removes the focus from an element
|
||||
bool removeFocus(IGUIElement* element) override;
|
||||
|
||||
//! Returns if the element has focus
|
||||
bool hasFocus(const IGUIElement* element, bool checkSubElements=false) const override;
|
||||
|
||||
//! Returns the element with the focus
|
||||
IGUIElement* getFocus() const override;
|
||||
|
||||
//! Returns the element last known to be under the mouse
|
||||
IGUIElement* getHovered() const override;
|
||||
|
||||
//! Returns the root gui element.
|
||||
IGUIElement* getRootGUIElement() 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;
|
||||
|
||||
//! Set the way the gui will handle focus changes
|
||||
void setFocusBehavior(u32 flags) override;
|
||||
|
||||
//! Get the way the gui does handle focus changes
|
||||
u32 getFocusBehavior() const override;
|
||||
|
||||
//! Adds a IGUIElement to deletion queue.
|
||||
void addToDeletionQueue(IGUIElement* element) override;
|
||||
|
||||
private:
|
||||
|
||||
//! clears the deletion queue
|
||||
void clearDeletionQueue();
|
||||
|
||||
void updateHoveredElement(core::position2d<s32> mousePos);
|
||||
|
||||
void loadBuiltInFont();
|
||||
|
||||
struct SFont
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUIFont* Font;
|
||||
|
||||
bool operator < (const SFont& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SSpriteBank
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUISpriteBank* Bank;
|
||||
|
||||
bool operator < (const SSpriteBank& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SToolTip
|
||||
{
|
||||
IGUIStaticText* Element;
|
||||
u32 LastTime;
|
||||
u32 EnterTime;
|
||||
u32 LaunchTime;
|
||||
u32 RelaunchTime;
|
||||
};
|
||||
|
||||
SToolTip ToolTip;
|
||||
|
||||
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;
|
||||
core::position2d<s32> LastHoveredMousePos;
|
||||
IGUISkin* CurrentSkin;
|
||||
io::IFileSystem* FileSystem;
|
||||
IEventReceiver* UserReceiver;
|
||||
IOSOperator* Operator;
|
||||
u32 FocusFlags;
|
||||
core::array<IGUIElement*> DeletionQueue;
|
||||
|
||||
static const io::path DefaultFontName;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIElement.h"
|
||||
#include "irrArray.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIEnvironment : public IGUIEnvironment, public IGUIElement
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEnvironment();
|
||||
|
||||
//! draws all gui elements
|
||||
void drawAll(bool useScreenSize) override;
|
||||
|
||||
//! returns the current video driver
|
||||
video::IVideoDriver* getVideoDriver() const override;
|
||||
|
||||
//! returns pointer to the filesystem
|
||||
io::IFileSystem* getFileSystem() const override;
|
||||
|
||||
//! returns a pointer to the OS operator
|
||||
IOSOperator* getOSOperator() const override;
|
||||
|
||||
//! posts an input event to the environment
|
||||
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;
|
||||
|
||||
//! removes all elements from the environment
|
||||
void clear() override;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! returns the current gui skin
|
||||
IGUISkin* getSkin() const override;
|
||||
|
||||
//! Sets a new GUI Skin
|
||||
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;
|
||||
|
||||
//! Creates the image list from the given texture.
|
||||
virtual IGUIImageList* createImageList(video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize, bool useAlphaChannel) override;
|
||||
|
||||
//! returns the font
|
||||
IGUIFont* getFont(const io::path& filename) override;
|
||||
|
||||
//! add an externally loaded font
|
||||
IGUIFont* addFont(const io::path& name, IGUIFont* font) override;
|
||||
|
||||
//! remove loaded font
|
||||
void removeFont(IGUIFont* font) override;
|
||||
|
||||
//! returns default font
|
||||
IGUIFont* getBuiltInFont() const override;
|
||||
|
||||
//! returns the sprite bank
|
||||
IGUISpriteBank* getSpriteBank(const io::path& filename) override;
|
||||
|
||||
//! returns the sprite bank
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! adds a list box
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Adds tab to the environment.
|
||||
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;
|
||||
|
||||
//! sets the focus to an element
|
||||
bool setFocus(IGUIElement* element) override;
|
||||
|
||||
//! removes the focus from an element
|
||||
bool removeFocus(IGUIElement* element) override;
|
||||
|
||||
//! Returns if the element has focus
|
||||
bool hasFocus(const IGUIElement* element, bool checkSubElements=false) const override;
|
||||
|
||||
//! Returns the element with the focus
|
||||
IGUIElement* getFocus() const override;
|
||||
|
||||
//! Returns the element last known to be under the mouse
|
||||
IGUIElement* getHovered() const override;
|
||||
|
||||
//! Returns the root gui element.
|
||||
IGUIElement* getRootGUIElement() 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;
|
||||
|
||||
//! Set the way the gui will handle focus changes
|
||||
void setFocusBehavior(u32 flags) override;
|
||||
|
||||
//! Get the way the gui does handle focus changes
|
||||
u32 getFocusBehavior() const override;
|
||||
|
||||
//! Adds a IGUIElement to deletion queue.
|
||||
void addToDeletionQueue(IGUIElement* element) override;
|
||||
|
||||
private:
|
||||
|
||||
//! clears the deletion queue
|
||||
void clearDeletionQueue();
|
||||
|
||||
void updateHoveredElement(core::position2d<s32> mousePos);
|
||||
|
||||
void loadBuiltInFont();
|
||||
|
||||
struct SFont
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUIFont* Font;
|
||||
|
||||
bool operator < (const SFont& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SSpriteBank
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUISpriteBank* Bank;
|
||||
|
||||
bool operator < (const SSpriteBank& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SToolTip
|
||||
{
|
||||
IGUIStaticText* Element;
|
||||
u32 LastTime;
|
||||
u32 EnterTime;
|
||||
u32 LaunchTime;
|
||||
u32 RelaunchTime;
|
||||
};
|
||||
|
||||
SToolTip ToolTip;
|
||||
|
||||
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;
|
||||
core::position2d<s32> LastHoveredMousePos;
|
||||
IGUISkin* CurrentSkin;
|
||||
io::IFileSystem* FileSystem;
|
||||
IEventReceiver* UserReceiver;
|
||||
IOSOperator* Operator;
|
||||
u32 FocusFlags;
|
||||
core::array<IGUIElement*> DeletionQueue;
|
||||
|
||||
static const io::path DefaultFontName;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,412 +1,412 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIFileOpenDialog.h"
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "IFileList.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IGUIElement::setDebugName("CGUIFileOpenDialog");
|
||||
#endif
|
||||
|
||||
Text = title;
|
||||
|
||||
FileSystem = Environment?Environment->getFileSystem():0;
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
FileSystem->grab();
|
||||
|
||||
if (restoreCWD)
|
||||
RestoreDirectory = FileSystem->getWorkingDirectory();
|
||||
if (startDir)
|
||||
{
|
||||
StartDirectory = startDir;
|
||||
FileSystem->changeWorkingDirectoryTo(startDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const s32 buttonw = skin ? skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) : 2;
|
||||
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");
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
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);
|
||||
}
|
||||
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
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");
|
||||
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");
|
||||
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->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->setSubElement(true);
|
||||
FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
FileNameText->grab();
|
||||
|
||||
setTabGroup(true);
|
||||
|
||||
fillListBox();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIFileOpenDialog::~CGUIFileOpenDialog()
|
||||
{
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
|
||||
if (OKButton)
|
||||
OKButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
if (FileBox)
|
||||
FileBox->drop();
|
||||
|
||||
if (FileNameText)
|
||||
FileNameText->drop();
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
// revert to original CWD if path was set in constructor
|
||||
if (RestoreDirectory.size())
|
||||
FileSystem->changeWorkingDirectoryTo(RestoreDirectory);
|
||||
FileSystem->drop();
|
||||
}
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the filename of the selected file. Returns NULL, if no file was selected.
|
||||
const wchar_t* CGUIFileOpenDialog::getFileName() const
|
||||
{
|
||||
return FileNameW.c_str();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return FileDirectoryFlat;
|
||||
}
|
||||
|
||||
const wchar_t* CGUIFileOpenDialog::getDirectoryNameW() const
|
||||
{
|
||||
return FileDirectoryFlatW.c_str();
|
||||
}
|
||||
|
||||
void CGUIFileOpenDialog::setFileName(const irr::io::path& name)
|
||||
{
|
||||
FileName = name;
|
||||
pathToStringW(FileNameW, FileName);
|
||||
}
|
||||
|
||||
void CGUIFileOpenDialog::setDirectoryName(const irr::io::path& name)
|
||||
{
|
||||
FileDirectory = name;
|
||||
FileDirectoryFlat = name;
|
||||
FileSystem->flattenFilename (FileDirectoryFlat );
|
||||
pathToStringW(FileDirectoryFlatW, FileDirectoryFlat);
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIFileOpenDialog::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
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)
|
||||
{
|
||||
sendCancelEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == OKButton )
|
||||
{
|
||||
if ( FileDirectory != L"" )
|
||||
{
|
||||
sendSelectedEvent( EGET_DIRECTORY_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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EGET_EDITBOX_ENTER:
|
||||
if (event.GUIEvent.Caller == FileNameText)
|
||||
{
|
||||
io::path dir( FileNameText->getText () );
|
||||
if ( FileSystem->changeWorkingDirectoryTo( dir ) )
|
||||
{
|
||||
fillListBox();
|
||||
setFileName("");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
return FileBox->OnEvent(event);
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
Dragging = true;
|
||||
return true;
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
Dragging = false;
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
|
||||
if ( !event.MouseInput.isLeftPressed () )
|
||||
Dragging = false;
|
||||
|
||||
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)
|
||||
|
||||
return true;
|
||||
|
||||
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIFileOpenDialog::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
|
||||
rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
|
||||
rect, &AbsoluteClippingRect);
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
rect.UpperLeftCorner.X += 2;
|
||||
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_WINDOW);
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect,
|
||||
skin->getColor(EGDC_ACTIVE_CAPTION),
|
||||
false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
void CGUIFileOpenDialog::pathToStringW(irr::core::stringw& result, const irr::io::path& p)
|
||||
{
|
||||
core::multibyteToWString(result, p);
|
||||
}
|
||||
|
||||
//! fills the listbox with files.
|
||||
void CGUIFileOpenDialog::fillListBox()
|
||||
{
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
|
||||
if (!FileSystem || !FileBox || !skin)
|
||||
return;
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
|
||||
FileBox->clear();
|
||||
|
||||
FileList = FileSystem->createFileList();
|
||||
core::stringw s;
|
||||
|
||||
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)
|
||||
{
|
||||
setDirectoryName(FileSystem->getWorkingDirectory());
|
||||
pathToStringW(s, FileDirectory);
|
||||
FileNameText->setText(s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type)
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = type;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file choose process has been cancelled
|
||||
void CGUIFileOpenDialog::sendCancelEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIFileOpenDialog.h"
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "IFileList.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IGUIElement::setDebugName("CGUIFileOpenDialog");
|
||||
#endif
|
||||
|
||||
Text = title;
|
||||
|
||||
FileSystem = Environment?Environment->getFileSystem():0;
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
FileSystem->grab();
|
||||
|
||||
if (restoreCWD)
|
||||
RestoreDirectory = FileSystem->getWorkingDirectory();
|
||||
if (startDir)
|
||||
{
|
||||
StartDirectory = startDir;
|
||||
FileSystem->changeWorkingDirectoryTo(startDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const s32 buttonw = skin ? skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) : 2;
|
||||
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");
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
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);
|
||||
}
|
||||
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
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");
|
||||
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");
|
||||
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->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->setSubElement(true);
|
||||
FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
FileNameText->grab();
|
||||
|
||||
setTabGroup(true);
|
||||
|
||||
fillListBox();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIFileOpenDialog::~CGUIFileOpenDialog()
|
||||
{
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
|
||||
if (OKButton)
|
||||
OKButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
if (FileBox)
|
||||
FileBox->drop();
|
||||
|
||||
if (FileNameText)
|
||||
FileNameText->drop();
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
// revert to original CWD if path was set in constructor
|
||||
if (RestoreDirectory.size())
|
||||
FileSystem->changeWorkingDirectoryTo(RestoreDirectory);
|
||||
FileSystem->drop();
|
||||
}
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the filename of the selected file. Returns NULL, if no file was selected.
|
||||
const wchar_t* CGUIFileOpenDialog::getFileName() const
|
||||
{
|
||||
return FileNameW.c_str();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return FileDirectoryFlat;
|
||||
}
|
||||
|
||||
const wchar_t* CGUIFileOpenDialog::getDirectoryNameW() const
|
||||
{
|
||||
return FileDirectoryFlatW.c_str();
|
||||
}
|
||||
|
||||
void CGUIFileOpenDialog::setFileName(const irr::io::path& name)
|
||||
{
|
||||
FileName = name;
|
||||
pathToStringW(FileNameW, FileName);
|
||||
}
|
||||
|
||||
void CGUIFileOpenDialog::setDirectoryName(const irr::io::path& name)
|
||||
{
|
||||
FileDirectory = name;
|
||||
FileDirectoryFlat = name;
|
||||
FileSystem->flattenFilename (FileDirectoryFlat );
|
||||
pathToStringW(FileDirectoryFlatW, FileDirectoryFlat);
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIFileOpenDialog::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
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)
|
||||
{
|
||||
sendCancelEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == OKButton )
|
||||
{
|
||||
if ( FileDirectory != L"" )
|
||||
{
|
||||
sendSelectedEvent( EGET_DIRECTORY_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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EGET_EDITBOX_ENTER:
|
||||
if (event.GUIEvent.Caller == FileNameText)
|
||||
{
|
||||
io::path dir( FileNameText->getText () );
|
||||
if ( FileSystem->changeWorkingDirectoryTo( dir ) )
|
||||
{
|
||||
fillListBox();
|
||||
setFileName("");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
return FileBox->OnEvent(event);
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
Dragging = true;
|
||||
return true;
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
Dragging = false;
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
|
||||
if ( !event.MouseInput.isLeftPressed () )
|
||||
Dragging = false;
|
||||
|
||||
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)
|
||||
|
||||
return true;
|
||||
|
||||
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIFileOpenDialog::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
|
||||
rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
|
||||
rect, &AbsoluteClippingRect);
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
rect.UpperLeftCorner.X += 2;
|
||||
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_WINDOW);
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect,
|
||||
skin->getColor(EGDC_ACTIVE_CAPTION),
|
||||
false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
void CGUIFileOpenDialog::pathToStringW(irr::core::stringw& result, const irr::io::path& p)
|
||||
{
|
||||
core::multibyteToWString(result, p);
|
||||
}
|
||||
|
||||
//! fills the listbox with files.
|
||||
void CGUIFileOpenDialog::fillListBox()
|
||||
{
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
|
||||
if (!FileSystem || !FileBox || !skin)
|
||||
return;
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
|
||||
FileBox->clear();
|
||||
|
||||
FileList = FileSystem->createFileList();
|
||||
core::stringw s;
|
||||
|
||||
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)
|
||||
{
|
||||
setDirectoryName(FileSystem->getWorkingDirectory());
|
||||
pathToStringW(s, FileDirectory);
|
||||
FileNameText->setText(s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type)
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = type;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file choose process has been cancelled
|
||||
void CGUIFileOpenDialog::sendCancelEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIListBox.h"
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IFileSystem.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
//! 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. 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 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;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
protected:
|
||||
|
||||
void setFileName(const irr::io::path& name);
|
||||
void setDirectoryName(const irr::io::path& name);
|
||||
|
||||
//! Ensure filenames are converted correct depending on wide-char settings
|
||||
void pathToStringW(irr::core::stringw& result, const irr::io::path& p);
|
||||
|
||||
//! fills the listbox with files.
|
||||
void fillListBox();
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIListBox.h"
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IFileSystem.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
//! 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. 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 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;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
protected:
|
||||
|
||||
void setFileName(const irr::io::path& name);
|
||||
void setDirectoryName(const irr::io::path& name);
|
||||
|
||||
//! Ensure filenames are converted correct depending on wide-char settings
|
||||
void pathToStringW(irr::core::stringw& result, const irr::io::path& p);
|
||||
|
||||
//! fills the listbox with files.
|
||||
void fillListBox();
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,108 +1,108 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "irrString.h"
|
||||
#include "IReadFile.h"
|
||||
#include "irrArray.h"
|
||||
#include <map>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
class IImage;
|
||||
}
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIEnvironment;
|
||||
|
||||
class CGUIFont : public IGUIFontBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIFont(IGUIEnvironment* env, const io::path& filename);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIFont();
|
||||
|
||||
//! loads a font from a texture file
|
||||
bool load(const io::path& filename);
|
||||
|
||||
//! loads a font from a texture 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;
|
||||
|
||||
//! returns the dimension of a text
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 getKerningHeight() const override;
|
||||
|
||||
//! gets the sprite bank
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
struct SFontArea
|
||||
{
|
||||
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);
|
||||
|
||||
void readPositions(video::IImage* texture, s32& lowerRightPositions);
|
||||
|
||||
s32 getAreaFromCharacter (const wchar_t c) const;
|
||||
void setMaxHeight();
|
||||
|
||||
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::stringw Invisible;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "irrString.h"
|
||||
#include "IReadFile.h"
|
||||
#include "irrArray.h"
|
||||
#include <map>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
class IImage;
|
||||
}
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIEnvironment;
|
||||
|
||||
class CGUIFont : public IGUIFontBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIFont(IGUIEnvironment* env, const io::path& filename);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIFont();
|
||||
|
||||
//! loads a font from a texture file
|
||||
bool load(const io::path& filename);
|
||||
|
||||
//! loads a font from a texture 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;
|
||||
|
||||
//! returns the dimension of a text
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 getKerningHeight() const override;
|
||||
|
||||
//! gets the sprite bank
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
struct SFontArea
|
||||
{
|
||||
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);
|
||||
|
||||
void readPositions(video::IImage* texture, s32& lowerRightPositions);
|
||||
|
||||
s32 getAreaFromCharacter (const wchar_t c) const;
|
||||
void setMaxHeight();
|
||||
|
||||
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::stringw Invisible;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,178 +1,178 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIImage.h"
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIImage");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIImage::~CGUIImage()
|
||||
{
|
||||
if (Texture)
|
||||
Texture->drop();
|
||||
}
|
||||
|
||||
|
||||
//! sets an image
|
||||
void CGUIImage::setImage(video::ITexture* image)
|
||||
{
|
||||
if (image == Texture)
|
||||
return;
|
||||
|
||||
if (Texture)
|
||||
Texture->drop();
|
||||
|
||||
Texture = image;
|
||||
|
||||
if (Texture)
|
||||
Texture->grab();
|
||||
}
|
||||
|
||||
//! Gets the image texture
|
||||
video::ITexture* CGUIImage::getImage() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
//! sets the color of the image
|
||||
void CGUIImage::setColor(video::SColor color)
|
||||
{
|
||||
Color = color;
|
||||
}
|
||||
|
||||
//! Gets the color of the image
|
||||
video::SColor CGUIImage::getColor() const
|
||||
{
|
||||
return Color;
|
||||
}
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIImage::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
if (Texture)
|
||||
{
|
||||
core::rect<s32> sourceRect(SourceRect);
|
||||
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};
|
||||
|
||||
core::rect<s32> clippingRect(AbsoluteClippingRect);
|
||||
checkBounds(clippingRect);
|
||||
|
||||
driver->draw2DImage(Texture, AbsoluteRect, sourceRect,
|
||||
&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);
|
||||
}
|
||||
}
|
||||
else if ( DrawBackground )
|
||||
{
|
||||
core::rect<s32> clippingRect(AbsoluteClippingRect);
|
||||
checkBounds(clippingRect);
|
||||
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_DARK_SHADOW), AbsoluteRect, &clippingRect);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return ScaleImage;
|
||||
}
|
||||
|
||||
//! Returns true if the image is using the alpha channel, false if not
|
||||
bool CGUIImage::isAlphaChannelUsed() const
|
||||
{
|
||||
return UseAlphaChannel;
|
||||
}
|
||||
|
||||
//! Sets the source rectangle of the image. By default the full image is used.
|
||||
void CGUIImage::setSourceRect(const core::rect<s32>& sourceRect)
|
||||
{
|
||||
SourceRect = sourceRect;
|
||||
}
|
||||
|
||||
//! Returns the customized source rectangle of the image to be used.
|
||||
core::rect<s32> CGUIImage::getSourceRect() const
|
||||
{
|
||||
return SourceRect;
|
||||
}
|
||||
|
||||
//! Restrict target drawing-area.
|
||||
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 )
|
||||
DrawBounds.UpperLeftCorner.X = DrawBounds.LowerRightCorner.X;
|
||||
if ( DrawBounds.UpperLeftCorner.Y > DrawBounds.LowerRightCorner.Y )
|
||||
DrawBounds.UpperLeftCorner.Y = DrawBounds.LowerRightCorner.Y;
|
||||
}
|
||||
|
||||
//! Get target drawing-area restrictions.
|
||||
core::rect<f32> CGUIImage::getDrawBounds() const
|
||||
{
|
||||
return DrawBounds;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIImage.h"
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIImage");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIImage::~CGUIImage()
|
||||
{
|
||||
if (Texture)
|
||||
Texture->drop();
|
||||
}
|
||||
|
||||
|
||||
//! sets an image
|
||||
void CGUIImage::setImage(video::ITexture* image)
|
||||
{
|
||||
if (image == Texture)
|
||||
return;
|
||||
|
||||
if (Texture)
|
||||
Texture->drop();
|
||||
|
||||
Texture = image;
|
||||
|
||||
if (Texture)
|
||||
Texture->grab();
|
||||
}
|
||||
|
||||
//! Gets the image texture
|
||||
video::ITexture* CGUIImage::getImage() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
//! sets the color of the image
|
||||
void CGUIImage::setColor(video::SColor color)
|
||||
{
|
||||
Color = color;
|
||||
}
|
||||
|
||||
//! Gets the color of the image
|
||||
video::SColor CGUIImage::getColor() const
|
||||
{
|
||||
return Color;
|
||||
}
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIImage::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
if (Texture)
|
||||
{
|
||||
core::rect<s32> sourceRect(SourceRect);
|
||||
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};
|
||||
|
||||
core::rect<s32> clippingRect(AbsoluteClippingRect);
|
||||
checkBounds(clippingRect);
|
||||
|
||||
driver->draw2DImage(Texture, AbsoluteRect, sourceRect,
|
||||
&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);
|
||||
}
|
||||
}
|
||||
else if ( DrawBackground )
|
||||
{
|
||||
core::rect<s32> clippingRect(AbsoluteClippingRect);
|
||||
checkBounds(clippingRect);
|
||||
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_DARK_SHADOW), AbsoluteRect, &clippingRect);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return ScaleImage;
|
||||
}
|
||||
|
||||
//! Returns true if the image is using the alpha channel, false if not
|
||||
bool CGUIImage::isAlphaChannelUsed() const
|
||||
{
|
||||
return UseAlphaChannel;
|
||||
}
|
||||
|
||||
//! Sets the source rectangle of the image. By default the full image is used.
|
||||
void CGUIImage::setSourceRect(const core::rect<s32>& sourceRect)
|
||||
{
|
||||
SourceRect = sourceRect;
|
||||
}
|
||||
|
||||
//! Returns the customized source rectangle of the image to be used.
|
||||
core::rect<s32> CGUIImage::getSourceRect() const
|
||||
{
|
||||
return SourceRect;
|
||||
}
|
||||
|
||||
//! Restrict target drawing-area.
|
||||
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 )
|
||||
DrawBounds.UpperLeftCorner.X = DrawBounds.LowerRightCorner.X;
|
||||
if ( DrawBounds.UpperLeftCorner.Y > DrawBounds.LowerRightCorner.Y )
|
||||
DrawBounds.UpperLeftCorner.Y = DrawBounds.LowerRightCorner.Y;
|
||||
}
|
||||
|
||||
//! Get target drawing-area restrictions.
|
||||
core::rect<f32> CGUIImage::getDrawBounds() const
|
||||
{
|
||||
return DrawBounds;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,99 +1,99 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIImage.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIImage.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de
|
||||
// modified by Thomas Alten
|
||||
|
||||
#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 )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName( "CGUIImageList" );
|
||||
#endif
|
||||
|
||||
if( Driver )
|
||||
{
|
||||
Driver->grab();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIImageList::~CGUIImageList()
|
||||
{
|
||||
if( Driver )
|
||||
{
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
if( Texture )
|
||||
{
|
||||
Texture->drop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Creates the image list from texture.
|
||||
bool CGUIImageList::createImageList(video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize,
|
||||
bool useAlphaChannel)
|
||||
{
|
||||
if( !texture )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Texture = texture;
|
||||
Texture->grab();
|
||||
|
||||
ImageSize = imageSize;
|
||||
|
||||
ImagesPerRow = Texture->getSize().Width / ImageSize.Width;
|
||||
ImageCount = ImagesPerRow * Texture->getSize().Height / ImageSize.Height;
|
||||
|
||||
UseAlphaChannel = useAlphaChannel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! 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*/ )
|
||||
{
|
||||
core::rect<s32> sourceRect;
|
||||
|
||||
if( !Driver || index < 0 || index >= ImageCount )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de
|
||||
// modified by Thomas Alten
|
||||
|
||||
#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 )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName( "CGUIImageList" );
|
||||
#endif
|
||||
|
||||
if( Driver )
|
||||
{
|
||||
Driver->grab();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIImageList::~CGUIImageList()
|
||||
{
|
||||
if( Driver )
|
||||
{
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
if( Texture )
|
||||
{
|
||||
Texture->drop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Creates the image list from texture.
|
||||
bool CGUIImageList::createImageList(video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize,
|
||||
bool useAlphaChannel)
|
||||
{
|
||||
if( !texture )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Texture = texture;
|
||||
Texture->grab();
|
||||
|
||||
ImageSize = imageSize;
|
||||
|
||||
ImagesPerRow = Texture->getSize().Width / ImageSize.Width;
|
||||
ImageCount = ImagesPerRow * Texture->getSize().Height / ImageSize.Height;
|
||||
|
||||
UseAlphaChannel = useAlphaChannel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! 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*/ )
|
||||
{
|
||||
core::rect<s32> sourceRect;
|
||||
|
||||
if( !Driver || index < 0 || index >= ImageCount )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIImageList.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIImageList : public IGUIImageList
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIImageList( video::IVideoDriver* Driver );
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIImageList();
|
||||
|
||||
//! Creates the image list from texture.
|
||||
//! \param texture: The texture to use
|
||||
//! \param imageSize: Size of a single image
|
||||
//! \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);
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the count of Images in the list.
|
||||
//! \return Returns the count of Images in the list.
|
||||
s32 getImageCount() const override
|
||||
{ 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; }
|
||||
|
||||
private:
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
video::ITexture* Texture;
|
||||
s32 ImageCount;
|
||||
core::dimension2d<s32> ImageSize;
|
||||
s32 ImagesPerRow;
|
||||
bool UseAlphaChannel;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIImageList.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIImageList : public IGUIImageList
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIImageList( video::IVideoDriver* Driver );
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIImageList();
|
||||
|
||||
//! Creates the image list from texture.
|
||||
//! \param texture: The texture to use
|
||||
//! \param imageSize: Size of a single image
|
||||
//! \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);
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the count of Images in the list.
|
||||
//! \return Returns the count of Images in the list.
|
||||
s32 getImageCount() const override
|
||||
{ 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; }
|
||||
|
||||
private:
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
video::ITexture* Texture;
|
||||
s32 ImageCount;
|
||||
core::dimension2d<s32> ImageSize;
|
||||
s32 ImagesPerRow;
|
||||
bool UseAlphaChannel;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,175 +1,175 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIListBox.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIFont;
|
||||
class IGUIScrollBar;
|
||||
|
||||
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
|
||||
{
|
||||
core::stringw Text;
|
||||
s32 Icon = -1;
|
||||
|
||||
// A multicolor extension
|
||||
struct ListItemOverrideColor
|
||||
{
|
||||
bool Use = false;
|
||||
video::SColor Color;
|
||||
};
|
||||
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
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIListBox.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIFont;
|
||||
class IGUIScrollBar;
|
||||
|
||||
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
|
||||
{
|
||||
core::stringw Text;
|
||||
s32 Icon = -1;
|
||||
|
||||
// A multicolor extension
|
||||
struct ListItemOverrideColor
|
||||
{
|
||||
bool Use = false;
|
||||
video::SColor Color;
|
||||
};
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,98 +1,98 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIScrollBar.h"
|
||||
#include "IGUIButton.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIScrollBar : public IGUIScrollBar
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIScrollBar(bool horizontal, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle,
|
||||
bool noclip=false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIScrollBar();
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() 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 minimum value of the scrollbar.
|
||||
s32 getMin() const override;
|
||||
|
||||
//! sets the minimum value of the scrollbar.
|
||||
void setMin(s32 min) override;
|
||||
|
||||
//! gets the small step value
|
||||
s32 getSmallStep() const override;
|
||||
|
||||
//! sets the small step value
|
||||
void setSmallStep(s32 step) override;
|
||||
|
||||
//! gets the large step value
|
||||
s32 getLargeStep() const override;
|
||||
|
||||
//! sets the large step value
|
||||
void setLargeStep(s32 step) override;
|
||||
|
||||
//! gets the current position of the scrollbar
|
||||
s32 getPos() const override;
|
||||
|
||||
//! sets the position of the scrollbar
|
||||
void setPos(s32 pos) override;
|
||||
|
||||
//! updates the rectangle
|
||||
void updateAbsolutePosition() override;
|
||||
|
||||
private:
|
||||
|
||||
void refreshControls();
|
||||
s32 getPosFromMousePos(const core::position2di &p) const;
|
||||
|
||||
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 ); }
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIScrollBar.h"
|
||||
#include "IGUIButton.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIScrollBar : public IGUIScrollBar
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIScrollBar(bool horizontal, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle,
|
||||
bool noclip=false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIScrollBar();
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() 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 minimum value of the scrollbar.
|
||||
s32 getMin() const override;
|
||||
|
||||
//! sets the minimum value of the scrollbar.
|
||||
void setMin(s32 min) override;
|
||||
|
||||
//! gets the small step value
|
||||
s32 getSmallStep() const override;
|
||||
|
||||
//! sets the small step value
|
||||
void setSmallStep(s32 step) override;
|
||||
|
||||
//! gets the large step value
|
||||
s32 getLargeStep() const override;
|
||||
|
||||
//! sets the large step value
|
||||
void setLargeStep(s32 step) override;
|
||||
|
||||
//! gets the current position of the scrollbar
|
||||
s32 getPos() const override;
|
||||
|
||||
//! sets the position of the scrollbar
|
||||
void setPos(s32 pos) override;
|
||||
|
||||
//! updates the rectangle
|
||||
void updateAbsolutePosition() override;
|
||||
|
||||
private:
|
||||
|
||||
void refreshControls();
|
||||
s32 getPosFromMousePos(const core::position2di &p) const;
|
||||
|
||||
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 ); }
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,231 +1,231 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
}
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUISkin : public IGUISkin
|
||||
{
|
||||
public:
|
||||
|
||||
CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUISkin();
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 the sprite bank used for drawing icons
|
||||
void setSpriteBank(IGUISpriteBank* bank) 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 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 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 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 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 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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
}
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUISkin : public IGUISkin
|
||||
{
|
||||
public:
|
||||
|
||||
CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUISkin();
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 the sprite bank used for drawing icons
|
||||
void setSpriteBank(IGUISpriteBank* bank) 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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 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 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 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 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 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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,265 +1,265 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUISpriteBank.h"
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ITexture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) :
|
||||
Environment(env), Driver(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUISpriteBank");
|
||||
#endif
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
Driver = Environment->getVideoDriver();
|
||||
if (Driver)
|
||||
Driver->grab();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CGUISpriteBank::~CGUISpriteBank()
|
||||
{
|
||||
clear();
|
||||
|
||||
// drop video driver
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
|
||||
core::array< core::rect<s32> >& CGUISpriteBank::getPositions()
|
||||
{
|
||||
return Rectangles;
|
||||
}
|
||||
|
||||
|
||||
core::array< SGUISprite >& CGUISpriteBank::getSprites()
|
||||
{
|
||||
return Sprites;
|
||||
}
|
||||
|
||||
|
||||
u32 CGUISpriteBank::getTextureCount() const
|
||||
{
|
||||
return Textures.size();
|
||||
}
|
||||
|
||||
|
||||
video::ITexture* CGUISpriteBank::getTexture(u32 index) const
|
||||
{
|
||||
if (index < Textures.size())
|
||||
return Textures[index];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CGUISpriteBank::addTexture(video::ITexture* texture)
|
||||
{
|
||||
if (texture)
|
||||
texture->grab();
|
||||
|
||||
Textures.push_back(texture);
|
||||
}
|
||||
|
||||
|
||||
void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture)
|
||||
{
|
||||
while (index >= Textures.size())
|
||||
Textures.push_back(0);
|
||||
|
||||
if (texture)
|
||||
texture->grab();
|
||||
|
||||
if (Textures[index])
|
||||
Textures[index]->drop();
|
||||
|
||||
Textures[index] = texture;
|
||||
}
|
||||
|
||||
|
||||
//! clear everything
|
||||
void CGUISpriteBank::clear()
|
||||
{
|
||||
// drop textures
|
||||
for (u32 i=0; i<Textures.size(); ++i)
|
||||
{
|
||||
if (Textures[i])
|
||||
Textures[i]->drop();
|
||||
}
|
||||
Textures.clear();
|
||||
Sprites.clear();
|
||||
Rectangles.clear();
|
||||
}
|
||||
|
||||
//! Add the texture and use it for a single non-animated sprite.
|
||||
s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* 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) );
|
||||
|
||||
SGUISprite sprite;
|
||||
sprite.frameTime = 0;
|
||||
|
||||
SGUISpriteFrame frame;
|
||||
frame.textureNumber = textureIndex;
|
||||
frame.rectNumber = rectangleIndex;
|
||||
sprite.Frames.push_back( frame );
|
||||
|
||||
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
|
||||
{
|
||||
frame = 0;
|
||||
if (index >= Sprites.size())
|
||||
return false;
|
||||
|
||||
const SGUISprite& sprite = Sprites[index];
|
||||
const u32 frameSize = sprite.Frames.size();
|
||||
if (frameSize < 1)
|
||||
return false;
|
||||
|
||||
if (sprite.frameTime)
|
||||
{
|
||||
u32 f = (time / sprite.frameTime);
|
||||
if (loop)
|
||||
frame = f % frameSize;
|
||||
else
|
||||
frame = (f >= frameSize) ? frameSize - 1 : f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! 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,
|
||||
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);
|
||||
if (!tex)
|
||||
return;
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
const core::rect<s32>& r = Rectangles[rn];
|
||||
core::position2di p(pos);
|
||||
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,
|
||||
u32 timeTicks, bool loop)
|
||||
{
|
||||
u32 frame = 0;
|
||||
if (!getFrameNr(frame,index, timeTicks, loop))
|
||||
return;
|
||||
|
||||
const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);
|
||||
if (!tex)
|
||||
return;
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
drawBatches.push_back(SDrawBatch());
|
||||
drawBatches[i].positions.reallocate(drawCount);
|
||||
drawBatches[i].sourceRects.reallocate(drawCount);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < drawCount; ++i)
|
||||
{
|
||||
const u32 index = indices[i];
|
||||
|
||||
// work out frame number
|
||||
u32 frame = 0;
|
||||
if (!getFrameNr(frame, index, currenttime - starttime, loop))
|
||||
return;
|
||||
|
||||
const u32 texNum = Sprites[index].Frames[frame].textureNumber;
|
||||
if (texNum >= drawBatches.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SDrawBatch& currentBatch = drawBatches[texNum];
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
const core::rect<s32>& r = Rectangles[rn];
|
||||
|
||||
if (center)
|
||||
{
|
||||
core::position2di p = pos[i];
|
||||
p -= r.getSize() / 2;
|
||||
|
||||
currentBatch.positions.push_back(p);
|
||||
currentBatch.sourceRects.push_back(r);
|
||||
}
|
||||
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())
|
||||
Driver->draw2DImageBatch(getTexture(i), drawBatches[i].positions,
|
||||
drawBatches[i].sourceRects, clip, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUISpriteBank.h"
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ITexture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) :
|
||||
Environment(env), Driver(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUISpriteBank");
|
||||
#endif
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
Driver = Environment->getVideoDriver();
|
||||
if (Driver)
|
||||
Driver->grab();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CGUISpriteBank::~CGUISpriteBank()
|
||||
{
|
||||
clear();
|
||||
|
||||
// drop video driver
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
|
||||
core::array< core::rect<s32> >& CGUISpriteBank::getPositions()
|
||||
{
|
||||
return Rectangles;
|
||||
}
|
||||
|
||||
|
||||
core::array< SGUISprite >& CGUISpriteBank::getSprites()
|
||||
{
|
||||
return Sprites;
|
||||
}
|
||||
|
||||
|
||||
u32 CGUISpriteBank::getTextureCount() const
|
||||
{
|
||||
return Textures.size();
|
||||
}
|
||||
|
||||
|
||||
video::ITexture* CGUISpriteBank::getTexture(u32 index) const
|
||||
{
|
||||
if (index < Textures.size())
|
||||
return Textures[index];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CGUISpriteBank::addTexture(video::ITexture* texture)
|
||||
{
|
||||
if (texture)
|
||||
texture->grab();
|
||||
|
||||
Textures.push_back(texture);
|
||||
}
|
||||
|
||||
|
||||
void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture)
|
||||
{
|
||||
while (index >= Textures.size())
|
||||
Textures.push_back(0);
|
||||
|
||||
if (texture)
|
||||
texture->grab();
|
||||
|
||||
if (Textures[index])
|
||||
Textures[index]->drop();
|
||||
|
||||
Textures[index] = texture;
|
||||
}
|
||||
|
||||
|
||||
//! clear everything
|
||||
void CGUISpriteBank::clear()
|
||||
{
|
||||
// drop textures
|
||||
for (u32 i=0; i<Textures.size(); ++i)
|
||||
{
|
||||
if (Textures[i])
|
||||
Textures[i]->drop();
|
||||
}
|
||||
Textures.clear();
|
||||
Sprites.clear();
|
||||
Rectangles.clear();
|
||||
}
|
||||
|
||||
//! Add the texture and use it for a single non-animated sprite.
|
||||
s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* 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) );
|
||||
|
||||
SGUISprite sprite;
|
||||
sprite.frameTime = 0;
|
||||
|
||||
SGUISpriteFrame frame;
|
||||
frame.textureNumber = textureIndex;
|
||||
frame.rectNumber = rectangleIndex;
|
||||
sprite.Frames.push_back( frame );
|
||||
|
||||
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
|
||||
{
|
||||
frame = 0;
|
||||
if (index >= Sprites.size())
|
||||
return false;
|
||||
|
||||
const SGUISprite& sprite = Sprites[index];
|
||||
const u32 frameSize = sprite.Frames.size();
|
||||
if (frameSize < 1)
|
||||
return false;
|
||||
|
||||
if (sprite.frameTime)
|
||||
{
|
||||
u32 f = (time / sprite.frameTime);
|
||||
if (loop)
|
||||
frame = f % frameSize;
|
||||
else
|
||||
frame = (f >= frameSize) ? frameSize - 1 : f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! 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,
|
||||
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);
|
||||
if (!tex)
|
||||
return;
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
const core::rect<s32>& r = Rectangles[rn];
|
||||
core::position2di p(pos);
|
||||
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,
|
||||
u32 timeTicks, bool loop)
|
||||
{
|
||||
u32 frame = 0;
|
||||
if (!getFrameNr(frame,index, timeTicks, loop))
|
||||
return;
|
||||
|
||||
const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);
|
||||
if (!tex)
|
||||
return;
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
drawBatches.push_back(SDrawBatch());
|
||||
drawBatches[i].positions.reallocate(drawCount);
|
||||
drawBatches[i].sourceRects.reallocate(drawCount);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < drawCount; ++i)
|
||||
{
|
||||
const u32 index = indices[i];
|
||||
|
||||
// work out frame number
|
||||
u32 frame = 0;
|
||||
if (!getFrameNr(frame, index, currenttime - starttime, loop))
|
||||
return;
|
||||
|
||||
const u32 texNum = Sprites[index].Frames[frame].textureNumber;
|
||||
if (texNum >= drawBatches.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SDrawBatch& currentBatch = drawBatches[texNum];
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
const core::rect<s32>& r = Rectangles[rn];
|
||||
|
||||
if (center)
|
||||
{
|
||||
core::position2di p = pos[i];
|
||||
p -= r.getSize() / 2;
|
||||
|
||||
currentBatch.positions.push_back(p);
|
||||
currentBatch.sourceRects.push_back(r);
|
||||
}
|
||||
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())
|
||||
Driver->draw2DImageBatch(getTexture(i), drawBatches[i].positions,
|
||||
drawBatches[i].sourceRects, clip, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace irr
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUISpriteBank.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
class ITexture;
|
||||
}
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIEnvironment;
|
||||
|
||||
//! Sprite bank interface.
|
||||
class CGUISpriteBank : public IGUISpriteBank
|
||||
{
|
||||
public:
|
||||
|
||||
CGUISpriteBank(IGUIEnvironment* env);
|
||||
virtual ~CGUISpriteBank();
|
||||
|
||||
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;
|
||||
|
||||
//! Add the texture and use it for a single non-animated sprite.
|
||||
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;
|
||||
|
||||
//! 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,
|
||||
u32 timeTicks = 0,
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
||||
bool getFrameNr(u32& frameNr, u32 index, u32 time, bool loop) const;
|
||||
|
||||
struct SDrawBatch
|
||||
{
|
||||
core::array<core::position2di> positions;
|
||||
core::array<core::recti> sourceRects;
|
||||
u32 textureNumber;
|
||||
};
|
||||
|
||||
core::array<SGUISprite> Sprites;
|
||||
core::array< core::rect<s32> > Rectangles;
|
||||
core::array<video::ITexture*> Textures;
|
||||
IGUIEnvironment* Environment;
|
||||
video::IVideoDriver* Driver;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUISpriteBank.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
class ITexture;
|
||||
}
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIEnvironment;
|
||||
|
||||
//! Sprite bank interface.
|
||||
class CGUISpriteBank : public IGUISpriteBank
|
||||
{
|
||||
public:
|
||||
|
||||
CGUISpriteBank(IGUIEnvironment* env);
|
||||
virtual ~CGUISpriteBank();
|
||||
|
||||
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;
|
||||
|
||||
//! Add the texture and use it for a single non-animated sprite.
|
||||
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;
|
||||
|
||||
//! 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,
|
||||
u32 timeTicks = 0,
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
||||
bool getFrameNr(u32& frameNr, u32 index, u32 time, bool loop) const;
|
||||
|
||||
struct SDrawBatch
|
||||
{
|
||||
core::array<core::position2di> positions;
|
||||
core::array<core::recti> sourceRects;
|
||||
u32 textureNumber;
|
||||
};
|
||||
|
||||
core::array<SGUISprite> Sprites;
|
||||
core::array< core::rect<s32> > Rectangles;
|
||||
core::array<video::ITexture*> Textures;
|
||||
IGUIEnvironment* Environment;
|
||||
video::IVideoDriver* Driver;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,133 +1,133 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIStaticText.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
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,
|
||||
bool background = false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIStaticText();
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
//! Sets another skin independent font.
|
||||
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 text.
|
||||
void setOverrideColor(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;
|
||||
|
||||
//! Gets the background color
|
||||
video::SColor getBackgroundColor() const override;
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
bool isDrawBackgroundEnabled() const override;
|
||||
|
||||
//! Sets whether to draw the border
|
||||
void setDrawBorder(bool draw) 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;
|
||||
|
||||
//! Gets the override color
|
||||
video::SColor getOverrideColor() 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
bool isWordWrapEnabled() const 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
|
||||
//! 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;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIStaticText.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
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,
|
||||
bool background = false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIStaticText();
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
//! Sets another skin independent font.
|
||||
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 text.
|
||||
void setOverrideColor(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;
|
||||
|
||||
//! Gets the background color
|
||||
video::SColor getBackgroundColor() const override;
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
bool isDrawBackgroundEnabled() const override;
|
||||
|
||||
//! Sets whether to draw the border
|
||||
void setDrawBorder(bool draw) 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;
|
||||
|
||||
//! Gets the override color
|
||||
video::SColor getOverrideColor() 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
bool isWordWrapEnabled() const 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 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;
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
|
||||
//! 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;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,181 +1,181 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUITabControl.h"
|
||||
#include "irrArray.h"
|
||||
#include "IGUISkin.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
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,
|
||||
s32 id);
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() 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 text
|
||||
void setTextColor(video::SColor c) 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;
|
||||
|
||||
video::SColor getTextColor() const override;
|
||||
|
||||
private:
|
||||
|
||||
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();
|
||||
|
||||
//! Adds a tab
|
||||
IGUITab* addTab(const wchar_t* caption, s32 id=-1) override;
|
||||
|
||||
//! Adds an existing tab
|
||||
s32 addTab(IGUITab* tab) override;
|
||||
|
||||
//! Insert the tab at the given index
|
||||
IGUITab* insertTab(s32 idx, 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;
|
||||
|
||||
//! Removes a tab from the tabcontrol
|
||||
void removeTab(s32 idx) override;
|
||||
|
||||
//! Clears the tabcontrol removing all tabs
|
||||
void clear() override;
|
||||
|
||||
//! Returns amount of tabs in the tabcontrol
|
||||
s32 getTabCount() const override;
|
||||
|
||||
//! Returns a tab based on zero based index
|
||||
IGUITab* getTab(s32 idx) const override;
|
||||
|
||||
//! Brings a tab to front.
|
||||
bool setActiveTab(s32 idx) override;
|
||||
|
||||
//! Brings a tab to front.
|
||||
bool setActiveTab(IGUITab *tab) override;
|
||||
|
||||
//! For given given tab find it's zero-based index (or -1 for not found)
|
||||
s32 getTabIndex(const IGUIElement *tab) const override;
|
||||
|
||||
//! Returns which tab is currently active
|
||||
s32 getActiveTab() const override;
|
||||
|
||||
//! get the the id of the tab at the given absolute coordinates
|
||||
s32 getTabAt(s32 xpos, s32 ypos) const override;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
//! Removes a child.
|
||||
void removeChild(IGUIElement* child) override;
|
||||
|
||||
//! Set the height of the tabs
|
||||
void setTabHeight( s32 height ) override;
|
||||
|
||||
//! Get the height of the tabs
|
||||
s32 getTabHeight() const 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 maximal width of a tab
|
||||
s32 getTabMaxWidth() const override;
|
||||
|
||||
//! Set the alignment of the tabs
|
||||
//! note: EGUIA_CENTER is not an option
|
||||
void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ) override;
|
||||
|
||||
//! Get the alignment of the tabs
|
||||
gui::EGUI_ALIGNMENT getTabVerticalAlignment() const override;
|
||||
|
||||
//! Set the extra width added to tabs on each side of the text
|
||||
void setTabExtraWidth( s32 extraWidth ) override;
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUITabControl.h"
|
||||
#include "irrArray.h"
|
||||
#include "IGUISkin.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
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,
|
||||
s32 id);
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() 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 text
|
||||
void setTextColor(video::SColor c) 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;
|
||||
|
||||
video::SColor getTextColor() const override;
|
||||
|
||||
private:
|
||||
|
||||
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();
|
||||
|
||||
//! Adds a tab
|
||||
IGUITab* addTab(const wchar_t* caption, s32 id=-1) override;
|
||||
|
||||
//! Adds an existing tab
|
||||
s32 addTab(IGUITab* tab) override;
|
||||
|
||||
//! Insert the tab at the given index
|
||||
IGUITab* insertTab(s32 idx, 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;
|
||||
|
||||
//! Removes a tab from the tabcontrol
|
||||
void removeTab(s32 idx) override;
|
||||
|
||||
//! Clears the tabcontrol removing all tabs
|
||||
void clear() override;
|
||||
|
||||
//! Returns amount of tabs in the tabcontrol
|
||||
s32 getTabCount() const override;
|
||||
|
||||
//! Returns a tab based on zero based index
|
||||
IGUITab* getTab(s32 idx) const override;
|
||||
|
||||
//! Brings a tab to front.
|
||||
bool setActiveTab(s32 idx) override;
|
||||
|
||||
//! Brings a tab to front.
|
||||
bool setActiveTab(IGUITab *tab) override;
|
||||
|
||||
//! For given given tab find it's zero-based index (or -1 for not found)
|
||||
s32 getTabIndex(const IGUIElement *tab) const override;
|
||||
|
||||
//! Returns which tab is currently active
|
||||
s32 getActiveTab() const override;
|
||||
|
||||
//! get the the id of the tab at the given absolute coordinates
|
||||
s32 getTabAt(s32 xpos, s32 ypos) const override;
|
||||
|
||||
//! called if an event happened.
|
||||
bool OnEvent(const SEvent& event) override;
|
||||
|
||||
//! draws the element and its children
|
||||
void draw() override;
|
||||
|
||||
//! Removes a child.
|
||||
void removeChild(IGUIElement* child) override;
|
||||
|
||||
//! Set the height of the tabs
|
||||
void setTabHeight( s32 height ) override;
|
||||
|
||||
//! Get the height of the tabs
|
||||
s32 getTabHeight() const 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 maximal width of a tab
|
||||
s32 getTabMaxWidth() const override;
|
||||
|
||||
//! Set the alignment of the tabs
|
||||
//! note: EGUIA_CENTER is not an option
|
||||
void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ) override;
|
||||
|
||||
//! Get the alignment of the tabs
|
||||
gui::EGUI_ALIGNMENT getTabVerticalAlignment() const override;
|
||||
|
||||
//! Set the extra width added to tabs on each side of the text
|
||||
void setTabExtraWidth( s32 extraWidth ) override;
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,428 +1,428 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "CBlit.h"
|
||||
#include "os.h"
|
||||
#include "SoftwareDriver2_helper.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (ownForeignMemory)
|
||||
{
|
||||
Data = (u8*)data;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 dataSize = getDataSizeFromFormat(Format, Size.Width, Size.Height);
|
||||
|
||||
Data = new u8[align_next(dataSize,16)];
|
||||
memcpy(Data, data, dataSize);
|
||||
DeleteMemory = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Constructor of empty image
|
||||
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) : IImage(format, size, true)
|
||||
{
|
||||
Data = new u8[align_next(getDataSizeFromFormat(Format, Size.Width, Size.Height),16)];
|
||||
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;
|
||||
|
||||
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_A8R8G8B8:
|
||||
{
|
||||
u32 * dest = (u32*) (Data + ( y * Pitch ) + ( x << 2 ));
|
||||
*dest = blend ? PixelBlend32 ( *dest, color.color ) : color.color;
|
||||
} break;
|
||||
|
||||
IRR_CASE_IIMAGE_COMPRESSED_FORMAT
|
||||
os::Printer::log("IImage::setPixel method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
|
||||
case ECF_UNKNOWN:
|
||||
os::Printer::log("IImage::setPixel unknown format.", ELL_WARNING);
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
|
||||
case ECF_R5G6B5:
|
||||
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]);
|
||||
}
|
||||
|
||||
IRR_CASE_IIMAGE_COMPRESSED_FORMAT
|
||||
os::Printer::log("IImage::getPixel method doesn't work with compressed images.", ELL_WARNING);
|
||||
break;
|
||||
|
||||
case ECF_UNKNOWN:
|
||||
os::Printer::log("IImage::getPixel unknown format.", ELL_WARNING);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SColor(0);
|
||||
}
|
||||
|
||||
|
||||
//! copies this surface into another at given position
|
||||
void CImage::copyTo(IImage* target, const core::position2d<s32>& pos)
|
||||
{
|
||||
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()))
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//! 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))
|
||||
{
|
||||
os::Printer::log("IImage::copyToNoScaling method doesn't work with compressed images.", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!target || !width || !height || !Size.Width || !Size.Height)
|
||||
return false;
|
||||
|
||||
const u32 bpp=getBitsPerPixelFromFormat(format)/8;
|
||||
if (0==pitch)
|
||||
pitch = width*bpp;
|
||||
|
||||
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)
|
||||
{
|
||||
// copy scanline
|
||||
memcpy(tgtpos, srcpos, bwidth);
|
||||
// clear pitch
|
||||
memset(tgtpos+bwidth, 0, rest);
|
||||
tgtpos += pitch;
|
||||
srcpos += Pitch;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!target || !width || !height || !Size.Width || !Size.Height)
|
||||
return;
|
||||
|
||||
const u32 bpp=getBitsPerPixelFromFormat(format)/8;
|
||||
if (0==pitch)
|
||||
pitch = width*bpp;
|
||||
|
||||
if (copyToNoScaling(target, width, height, format, pitch))
|
||||
return;
|
||||
|
||||
// NOTE: Scaling is coded to keep the border pixels intact.
|
||||
// Alternatively we could for example work with first pixel being taken at half step-size.
|
||||
// Then we have one more step here and it would be:
|
||||
// sourceXStep = (f32)(Size.Width-1) / (f32)(width);
|
||||
// And sx would start at 0.5f + sourceXStep / 2.f;
|
||||
// Similar for y.
|
||||
// As scaling is done without any antialiasing it doesn't matter too much which outermost pixels we use and keeping
|
||||
// border pixels intact is probably mostly better (with AA the other solution would be more correct).
|
||||
// This is however unnecessary (and unexpected) for scaling to integer multiples, so don't do it there.
|
||||
f32 sourceXStep, sourceYStep;
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
s32 yval=0, syval=0;
|
||||
f32 sy = sourceYStart;
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
const core::dimension2d<u32>& targetSize = target->getDimension();
|
||||
|
||||
if (targetSize==Size)
|
||||
{
|
||||
copyTo(target);
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
sx += sourceXStep;
|
||||
}
|
||||
sy += sourceYStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! fills the surface with given color
|
||||
void CImage::fill(const SColor &color)
|
||||
{
|
||||
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;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// TODO: Handle other formats
|
||||
return;
|
||||
}
|
||||
memset32( Data, c, getImageDataSizeInBytes() );
|
||||
}
|
||||
|
||||
|
||||
//! get a filtered pixel
|
||||
inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::getPixelBox method doesn't work with compressed images.", ELL_WARNING);
|
||||
return SColor(0);
|
||||
}
|
||||
|
||||
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 )
|
||||
);
|
||||
|
||||
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 );
|
||||
|
||||
c.set( a, r, g, b );
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "CBlit.h"
|
||||
#include "os.h"
|
||||
#include "SoftwareDriver2_helper.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (ownForeignMemory)
|
||||
{
|
||||
Data = (u8*)data;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 dataSize = getDataSizeFromFormat(Format, Size.Width, Size.Height);
|
||||
|
||||
Data = new u8[align_next(dataSize,16)];
|
||||
memcpy(Data, data, dataSize);
|
||||
DeleteMemory = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Constructor of empty image
|
||||
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) : IImage(format, size, true)
|
||||
{
|
||||
Data = new u8[align_next(getDataSizeFromFormat(Format, Size.Width, Size.Height),16)];
|
||||
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;
|
||||
|
||||
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_A8R8G8B8:
|
||||
{
|
||||
u32 * dest = (u32*) (Data + ( y * Pitch ) + ( x << 2 ));
|
||||
*dest = blend ? PixelBlend32 ( *dest, color.color ) : color.color;
|
||||
} break;
|
||||
|
||||
IRR_CASE_IIMAGE_COMPRESSED_FORMAT
|
||||
os::Printer::log("IImage::setPixel method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
|
||||
case ECF_UNKNOWN:
|
||||
os::Printer::log("IImage::setPixel unknown format.", ELL_WARNING);
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
|
||||
case ECF_R5G6B5:
|
||||
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]);
|
||||
}
|
||||
|
||||
IRR_CASE_IIMAGE_COMPRESSED_FORMAT
|
||||
os::Printer::log("IImage::getPixel method doesn't work with compressed images.", ELL_WARNING);
|
||||
break;
|
||||
|
||||
case ECF_UNKNOWN:
|
||||
os::Printer::log("IImage::getPixel unknown format.", ELL_WARNING);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SColor(0);
|
||||
}
|
||||
|
||||
|
||||
//! copies this surface into another at given position
|
||||
void CImage::copyTo(IImage* target, const core::position2d<s32>& pos)
|
||||
{
|
||||
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()))
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//! 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))
|
||||
{
|
||||
os::Printer::log("IImage::copyToNoScaling method doesn't work with compressed images.", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!target || !width || !height || !Size.Width || !Size.Height)
|
||||
return false;
|
||||
|
||||
const u32 bpp=getBitsPerPixelFromFormat(format)/8;
|
||||
if (0==pitch)
|
||||
pitch = width*bpp;
|
||||
|
||||
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)
|
||||
{
|
||||
// copy scanline
|
||||
memcpy(tgtpos, srcpos, bwidth);
|
||||
// clear pitch
|
||||
memset(tgtpos+bwidth, 0, rest);
|
||||
tgtpos += pitch;
|
||||
srcpos += Pitch;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!target || !width || !height || !Size.Width || !Size.Height)
|
||||
return;
|
||||
|
||||
const u32 bpp=getBitsPerPixelFromFormat(format)/8;
|
||||
if (0==pitch)
|
||||
pitch = width*bpp;
|
||||
|
||||
if (copyToNoScaling(target, width, height, format, pitch))
|
||||
return;
|
||||
|
||||
// NOTE: Scaling is coded to keep the border pixels intact.
|
||||
// Alternatively we could for example work with first pixel being taken at half step-size.
|
||||
// Then we have one more step here and it would be:
|
||||
// sourceXStep = (f32)(Size.Width-1) / (f32)(width);
|
||||
// And sx would start at 0.5f + sourceXStep / 2.f;
|
||||
// Similar for y.
|
||||
// As scaling is done without any antialiasing it doesn't matter too much which outermost pixels we use and keeping
|
||||
// border pixels intact is probably mostly better (with AA the other solution would be more correct).
|
||||
// This is however unnecessary (and unexpected) for scaling to integer multiples, so don't do it there.
|
||||
f32 sourceXStep, sourceYStep;
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
s32 yval=0, syval=0;
|
||||
f32 sy = sourceYStart;
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
const core::dimension2d<u32>& targetSize = target->getDimension();
|
||||
|
||||
if (targetSize==Size)
|
||||
{
|
||||
copyTo(target);
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
sx += sourceXStep;
|
||||
}
|
||||
sy += sourceYStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! fills the surface with given color
|
||||
void CImage::fill(const SColor &color)
|
||||
{
|
||||
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;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// TODO: Handle other formats
|
||||
return;
|
||||
}
|
||||
memset32( Data, c, getImageDataSizeInBytes() );
|
||||
}
|
||||
|
||||
|
||||
//! get a filtered pixel
|
||||
inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const
|
||||
{
|
||||
if (IImage::isCompressedFormat(Format))
|
||||
{
|
||||
os::Printer::log("IImage::getPixelBox method doesn't work with compressed images.", ELL_WARNING);
|
||||
return SColor(0);
|
||||
}
|
||||
|
||||
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 )
|
||||
);
|
||||
|
||||
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 );
|
||||
|
||||
c.set( a, r, g, b );
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImage.h"
|
||||
#include "rect.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! check sanity of image dimensions to prevent issues later, for use by CImageLoaders
|
||||
inline bool checkImageDimensions(u32 width, u32 height)
|
||||
{
|
||||
// 4 * 23000 * 23000 is just under S32_MAX
|
||||
return width <= 23000 && height <= 23000;
|
||||
}
|
||||
|
||||
//! IImage implementation with a lot of special image operations for
|
||||
//! 16 bit A1R5G5B5/32 Bit A8R8G8B8 images, which are used by the SoftwareDevice.
|
||||
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);
|
||||
|
||||
//! constructor for empty image
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! copies this surface into another, scaling it to fit.
|
||||
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;
|
||||
|
||||
//! copies this surface into another
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! copies this surface into another, scaling it to fit, applying a box filter
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImage.h"
|
||||
#include "rect.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! check sanity of image dimensions to prevent issues later, for use by CImageLoaders
|
||||
inline bool checkImageDimensions(u32 width, u32 height)
|
||||
{
|
||||
// 4 * 23000 * 23000 is just under S32_MAX
|
||||
return width <= 23000 && height <= 23000;
|
||||
}
|
||||
|
||||
//! IImage implementation with a lot of special image operations for
|
||||
//! 16 bit A1R5G5B5/32 Bit A8R8G8B8 images, which are used by the SoftwareDevice.
|
||||
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);
|
||||
|
||||
//! constructor for empty image
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! copies this surface into another, scaling it to fit.
|
||||
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;
|
||||
|
||||
//! copies this surface into another
|
||||
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;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! copies this surface into another, scaling it to fit, applying a box filter
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,416 +1,416 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderBMP.h"
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "SColor.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "CImage.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CImageLoaderBMP::CImageLoaderBMP()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageLoaderBMP");
|
||||
#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
|
||||
{
|
||||
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
|
||||
{
|
||||
u16 headerID;
|
||||
file->read(&headerID, sizeof(u16));
|
||||
#ifdef __BIG_ENDIAN__
|
||||
headerID = os::Byteswap::byteswap(headerID);
|
||||
#endif
|
||||
return headerID == 0x4d42;
|
||||
}
|
||||
|
||||
// UB-safe overflow check
|
||||
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);
|
||||
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
|
||||
// same for d
|
||||
#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
|
||||
{
|
||||
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);
|
||||
|
||||
switch(*p)
|
||||
{
|
||||
case 0: // end of line
|
||||
++p;
|
||||
++line;
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 count = (u8)*p; ++p;
|
||||
CHECKP(1);
|
||||
u8 color = *p; ++p;
|
||||
CHECKD(count);
|
||||
for (s32 i=0; i<count; ++i)
|
||||
{
|
||||
*d = color;
|
||||
++d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
delete [] bmpData;
|
||||
bmpData = newBmp;
|
||||
}
|
||||
|
||||
// how many bytes will be touched given the current state of decompress4BitRLE
|
||||
static inline u32 shiftedCount(s32 count, s32 shift)
|
||||
{
|
||||
_IRR_DEBUG_BREAK_IF(count < 0)
|
||||
u32 ret = count / 2;
|
||||
if (shift == 0 || count % 2 == 1)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
s32 line = 0;
|
||||
s32 shift = 4;
|
||||
|
||||
while (p < pEnd && d < destEnd)
|
||||
{
|
||||
if (*p == 0)
|
||||
{
|
||||
++p; CHECKP(1);
|
||||
|
||||
switch(*p)
|
||||
{
|
||||
case 0: // end of line
|
||||
++p;
|
||||
++line;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CHECKP(readAdditional);
|
||||
for (s32 i=0; i<readAdditional; ++i)
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 count = (u8)*p; ++p;
|
||||
CHECKP(1);
|
||||
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)
|
||||
{
|
||||
u8 mask = 0x0f << shift;
|
||||
u8 toSet = (shift==0 ? color1 : color2) << shift;
|
||||
*d = (*d & (~mask)) | (toSet & mask);
|
||||
|
||||
shift -= 4;
|
||||
if (shift < 0)
|
||||
{
|
||||
shift = 4;
|
||||
++d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
delete [] bmpData;
|
||||
bmpData = newBmp;
|
||||
}
|
||||
|
||||
#undef CHECKOFF
|
||||
#undef CHECKP
|
||||
#undef CHECKD
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
SBMPHeader header;
|
||||
|
||||
file->read(&header, sizeof(header));
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
header.Id = os::Byteswap::byteswap(header.Id);
|
||||
header.FileSize = os::Byteswap::byteswap(header.FileSize);
|
||||
header.BitmapDataOffset = os::Byteswap::byteswap(header.BitmapDataOffset);
|
||||
header.BitmapHeaderSize = os::Byteswap::byteswap(header.BitmapHeaderSize);
|
||||
header.Width = os::Byteswap::byteswap(header.Width);
|
||||
header.Height = os::Byteswap::byteswap(header.Height);
|
||||
header.Planes = os::Byteswap::byteswap(header.Planes);
|
||||
header.BPP = os::Byteswap::byteswap(header.BPP);
|
||||
header.Compression = os::Byteswap::byteswap(header.Compression);
|
||||
header.BitmapDataSize = os::Byteswap::byteswap(header.BitmapDataSize);
|
||||
header.PixelPerMeterX = os::Byteswap::byteswap(header.PixelPerMeterX);
|
||||
header.PixelPerMeterY = os::Byteswap::byteswap(header.PixelPerMeterY);
|
||||
header.Colors = os::Byteswap::byteswap(header.Colors);
|
||||
header.ImportantColors = os::Byteswap::byteswap(header.ImportantColors);
|
||||
#endif
|
||||
|
||||
s32 pitch = 0;
|
||||
|
||||
//! return if the header is false
|
||||
|
||||
if (header.Id != 0x4d42)
|
||||
return 0;
|
||||
|
||||
if (header.Compression > 2) // we'll only handle RLE-Compression
|
||||
{
|
||||
os::Printer::log("Compression mode not supported.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// read palette
|
||||
|
||||
long pos = file->getPos();
|
||||
constexpr s32 paletteAllocSize = 256;
|
||||
s32 paletteSize = (header.BitmapDataOffset - pos) / 4;
|
||||
paletteSize = core::clamp(paletteSize, 0, paletteAllocSize);
|
||||
|
||||
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)
|
||||
paletteData[i] = os::Byteswap::byteswap(paletteData[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// read image data
|
||||
|
||||
if (!header.BitmapDataSize)
|
||||
{
|
||||
// okay, lets guess the size
|
||||
// some tools simply don't set it
|
||||
header.BitmapDataSize = static_cast<u32>(file->getSize()) - header.BitmapDataOffset;
|
||||
}
|
||||
|
||||
file->seek(header.BitmapDataOffset);
|
||||
|
||||
s32 widthInBytes;
|
||||
{
|
||||
f32 t = (header.Width) * (header.BPP / 8.0f);
|
||||
widthInBytes = (s32)t;
|
||||
t -= widthInBytes;
|
||||
if (t!=0.0f)
|
||||
++widthInBytes;
|
||||
}
|
||||
|
||||
const s32 lineSize = widthInBytes + ((4-(widthInBytes%4)))%4;
|
||||
pitch = lineSize - widthInBytes;
|
||||
|
||||
u8* bmpData = new u8[header.BitmapDataSize];
|
||||
file->read(bmpData, header.BitmapDataSize);
|
||||
|
||||
// decompress data if needed
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
if (header.BitmapDataSize < lineSize * header.Height)
|
||||
{
|
||||
os::Printer::log("Bitmap data is cut off.", ELL_ERROR);
|
||||
|
||||
delete [] paletteData;
|
||||
delete [] bmpData;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create surface
|
||||
core::dimension2d<u32> dim;
|
||||
dim.Width = header.Width;
|
||||
dim.Height = header.Height;
|
||||
|
||||
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);
|
||||
break;
|
||||
case 4:
|
||||
image = new CImage(ECF_A1R5G5B5, dim);
|
||||
if (image)
|
||||
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);
|
||||
break;
|
||||
case 16:
|
||||
image = new CImage(ECF_A1R5G5B5, dim);
|
||||
if (image)
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
};
|
||||
|
||||
// clean up
|
||||
|
||||
delete [] paletteData;
|
||||
delete [] bmpData;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
//! creates a loader which is able to load windows bitmaps
|
||||
IImageLoader* createImageLoaderBMP()
|
||||
{
|
||||
return new CImageLoaderBMP;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderBMP.h"
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "SColor.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "CImage.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CImageLoaderBMP::CImageLoaderBMP()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageLoaderBMP");
|
||||
#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
|
||||
{
|
||||
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
|
||||
{
|
||||
u16 headerID;
|
||||
file->read(&headerID, sizeof(u16));
|
||||
#ifdef __BIG_ENDIAN__
|
||||
headerID = os::Byteswap::byteswap(headerID);
|
||||
#endif
|
||||
return headerID == 0x4d42;
|
||||
}
|
||||
|
||||
// UB-safe overflow check
|
||||
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);
|
||||
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
|
||||
// same for d
|
||||
#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
|
||||
{
|
||||
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);
|
||||
|
||||
switch(*p)
|
||||
{
|
||||
case 0: // end of line
|
||||
++p;
|
||||
++line;
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 count = (u8)*p; ++p;
|
||||
CHECKP(1);
|
||||
u8 color = *p; ++p;
|
||||
CHECKD(count);
|
||||
for (s32 i=0; i<count; ++i)
|
||||
{
|
||||
*d = color;
|
||||
++d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
delete [] bmpData;
|
||||
bmpData = newBmp;
|
||||
}
|
||||
|
||||
// how many bytes will be touched given the current state of decompress4BitRLE
|
||||
static inline u32 shiftedCount(s32 count, s32 shift)
|
||||
{
|
||||
_IRR_DEBUG_BREAK_IF(count < 0)
|
||||
u32 ret = count / 2;
|
||||
if (shift == 0 || count % 2 == 1)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
s32 line = 0;
|
||||
s32 shift = 4;
|
||||
|
||||
while (p < pEnd && d < destEnd)
|
||||
{
|
||||
if (*p == 0)
|
||||
{
|
||||
++p; CHECKP(1);
|
||||
|
||||
switch(*p)
|
||||
{
|
||||
case 0: // end of line
|
||||
++p;
|
||||
++line;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CHECKP(readAdditional);
|
||||
for (s32 i=0; i<readAdditional; ++i)
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 count = (u8)*p; ++p;
|
||||
CHECKP(1);
|
||||
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)
|
||||
{
|
||||
u8 mask = 0x0f << shift;
|
||||
u8 toSet = (shift==0 ? color1 : color2) << shift;
|
||||
*d = (*d & (~mask)) | (toSet & mask);
|
||||
|
||||
shift -= 4;
|
||||
if (shift < 0)
|
||||
{
|
||||
shift = 4;
|
||||
++d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
delete [] bmpData;
|
||||
bmpData = newBmp;
|
||||
}
|
||||
|
||||
#undef CHECKOFF
|
||||
#undef CHECKP
|
||||
#undef CHECKD
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
SBMPHeader header;
|
||||
|
||||
file->read(&header, sizeof(header));
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
header.Id = os::Byteswap::byteswap(header.Id);
|
||||
header.FileSize = os::Byteswap::byteswap(header.FileSize);
|
||||
header.BitmapDataOffset = os::Byteswap::byteswap(header.BitmapDataOffset);
|
||||
header.BitmapHeaderSize = os::Byteswap::byteswap(header.BitmapHeaderSize);
|
||||
header.Width = os::Byteswap::byteswap(header.Width);
|
||||
header.Height = os::Byteswap::byteswap(header.Height);
|
||||
header.Planes = os::Byteswap::byteswap(header.Planes);
|
||||
header.BPP = os::Byteswap::byteswap(header.BPP);
|
||||
header.Compression = os::Byteswap::byteswap(header.Compression);
|
||||
header.BitmapDataSize = os::Byteswap::byteswap(header.BitmapDataSize);
|
||||
header.PixelPerMeterX = os::Byteswap::byteswap(header.PixelPerMeterX);
|
||||
header.PixelPerMeterY = os::Byteswap::byteswap(header.PixelPerMeterY);
|
||||
header.Colors = os::Byteswap::byteswap(header.Colors);
|
||||
header.ImportantColors = os::Byteswap::byteswap(header.ImportantColors);
|
||||
#endif
|
||||
|
||||
s32 pitch = 0;
|
||||
|
||||
//! return if the header is false
|
||||
|
||||
if (header.Id != 0x4d42)
|
||||
return 0;
|
||||
|
||||
if (header.Compression > 2) // we'll only handle RLE-Compression
|
||||
{
|
||||
os::Printer::log("Compression mode not supported.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// read palette
|
||||
|
||||
long pos = file->getPos();
|
||||
constexpr s32 paletteAllocSize = 256;
|
||||
s32 paletteSize = (header.BitmapDataOffset - pos) / 4;
|
||||
paletteSize = core::clamp(paletteSize, 0, paletteAllocSize);
|
||||
|
||||
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)
|
||||
paletteData[i] = os::Byteswap::byteswap(paletteData[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// read image data
|
||||
|
||||
if (!header.BitmapDataSize)
|
||||
{
|
||||
// okay, lets guess the size
|
||||
// some tools simply don't set it
|
||||
header.BitmapDataSize = static_cast<u32>(file->getSize()) - header.BitmapDataOffset;
|
||||
}
|
||||
|
||||
file->seek(header.BitmapDataOffset);
|
||||
|
||||
s32 widthInBytes;
|
||||
{
|
||||
f32 t = (header.Width) * (header.BPP / 8.0f);
|
||||
widthInBytes = (s32)t;
|
||||
t -= widthInBytes;
|
||||
if (t!=0.0f)
|
||||
++widthInBytes;
|
||||
}
|
||||
|
||||
const s32 lineSize = widthInBytes + ((4-(widthInBytes%4)))%4;
|
||||
pitch = lineSize - widthInBytes;
|
||||
|
||||
u8* bmpData = new u8[header.BitmapDataSize];
|
||||
file->read(bmpData, header.BitmapDataSize);
|
||||
|
||||
// decompress data if needed
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
if (header.BitmapDataSize < lineSize * header.Height)
|
||||
{
|
||||
os::Printer::log("Bitmap data is cut off.", ELL_ERROR);
|
||||
|
||||
delete [] paletteData;
|
||||
delete [] bmpData;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create surface
|
||||
core::dimension2d<u32> dim;
|
||||
dim.Width = header.Width;
|
||||
dim.Height = header.Height;
|
||||
|
||||
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);
|
||||
break;
|
||||
case 4:
|
||||
image = new CImage(ECF_A1R5G5B5, dim);
|
||||
if (image)
|
||||
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);
|
||||
break;
|
||||
case 16:
|
||||
image = new CImage(ECF_A1R5G5B5, dim);
|
||||
if (image)
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
};
|
||||
|
||||
// clean up
|
||||
|
||||
delete [] paletteData;
|
||||
delete [] bmpData;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
//! creates a loader which is able to load windows bitmaps
|
||||
IImageLoader* createImageLoaderBMP()
|
||||
{
|
||||
return new CImageLoaderBMP;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,85 +1,85 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
/*!
|
||||
Surface Loader for Windows bitmaps
|
||||
*/
|
||||
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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* loadImage(io::IReadFile* file) const override;
|
||||
|
||||
private:
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
/*!
|
||||
Surface Loader for Windows bitmaps
|
||||
*/
|
||||
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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* loadImage(io::IReadFile* file) const override;
|
||||
|
||||
private:
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,286 +1,286 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderJPG.h"
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "CImage.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CImageLoaderJPG::CImageLoaderJPG()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageLoaderJPG");
|
||||
#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
|
||||
{
|
||||
return core::hasFileExtension ( filename, "jpg", "jpeg" );
|
||||
}
|
||||
|
||||
// struct for handling jpeg errors
|
||||
struct irr_jpeg_error_mgr
|
||||
{
|
||||
// public jpeg error fields
|
||||
struct jpeg_error_mgr pub;
|
||||
|
||||
// for longjmp, to return to caller on a fatal error
|
||||
jmp_buf setjmp_buffer;
|
||||
|
||||
// for having access to the filename when printing the error messages
|
||||
core::stringc* filename;
|
||||
};
|
||||
|
||||
void CImageLoaderJPG::init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean CImageLoaderJPG::fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
// DO NOTHING
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CImageLoaderJPG::skip_input_data (j_decompress_ptr cinfo, long count)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
|
||||
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 really points to a irr_error_mgr struct
|
||||
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.
|
||||
c8 temp1[JMSG_LENGTH_MAX];
|
||||
(*cinfo->err->format_message)(cinfo, temp1);
|
||||
core::stringc errMsg("JPEG FATAL ERROR in ");
|
||||
|
||||
irr_jpeg_error_mgr* myerr = (irr_jpeg_error_mgr*)cinfo->err;
|
||||
errMsg += *myerr->filename;
|
||||
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
|
||||
{
|
||||
if (!(file && file->seek(0)))
|
||||
return false;
|
||||
unsigned char header[3];
|
||||
size_t headerLen = file->read(header, sizeof(header));
|
||||
return headerLen >= 3 && !memcmp(header, "\xFF\xD8\xFF", 3);
|
||||
}
|
||||
|
||||
//! creates a surface from the file
|
||||
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()];
|
||||
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.
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
cinfo.err->error_exit = error_exit;
|
||||
cinfo.err->output_message = output_message;
|
||||
jerr.filename = &filename;
|
||||
|
||||
// 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 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;
|
||||
|
||||
// return null pointer
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Now we can initialize the JPEG decompression object.
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
// specify data source
|
||||
jpeg_source_mgr jsrc;
|
||||
|
||||
// Set up data pointer
|
||||
jsrc.bytes_in_buffer = file->getSize();
|
||||
jsrc.next_input_byte = (JOCTET*)input;
|
||||
cinfo.src = &jsrc;
|
||||
|
||||
jsrc.init_source = init_source;
|
||||
jsrc.fill_input_buffer = fill_input_buffer;
|
||||
jsrc.skip_input_data = skip_input_data;
|
||||
jsrc.resync_to_restart = jpeg_resync_to_restart;
|
||||
jsrc.term_source = term_source;
|
||||
|
||||
// Decodes JPG input from whatever source
|
||||
// Does everything AFTER jpeg_create_decompress
|
||||
// and BEFORE jpeg_destroy_decompress
|
||||
// Caller is responsible for arranging these + setting up cinfo
|
||||
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
cinfo.out_color_space=JCS_RGB;
|
||||
cinfo.out_color_components=3;
|
||||
}
|
||||
cinfo.output_gamma=2.2;
|
||||
cinfo.do_fancy_upsampling=FALSE;
|
||||
|
||||
// reject unreasonable sizes
|
||||
if (!checkImageDimensions(cinfo.image_width, cinfo.image_height))
|
||||
longjmp(jerr.setjmp_buffer, 1);
|
||||
|
||||
// Start decompressor
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
// Get image data
|
||||
u32 rowspan = cinfo.image_width * cinfo.out_color_components;
|
||||
u32 width = cinfo.image_width;
|
||||
u32 height = cinfo.image_height;
|
||||
|
||||
// Allocate memory for buffer
|
||||
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];
|
||||
|
||||
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 );
|
||||
|
||||
delete [] rowPtr;
|
||||
// Finish decompression
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
// Release JPEG decompression object
|
||||
// This is an important step since it will release a good deal of memory.
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
// convert image
|
||||
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)
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
delete [] output;
|
||||
}
|
||||
else
|
||||
image = new CImage(ECF_R8G8B8,
|
||||
core::dimension2d<u32>(width, height), output);
|
||||
|
||||
delete [] input;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! creates a loader which is able to load jpeg images
|
||||
IImageLoader* createImageLoaderJPG()
|
||||
{
|
||||
return new CImageLoaderJPG();
|
||||
}
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderJPG.h"
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "CImage.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CImageLoaderJPG::CImageLoaderJPG()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageLoaderJPG");
|
||||
#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
|
||||
{
|
||||
return core::hasFileExtension ( filename, "jpg", "jpeg" );
|
||||
}
|
||||
|
||||
// struct for handling jpeg errors
|
||||
struct irr_jpeg_error_mgr
|
||||
{
|
||||
// public jpeg error fields
|
||||
struct jpeg_error_mgr pub;
|
||||
|
||||
// for longjmp, to return to caller on a fatal error
|
||||
jmp_buf setjmp_buffer;
|
||||
|
||||
// for having access to the filename when printing the error messages
|
||||
core::stringc* filename;
|
||||
};
|
||||
|
||||
void CImageLoaderJPG::init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean CImageLoaderJPG::fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
// DO NOTHING
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CImageLoaderJPG::skip_input_data (j_decompress_ptr cinfo, long count)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
|
||||
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 really points to a irr_error_mgr struct
|
||||
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.
|
||||
c8 temp1[JMSG_LENGTH_MAX];
|
||||
(*cinfo->err->format_message)(cinfo, temp1);
|
||||
core::stringc errMsg("JPEG FATAL ERROR in ");
|
||||
|
||||
irr_jpeg_error_mgr* myerr = (irr_jpeg_error_mgr*)cinfo->err;
|
||||
errMsg += *myerr->filename;
|
||||
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
|
||||
{
|
||||
if (!(file && file->seek(0)))
|
||||
return false;
|
||||
unsigned char header[3];
|
||||
size_t headerLen = file->read(header, sizeof(header));
|
||||
return headerLen >= 3 && !memcmp(header, "\xFF\xD8\xFF", 3);
|
||||
}
|
||||
|
||||
//! creates a surface from the file
|
||||
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()];
|
||||
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.
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
cinfo.err->error_exit = error_exit;
|
||||
cinfo.err->output_message = output_message;
|
||||
jerr.filename = &filename;
|
||||
|
||||
// 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 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;
|
||||
|
||||
// return null pointer
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Now we can initialize the JPEG decompression object.
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
// specify data source
|
||||
jpeg_source_mgr jsrc;
|
||||
|
||||
// Set up data pointer
|
||||
jsrc.bytes_in_buffer = file->getSize();
|
||||
jsrc.next_input_byte = (JOCTET*)input;
|
||||
cinfo.src = &jsrc;
|
||||
|
||||
jsrc.init_source = init_source;
|
||||
jsrc.fill_input_buffer = fill_input_buffer;
|
||||
jsrc.skip_input_data = skip_input_data;
|
||||
jsrc.resync_to_restart = jpeg_resync_to_restart;
|
||||
jsrc.term_source = term_source;
|
||||
|
||||
// Decodes JPG input from whatever source
|
||||
// Does everything AFTER jpeg_create_decompress
|
||||
// and BEFORE jpeg_destroy_decompress
|
||||
// Caller is responsible for arranging these + setting up cinfo
|
||||
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
cinfo.out_color_space=JCS_RGB;
|
||||
cinfo.out_color_components=3;
|
||||
}
|
||||
cinfo.output_gamma=2.2;
|
||||
cinfo.do_fancy_upsampling=FALSE;
|
||||
|
||||
// reject unreasonable sizes
|
||||
if (!checkImageDimensions(cinfo.image_width, cinfo.image_height))
|
||||
longjmp(jerr.setjmp_buffer, 1);
|
||||
|
||||
// Start decompressor
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
// Get image data
|
||||
u32 rowspan = cinfo.image_width * cinfo.out_color_components;
|
||||
u32 width = cinfo.image_width;
|
||||
u32 height = cinfo.image_height;
|
||||
|
||||
// Allocate memory for buffer
|
||||
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];
|
||||
|
||||
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 );
|
||||
|
||||
delete [] rowPtr;
|
||||
// Finish decompression
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
// Release JPEG decompression object
|
||||
// This is an important step since it will release a good deal of memory.
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
// convert image
|
||||
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)
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
delete [] output;
|
||||
}
|
||||
else
|
||||
image = new CImage(ECF_R8G8B8,
|
||||
core::dimension2d<u32>(width, height), output);
|
||||
|
||||
delete [] input;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! creates a loader which is able to load jpeg images
|
||||
IImageLoader* createImageLoaderJPG()
|
||||
{
|
||||
return new CImageLoaderJPG();
|
||||
}
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,91 +1,91 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
#include <stdio.h> // 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();
|
||||
|
||||
//! destructor
|
||||
virtual ~CImageLoaderJPG();
|
||||
|
||||
//! 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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* loadImage(io::IReadFile* file) const override;
|
||||
|
||||
private:
|
||||
// several methods used via function pointers by jpeglib
|
||||
|
||||
/* Receives control for a fatal error. Information sufficient to
|
||||
generate the error message has been stored in cinfo->err; call
|
||||
output_message to display it. Control must NOT return to the caller;
|
||||
generally this routine will exit() or longjmp() somewhere.
|
||||
Typically you would override this routine to get rid of the exit()
|
||||
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);
|
||||
|
||||
/* output error messages via Irrlicht logger. */
|
||||
static void output_message(j_common_ptr cinfo);
|
||||
|
||||
/* Initialize source. This is called by jpeg_read_header() before any
|
||||
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);
|
||||
|
||||
/* This is called whenever bytes_in_buffer has reached zero and more
|
||||
data is wanted. In typical applications, it should read fresh data
|
||||
into the buffer (ignoring the current state of next_input_byte and
|
||||
bytes_in_buffer), reset the pointer & count to the start of the
|
||||
buffer, and return TRUE indicating that the buffer has been reloaded.
|
||||
It is not necessary to fill the buffer entirely, only to obtain at
|
||||
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);
|
||||
|
||||
/* Skip num_bytes worth of data. The buffer pointer and count should
|
||||
be advanced over num_bytes input bytes, refilling the buffer as
|
||||
needed. This is used to skip over a potentially large amount of
|
||||
uninteresting data (such as an APPn marker). In some applications
|
||||
it may be possible to optimize away the reading of the skipped data,
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
#include <stdio.h> // 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();
|
||||
|
||||
//! destructor
|
||||
virtual ~CImageLoaderJPG();
|
||||
|
||||
//! 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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* loadImage(io::IReadFile* file) const override;
|
||||
|
||||
private:
|
||||
// several methods used via function pointers by jpeglib
|
||||
|
||||
/* Receives control for a fatal error. Information sufficient to
|
||||
generate the error message has been stored in cinfo->err; call
|
||||
output_message to display it. Control must NOT return to the caller;
|
||||
generally this routine will exit() or longjmp() somewhere.
|
||||
Typically you would override this routine to get rid of the exit()
|
||||
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);
|
||||
|
||||
/* output error messages via Irrlicht logger. */
|
||||
static void output_message(j_common_ptr cinfo);
|
||||
|
||||
/* Initialize source. This is called by jpeg_read_header() before any
|
||||
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);
|
||||
|
||||
/* This is called whenever bytes_in_buffer has reached zero and more
|
||||
data is wanted. In typical applications, it should read fresh data
|
||||
into the buffer (ignoring the current state of next_input_byte and
|
||||
bytes_in_buffer), reset the pointer & count to the start of the
|
||||
buffer, and return TRUE indicating that the buffer has been reloaded.
|
||||
It is not necessary to fill the buffer entirely, only to obtain at
|
||||
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);
|
||||
|
||||
/* Skip num_bytes worth of data. The buffer pointer and count should
|
||||
be advanced over num_bytes input bytes, refilling the buffer as
|
||||
needed. This is used to skip over a potentially large amount of
|
||||
uninteresting data (such as an APPn marker). In some applications
|
||||
it may be possible to optimize away the reading of the skipped data,
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,265 +1,265 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderPNG.h"
|
||||
|
||||
#include <png.h> // use system lib png
|
||||
|
||||
#include "CImage.h"
|
||||
#include "CReadFile.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// PNG function for error handling
|
||||
static void png_cpexcept_error(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG fatal error", msg, ELL_ERROR);
|
||||
longjmp(png_jmpbuf(png_ptr), 1);
|
||||
}
|
||||
|
||||
// PNG function for warning handling
|
||||
static void png_cpexcept_warn(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG warning", msg, ELL_WARNING);
|
||||
}
|
||||
|
||||
// PNG function for file reading
|
||||
void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
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);
|
||||
// }
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
png_byte buffer[8];
|
||||
// Read the first few bytes of the PNG file
|
||||
if (file->read(buffer, 8) != 8)
|
||||
return false;
|
||||
|
||||
// Check if it really is a PNG file
|
||||
return !png_sig_cmp(buffer, 0, 8);
|
||||
}
|
||||
|
||||
|
||||
// load in the image data
|
||||
IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
if (!file)
|
||||
return 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 )
|
||||
{
|
||||
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) )
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
delete [] RowPointers;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// changed by zola so we don't need to have public FILE pointers
|
||||
png_set_read_fn(png_ptr, file, user_read_data_fcn);
|
||||
|
||||
png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature
|
||||
|
||||
png_read_info(png_ptr, info_ptr); // Read the info section of the png file
|
||||
|
||||
u32 Width;
|
||||
u32 Height;
|
||||
s32 BitDepth;
|
||||
s32 ColorType;
|
||||
{
|
||||
// Use temporary variables to avoid passing cast pointers
|
||||
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;
|
||||
}
|
||||
|
||||
if (!checkImageDimensions(Width, Height))
|
||||
png_cpexcept_error(png_ptr, "Unreasonable size");
|
||||
|
||||
// Convert palette color to true color
|
||||
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)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
else
|
||||
png_set_packing(png_ptr);
|
||||
}
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
|
||||
// Convert high bit colors to 8 bit colors
|
||||
if (BitDepth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
// Convert gray color to true color
|
||||
if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
int intent;
|
||||
const double screen_gamma = 2.2;
|
||||
|
||||
if (png_get_sRGB(png_ptr, info_ptr, &intent))
|
||||
png_set_gamma(png_ptr, screen_gamma, 0.45455);
|
||||
else
|
||||
{
|
||||
double image_gamma;
|
||||
if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
|
||||
png_set_gamma(png_ptr, screen_gamma, image_gamma);
|
||||
else
|
||||
png_set_gamma(png_ptr, screen_gamma, 0.45455);
|
||||
}
|
||||
|
||||
// Update the changes in between, as we need to get the new color type
|
||||
// for proper processing of the RGBA type
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
{
|
||||
// Use temporary variables to avoid passing cast pointers
|
||||
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;
|
||||
}
|
||||
|
||||
// Convert RGBA to BGRA
|
||||
if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
png_set_swap_alpha(png_ptr);
|
||||
#else
|
||||
png_set_bgr(png_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create the image structure to be filled by png data
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Create array of pointers to rows in image data
|
||||
RowPointers = new png_bytep[Height];
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
data += image->getPitch();
|
||||
}
|
||||
|
||||
// for proper error handling
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
delete [] RowPointers;
|
||||
delete image;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read data using the library function that handles all transformations including interlacing
|
||||
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
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
IImageLoader* createImageLoaderPNG()
|
||||
{
|
||||
return new CImageLoaderPng();
|
||||
}
|
||||
|
||||
|
||||
}// end namespace irr
|
||||
}//end namespace video
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderPNG.h"
|
||||
|
||||
#include <png.h> // use system lib png
|
||||
|
||||
#include "CImage.h"
|
||||
#include "CReadFile.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// PNG function for error handling
|
||||
static void png_cpexcept_error(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG fatal error", msg, ELL_ERROR);
|
||||
longjmp(png_jmpbuf(png_ptr), 1);
|
||||
}
|
||||
|
||||
// PNG function for warning handling
|
||||
static void png_cpexcept_warn(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG warning", msg, ELL_WARNING);
|
||||
}
|
||||
|
||||
// PNG function for file reading
|
||||
void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
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);
|
||||
// }
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
png_byte buffer[8];
|
||||
// Read the first few bytes of the PNG file
|
||||
if (file->read(buffer, 8) != 8)
|
||||
return false;
|
||||
|
||||
// Check if it really is a PNG file
|
||||
return !png_sig_cmp(buffer, 0, 8);
|
||||
}
|
||||
|
||||
|
||||
// load in the image data
|
||||
IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
if (!file)
|
||||
return 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 )
|
||||
{
|
||||
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) )
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
delete [] RowPointers;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// changed by zola so we don't need to have public FILE pointers
|
||||
png_set_read_fn(png_ptr, file, user_read_data_fcn);
|
||||
|
||||
png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature
|
||||
|
||||
png_read_info(png_ptr, info_ptr); // Read the info section of the png file
|
||||
|
||||
u32 Width;
|
||||
u32 Height;
|
||||
s32 BitDepth;
|
||||
s32 ColorType;
|
||||
{
|
||||
// Use temporary variables to avoid passing cast pointers
|
||||
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;
|
||||
}
|
||||
|
||||
if (!checkImageDimensions(Width, Height))
|
||||
png_cpexcept_error(png_ptr, "Unreasonable size");
|
||||
|
||||
// Convert palette color to true color
|
||||
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)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
else
|
||||
png_set_packing(png_ptr);
|
||||
}
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
|
||||
// Convert high bit colors to 8 bit colors
|
||||
if (BitDepth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
// Convert gray color to true color
|
||||
if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
int intent;
|
||||
const double screen_gamma = 2.2;
|
||||
|
||||
if (png_get_sRGB(png_ptr, info_ptr, &intent))
|
||||
png_set_gamma(png_ptr, screen_gamma, 0.45455);
|
||||
else
|
||||
{
|
||||
double image_gamma;
|
||||
if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
|
||||
png_set_gamma(png_ptr, screen_gamma, image_gamma);
|
||||
else
|
||||
png_set_gamma(png_ptr, screen_gamma, 0.45455);
|
||||
}
|
||||
|
||||
// Update the changes in between, as we need to get the new color type
|
||||
// for proper processing of the RGBA type
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
{
|
||||
// Use temporary variables to avoid passing cast pointers
|
||||
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;
|
||||
}
|
||||
|
||||
// Convert RGBA to BGRA
|
||||
if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
png_set_swap_alpha(png_ptr);
|
||||
#else
|
||||
png_set_bgr(png_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create the image structure to be filled by png data
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Create array of pointers to rows in image data
|
||||
RowPointers = new png_bytep[Height];
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
data += image->getPitch();
|
||||
}
|
||||
|
||||
// for proper error handling
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
delete [] RowPointers;
|
||||
delete image;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read data using the library function that handles all transformations including interlacing
|
||||
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
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
IImageLoader* createImageLoaderPNG()
|
||||
{
|
||||
return new CImageLoaderPng();
|
||||
}
|
||||
|
||||
|
||||
}// end namespace irr
|
||||
}//end namespace video
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// this file was created by rt (www.tomkorp.com), based on ttk's png-reader
|
||||
// i wanted to be able to read in PNG images with irrlicht :)
|
||||
// why? lossless compression with 8-bit alpha channel!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Surface Loader for PNG files
|
||||
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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* loadImage(io::IReadFile* file) const override;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// this file was created by rt (www.tomkorp.com), based on ttk's png-reader
|
||||
// i wanted to be able to read in PNG images with irrlicht :)
|
||||
// why? lossless compression with 8-bit alpha channel!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Surface Loader for PNG files
|
||||
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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* loadImage(io::IReadFile* file) const override;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,238 +1,238 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderTGA.h"
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "os.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return core::hasFileExtension ( filename, "tga" );
|
||||
}
|
||||
|
||||
|
||||
//! loads a compressed tga.
|
||||
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.
|
||||
|
||||
s32 bytesPerPixel = header.PixelDepth/8;
|
||||
s32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel;
|
||||
u8* data = new u8[imageSize];
|
||||
s32 currentByte = 0;
|
||||
|
||||
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
|
||||
{
|
||||
chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels
|
||||
|
||||
file->read(&data[currentByte], bytesPerPixel * chunkheader);
|
||||
currentByte += bytesPerPixel * chunkheader;
|
||||
}
|
||||
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
|
||||
|
||||
s32 dataOffset = currentByte;
|
||||
file->read(&data[dataOffset], bytesPerPixel);
|
||||
|
||||
currentByte += bytesPerPixel;
|
||||
|
||||
for(s32 counter = 1; counter < chunkheader; counter++)
|
||||
{
|
||||
for(s32 elementCounter=0; elementCounter < bytesPerPixel; elementCounter++)
|
||||
data[currentByte + elementCounter] = data[dataOffset + elementCounter];
|
||||
|
||||
currentByte += bytesPerPixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
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->read(&footer, sizeof(STGAFooter));
|
||||
return (!strcmp(footer.Signature,"TRUEVISION-XFILE.")); // very old tgas are refused.
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
STGAHeader header;
|
||||
u32 *palette = 0;
|
||||
|
||||
file->read(&header, sizeof(STGAHeader));
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
header.ColorMapLength = os::Byteswap::byteswap(header.ColorMapLength);
|
||||
header.ImageWidth = os::Byteswap::byteswap(header.ImageWidth);
|
||||
header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight);
|
||||
#endif
|
||||
|
||||
if (!checkImageDimensions(header.ImageWidth, header.ImageHeight))
|
||||
{
|
||||
os::Printer::log("Image dimensions too large in file", file->getFileName(), ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip image identification field
|
||||
if (header.IdLength)
|
||||
file->seek(header.IdLength, true);
|
||||
|
||||
if (header.ColorMapType)
|
||||
{
|
||||
// create 32 bit palette
|
||||
palette = new u32[ header.ColorMapLength];
|
||||
|
||||
// read color map
|
||||
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;
|
||||
}
|
||||
delete [] colorMap;
|
||||
}
|
||||
|
||||
// read image
|
||||
|
||||
u8* data = 0;
|
||||
|
||||
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;
|
||||
data = new u8[imageSize];
|
||||
file->read(data, imageSize);
|
||||
}
|
||||
else
|
||||
if(header.ImageType == 10)
|
||||
{
|
||||
// Runlength encoded RGB images
|
||||
data = loadCompressedImage(file, header);
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR);
|
||||
delete [] palette;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IImage* image = 0;
|
||||
|
||||
switch(header.PixelDepth)
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
if (header.ImageType==3) // grey image
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
case 16:
|
||||
image = new CImage(ECF_A1R5G5B5,
|
||||
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);
|
||||
break;
|
||||
case 24:
|
||||
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);
|
||||
break;
|
||||
case 32:
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
delete [] palette;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
//! creates a loader which is able to load tgas
|
||||
IImageLoader* createImageLoaderTGA()
|
||||
{
|
||||
return new CImageLoaderTGA();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageLoaderTGA.h"
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "os.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return core::hasFileExtension ( filename, "tga" );
|
||||
}
|
||||
|
||||
|
||||
//! loads a compressed tga.
|
||||
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.
|
||||
|
||||
s32 bytesPerPixel = header.PixelDepth/8;
|
||||
s32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel;
|
||||
u8* data = new u8[imageSize];
|
||||
s32 currentByte = 0;
|
||||
|
||||
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
|
||||
{
|
||||
chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels
|
||||
|
||||
file->read(&data[currentByte], bytesPerPixel * chunkheader);
|
||||
currentByte += bytesPerPixel * chunkheader;
|
||||
}
|
||||
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
|
||||
|
||||
s32 dataOffset = currentByte;
|
||||
file->read(&data[dataOffset], bytesPerPixel);
|
||||
|
||||
currentByte += bytesPerPixel;
|
||||
|
||||
for(s32 counter = 1; counter < chunkheader; counter++)
|
||||
{
|
||||
for(s32 elementCounter=0; elementCounter < bytesPerPixel; elementCounter++)
|
||||
data[currentByte + elementCounter] = data[dataOffset + elementCounter];
|
||||
|
||||
currentByte += bytesPerPixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
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->read(&footer, sizeof(STGAFooter));
|
||||
return (!strcmp(footer.Signature,"TRUEVISION-XFILE.")); // very old tgas are refused.
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! creates a surface from the file
|
||||
IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
STGAHeader header;
|
||||
u32 *palette = 0;
|
||||
|
||||
file->read(&header, sizeof(STGAHeader));
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
header.ColorMapLength = os::Byteswap::byteswap(header.ColorMapLength);
|
||||
header.ImageWidth = os::Byteswap::byteswap(header.ImageWidth);
|
||||
header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight);
|
||||
#endif
|
||||
|
||||
if (!checkImageDimensions(header.ImageWidth, header.ImageHeight))
|
||||
{
|
||||
os::Printer::log("Image dimensions too large in file", file->getFileName(), ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip image identification field
|
||||
if (header.IdLength)
|
||||
file->seek(header.IdLength, true);
|
||||
|
||||
if (header.ColorMapType)
|
||||
{
|
||||
// create 32 bit palette
|
||||
palette = new u32[ header.ColorMapLength];
|
||||
|
||||
// read color map
|
||||
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;
|
||||
}
|
||||
delete [] colorMap;
|
||||
}
|
||||
|
||||
// read image
|
||||
|
||||
u8* data = 0;
|
||||
|
||||
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;
|
||||
data = new u8[imageSize];
|
||||
file->read(data, imageSize);
|
||||
}
|
||||
else
|
||||
if(header.ImageType == 10)
|
||||
{
|
||||
// Runlength encoded RGB images
|
||||
data = loadCompressedImage(file, header);
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR);
|
||||
delete [] palette;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IImage* image = 0;
|
||||
|
||||
switch(header.PixelDepth)
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
if (header.ImageType==3) // grey image
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
case 16:
|
||||
image = new CImage(ECF_A1R5G5B5,
|
||||
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);
|
||||
break;
|
||||
case 24:
|
||||
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);
|
||||
break;
|
||||
case 32:
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
delete [] palette;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
//! creates a loader which is able to load tgas
|
||||
IImageLoader* createImageLoaderTGA()
|
||||
{
|
||||
return new CImageLoaderTGA();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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;
|
||||
|
||||
struct STGAFooter
|
||||
{
|
||||
u32 ExtensionOffset;
|
||||
u32 DeveloperOffset;
|
||||
c8 Signature[18];
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
/*!
|
||||
Surface Loader for targa images
|
||||
*/
|
||||
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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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;
|
||||
|
||||
struct STGAFooter
|
||||
{
|
||||
u32 ExtensionOffset;
|
||||
u32 DeveloperOffset;
|
||||
c8 Signature[18];
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
/*!
|
||||
Surface Loader for targa images
|
||||
*/
|
||||
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;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool isALoadableFileFormat(io::IReadFile* file) const override;
|
||||
|
||||
//! creates a surface from the file
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,213 +1,213 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageWriterJPG.h"
|
||||
|
||||
#include "CColorConverter.h"
|
||||
#include "IWriteFile.h"
|
||||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
#include "os.h"
|
||||
|
||||
#include <stdio.h> // required for jpeglib.h
|
||||
extern "C"
|
||||
{
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
}
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// The writer uses a 4k buffer and flushes to disk each time it's filled
|
||||
#define OUTPUT_BUF_SIZE 4096
|
||||
typedef struct
|
||||
{
|
||||
struct jpeg_destination_mgr pub;/* public fields */
|
||||
|
||||
io::IWriteFile* file; /* target file */
|
||||
JOCTET buffer[OUTPUT_BUF_SIZE]; /* image buffer */
|
||||
} mem_destination_mgr;
|
||||
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
// for now just exit upon file error
|
||||
if (dest->file->write(dest->buffer, OUTPUT_BUF_SIZE) != OUTPUT_BUF_SIZE)
|
||||
ERREXIT (cinfo, JERR_FILE_WRITE);
|
||||
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void jpeg_term_destination(j_compress_ptr cinfo)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// set up buffer data
|
||||
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));
|
||||
}
|
||||
|
||||
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; /* for casting */
|
||||
|
||||
/* Initialize method pointers */
|
||||
dest->pub.init_destination = jpeg_init_destination;
|
||||
dest->pub.empty_output_buffer = jpeg_empty_output_buffer;
|
||||
dest->pub.term_destination = jpeg_term_destination;
|
||||
|
||||
/* Initialize private member */
|
||||
dest->file = file;
|
||||
}
|
||||
|
||||
|
||||
/* write_JPEG_memory: store JPEG compressed image into memory.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
// couldn't find a color converter
|
||||
if ( 0 == format )
|
||||
return false;
|
||||
|
||||
const core::dimension2du dim = image->getDimension();
|
||||
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
|
||||
jpeg_create_compress(&cinfo);
|
||||
jpeg_file_dest(&cinfo, file);
|
||||
cinfo.image_width = dim.Width;
|
||||
cinfo.image_height = dim.Height;
|
||||
cinfo.input_components = 3;
|
||||
cinfo.in_color_space = JCS_RGB;
|
||||
|
||||
jpeg_set_defaults(&cinfo);
|
||||
|
||||
if ( 0 == quality )
|
||||
quality = 75;
|
||||
|
||||
jpeg_set_quality(&cinfo, quality, TRUE);
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
u8 * dest = new u8[dim.Width*3];
|
||||
|
||||
if (dest)
|
||||
{
|
||||
const u32 pitch = image->getPitch();
|
||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||
row_pointer[0] = dest;
|
||||
|
||||
u8* src = (u8*)image->getData();
|
||||
|
||||
while (cinfo.next_scanline < cinfo.image_height)
|
||||
{
|
||||
// convert next line
|
||||
format( src, dim.Width, dest );
|
||||
src += pitch;
|
||||
jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
|
||||
delete [] dest;
|
||||
|
||||
/* Step 6: Finish compression */
|
||||
jpeg_finish_compress(&cinfo);
|
||||
}
|
||||
|
||||
/* Step 7: Destroy */
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
return (dest != 0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
IImageWriter* createImageWriterJPG()
|
||||
{
|
||||
return new CImageWriterJPG;
|
||||
}
|
||||
|
||||
CImageWriterJPG::CImageWriterJPG()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageWriterJPG");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CImageWriterJPG::isAWriteableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "jpg", "jpeg" );
|
||||
}
|
||||
|
||||
|
||||
bool CImageWriterJPG::writeImage(io::IWriteFile *file, IImage *image, u32 quality) const
|
||||
{
|
||||
return writeJPEGFile(file, image, quality);
|
||||
}
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageWriterJPG.h"
|
||||
|
||||
#include "CColorConverter.h"
|
||||
#include "IWriteFile.h"
|
||||
#include "CImage.h"
|
||||
#include "irrString.h"
|
||||
#include "os.h"
|
||||
|
||||
#include <stdio.h> // required for jpeglib.h
|
||||
extern "C"
|
||||
{
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
}
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// The writer uses a 4k buffer and flushes to disk each time it's filled
|
||||
#define OUTPUT_BUF_SIZE 4096
|
||||
typedef struct
|
||||
{
|
||||
struct jpeg_destination_mgr pub;/* public fields */
|
||||
|
||||
io::IWriteFile* file; /* target file */
|
||||
JOCTET buffer[OUTPUT_BUF_SIZE]; /* image buffer */
|
||||
} mem_destination_mgr;
|
||||
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
// for now just exit upon file error
|
||||
if (dest->file->write(dest->buffer, OUTPUT_BUF_SIZE) != OUTPUT_BUF_SIZE)
|
||||
ERREXIT (cinfo, JERR_FILE_WRITE);
|
||||
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void jpeg_term_destination(j_compress_ptr cinfo)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// set up buffer data
|
||||
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));
|
||||
}
|
||||
|
||||
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; /* for casting */
|
||||
|
||||
/* Initialize method pointers */
|
||||
dest->pub.init_destination = jpeg_init_destination;
|
||||
dest->pub.empty_output_buffer = jpeg_empty_output_buffer;
|
||||
dest->pub.term_destination = jpeg_term_destination;
|
||||
|
||||
/* Initialize private member */
|
||||
dest->file = file;
|
||||
}
|
||||
|
||||
|
||||
/* write_JPEG_memory: store JPEG compressed image into memory.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
// couldn't find a color converter
|
||||
if ( 0 == format )
|
||||
return false;
|
||||
|
||||
const core::dimension2du dim = image->getDimension();
|
||||
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
|
||||
jpeg_create_compress(&cinfo);
|
||||
jpeg_file_dest(&cinfo, file);
|
||||
cinfo.image_width = dim.Width;
|
||||
cinfo.image_height = dim.Height;
|
||||
cinfo.input_components = 3;
|
||||
cinfo.in_color_space = JCS_RGB;
|
||||
|
||||
jpeg_set_defaults(&cinfo);
|
||||
|
||||
if ( 0 == quality )
|
||||
quality = 75;
|
||||
|
||||
jpeg_set_quality(&cinfo, quality, TRUE);
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
u8 * dest = new u8[dim.Width*3];
|
||||
|
||||
if (dest)
|
||||
{
|
||||
const u32 pitch = image->getPitch();
|
||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||
row_pointer[0] = dest;
|
||||
|
||||
u8* src = (u8*)image->getData();
|
||||
|
||||
while (cinfo.next_scanline < cinfo.image_height)
|
||||
{
|
||||
// convert next line
|
||||
format( src, dim.Width, dest );
|
||||
src += pitch;
|
||||
jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
|
||||
delete [] dest;
|
||||
|
||||
/* Step 6: Finish compression */
|
||||
jpeg_finish_compress(&cinfo);
|
||||
}
|
||||
|
||||
/* Step 7: Destroy */
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
return (dest != 0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
IImageWriter* createImageWriterJPG()
|
||||
{
|
||||
return new CImageWriterJPG;
|
||||
}
|
||||
|
||||
CImageWriterJPG::CImageWriterJPG()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageWriterJPG");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CImageWriterJPG::isAWriteableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "jpg", "jpeg" );
|
||||
}
|
||||
|
||||
|
||||
bool CImageWriterJPG::writeImage(io::IWriteFile *file, IImage *image, u32 quality) const
|
||||
{
|
||||
return writeJPEGFile(file, image, quality);
|
||||
}
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageWriter.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CImageWriterJPG : public IImageWriter
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CImageWriterJPG();
|
||||
|
||||
//! return true if this writer can write a file with the given extension
|
||||
bool isAWriteableFileExtension(const io::path& filename) const override;
|
||||
|
||||
//! write image to file
|
||||
bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageWriter.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CImageWriterJPG : public IImageWriter
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CImageWriterJPG();
|
||||
|
||||
//! return true if this writer can write a file with the given extension
|
||||
bool isAWriteableFileExtension(const io::path& filename) const override;
|
||||
|
||||
//! write image to file
|
||||
bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,201 +1,201 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageWriterPNG.h"
|
||||
|
||||
#include "CImageLoaderPNG.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "IWriteFile.h"
|
||||
#include "irrString.h"
|
||||
#include "os.h" // for logging
|
||||
|
||||
#include <png.h> // use system lib png
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
IImageWriter* createImageWriterPNG()
|
||||
{
|
||||
return new CImageWriterPNG;
|
||||
}
|
||||
|
||||
// PNG function for error handling
|
||||
static void png_cpexcept_error(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG fatal error", msg, ELL_ERROR);
|
||||
longjmp(png_jmpbuf(png_ptr), 1);
|
||||
}
|
||||
|
||||
// PNG function for warning handling
|
||||
static void png_cpexcept_warning(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG warning", msg, ELL_WARNING);
|
||||
}
|
||||
|
||||
// PNG function for file writing
|
||||
void PNGAPI user_write_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
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);
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
|
||||
CImageWriterPNG::CImageWriterPNG()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageWriterPNG");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CImageWriterPNG::isAWriteableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "png" );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
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())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
case ECF_R5G6B5:
|
||||
lineWidth*=3;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
case ECF_A1R5G5B5:
|
||||
lineWidth*=4;
|
||||
break;
|
||||
// TODO: Error handling in case of unsupported color format
|
||||
default:
|
||||
break;
|
||||
}
|
||||
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())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
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);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
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);
|
||||
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;
|
||||
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)
|
||||
{
|
||||
os::Printer::log("PNGWriter: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
delete [] tmpImage;
|
||||
return false;
|
||||
}
|
||||
|
||||
data=tmpImage;
|
||||
// Fill array of pointers to rows in image 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)))
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
delete [] RowPointers;
|
||||
delete [] tmpImage;
|
||||
return false;
|
||||
}
|
||||
|
||||
png_set_rows(png_ptr, info_ptr, RowPointers);
|
||||
|
||||
if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5)
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL);
|
||||
else
|
||||
{
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
}
|
||||
|
||||
delete [] RowPointers;
|
||||
delete [] tmpImage;
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CImageWriterPNG.h"
|
||||
|
||||
#include "CImageLoaderPNG.h"
|
||||
#include "CColorConverter.h"
|
||||
#include "IWriteFile.h"
|
||||
#include "irrString.h"
|
||||
#include "os.h" // for logging
|
||||
|
||||
#include <png.h> // use system lib png
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
IImageWriter* createImageWriterPNG()
|
||||
{
|
||||
return new CImageWriterPNG;
|
||||
}
|
||||
|
||||
// PNG function for error handling
|
||||
static void png_cpexcept_error(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG fatal error", msg, ELL_ERROR);
|
||||
longjmp(png_jmpbuf(png_ptr), 1);
|
||||
}
|
||||
|
||||
// PNG function for warning handling
|
||||
static void png_cpexcept_warning(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
os::Printer::log("PNG warning", msg, ELL_WARNING);
|
||||
}
|
||||
|
||||
// PNG function for file writing
|
||||
void PNGAPI user_write_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
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);
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
|
||||
CImageWriterPNG::CImageWriterPNG()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CImageWriterPNG");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CImageWriterPNG::isAWriteableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "png" );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
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())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
case ECF_R5G6B5:
|
||||
lineWidth*=3;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
case ECF_A1R5G5B5:
|
||||
lineWidth*=4;
|
||||
break;
|
||||
// TODO: Error handling in case of unsupported color format
|
||||
default:
|
||||
break;
|
||||
}
|
||||
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())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
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);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
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);
|
||||
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;
|
||||
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)
|
||||
{
|
||||
os::Printer::log("PNGWriter: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
delete [] tmpImage;
|
||||
return false;
|
||||
}
|
||||
|
||||
data=tmpImage;
|
||||
// Fill array of pointers to rows in image 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)))
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
delete [] RowPointers;
|
||||
delete [] tmpImage;
|
||||
return false;
|
||||
}
|
||||
|
||||
png_set_rows(png_ptr, info_ptr, RowPointers);
|
||||
|
||||
if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5)
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL);
|
||||
else
|
||||
{
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
}
|
||||
|
||||
delete [] RowPointers;
|
||||
delete [] tmpImage;
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageWriter.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CImageWriterPNG : public IImageWriter
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CImageWriterPNG();
|
||||
|
||||
//! return true if this writer can write a file with the given extension
|
||||
bool isAWriteableFileExtension(const io::path& filename) const override;
|
||||
|
||||
//! write image to file
|
||||
bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const override;
|
||||
};
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IImageWriter.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CImageWriterPNG : public IImageWriter
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CImageWriterPNG();
|
||||
|
||||
//! return true if this writer can write a file with the given extension
|
||||
bool isAWriteableFileExtension(const io::path& filename) const override;
|
||||
|
||||
//! write image to file
|
||||
bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const override;
|
||||
};
|
||||
|
||||
} // namespace video
|
||||
} // namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,483 +1,483 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "ICursorControl.h"
|
||||
#include "os.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#ifdef _IRR_LINUX_X11_XINPUT2_
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define KeySym s32
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
~CCursorControl();
|
||||
|
||||
//! 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
|
||||
}
|
||||
|
||||
//! 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
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
|
||||
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,
|
||||
DeviceId,
|
||||
None,
|
||||
Device->XWindow, 0, 0,
|
||||
Device->Width,
|
||||
Device->Height,
|
||||
ReferenceRect.UpperLeftCorner.X + x,
|
||||
ReferenceRect.UpperLeftCorner.Y + y);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
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,
|
||||
DeviceId,
|
||||
None,
|
||||
Device->XWindow, 0, 0,
|
||||
Device->Width,
|
||||
Device->Height, x, y);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
XWarpPointer(Device->XDisplay,
|
||||
None,
|
||||
Device->XWindow, 0, 0,
|
||||
Device->Width,
|
||||
Device->Height, x, y);
|
||||
}
|
||||
}
|
||||
XFlush(Device->XDisplay);
|
||||
}
|
||||
#endif
|
||||
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.
|
||||
core::position2d<f32> getRelativePosition(bool updateCursor) override
|
||||
{
|
||||
if ( updateCursor )
|
||||
updateCursorPos();
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
//! 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; }
|
||||
|
||||
void update();
|
||||
void clearCursors();
|
||||
#endif
|
||||
private:
|
||||
|
||||
void updateCursorPos()
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
if (Null)
|
||||
return;
|
||||
|
||||
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,
|
||||
&tmp, &tmp,
|
||||
&itmp1, &itmp2,
|
||||
&CursorPos.X, &CursorPos.Y, &maskreturn);
|
||||
#endif
|
||||
}
|
||||
|
||||
CIrrDeviceLinux* Device;
|
||||
core::position2d<s32> CursorPos;
|
||||
core::rect<s32> ReferenceRect;
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior;
|
||||
u32 LastQuery;
|
||||
Cursor InvisCursor;
|
||||
|
||||
#ifdef _IRR_LINUX_X11_XINPUT2_
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_X11_DEVICE_
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "ICursorControl.h"
|
||||
#include "os.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#ifdef _IRR_LINUX_X11_XINPUT2_
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define KeySym s32
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
~CCursorControl();
|
||||
|
||||
//! 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
|
||||
}
|
||||
|
||||
//! 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
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
|
||||
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,
|
||||
DeviceId,
|
||||
None,
|
||||
Device->XWindow, 0, 0,
|
||||
Device->Width,
|
||||
Device->Height,
|
||||
ReferenceRect.UpperLeftCorner.X + x,
|
||||
ReferenceRect.UpperLeftCorner.Y + y);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
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,
|
||||
DeviceId,
|
||||
None,
|
||||
Device->XWindow, 0, 0,
|
||||
Device->Width,
|
||||
Device->Height, x, y);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
XWarpPointer(Device->XDisplay,
|
||||
None,
|
||||
Device->XWindow, 0, 0,
|
||||
Device->Width,
|
||||
Device->Height, x, y);
|
||||
}
|
||||
}
|
||||
XFlush(Device->XDisplay);
|
||||
}
|
||||
#endif
|
||||
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.
|
||||
core::position2d<f32> getRelativePosition(bool updateCursor) override
|
||||
{
|
||||
if ( updateCursor )
|
||||
updateCursorPos();
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
//! 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; }
|
||||
|
||||
void update();
|
||||
void clearCursors();
|
||||
#endif
|
||||
private:
|
||||
|
||||
void updateCursorPos()
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
if (Null)
|
||||
return;
|
||||
|
||||
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,
|
||||
&tmp, &tmp,
|
||||
&itmp1, &itmp2,
|
||||
&CursorPos.X, &CursorPos.Y, &maskreturn);
|
||||
#endif
|
||||
}
|
||||
|
||||
CIrrDeviceLinux* Device;
|
||||
core::position2d<s32> CursorPos;
|
||||
core::rect<s32> ReferenceRect;
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior;
|
||||
u32 LastQuery;
|
||||
Cursor InvisCursor;
|
||||
|
||||
#ifdef _IRR_LINUX_X11_XINPUT2_
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_X11_DEVICE_
|
||||
|
||||
@@ -1,249 +1,249 @@
|
||||
// Copyright (C) 2005-2006 Etienne Petitjean
|
||||
// Copyright (C) 2007-2012 Christian Stehno
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
#import <AppKit/NSWindow.h>
|
||||
#import <AppKit/NSBitmapImageRep.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
class CIrrDeviceMacOSX;
|
||||
}
|
||||
|
||||
@interface CIrrDelegateOSX : NSObject
|
||||
|
||||
- (id)initWithDevice:(irr::CIrrDeviceMacOSX*)device;
|
||||
- (void)terminate:(id)sender;
|
||||
- (BOOL)isQuit;
|
||||
|
||||
@end
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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:
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_
|
||||
// Copyright (C) 2005-2006 Etienne Petitjean
|
||||
// Copyright (C) 2007-2012 Christian Stehno
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
#import <AppKit/NSWindow.h>
|
||||
#import <AppKit/NSBitmapImageRep.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
class CIrrDeviceMacOSX;
|
||||
}
|
||||
|
||||
@interface CIrrDelegateOSX : NSObject
|
||||
|
||||
- (id)initWithDevice:(irr::CIrrDeviceMacOSX*)device;
|
||||
- (void)terminate:(id)sender;
|
||||
- (BOOL)isQuit;
|
||||
|
||||
@end
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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:
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_
|
||||
|
||||
@@ -471,12 +471,12 @@ static bool firstLaunch = true;
|
||||
- (id)initWithDevice:(irr::CIrrDeviceMacOSX*)device
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
Device = device;
|
||||
|
||||
|
||||
Quit = false;
|
||||
|
||||
|
||||
return (self);
|
||||
}
|
||||
|
||||
@@ -528,7 +528,7 @@ static bool firstLaunch = true;
|
||||
{
|
||||
NSWindow *window;
|
||||
NSRect frame;
|
||||
|
||||
|
||||
window = [aNotification object];
|
||||
frame = [window frame];
|
||||
Device->setResize((int)frame.size.width,(int)frame.size.height);
|
||||
@@ -646,15 +646,15 @@ bool CIrrDeviceMacOSX::createWindow()
|
||||
CGDisplayErr error;
|
||||
bool result = false;
|
||||
Display = CGMainDisplayID();
|
||||
|
||||
|
||||
CGRect displayRect;
|
||||
CGDisplayModeRef displaymode, olddisplaymode;
|
||||
|
||||
|
||||
ScreenWidth = (int)CGDisplayPixelsWide(Display);
|
||||
ScreenHeight = (int)CGDisplayPixelsHigh(Display);
|
||||
|
||||
|
||||
const NSBackingStoreType type = (CreationParams.DriverType == video::EDT_OPENGL) ? NSBackingStoreBuffered : NSBackingStoreNonretained;
|
||||
|
||||
|
||||
// TODO: fullscreen
|
||||
//if (!CreationParams.Fullscreen)
|
||||
{
|
||||
@@ -662,25 +662,25 @@ bool CIrrDeviceMacOSX::createWindow()
|
||||
{
|
||||
int x = (CreationParams.WindowPosition.X > 0) ? CreationParams.WindowPosition.X : 0;
|
||||
int y = (CreationParams.WindowPosition.Y > 0) ? CreationParams.WindowPosition.Y : 0;
|
||||
|
||||
|
||||
if (CreationParams.WindowPosition.Y > -1)
|
||||
{
|
||||
int screenHeight = [[[NSScreen screens] objectAtIndex:0] frame].size.height;
|
||||
y = screenHeight - y - CreationParams.WindowSize.Height;
|
||||
}
|
||||
|
||||
|
||||
Window = [[NSWindow alloc] initWithContentRect:NSMakeRect(x, y, CreationParams.WindowSize.Width,CreationParams.WindowSize.Height) styleMask:NSTitledWindowMask+NSClosableWindowMask+NSResizableWindowMask backing:type defer:FALSE];
|
||||
|
||||
if (CreationParams.WindowPosition.X == -1 && CreationParams.WindowPosition.Y == -1)
|
||||
[Window center];
|
||||
}
|
||||
|
||||
|
||||
DeviceWidth = CreationParams.WindowSize.Width;
|
||||
DeviceHeight = CreationParams.WindowSize.Height;
|
||||
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (Window)
|
||||
@@ -691,7 +691,7 @@ bool CIrrDeviceMacOSX::createWindow()
|
||||
[Window makeKeyAndOrderFront:nil];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ void CIrrDeviceMacOSX::setResize(int width, int height)
|
||||
if (CreationParams.DriverType == video::EDT_OPENGL)
|
||||
{
|
||||
NSOpenGLContext* Context = (NSOpenGLContext*)ContextManager->getContext().OpenGLOSX.Context;
|
||||
|
||||
|
||||
if (Context)
|
||||
[Context update];
|
||||
}
|
||||
@@ -741,13 +741,13 @@ void CIrrDeviceMacOSX::createDriver()
|
||||
{
|
||||
os::Printer::log("Could not create OpenGL driver.", ELL_ERROR);
|
||||
}
|
||||
|
||||
if (Window)
|
||||
|
||||
if (Window)
|
||||
{
|
||||
[[Window contentView] setWantsBestResolutionOpenGLSurface:NO];
|
||||
[(NSOpenGLContext*)ContextManager->getContext().OpenGLOSX.Context setView:[Window contentView]];
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
[(NSView*)CreationParams.WindowId setWantsBestResolutionOpenGLSurface:NO];
|
||||
[(NSOpenGLContext*)ContextManager->getContext().OpenGLOSX.Context setView:(NSView*)CreationParams.WindowId];
|
||||
@@ -1082,7 +1082,7 @@ void CIrrDeviceMacOSX::postMouseEvent(void *event,irr::SEvent &ievent)
|
||||
{
|
||||
ievent.MouseInput.Shift = ([(NSEvent *)event modifierFlags] & NSShiftKeyMask) != 0;
|
||||
ievent.MouseInput.Control = ([(NSEvent *)event modifierFlags] & NSControlKeyMask) != 0;
|
||||
|
||||
|
||||
postEventFromUser(ievent);
|
||||
}
|
||||
|
||||
@@ -1162,8 +1162,8 @@ void CIrrDeviceMacOSX::setCursorVisible(bool visible)
|
||||
else
|
||||
CGDisplayHideCursor(CGMainDisplayID());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CIrrDeviceMacOSX::setWindow(NSWindow* window)
|
||||
{
|
||||
Window = window;
|
||||
@@ -1326,7 +1326,7 @@ void CIrrDeviceMacOSX::restoreWindow()
|
||||
{
|
||||
[Window deminiaturize:[NSApp self]];
|
||||
}
|
||||
|
||||
|
||||
//! Get the position of this window on screen
|
||||
core::position2di CIrrDeviceMacOSX::getWindowPosition()
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,325 +1,325 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
// This device code is based on the original SDL device implementation
|
||||
// contributed by Shane Parker (sirshane).
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
|
||||
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
|
||||
#include <emscripten/html5.h>
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
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:
|
||||
|
||||
CCursorControl(CIrrDeviceSDL* dev)
|
||||
: Device(dev), IsVisible(true)
|
||||
{
|
||||
initCursors();
|
||||
}
|
||||
|
||||
//! 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 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,
|
||||
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 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;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
// 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();
|
||||
|
||||
//! create the driver
|
||||
void createDriver();
|
||||
|
||||
bool createWindow();
|
||||
|
||||
void createKeyMap();
|
||||
|
||||
void logAttributes();
|
||||
SDL_GLContext Context;
|
||||
SDL_Window *Window;
|
||||
int SDL_Flags;
|
||||
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
|
||||
core::array<SDL_Joystick*> Joysticks;
|
||||
#endif
|
||||
|
||||
s32 MouseX, MouseY;
|
||||
s32 MouseXRel, MouseYRel;
|
||||
u32 MouseButtonStates;
|
||||
|
||||
u32 Width, Height;
|
||||
|
||||
bool Resizable;
|
||||
|
||||
struct SKeyMap
|
||||
{
|
||||
SKeyMap() {}
|
||||
SKeyMap(s32 x11, s32 win32)
|
||||
: SDLKey(x11), Win32Key(win32)
|
||||
{
|
||||
}
|
||||
|
||||
s32 SDLKey;
|
||||
s32 Win32Key;
|
||||
|
||||
bool operator<(const SKeyMap& o) const
|
||||
{
|
||||
return SDLKey<o.SDLKey;
|
||||
}
|
||||
};
|
||||
|
||||
core::array<SKeyMap> KeyMap;
|
||||
SDL_SysWMinfo Info;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_SDL_DEVICE_
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
// This device code is based on the original SDL device implementation
|
||||
// contributed by Shane Parker (sirshane).
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
|
||||
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
|
||||
#include <emscripten/html5.h>
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
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:
|
||||
|
||||
CCursorControl(CIrrDeviceSDL* dev)
|
||||
: Device(dev), IsVisible(true)
|
||||
{
|
||||
initCursors();
|
||||
}
|
||||
|
||||
//! 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 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,
|
||||
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 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;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
// 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();
|
||||
|
||||
//! create the driver
|
||||
void createDriver();
|
||||
|
||||
bool createWindow();
|
||||
|
||||
void createKeyMap();
|
||||
|
||||
void logAttributes();
|
||||
SDL_GLContext Context;
|
||||
SDL_Window *Window;
|
||||
int SDL_Flags;
|
||||
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
|
||||
core::array<SDL_Joystick*> Joysticks;
|
||||
#endif
|
||||
|
||||
s32 MouseX, MouseY;
|
||||
s32 MouseXRel, MouseYRel;
|
||||
u32 MouseButtonStates;
|
||||
|
||||
u32 Width, Height;
|
||||
|
||||
bool Resizable;
|
||||
|
||||
struct SKeyMap
|
||||
{
|
||||
SKeyMap() {}
|
||||
SKeyMap(s32 x11, s32 win32)
|
||||
: SDLKey(x11), Win32Key(win32)
|
||||
{
|
||||
}
|
||||
|
||||
s32 SDLKey;
|
||||
s32 Win32Key;
|
||||
|
||||
bool operator<(const SKeyMap& o) const
|
||||
{
|
||||
return SDLKey<o.SDLKey;
|
||||
}
|
||||
};
|
||||
|
||||
core::array<SKeyMap> KeyMap;
|
||||
SDL_SysWMinfo Info;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_SDL_DEVICE_
|
||||
|
||||
@@ -1,412 +1,412 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IEventReceiver.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IGUIElement.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "os.h"
|
||||
#include "CTimer.h"
|
||||
#include "CLogger.h"
|
||||
#include "irrString.h"
|
||||
#include "IrrCompileConfig.h" // for IRRLICHT_SDK_VERSION
|
||||
|
||||
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)
|
||||
{
|
||||
Timer = new CTimer();
|
||||
if (os::Printer::Logger)
|
||||
{
|
||||
os::Printer::Logger->grab();
|
||||
Logger = (CLogger*)os::Printer::Logger;
|
||||
Logger->setReceiver(UserReceiver);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger = new CLogger(UserReceiver);
|
||||
os::Printer::Logger = Logger;
|
||||
}
|
||||
Logger->setLogLevel(CreationParams.LoggingLevel);
|
||||
|
||||
os::Printer::Logger = Logger;
|
||||
|
||||
FileSystem = io::createFileSystem();
|
||||
|
||||
core::stringc s = "Irrlicht Engine version ";
|
||||
s.append(getVersion());
|
||||
os::Printer::log(s.c_str(), ELL_INFORMATION);
|
||||
|
||||
checkVersion(params.SDK_version_do_not_use);
|
||||
}
|
||||
|
||||
|
||||
CIrrDeviceStub::~CIrrDeviceStub()
|
||||
{
|
||||
if (GUIEnvironment)
|
||||
GUIEnvironment->drop();
|
||||
|
||||
if (SceneManager)
|
||||
SceneManager->drop();
|
||||
|
||||
if (VideoDriver)
|
||||
VideoDriver->drop();
|
||||
|
||||
if (ContextManager)
|
||||
ContextManager->drop();
|
||||
|
||||
if ( FileSystem )
|
||||
FileSystem->drop();
|
||||
|
||||
if (InputReceivingSceneManager)
|
||||
InputReceivingSceneManager->drop();
|
||||
|
||||
if (CursorControl)
|
||||
CursorControl->drop();
|
||||
|
||||
if (Operator)
|
||||
Operator->drop();
|
||||
|
||||
CursorControl = 0;
|
||||
|
||||
if (Timer)
|
||||
Timer->drop();
|
||||
|
||||
if (Logger->drop())
|
||||
os::Printer::Logger = 0;
|
||||
}
|
||||
|
||||
|
||||
void CIrrDeviceStub::createGUIAndScene()
|
||||
{
|
||||
// create gui environment
|
||||
GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator);
|
||||
|
||||
// create Scene manager
|
||||
SceneManager = scene::createSceneManager(VideoDriver, CursorControl);
|
||||
|
||||
setEventReceiver(UserReceiver);
|
||||
}
|
||||
|
||||
|
||||
//! returns the video driver
|
||||
video::IVideoDriver* CIrrDeviceStub::getVideoDriver()
|
||||
{
|
||||
return VideoDriver;
|
||||
}
|
||||
|
||||
|
||||
//! return file system
|
||||
io::IFileSystem* CIrrDeviceStub::getFileSystem()
|
||||
{
|
||||
return FileSystem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the gui environment
|
||||
gui::IGUIEnvironment* CIrrDeviceStub::getGUIEnvironment()
|
||||
{
|
||||
return GUIEnvironment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the scene manager
|
||||
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()
|
||||
{
|
||||
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
|
||||
{
|
||||
return IRRLICHT_SDK_VERSION;
|
||||
}
|
||||
|
||||
//! \return Returns a pointer to the mouse cursor control interface.
|
||||
gui::ICursorControl* CIrrDeviceStub::getCursorControl()
|
||||
{
|
||||
return CursorControl;
|
||||
}
|
||||
|
||||
|
||||
//! return the context manager
|
||||
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)
|
||||
{
|
||||
if (strcmp(getVersion(), version))
|
||||
{
|
||||
core::stringc w;
|
||||
w = "Warning: The library version of the Irrlicht Engine (";
|
||||
w += getVersion();
|
||||
w += ") does not match the version the application was compiled with (";
|
||||
w += version;
|
||||
w += "). This may cause problems.";
|
||||
os::Printer::log(w.c_str(), ELL_WARNING);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
++MouseMultiClicks.CountSuccessiveClicks;
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseMultiClicks.CountSuccessiveClicks = 1;
|
||||
}
|
||||
|
||||
MouseMultiClicks.LastMouseInputEvent = inputEvent;
|
||||
MouseMultiClicks.LastClickTime = clickTime;
|
||||
MouseMultiClicks.LastClick.X = mouseX;
|
||||
MouseMultiClicks.LastClick.Y = mouseY;
|
||||
|
||||
return MouseMultiClicks.CountSuccessiveClicks;
|
||||
}
|
||||
|
||||
|
||||
//! send the event to the right receiver
|
||||
bool CIrrDeviceStub::postEventFromUser(const SEvent& event)
|
||||
{
|
||||
bool absorbed = false;
|
||||
|
||||
if (UserReceiver)
|
||||
absorbed = UserReceiver->OnEvent(event);
|
||||
|
||||
if (!absorbed && GUIEnvironment)
|
||||
absorbed = GUIEnvironment->postEventFromUser(event);
|
||||
|
||||
scene::ISceneManager* inputReceiver = InputReceivingSceneManager;
|
||||
if (!inputReceiver)
|
||||
inputReceiver = SceneManager;
|
||||
|
||||
if (!absorbed && inputReceiver)
|
||||
absorbed = inputReceiver->postEventFromUser(event);
|
||||
|
||||
return absorbed;
|
||||
}
|
||||
|
||||
|
||||
//! Sets a new event receiver to receive events
|
||||
void CIrrDeviceStub::setEventReceiver(IEventReceiver* receiver)
|
||||
{
|
||||
UserReceiver = receiver;
|
||||
Logger->setReceiver(receiver);
|
||||
if (GUIEnvironment)
|
||||
GUIEnvironment->setUserEventReceiver(receiver);
|
||||
}
|
||||
|
||||
|
||||
//! Returns poinhter to the current event receiver. Returns 0 if there is none.
|
||||
IEventReceiver* CIrrDeviceStub::getEventReceiver()
|
||||
{
|
||||
return UserReceiver;
|
||||
}
|
||||
|
||||
|
||||
//! \return Returns a pointer to the logger.
|
||||
ILogger* CIrrDeviceStub::getLogger()
|
||||
{
|
||||
return Logger;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the operation system opertator object.
|
||||
IOSOperator* CIrrDeviceStub::getOSOperator()
|
||||
{
|
||||
return Operator;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the input receiving scene manager.
|
||||
void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneManager)
|
||||
{
|
||||
if (sceneManager)
|
||||
sceneManager->grab();
|
||||
if (InputReceivingSceneManager)
|
||||
InputReceivingSceneManager->drop();
|
||||
|
||||
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
|
||||
{
|
||||
return video::ECF_R5G6B5;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateAccelerometer(float updateInterval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::deactivateAccelerometer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isAccelerometerActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isAccelerometerAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateGyroscope(float updateInterval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::deactivateGyroscope()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isGyroscopeActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isGyroscopeAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateDeviceMotion(float updateInterval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::deactivateDeviceMotion()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isDeviceMotionActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isDeviceMotionAvailable()
|
||||
{
|
||||
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 )
|
||||
{
|
||||
MouseMultiClicks.DoubleClickTime = timeMs;
|
||||
}
|
||||
|
||||
//! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse.
|
||||
u32 CIrrDeviceStub::getDoubleClickTime() const
|
||||
{
|
||||
return MouseMultiClicks.DoubleClickTime;
|
||||
}
|
||||
|
||||
//! Remove all messages pending in the system message loop
|
||||
void CIrrDeviceStub::clearSystemMessages()
|
||||
{
|
||||
}
|
||||
|
||||
//! Get the display density in dots per inch.
|
||||
float CIrrDeviceStub::getDisplayDensity() const
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
//! Checks whether the input device should take input from the IME
|
||||
bool CIrrDeviceStub::acceptsIME()
|
||||
{
|
||||
if (!GUIEnvironment)
|
||||
return false;
|
||||
gui::IGUIElement *elem = GUIEnvironment->getFocus();
|
||||
return elem && elem->acceptsIME();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IEventReceiver.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IGUIElement.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "os.h"
|
||||
#include "CTimer.h"
|
||||
#include "CLogger.h"
|
||||
#include "irrString.h"
|
||||
#include "IrrCompileConfig.h" // for IRRLICHT_SDK_VERSION
|
||||
|
||||
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)
|
||||
{
|
||||
Timer = new CTimer();
|
||||
if (os::Printer::Logger)
|
||||
{
|
||||
os::Printer::Logger->grab();
|
||||
Logger = (CLogger*)os::Printer::Logger;
|
||||
Logger->setReceiver(UserReceiver);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger = new CLogger(UserReceiver);
|
||||
os::Printer::Logger = Logger;
|
||||
}
|
||||
Logger->setLogLevel(CreationParams.LoggingLevel);
|
||||
|
||||
os::Printer::Logger = Logger;
|
||||
|
||||
FileSystem = io::createFileSystem();
|
||||
|
||||
core::stringc s = "Irrlicht Engine version ";
|
||||
s.append(getVersion());
|
||||
os::Printer::log(s.c_str(), ELL_INFORMATION);
|
||||
|
||||
checkVersion(params.SDK_version_do_not_use);
|
||||
}
|
||||
|
||||
|
||||
CIrrDeviceStub::~CIrrDeviceStub()
|
||||
{
|
||||
if (GUIEnvironment)
|
||||
GUIEnvironment->drop();
|
||||
|
||||
if (SceneManager)
|
||||
SceneManager->drop();
|
||||
|
||||
if (VideoDriver)
|
||||
VideoDriver->drop();
|
||||
|
||||
if (ContextManager)
|
||||
ContextManager->drop();
|
||||
|
||||
if ( FileSystem )
|
||||
FileSystem->drop();
|
||||
|
||||
if (InputReceivingSceneManager)
|
||||
InputReceivingSceneManager->drop();
|
||||
|
||||
if (CursorControl)
|
||||
CursorControl->drop();
|
||||
|
||||
if (Operator)
|
||||
Operator->drop();
|
||||
|
||||
CursorControl = 0;
|
||||
|
||||
if (Timer)
|
||||
Timer->drop();
|
||||
|
||||
if (Logger->drop())
|
||||
os::Printer::Logger = 0;
|
||||
}
|
||||
|
||||
|
||||
void CIrrDeviceStub::createGUIAndScene()
|
||||
{
|
||||
// create gui environment
|
||||
GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator);
|
||||
|
||||
// create Scene manager
|
||||
SceneManager = scene::createSceneManager(VideoDriver, CursorControl);
|
||||
|
||||
setEventReceiver(UserReceiver);
|
||||
}
|
||||
|
||||
|
||||
//! returns the video driver
|
||||
video::IVideoDriver* CIrrDeviceStub::getVideoDriver()
|
||||
{
|
||||
return VideoDriver;
|
||||
}
|
||||
|
||||
|
||||
//! return file system
|
||||
io::IFileSystem* CIrrDeviceStub::getFileSystem()
|
||||
{
|
||||
return FileSystem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the gui environment
|
||||
gui::IGUIEnvironment* CIrrDeviceStub::getGUIEnvironment()
|
||||
{
|
||||
return GUIEnvironment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the scene manager
|
||||
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()
|
||||
{
|
||||
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
|
||||
{
|
||||
return IRRLICHT_SDK_VERSION;
|
||||
}
|
||||
|
||||
//! \return Returns a pointer to the mouse cursor control interface.
|
||||
gui::ICursorControl* CIrrDeviceStub::getCursorControl()
|
||||
{
|
||||
return CursorControl;
|
||||
}
|
||||
|
||||
|
||||
//! return the context manager
|
||||
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)
|
||||
{
|
||||
if (strcmp(getVersion(), version))
|
||||
{
|
||||
core::stringc w;
|
||||
w = "Warning: The library version of the Irrlicht Engine (";
|
||||
w += getVersion();
|
||||
w += ") does not match the version the application was compiled with (";
|
||||
w += version;
|
||||
w += "). This may cause problems.";
|
||||
os::Printer::log(w.c_str(), ELL_WARNING);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
++MouseMultiClicks.CountSuccessiveClicks;
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseMultiClicks.CountSuccessiveClicks = 1;
|
||||
}
|
||||
|
||||
MouseMultiClicks.LastMouseInputEvent = inputEvent;
|
||||
MouseMultiClicks.LastClickTime = clickTime;
|
||||
MouseMultiClicks.LastClick.X = mouseX;
|
||||
MouseMultiClicks.LastClick.Y = mouseY;
|
||||
|
||||
return MouseMultiClicks.CountSuccessiveClicks;
|
||||
}
|
||||
|
||||
|
||||
//! send the event to the right receiver
|
||||
bool CIrrDeviceStub::postEventFromUser(const SEvent& event)
|
||||
{
|
||||
bool absorbed = false;
|
||||
|
||||
if (UserReceiver)
|
||||
absorbed = UserReceiver->OnEvent(event);
|
||||
|
||||
if (!absorbed && GUIEnvironment)
|
||||
absorbed = GUIEnvironment->postEventFromUser(event);
|
||||
|
||||
scene::ISceneManager* inputReceiver = InputReceivingSceneManager;
|
||||
if (!inputReceiver)
|
||||
inputReceiver = SceneManager;
|
||||
|
||||
if (!absorbed && inputReceiver)
|
||||
absorbed = inputReceiver->postEventFromUser(event);
|
||||
|
||||
return absorbed;
|
||||
}
|
||||
|
||||
|
||||
//! Sets a new event receiver to receive events
|
||||
void CIrrDeviceStub::setEventReceiver(IEventReceiver* receiver)
|
||||
{
|
||||
UserReceiver = receiver;
|
||||
Logger->setReceiver(receiver);
|
||||
if (GUIEnvironment)
|
||||
GUIEnvironment->setUserEventReceiver(receiver);
|
||||
}
|
||||
|
||||
|
||||
//! Returns poinhter to the current event receiver. Returns 0 if there is none.
|
||||
IEventReceiver* CIrrDeviceStub::getEventReceiver()
|
||||
{
|
||||
return UserReceiver;
|
||||
}
|
||||
|
||||
|
||||
//! \return Returns a pointer to the logger.
|
||||
ILogger* CIrrDeviceStub::getLogger()
|
||||
{
|
||||
return Logger;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the operation system opertator object.
|
||||
IOSOperator* CIrrDeviceStub::getOSOperator()
|
||||
{
|
||||
return Operator;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the input receiving scene manager.
|
||||
void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneManager)
|
||||
{
|
||||
if (sceneManager)
|
||||
sceneManager->grab();
|
||||
if (InputReceivingSceneManager)
|
||||
InputReceivingSceneManager->drop();
|
||||
|
||||
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
|
||||
{
|
||||
return video::ECF_R5G6B5;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateAccelerometer(float updateInterval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::deactivateAccelerometer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isAccelerometerActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isAccelerometerAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateGyroscope(float updateInterval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::deactivateGyroscope()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isGyroscopeActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isGyroscopeAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::activateDeviceMotion(float updateInterval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::deactivateDeviceMotion()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isDeviceMotionActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//! No-op in this implementation
|
||||
bool CIrrDeviceStub::isDeviceMotionAvailable()
|
||||
{
|
||||
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 )
|
||||
{
|
||||
MouseMultiClicks.DoubleClickTime = timeMs;
|
||||
}
|
||||
|
||||
//! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse.
|
||||
u32 CIrrDeviceStub::getDoubleClickTime() const
|
||||
{
|
||||
return MouseMultiClicks.DoubleClickTime;
|
||||
}
|
||||
|
||||
//! Remove all messages pending in the system message loop
|
||||
void CIrrDeviceStub::clearSystemMessages()
|
||||
{
|
||||
}
|
||||
|
||||
//! Get the display density in dots per inch.
|
||||
float CIrrDeviceStub::getDisplayDensity() const
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
//! Checks whether the input device should take input from the IME
|
||||
bool CIrrDeviceStub::acceptsIME()
|
||||
{
|
||||
if (!GUIEnvironment)
|
||||
return false;
|
||||
gui::IGUIElement *elem = GUIEnvironment->getFocus();
|
||||
return elem && elem->acceptsIME();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
@@ -1,207 +1,207 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "IContextManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
// lots of prototypes:
|
||||
class ILogger;
|
||||
class CLogger;
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "IContextManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
// lots of prototypes:
|
||||
class ILogger;
|
||||
class CLogger;
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,425 +1,425 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h> // For JOYCAPS
|
||||
#include <windowsx.h>
|
||||
#if !defined(GET_X_LPARAM)
|
||||
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||||
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
struct SJoystickWin32Control;
|
||||
|
||||
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();
|
||||
|
||||
//! 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 )
|
||||
{
|
||||
#ifdef CURSOR_SUPPRESSED
|
||||
// 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 ) ||
|
||||
(visible && showResult >= 0))
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
/** 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
|
||||
{
|
||||
BorderX = BorderY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! 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();
|
||||
|
||||
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
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h> // For JOYCAPS
|
||||
#include <windowsx.h>
|
||||
#if !defined(GET_X_LPARAM)
|
||||
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||||
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
struct SJoystickWin32Control;
|
||||
|
||||
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();
|
||||
|
||||
//! 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 )
|
||||
{
|
||||
#ifdef CURSOR_SUPPRESSED
|
||||
// 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 ) ||
|
||||
(visible && showResult >= 0))
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
/** 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
|
||||
{
|
||||
BorderX = BorderY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! 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();
|
||||
|
||||
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
|
||||
|
||||
@@ -1,128 +1,128 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CLimitReadFile.h"
|
||||
#include "irrMath.h"
|
||||
#include "irrString.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CLimitReadFile");
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
if (0 == File)
|
||||
return 0;
|
||||
|
||||
#if 1
|
||||
long r = AreaStart + Pos;
|
||||
long toRead = core::min_(AreaEnd, r + (long)sizeToRead) - core::max_(AreaStart, r);
|
||||
if (toRead < 0)
|
||||
return 0;
|
||||
File->seek(r);
|
||||
r = (long)File->read(buffer, toRead);
|
||||
Pos += r;
|
||||
return r;
|
||||
#else
|
||||
const long pos = File->getPos();
|
||||
|
||||
if (pos >= AreaEnd)
|
||||
return 0;
|
||||
|
||||
if (pos + (long)sizeToRead >= AreaEnd)
|
||||
sizeToRead = AreaEnd - pos;
|
||||
|
||||
return File->read(buffer, 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);
|
||||
return true;
|
||||
#else
|
||||
const long pos = File->getPos();
|
||||
|
||||
if (relativeMovement)
|
||||
{
|
||||
if (pos + finalPos > AreaEnd)
|
||||
finalPos = AreaEnd - pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
finalPos += AreaStart;
|
||||
if (finalPos > AreaEnd)
|
||||
return false;
|
||||
}
|
||||
|
||||
return File->seek(finalPos, relativeMovement);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! returns size of file
|
||||
long CLimitReadFile::getSize() const
|
||||
{
|
||||
return AreaEnd - AreaStart;
|
||||
}
|
||||
|
||||
|
||||
//! returns where in the file we are.
|
||||
long CLimitReadFile::getPos() const
|
||||
{
|
||||
#if 1
|
||||
return Pos;
|
||||
#else
|
||||
return File->getPos() - AreaStart;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! returns name of file
|
||||
const io::path& CLimitReadFile::getFileName() const
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CLimitReadFile.h"
|
||||
#include "irrMath.h"
|
||||
#include "irrString.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CLimitReadFile");
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
if (0 == File)
|
||||
return 0;
|
||||
|
||||
#if 1
|
||||
long r = AreaStart + Pos;
|
||||
long toRead = core::min_(AreaEnd, r + (long)sizeToRead) - core::max_(AreaStart, r);
|
||||
if (toRead < 0)
|
||||
return 0;
|
||||
File->seek(r);
|
||||
r = (long)File->read(buffer, toRead);
|
||||
Pos += r;
|
||||
return r;
|
||||
#else
|
||||
const long pos = File->getPos();
|
||||
|
||||
if (pos >= AreaEnd)
|
||||
return 0;
|
||||
|
||||
if (pos + (long)sizeToRead >= AreaEnd)
|
||||
sizeToRead = AreaEnd - pos;
|
||||
|
||||
return File->read(buffer, 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);
|
||||
return true;
|
||||
#else
|
||||
const long pos = File->getPos();
|
||||
|
||||
if (relativeMovement)
|
||||
{
|
||||
if (pos + finalPos > AreaEnd)
|
||||
finalPos = AreaEnd - pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
finalPos += AreaStart;
|
||||
if (finalPos > AreaEnd)
|
||||
return false;
|
||||
}
|
||||
|
||||
return File->seek(finalPos, relativeMovement);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! returns size of file
|
||||
long CLimitReadFile::getSize() const
|
||||
{
|
||||
return AreaEnd - AreaStart;
|
||||
}
|
||||
|
||||
|
||||
//! returns where in the file we are.
|
||||
long CLimitReadFile::getPos() const
|
||||
{
|
||||
#if 1
|
||||
return Pos;
|
||||
#else
|
||||
return File->getPos() - AreaStart;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! returns name of file
|
||||
const io::path& CLimitReadFile::getFileName() const
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
return ERFT_LIMIT_READ_FILE;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
io::path Filename;
|
||||
long AreaStart;
|
||||
long AreaEnd;
|
||||
long Pos;
|
||||
IReadFile* File;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IReadFile.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
return ERFT_LIMIT_READ_FILE;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
io::path Filename;
|
||||
long AreaStart;
|
||||
long AreaEnd;
|
||||
long Pos;
|
||||
IReadFile* File;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,102 +1,102 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CLogger.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//! 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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//! 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);
|
||||
}
|
||||
|
||||
//! Prints out a text into the log
|
||||
void CLogger::log(const wchar_t* text, ELOG_LEVEL ll)
|
||||
{
|
||||
if (ll < LogLevel)
|
||||
return;
|
||||
|
||||
core::stringc s = text;
|
||||
log(s.c_str(), ll);
|
||||
}
|
||||
|
||||
|
||||
//! Prints out a text into the log
|
||||
void CLogger::log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll)
|
||||
{
|
||||
if (ll < LogLevel)
|
||||
return;
|
||||
|
||||
core::stringc s1 = text;
|
||||
core::stringc s2 = hint;
|
||||
log(s1.c_str(), s2.c_str(), ll);
|
||||
}
|
||||
|
||||
//! Prints out a text into the log
|
||||
void CLogger::log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll)
|
||||
{
|
||||
if (ll < LogLevel)
|
||||
return;
|
||||
|
||||
core::stringc s2 = hint;
|
||||
log( text, s2.c_str(), ll);
|
||||
}
|
||||
|
||||
//! Sets a new event receiver
|
||||
void CLogger::setReceiver(IEventReceiver* r)
|
||||
{
|
||||
Receiver = r;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CLogger.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//! 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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//! 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);
|
||||
}
|
||||
|
||||
//! Prints out a text into the log
|
||||
void CLogger::log(const wchar_t* text, ELOG_LEVEL ll)
|
||||
{
|
||||
if (ll < LogLevel)
|
||||
return;
|
||||
|
||||
core::stringc s = text;
|
||||
log(s.c_str(), ll);
|
||||
}
|
||||
|
||||
|
||||
//! Prints out a text into the log
|
||||
void CLogger::log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll)
|
||||
{
|
||||
if (ll < LogLevel)
|
||||
return;
|
||||
|
||||
core::stringc s1 = text;
|
||||
core::stringc s2 = hint;
|
||||
log(s1.c_str(), s2.c_str(), ll);
|
||||
}
|
||||
|
||||
//! Prints out a text into the log
|
||||
void CLogger::log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll)
|
||||
{
|
||||
if (ll < LogLevel)
|
||||
return;
|
||||
|
||||
core::stringc s2 = hint;
|
||||
log( text, s2.c_str(), ll);
|
||||
}
|
||||
|
||||
//! Sets a new event receiver
|
||||
void CLogger::setReceiver(IEventReceiver* r)
|
||||
{
|
||||
Receiver = r;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ILogger.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
#include "IEventReceiver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
//! Class for logging messages, warnings and errors to stdout
|
||||
class CLogger : public ILogger
|
||||
{
|
||||
public:
|
||||
|
||||
CLogger(IEventReceiver* r);
|
||||
|
||||
//! Returns the current set log level.
|
||||
ELOG_LEVEL getLogLevel() const override;
|
||||
|
||||
//! Sets a new log level. void setLogLevel(ELOG_LEVEL ll) override;
|
||||
void setLogLevel(ELOG_LEVEL ll) override;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const c8* text, ELOG_LEVEL ll=ELL_INFORMATION) override;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const wchar_t* 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;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) override;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) override;
|
||||
|
||||
//! Sets a new event receiver
|
||||
void setReceiver(IEventReceiver* r);
|
||||
|
||||
private:
|
||||
|
||||
ELOG_LEVEL LogLevel;
|
||||
IEventReceiver* Receiver;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ILogger.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
#include "IEventReceiver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
//! Class for logging messages, warnings and errors to stdout
|
||||
class CLogger : public ILogger
|
||||
{
|
||||
public:
|
||||
|
||||
CLogger(IEventReceiver* r);
|
||||
|
||||
//! Returns the current set log level.
|
||||
ELOG_LEVEL getLogLevel() const override;
|
||||
|
||||
//! Sets a new log level. void setLogLevel(ELOG_LEVEL ll) override;
|
||||
void setLogLevel(ELOG_LEVEL ll) override;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const c8* text, ELOG_LEVEL ll=ELL_INFORMATION) override;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const wchar_t* 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;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) override;
|
||||
|
||||
//! Prints out a text into the log
|
||||
void log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) override;
|
||||
|
||||
//! Sets a new event receiver
|
||||
void setReceiver(IEventReceiver* r);
|
||||
|
||||
private:
|
||||
|
||||
ELOG_LEVEL LogLevel;
|
||||
IEventReceiver* Receiver;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
@@ -1,187 +1,187 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CMemoryFile.h"
|
||||
#include "irrString.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CMemoryReadFile");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CMemoryReadFile::~CMemoryReadFile()
|
||||
{
|
||||
if (deleteMemoryWhenDropped)
|
||||
delete [] (c8*)Buffer;
|
||||
}
|
||||
|
||||
|
||||
//! returns how much was read
|
||||
size_t CMemoryReadFile::read(void* buffer, size_t sizeToRead)
|
||||
{
|
||||
long amount = static_cast<long>(sizeToRead);
|
||||
if (Pos + amount > Len)
|
||||
amount -= Pos + amount - Len;
|
||||
|
||||
if (amount <= 0)
|
||||
return 0;
|
||||
|
||||
c8* p = (c8*)Buffer;
|
||||
memcpy(buffer, p + Pos, amount);
|
||||
|
||||
Pos += amount;
|
||||
|
||||
return static_cast<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 CMemoryReadFile::seek(long finalPos, bool relativeMovement)
|
||||
{
|
||||
if (relativeMovement)
|
||||
{
|
||||
if (Pos + finalPos < 0 || Pos + finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos += finalPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (finalPos < 0 || finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos = finalPos;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
|
||||
CMemoryWriteFile::CMemoryWriteFile(void* memory, long len, const io::path& fileName, bool d)
|
||||
: Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CMemoryWriteFile");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CMemoryWriteFile::~CMemoryWriteFile()
|
||||
{
|
||||
if (deleteMemoryWhenDropped)
|
||||
delete [] (c8*)Buffer;
|
||||
}
|
||||
|
||||
|
||||
//! returns how much was written
|
||||
size_t CMemoryWriteFile::write(const void* buffer, size_t sizeToWrite)
|
||||
{
|
||||
long amount = (long)sizeToWrite;
|
||||
if (Pos + amount > Len)
|
||||
amount -= Pos + amount - Len;
|
||||
|
||||
if (amount <= 0)
|
||||
return 0;
|
||||
|
||||
c8* p = (c8*)Buffer;
|
||||
memcpy(p + Pos, buffer, amount);
|
||||
|
||||
Pos += amount;
|
||||
|
||||
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 (Pos + finalPos < 0 || Pos + finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos += finalPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (finalPos < 0 || finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos = finalPos;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
bool CMemoryWriteFile::flush()
|
||||
{
|
||||
return true; // no buffering, so nothing to do
|
||||
}
|
||||
|
||||
IReadFile* createMemoryReadFile(const void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped)
|
||||
{
|
||||
CMemoryReadFile* file = new CMemoryReadFile(memory, size, fileName, deleteMemoryWhenDropped);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
IWriteFile* createMemoryWriteFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped)
|
||||
{
|
||||
CMemoryWriteFile* file = new CMemoryWriteFile(memory, size, fileName, deleteMemoryWhenDropped);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CMemoryFile.h"
|
||||
#include "irrString.h"
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CMemoryReadFile");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CMemoryReadFile::~CMemoryReadFile()
|
||||
{
|
||||
if (deleteMemoryWhenDropped)
|
||||
delete [] (c8*)Buffer;
|
||||
}
|
||||
|
||||
|
||||
//! returns how much was read
|
||||
size_t CMemoryReadFile::read(void* buffer, size_t sizeToRead)
|
||||
{
|
||||
long amount = static_cast<long>(sizeToRead);
|
||||
if (Pos + amount > Len)
|
||||
amount -= Pos + amount - Len;
|
||||
|
||||
if (amount <= 0)
|
||||
return 0;
|
||||
|
||||
c8* p = (c8*)Buffer;
|
||||
memcpy(buffer, p + Pos, amount);
|
||||
|
||||
Pos += amount;
|
||||
|
||||
return static_cast<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 CMemoryReadFile::seek(long finalPos, bool relativeMovement)
|
||||
{
|
||||
if (relativeMovement)
|
||||
{
|
||||
if (Pos + finalPos < 0 || Pos + finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos += finalPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (finalPos < 0 || finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos = finalPos;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
|
||||
CMemoryWriteFile::CMemoryWriteFile(void* memory, long len, const io::path& fileName, bool d)
|
||||
: Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CMemoryWriteFile");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CMemoryWriteFile::~CMemoryWriteFile()
|
||||
{
|
||||
if (deleteMemoryWhenDropped)
|
||||
delete [] (c8*)Buffer;
|
||||
}
|
||||
|
||||
|
||||
//! returns how much was written
|
||||
size_t CMemoryWriteFile::write(const void* buffer, size_t sizeToWrite)
|
||||
{
|
||||
long amount = (long)sizeToWrite;
|
||||
if (Pos + amount > Len)
|
||||
amount -= Pos + amount - Len;
|
||||
|
||||
if (amount <= 0)
|
||||
return 0;
|
||||
|
||||
c8* p = (c8*)Buffer;
|
||||
memcpy(p + Pos, buffer, amount);
|
||||
|
||||
Pos += amount;
|
||||
|
||||
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 (Pos + finalPos < 0 || Pos + finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos += finalPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (finalPos < 0 || finalPos > Len)
|
||||
return false;
|
||||
|
||||
Pos = finalPos;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return Filename;
|
||||
}
|
||||
|
||||
bool CMemoryWriteFile::flush()
|
||||
{
|
||||
return true; // no buffering, so nothing to do
|
||||
}
|
||||
|
||||
IReadFile* createMemoryReadFile(const void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped)
|
||||
{
|
||||
CMemoryReadFile* file = new CMemoryReadFile(memory, size, fileName, deleteMemoryWhenDropped);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
IWriteFile* createMemoryWriteFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped)
|
||||
{
|
||||
CMemoryWriteFile* file = new CMemoryWriteFile(memory, size, fileName, deleteMemoryWhenDropped);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user