mirror of
https://github.com/minetest/irrlicht.git
synced 2025-06-28 06:20:21 +02:00
Merging r5975 through r6036 from trunk to ogl-es branch.
GLES drivers adapted, but only did make compile-tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
110
source/Irrlicht/Android/CAndroidAssetFileArchive.cpp
Normal file
110
source/Irrlicht/Android/CAndroidAssetFileArchive.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
// 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
|
||||
|
||||
#include "IrrCompileConfig.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_
|
70
source/Irrlicht/Android/CAndroidAssetFileArchive.h
Normal file
70
source/Irrlicht/Android/CAndroidAssetFileArchive.h
Normal file
@ -0,0 +1,70 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_ANDROID_ASSET_FILE_ARCHIVE_H_INCLUDED__
|
||||
#define __C_ANDROID_ASSET_FILE_ARCHIVE_H_INCLUDED__
|
||||
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#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
|
||||
virtual const io::path& getArchiveName() const _IRR_OVERRIDE_ {return Path;}
|
||||
|
||||
protected:
|
||||
//! Android's asset manager
|
||||
AAssetManager *AssetManager;
|
||||
|
||||
}; // CAndroidAssetFileArchive
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_ANDROID_ASSET_READER_
|
||||
#endif // __C_ANDROID_ASSET_READER_H_INCLUDED__
|
||||
|
73
source/Irrlicht/Android/CAndroidAssetReader.cpp
Normal file
73
source/Irrlicht/Android/CAndroidAssetReader.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
// 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
|
||||
|
||||
#include "IrrCompileConfig.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_
|
75
source/Irrlicht/Android/CAndroidAssetReader.h
Normal file
75
source/Irrlicht/Android/CAndroidAssetReader.h
Normal file
@ -0,0 +1,75 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_ANDROID_ASSET_READER_H_INCLUDED__
|
||||
#define __C_ANDROID_ASSET_READER_H_INCLUDED__
|
||||
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#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_
|
||||
#endif // __C_ANDROID_ASSET_READER_H_INCLUDED__
|
||||
|
869
source/Irrlicht/Android/CIrrDeviceAndroid.cpp
Normal file
869
source/Irrlicht/Android/CIrrDeviceAndroid.cpp
Normal file
@ -0,0 +1,869 @@
|
||||
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
||||
// Copyright (C) 2007-2011 Christian Stehno
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CIrrDeviceAndroid.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include "os.h"
|
||||
#include "CFileSystem.h"
|
||||
#include "CAndroidAssetReader.h"
|
||||
#include "CAndroidAssetFileArchive.h"
|
||||
#include "CKeyEventWrapper.h"
|
||||
#include "CEGLManager.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "CEGLManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
IVideoDriver* createOGLES1Driver(const SIrrlichtCreationParameters& params,
|
||||
io::IFileSystem* io, video::IContextManager* contextManager);
|
||||
|
||||
IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
|
||||
io::IFileSystem* io, video::IContextManager* contextManager);
|
||||
}
|
||||
}
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
||||
: CIrrDeviceStub(param), Accelerometer(0), Gyroscope(0), Focused(false), Initialized(false), Paused(true), JNIEnvAttachedToVM(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CIrrDeviceAndroid");
|
||||
#endif
|
||||
|
||||
// Get the interface to the native Android activity.
|
||||
Android = (android_app*)(param.PrivateData);
|
||||
|
||||
// Set the private data so we can use it in any static callbacks.
|
||||
Android->userData = this;
|
||||
|
||||
// Set the default command handler. This is a callback function that the Android
|
||||
// OS invokes to send the native activity messages.
|
||||
Android->onAppCmd = handleAndroidCommand;
|
||||
|
||||
createKeyMap();
|
||||
|
||||
// Create a sensor manager to receive touch screen events from the java activity.
|
||||
SensorManager = ASensorManager_getInstance();
|
||||
SensorEventQueue = ASensorManager_createEventQueue(SensorManager, Android->looper, LOOPER_ID_USER, 0, 0);
|
||||
Android->onInputEvent = handleInput;
|
||||
|
||||
// Create EGL manager.
|
||||
ContextManager = new video::CEGLManager();
|
||||
|
||||
os::Printer::log("Waiting for Android activity window to be created.", ELL_DEBUG);
|
||||
|
||||
do
|
||||
{
|
||||
s32 Events = 0;
|
||||
android_poll_source* Source = 0;
|
||||
|
||||
while ((ALooper_pollAll(((Focused && !Paused) || !Initialized) ? 0 : -1, 0, &Events, (void**)&Source)) >= 0)
|
||||
{
|
||||
if(Source)
|
||||
Source->process(Android, Source);
|
||||
}
|
||||
}
|
||||
while(!Initialized);
|
||||
}
|
||||
|
||||
|
||||
CIrrDeviceAndroid::~CIrrDeviceAndroid()
|
||||
{
|
||||
if (GUIEnvironment)
|
||||
{
|
||||
GUIEnvironment->drop();
|
||||
GUIEnvironment = 0;
|
||||
}
|
||||
|
||||
if (SceneManager)
|
||||
{
|
||||
SceneManager->drop();
|
||||
SceneManager = 0;
|
||||
}
|
||||
|
||||
if (VideoDriver)
|
||||
{
|
||||
VideoDriver->drop();
|
||||
VideoDriver = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::run()
|
||||
{
|
||||
if (!Initialized)
|
||||
return false;
|
||||
|
||||
os::Timer::tick();
|
||||
|
||||
s32 id;
|
||||
s32 Events = 0;
|
||||
android_poll_source* Source = 0;
|
||||
|
||||
while ((id = ALooper_pollAll(((Focused && !Paused) || !Initialized) ? 0 : -1, 0, &Events, (void**)&Source)) >= 0)
|
||||
{
|
||||
if(Source)
|
||||
Source->process(Android, Source);
|
||||
|
||||
// if a sensor has data, we'll process it now.
|
||||
if (id == LOOPER_ID_USER)
|
||||
{
|
||||
ASensorEvent sensorEvent;
|
||||
while (ASensorEventQueue_getEvents(SensorEventQueue, &sensorEvent, 1) > 0)
|
||||
{
|
||||
switch (sensorEvent.type)
|
||||
{
|
||||
case ASENSOR_TYPE_ACCELEROMETER:
|
||||
SEvent accEvent;
|
||||
accEvent.EventType = EET_ACCELEROMETER_EVENT;
|
||||
accEvent.AccelerometerEvent.X = sensorEvent.acceleration.x;
|
||||
accEvent.AccelerometerEvent.Y = sensorEvent.acceleration.y;
|
||||
accEvent.AccelerometerEvent.Z = sensorEvent.acceleration.z;
|
||||
|
||||
postEventFromUser(accEvent);
|
||||
break;
|
||||
|
||||
case ASENSOR_TYPE_GYROSCOPE:
|
||||
SEvent gyroEvent;
|
||||
gyroEvent.EventType = EET_GYROSCOPE_EVENT;
|
||||
gyroEvent.GyroscopeEvent.X = sensorEvent.vector.x;
|
||||
gyroEvent.GyroscopeEvent.Y = sensorEvent.vector.y;
|
||||
gyroEvent.GyroscopeEvent.Z = sensorEvent.vector.z;
|
||||
|
||||
postEventFromUser(gyroEvent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!Initialized)
|
||||
break;
|
||||
}
|
||||
|
||||
return Initialized;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::yield()
|
||||
{
|
||||
struct timespec ts = {0,1};
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::sleep(u32 timeMs, bool pauseTimer)
|
||||
{
|
||||
const bool wasStopped = Timer ? Timer->isStopped() : true;
|
||||
|
||||
struct timespec ts;
|
||||
ts.tv_sec = (time_t) (timeMs / 1000);
|
||||
ts.tv_nsec = (long) (timeMs % 1000) * 1000000;
|
||||
|
||||
if (pauseTimer && !wasStopped)
|
||||
Timer->stop();
|
||||
|
||||
nanosleep(&ts, NULL);
|
||||
|
||||
if (pauseTimer && !wasStopped)
|
||||
Timer->start();
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::setWindowCaption(const wchar_t* text)
|
||||
{
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::present(video::IImage* surface, void* windowId, core::rect<s32>* srcClip)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isWindowActive() const
|
||||
{
|
||||
return (Focused && !Paused);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isWindowFocused() const
|
||||
{
|
||||
return Focused;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isWindowMinimized() const
|
||||
{
|
||||
return !Focused;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::closeDevice()
|
||||
{
|
||||
ANativeActivity_finish(Android->activity);
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::setResizable(bool resize)
|
||||
{
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::minimizeWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::maximizeWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::restoreWindow()
|
||||
{
|
||||
}
|
||||
|
||||
core::position2di CIrrDeviceAndroid::getWindowPosition()
|
||||
{
|
||||
return core::position2di(0, 0);
|
||||
}
|
||||
|
||||
E_DEVICE_TYPE CIrrDeviceAndroid::getType() const
|
||||
{
|
||||
return EIDT_ANDROID;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::handleAndroidCommand(android_app* app, int32_t cmd)
|
||||
{
|
||||
CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData;
|
||||
|
||||
SEvent event;
|
||||
event.EventType = EET_SYSTEM_EVENT;
|
||||
event.SystemEvent.EventType = ESET_ANDROID_CMD;
|
||||
event.SystemEvent.AndroidCmd.Cmd = cmd;
|
||||
if ( device->postEventFromUser(event) )
|
||||
return;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case APP_CMD_INPUT_CHANGED:
|
||||
os::Printer::log("Android command APP_CMD_INPUT_CHANGED", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_WINDOW_RESIZED:
|
||||
os::Printer::log("Android command APP_CMD_WINDOW_RESIZED", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_WINDOW_REDRAW_NEEDED:
|
||||
os::Printer::log("Android command APP_CMD_WINDOW_REDRAW_NEEDED", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_SAVE_STATE:
|
||||
os::Printer::log("Android command APP_CMD_SAVE_STATE", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_CONTENT_RECT_CHANGED:
|
||||
os::Printer::log("Android command APP_CMD_CONTENT_RECT_CHANGED", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_CONFIG_CHANGED:
|
||||
os::Printer::log("Android command APP_CMD_CONFIG_CHANGED", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_LOW_MEMORY:
|
||||
os::Printer::log("Android command APP_CMD_LOW_MEMORY", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_START:
|
||||
os::Printer::log("Android command APP_CMD_START", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
os::Printer::log("Android command APP_CMD_INIT_WINDOW", ELL_DEBUG);
|
||||
device->getExposedVideoData().OGLESAndroid.Window = app->window;
|
||||
|
||||
if (device->CreationParams.WindowSize.Width == 0 || device->CreationParams.WindowSize.Height == 0)
|
||||
{
|
||||
device->CreationParams.WindowSize.Width = ANativeWindow_getWidth(app->window);
|
||||
device->CreationParams.WindowSize.Height = ANativeWindow_getHeight(app->window);
|
||||
}
|
||||
|
||||
device->getContextManager()->initialize(device->CreationParams, device->ExposedVideoData);
|
||||
device->getContextManager()->generateSurface();
|
||||
device->getContextManager()->generateContext();
|
||||
device->getContextManager()->activateContext(device->getContextManager()->getContext());
|
||||
|
||||
if (!device->Initialized)
|
||||
{
|
||||
io::CAndroidAssetFileArchive* assets = new io::CAndroidAssetFileArchive( device->Android->activity->assetManager, false, false);
|
||||
assets->addDirectoryToFileList("");
|
||||
device->FileSystem->addFileArchive(assets);
|
||||
assets->drop();
|
||||
|
||||
device->createDriver();
|
||||
|
||||
if (device->VideoDriver)
|
||||
device->createGUIAndScene();
|
||||
}
|
||||
device->Initialized = true;
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
os::Printer::log("Android command APP_CMD_TERM_WINDOW", ELL_DEBUG);
|
||||
device->getContextManager()->destroySurface();
|
||||
break;
|
||||
case APP_CMD_GAINED_FOCUS:
|
||||
os::Printer::log("Android command APP_CMD_GAINED_FOCUS", ELL_DEBUG);
|
||||
device->Focused = true;
|
||||
break;
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
os::Printer::log("Android command APP_CMD_LOST_FOCUS", ELL_DEBUG);
|
||||
device->Focused = false;
|
||||
break;
|
||||
case APP_CMD_DESTROY:
|
||||
os::Printer::log("Android command APP_CMD_DESTROY", ELL_DEBUG);
|
||||
if ( device->JNIEnvAttachedToVM )
|
||||
{
|
||||
device->JNIEnvAttachedToVM = 0;
|
||||
device->Android->activity->vm->DetachCurrentThread();
|
||||
}
|
||||
device->Initialized = false;
|
||||
break;
|
||||
case APP_CMD_PAUSE:
|
||||
os::Printer::log("Android command APP_CMD_PAUSE", ELL_DEBUG);
|
||||
device->Paused = true;
|
||||
break;
|
||||
case APP_CMD_STOP:
|
||||
os::Printer::log("Android command APP_CMD_STOP", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_RESUME:
|
||||
os::Printer::log("Android command APP_CMD_RESUME", ELL_DEBUG);
|
||||
device->Paused = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent)
|
||||
{
|
||||
CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData;
|
||||
s32 status = 0;
|
||||
|
||||
switch ( AInputEvent_getType(androidEvent) )
|
||||
{
|
||||
case AINPUT_EVENT_TYPE_MOTION:
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_TOUCH_INPUT_EVENT;
|
||||
|
||||
s32 eventAction = AMotionEvent_getAction(androidEvent);
|
||||
s32 eventType = eventAction & AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
#if 0
|
||||
// Useful for debugging. We might have to pass some of those infos on at some point.
|
||||
// but preferably device independent (so iphone can use same irrlicht flags).
|
||||
int32_t flags = AMotionEvent_getFlags(androidEvent);
|
||||
os::Printer::log("flags: ", core::stringc(flags).c_str(), ELL_DEBUG);
|
||||
int32_t metaState = AMotionEvent_getMetaState(androidEvent);
|
||||
os::Printer::log("metaState: ", core::stringc(metaState).c_str(), ELL_DEBUG);
|
||||
int32_t edgeFlags = AMotionEvent_getEdgeFlags(androidEvent);
|
||||
os::Printer::log("edgeFlags: ", core::stringc(flags).c_str(), ELL_DEBUG);
|
||||
#endif
|
||||
|
||||
bool touchReceived = true;
|
||||
|
||||
switch (eventType)
|
||||
{
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
event.TouchInput.Event = ETIE_PRESSED_DOWN;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
event.TouchInput.Event = ETIE_MOVED;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
event.TouchInput.Event = ETIE_LEFT_UP;
|
||||
break;
|
||||
default:
|
||||
touchReceived = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (touchReceived)
|
||||
{
|
||||
// Process all touches for move action.
|
||||
if (event.TouchInput.Event == ETIE_MOVED)
|
||||
{
|
||||
s32 pointerCount = AMotionEvent_getPointerCount(androidEvent);
|
||||
|
||||
for (s32 i = 0; i < pointerCount; ++i)
|
||||
{
|
||||
event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i);
|
||||
event.TouchInput.X = AMotionEvent_getX(androidEvent, i);
|
||||
event.TouchInput.Y = AMotionEvent_getY(androidEvent, i);
|
||||
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
}
|
||||
else // Process one touch for other actions.
|
||||
{
|
||||
s32 pointerIndex = (eventAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex);
|
||||
event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex);
|
||||
event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex);
|
||||
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AINPUT_EVENT_TYPE_KEY:
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_KEY_INPUT_EVENT;
|
||||
|
||||
int32_t keyCode = AKeyEvent_getKeyCode(androidEvent);
|
||||
// os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG);
|
||||
|
||||
int32_t keyAction = AKeyEvent_getAction(androidEvent);
|
||||
int32_t keyMetaState = AKeyEvent_getMetaState(androidEvent);
|
||||
|
||||
if ( keyCode >= 0 && (u32)keyCode < device->KeyMap.size() )
|
||||
event.KeyInput.Key = device->KeyMap[keyCode];
|
||||
else
|
||||
event.KeyInput.Key = KEY_UNKNOWN;
|
||||
event.KeyInput.SystemKeyCode = (u32)keyCode;
|
||||
if ( keyAction == AKEY_EVENT_ACTION_DOWN )
|
||||
event.KeyInput.PressedDown = true;
|
||||
else if ( keyAction == AKEY_EVENT_ACTION_UP )
|
||||
event.KeyInput.PressedDown = false;
|
||||
else if ( keyAction == AKEY_EVENT_ACTION_MULTIPLE )
|
||||
{
|
||||
// TODO: Multiple duplicate key events have occurred in a row,
|
||||
// or a complex string is being delivered. The repeat_count
|
||||
// property of the key event contains the number of times the
|
||||
// given key code should be executed.
|
||||
// I guess this might necessary for more complicated i18n key input,
|
||||
// but don't see yet how to handle this correctly.
|
||||
}
|
||||
|
||||
/* no use for meta keys so far.
|
||||
if ( keyMetaState & AMETA_ALT_ON
|
||||
|| keyMetaState & AMETA_ALT_LEFT_ON
|
||||
|| keyMetaState & AMETA_ALT_RIGHT_ON )
|
||||
;
|
||||
// what is a sym?
|
||||
if ( keyMetaState & AMETA_SYM_ON )
|
||||
;
|
||||
*/
|
||||
if ( keyMetaState & AMETA_SHIFT_ON
|
||||
|| keyMetaState & AMETA_SHIFT_LEFT_ON
|
||||
|| keyMetaState & AMETA_SHIFT_RIGHT_ON )
|
||||
event.KeyInput.Shift = true;
|
||||
else
|
||||
event.KeyInput.Shift = false;
|
||||
event.KeyInput.Control = false;
|
||||
|
||||
// Having memory allocations + going through JNI for each key-press is pretty bad (slow).
|
||||
// So we do it only for those keys which are likely text-characters and avoid it for all other keys.
|
||||
// So it's fast for keys like game controller input and special keys. And text keys are typically
|
||||
// only used or entering text and not for gaming on Android, so speed likely doesn't matter there too much.
|
||||
if ( event.KeyInput.Key > 0 )
|
||||
{
|
||||
// TODO:
|
||||
// Not sure why we have to attach a JNIEnv here, but it won't work when doing that in the constructor or
|
||||
// trying to use the activity->env. My best guess is that the event-handling happens in an own thread.
|
||||
// It means JNIEnvAttachedToVM will never get detached as I don't know a safe way where to do that
|
||||
// (we could attach & detach each time, but that would probably be slow)
|
||||
// Also - it has to be each time as it get's invalid when the application mode changes.
|
||||
if ( device->Initialized && device->Android && device->Android->activity && device->Android->activity->vm )
|
||||
{
|
||||
JavaVMAttachArgs attachArgs;
|
||||
attachArgs.version = JNI_VERSION_1_6;
|
||||
attachArgs.name = 0;
|
||||
attachArgs.group = NULL;
|
||||
|
||||
// Not a big problem calling it each time - it's a no-op when the thread already is attached.
|
||||
// And we have to do that as someone else can have detached the thread in the meantime.
|
||||
jint result = device->Android->activity->vm->AttachCurrentThread(&device->JNIEnvAttachedToVM, &attachArgs);
|
||||
if(result == JNI_ERR)
|
||||
{
|
||||
os::Printer::log("AttachCurrentThread for the JNI environment failed.", ELL_WARNING);
|
||||
device->JNIEnvAttachedToVM = 0;
|
||||
}
|
||||
|
||||
if ( device->JNIEnvAttachedToVM )
|
||||
{
|
||||
jni::CKeyEventWrapper * keyEventWrapper = new jni::CKeyEventWrapper(device->JNIEnvAttachedToVM, keyAction, keyCode);
|
||||
event.KeyInput.Char = keyEventWrapper->getUnicodeChar(keyMetaState);
|
||||
delete keyEventWrapper;
|
||||
}
|
||||
}
|
||||
if ( event.KeyInput.Key == KEY_BACK )
|
||||
{
|
||||
event.KeyInput.Char = 0x08; // same key-code as on other operating systems. Otherwise we have to handle too much system specific stuff in the editbox.
|
||||
}
|
||||
//os::Printer::log("char-code: ", core::stringc((int)event.KeyInput.Char).c_str(), ELL_DEBUG);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG);
|
||||
event.KeyInput.Char = 0;
|
||||
}
|
||||
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::createDriver()
|
||||
{
|
||||
switch(CreationParams.DriverType)
|
||||
{
|
||||
case video::EDT_OGLES1:
|
||||
#ifdef _IRR_COMPILE_WITH_OGLES1_
|
||||
VideoDriver = video::createOGLES1Driver(CreationParams, FileSystem, ContextManager);
|
||||
#else
|
||||
os::Printer::log("No OpenGL ES 1.0 support compiled in.", ELL_ERROR);
|
||||
#endif
|
||||
break;
|
||||
case video::EDT_OGLES2:
|
||||
#ifdef _IRR_COMPILE_WITH_OGLES2_
|
||||
VideoDriver = video::createOGLES2Driver(CreationParams, FileSystem, ContextManager);
|
||||
#else
|
||||
os::Printer::log("No OpenGL ES 2.0 support compiled in.", ELL_ERROR);
|
||||
#endif
|
||||
break;
|
||||
case video::EDT_NULL:
|
||||
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
|
||||
break;
|
||||
case video::EDT_SOFTWARE:
|
||||
case video::EDT_BURNINGSVIDEO:
|
||||
case video::EDT_OPENGL:
|
||||
case video::DEPRECATED_EDT_DIRECT3D8_NO_LONGER_EXISTS:
|
||||
case video::EDT_DIRECT3D9:
|
||||
os::Printer::log("This driver is not available in Android. Try OpenGL ES 1.0 or ES 2.0.", ELL_ERROR);
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
video::SExposedVideoData& CIrrDeviceAndroid::getExposedVideoData()
|
||||
{
|
||||
return ExposedVideoData;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::createKeyMap()
|
||||
{
|
||||
KeyMap.set_used(223);
|
||||
|
||||
KeyMap[0] = KEY_UNKNOWN; // AKEYCODE_UNKNOWN
|
||||
KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT
|
||||
KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT
|
||||
KeyMap[3] = KEY_HOME; // AKEYCODE_HOME
|
||||
KeyMap[4] = KEY_BACK; // AKEYCODE_BACK
|
||||
KeyMap[5] = KEY_UNKNOWN; // AKEYCODE_CALL
|
||||
KeyMap[6] = KEY_UNKNOWN; // AKEYCODE_ENDCALL
|
||||
KeyMap[7] = KEY_KEY_0; // AKEYCODE_0
|
||||
KeyMap[8] = KEY_KEY_1; // AKEYCODE_1
|
||||
KeyMap[9] = KEY_KEY_2; // AKEYCODE_2
|
||||
KeyMap[10] = KEY_KEY_3; // AKEYCODE_3
|
||||
KeyMap[11] = KEY_KEY_4; // AKEYCODE_4
|
||||
KeyMap[12] = KEY_KEY_5; // AKEYCODE_5
|
||||
KeyMap[13] = KEY_KEY_6; // AKEYCODE_6
|
||||
KeyMap[14] = KEY_KEY_7; // AKEYCODE_7
|
||||
KeyMap[15] = KEY_KEY_8; // AKEYCODE_8
|
||||
KeyMap[16] = KEY_KEY_9; // AKEYCODE_9
|
||||
KeyMap[17] = KEY_UNKNOWN; // AKEYCODE_STAR
|
||||
KeyMap[18] = KEY_UNKNOWN; // AKEYCODE_POUND
|
||||
KeyMap[19] = KEY_UP; // AKEYCODE_DPAD_UP
|
||||
KeyMap[20] = KEY_DOWN; // AKEYCODE_DPAD_DOWN
|
||||
KeyMap[21] = KEY_LEFT; // AKEYCODE_DPAD_LEFT
|
||||
KeyMap[22] = KEY_RIGHT; // AKEYCODE_DPAD_RIGHT
|
||||
KeyMap[23] = KEY_SELECT; // AKEYCODE_DPAD_CENTER
|
||||
KeyMap[24] = KEY_VOLUME_DOWN; // AKEYCODE_VOLUME_UP
|
||||
KeyMap[25] = KEY_VOLUME_UP; // AKEYCODE_VOLUME_DOWN
|
||||
KeyMap[26] = KEY_UNKNOWN; // AKEYCODE_POWER
|
||||
KeyMap[27] = KEY_UNKNOWN; // AKEYCODE_CAMERA
|
||||
KeyMap[28] = KEY_CLEAR; // AKEYCODE_CLEAR
|
||||
KeyMap[29] = KEY_KEY_A; // AKEYCODE_A
|
||||
KeyMap[30] = KEY_KEY_B; // AKEYCODE_B
|
||||
KeyMap[31] = KEY_KEY_C; // AKEYCODE_C
|
||||
KeyMap[32] = KEY_KEY_D; // AKEYCODE_D
|
||||
KeyMap[33] = KEY_KEY_E; // AKEYCODE_E
|
||||
KeyMap[34] = KEY_KEY_F; // AKEYCODE_F
|
||||
KeyMap[35] = KEY_KEY_G; // AKEYCODE_G
|
||||
KeyMap[36] = KEY_KEY_H; // AKEYCODE_H
|
||||
KeyMap[37] = KEY_KEY_I; // AKEYCODE_I
|
||||
KeyMap[38] = KEY_KEY_J; // AKEYCODE_J
|
||||
KeyMap[39] = KEY_KEY_K; // AKEYCODE_K
|
||||
KeyMap[40] = KEY_KEY_L; // AKEYCODE_L
|
||||
KeyMap[41] = KEY_KEY_M; // AKEYCODE_M
|
||||
KeyMap[42] = KEY_KEY_N; // AKEYCODE_N
|
||||
KeyMap[43] = KEY_KEY_O; // AKEYCODE_O
|
||||
KeyMap[44] = KEY_KEY_P; // AKEYCODE_P
|
||||
KeyMap[45] = KEY_KEY_Q; // AKEYCODE_Q
|
||||
KeyMap[46] = KEY_KEY_R; // AKEYCODE_R
|
||||
KeyMap[47] = KEY_KEY_S; // AKEYCODE_S
|
||||
KeyMap[48] = KEY_KEY_T; // AKEYCODE_T
|
||||
KeyMap[49] = KEY_KEY_U; // AKEYCODE_U
|
||||
KeyMap[50] = KEY_KEY_V; // AKEYCODE_V
|
||||
KeyMap[51] = KEY_KEY_W; // AKEYCODE_W
|
||||
KeyMap[52] = KEY_KEY_X; // AKEYCODE_X
|
||||
KeyMap[53] = KEY_KEY_Y; // AKEYCODE_Y
|
||||
KeyMap[54] = KEY_KEY_Z; // AKEYCODE_Z
|
||||
KeyMap[55] = KEY_COMMA; // AKEYCODE_COMMA
|
||||
KeyMap[56] = KEY_PERIOD; // AKEYCODE_PERIOD
|
||||
KeyMap[57] = KEY_MENU; // AKEYCODE_ALT_LEFT
|
||||
KeyMap[58] = KEY_MENU; // AKEYCODE_ALT_RIGHT
|
||||
KeyMap[59] = KEY_LSHIFT; // AKEYCODE_SHIFT_LEFT
|
||||
KeyMap[60] = KEY_RSHIFT; // AKEYCODE_SHIFT_RIGHT
|
||||
KeyMap[61] = KEY_TAB; // AKEYCODE_TAB
|
||||
KeyMap[62] = KEY_SPACE; // AKEYCODE_SPACE
|
||||
KeyMap[63] = KEY_UNKNOWN; // AKEYCODE_SYM
|
||||
KeyMap[64] = KEY_UNKNOWN; // AKEYCODE_EXPLORER
|
||||
KeyMap[65] = KEY_UNKNOWN; // AKEYCODE_ENVELOPE
|
||||
KeyMap[66] = KEY_RETURN; // AKEYCODE_ENTER
|
||||
KeyMap[67] = KEY_BACK; // AKEYCODE_DEL
|
||||
KeyMap[68] = KEY_OEM_3; // AKEYCODE_GRAVE
|
||||
KeyMap[69] = KEY_MINUS; // AKEYCODE_MINUS
|
||||
KeyMap[70] = KEY_UNKNOWN; // AKEYCODE_EQUALS
|
||||
KeyMap[71] = KEY_UNKNOWN; // AKEYCODE_LEFT_BRACKET
|
||||
KeyMap[72] = KEY_UNKNOWN; // AKEYCODE_RIGHT_BRACKET
|
||||
KeyMap[73] = KEY_UNKNOWN; // AKEYCODE_BACKSLASH
|
||||
KeyMap[74] = KEY_UNKNOWN; // AKEYCODE_SEMICOLON
|
||||
KeyMap[75] = KEY_UNKNOWN; // AKEYCODE_APOSTROPHE
|
||||
KeyMap[76] = KEY_UNKNOWN; // AKEYCODE_SLASH
|
||||
KeyMap[77] = KEY_UNKNOWN; // AKEYCODE_AT
|
||||
KeyMap[78] = KEY_UNKNOWN; // AKEYCODE_NUM
|
||||
KeyMap[79] = KEY_UNKNOWN; // AKEYCODE_HEADSETHOOK
|
||||
KeyMap[80] = KEY_UNKNOWN; // AKEYCODE_FOCUS (*Camera* focus)
|
||||
KeyMap[81] = KEY_PLUS; // AKEYCODE_PLUS
|
||||
KeyMap[82] = KEY_MENU; // AKEYCODE_MENU
|
||||
KeyMap[83] = KEY_UNKNOWN; // AKEYCODE_NOTIFICATION
|
||||
KeyMap[84] = KEY_UNKNOWN; // AKEYCODE_SEARCH
|
||||
KeyMap[85] = KEY_MEDIA_PLAY_PAUSE; // AKEYCODE_MEDIA_PLAY_PAUSE
|
||||
KeyMap[86] = KEY_MEDIA_STOP; // AKEYCODE_MEDIA_STOP
|
||||
KeyMap[87] = KEY_MEDIA_NEXT_TRACK; // AKEYCODE_MEDIA_NEXT
|
||||
KeyMap[88] = KEY_MEDIA_PREV_TRACK; // AKEYCODE_MEDIA_PREVIOUS
|
||||
KeyMap[89] = KEY_UNKNOWN; // AKEYCODE_MEDIA_REWIND
|
||||
KeyMap[90] = KEY_UNKNOWN; // AKEYCODE_MEDIA_FAST_FORWARD
|
||||
KeyMap[91] = KEY_VOLUME_MUTE; // AKEYCODE_MUTE
|
||||
KeyMap[92] = KEY_PRIOR; // AKEYCODE_PAGE_UP
|
||||
KeyMap[93] = KEY_NEXT; // AKEYCODE_PAGE_DOWN
|
||||
KeyMap[94] = KEY_UNKNOWN; // AKEYCODE_PICTSYMBOLS
|
||||
KeyMap[95] = KEY_UNKNOWN; // AKEYCODE_SWITCH_CHARSET
|
||||
|
||||
// following look like controller inputs
|
||||
KeyMap[96] = KEY_UNKNOWN; // AKEYCODE_BUTTON_A
|
||||
KeyMap[97] = KEY_UNKNOWN; // AKEYCODE_BUTTON_B
|
||||
KeyMap[98] = KEY_UNKNOWN; // AKEYCODE_BUTTON_C
|
||||
KeyMap[99] = KEY_UNKNOWN; // AKEYCODE_BUTTON_X
|
||||
KeyMap[100] = KEY_UNKNOWN; // AKEYCODE_BUTTON_Y
|
||||
KeyMap[101] = KEY_UNKNOWN; // AKEYCODE_BUTTON_Z
|
||||
KeyMap[102] = KEY_UNKNOWN; // AKEYCODE_BUTTON_L1
|
||||
KeyMap[103] = KEY_UNKNOWN; // AKEYCODE_BUTTON_R1
|
||||
KeyMap[104] = KEY_UNKNOWN; // AKEYCODE_BUTTON_L2
|
||||
KeyMap[105] = KEY_UNKNOWN; // AKEYCODE_BUTTON_R2
|
||||
KeyMap[106] = KEY_UNKNOWN; // AKEYCODE_BUTTON_THUMBL
|
||||
KeyMap[107] = KEY_UNKNOWN; // AKEYCODE_BUTTON_THUMBR
|
||||
KeyMap[108] = KEY_UNKNOWN; // AKEYCODE_BUTTON_START
|
||||
KeyMap[109] = KEY_UNKNOWN; // AKEYCODE_BUTTON_SELECT
|
||||
KeyMap[110] = KEY_UNKNOWN; // AKEYCODE_BUTTON_MODE
|
||||
|
||||
KeyMap[111] = KEY_ESCAPE; // AKEYCODE_ESCAPE
|
||||
KeyMap[112] = KEY_DELETE; // AKEYCODE_FORWARD_DEL
|
||||
KeyMap[113] = KEY_CONTROL; // AKEYCODE_CTRL_LEFT
|
||||
KeyMap[114] = KEY_CONTROL; // AKEYCODE_CTRL_RIGHT
|
||||
KeyMap[115] = KEY_CAPITAL; // AKEYCODE_CAPS_LOCK
|
||||
KeyMap[116] = KEY_SCROLL; // AKEYCODE_SCROLL_LOCK
|
||||
KeyMap[117] = KEY_UNKNOWN; // AKEYCODE_META_LEFT
|
||||
KeyMap[118] = KEY_UNKNOWN; // AKEYCODE_META_RIGHT
|
||||
KeyMap[119] = KEY_UNKNOWN; // AKEYCODE_FUNCTION
|
||||
KeyMap[120] = KEY_SNAPSHOT; // AKEYCODE_SYSRQ
|
||||
KeyMap[121] = KEY_PAUSE; // AKEYCODE_BREAK
|
||||
KeyMap[122] = KEY_HOME; // AKEYCODE_MOVE_HOME
|
||||
KeyMap[123] = KEY_END; // AKEYCODE_MOVE_END
|
||||
KeyMap[124] = KEY_INSERT; // AKEYCODE_INSERT
|
||||
KeyMap[125] = KEY_UNKNOWN; // AKEYCODE_FORWARD
|
||||
KeyMap[126] = KEY_PLAY; // AKEYCODE_MEDIA_PLAY
|
||||
KeyMap[127] = KEY_MEDIA_PLAY_PAUSE; // AKEYCODE_MEDIA_PAUSE
|
||||
KeyMap[128] = KEY_UNKNOWN; // AKEYCODE_MEDIA_CLOSE
|
||||
KeyMap[129] = KEY_UNKNOWN; // AKEYCODE_MEDIA_EJECT
|
||||
KeyMap[130] = KEY_UNKNOWN; // AKEYCODE_MEDIA_RECORD
|
||||
KeyMap[131] = KEY_F1; // AKEYCODE_F1
|
||||
KeyMap[132] = KEY_F2; // AKEYCODE_F2
|
||||
KeyMap[133] = KEY_F3; // AKEYCODE_F3
|
||||
KeyMap[134] = KEY_F4; // AKEYCODE_F4
|
||||
KeyMap[135] = KEY_F5; // AKEYCODE_F5
|
||||
KeyMap[136] = KEY_F6; // AKEYCODE_F6
|
||||
KeyMap[137] = KEY_F7; // AKEYCODE_F7
|
||||
KeyMap[138] = KEY_F8; // AKEYCODE_F8
|
||||
KeyMap[139] = KEY_F9; // AKEYCODE_F9
|
||||
KeyMap[140] = KEY_F10; // AKEYCODE_F10
|
||||
KeyMap[141] = KEY_F11; // AKEYCODE_F11
|
||||
KeyMap[142] = KEY_F12; // AKEYCODE_F12
|
||||
KeyMap[143] = KEY_NUMLOCK; // AKEYCODE_NUM_LOCK
|
||||
KeyMap[144] = KEY_NUMPAD0; // AKEYCODE_NUMPAD_0
|
||||
KeyMap[145] = KEY_NUMPAD1; // AKEYCODE_NUMPAD_1
|
||||
KeyMap[146] = KEY_NUMPAD2; // AKEYCODE_NUMPAD_2
|
||||
KeyMap[147] = KEY_NUMPAD3; // AKEYCODE_NUMPAD_3
|
||||
KeyMap[148] = KEY_NUMPAD4; // AKEYCODE_NUMPAD_4
|
||||
KeyMap[149] = KEY_NUMPAD5; // AKEYCODE_NUMPAD_5
|
||||
KeyMap[150] = KEY_NUMPAD6; // AKEYCODE_NUMPAD_6
|
||||
KeyMap[151] = KEY_NUMPAD7; // AKEYCODE_NUMPAD_7
|
||||
KeyMap[152] = KEY_NUMPAD8; // AKEYCODE_NUMPAD_8
|
||||
KeyMap[153] = KEY_NUMPAD9; // AKEYCODE_NUMPAD_9
|
||||
KeyMap[154] = KEY_DIVIDE; // AKEYCODE_NUMPAD_DIVIDE
|
||||
KeyMap[155] = KEY_MULTIPLY; // AKEYCODE_NUMPAD_MULTIPLY
|
||||
KeyMap[156] = KEY_SUBTRACT; // AKEYCODE_NUMPAD_SUBTRACT
|
||||
KeyMap[157] = KEY_ADD; // AKEYCODE_NUMPAD_ADD
|
||||
KeyMap[158] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_DOT
|
||||
KeyMap[159] = KEY_COMMA; // AKEYCODE_NUMPAD_COMMA
|
||||
KeyMap[160] = KEY_RETURN; // AKEYCODE_NUMPAD_ENTER
|
||||
KeyMap[161] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_EQUALS
|
||||
KeyMap[162] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_LEFT_PAREN
|
||||
KeyMap[163] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_RIGHT_PAREN
|
||||
KeyMap[164] = KEY_VOLUME_MUTE; // AKEYCODE_VOLUME_MUTE
|
||||
KeyMap[165] = KEY_UNKNOWN; // AKEYCODE_INFO
|
||||
KeyMap[166] = KEY_UNKNOWN; // AKEYCODE_CHANNEL_UP
|
||||
KeyMap[167] = KEY_UNKNOWN; // AKEYCODE_CHANNEL_DOWN
|
||||
KeyMap[168] = KEY_ZOOM; // AKEYCODE_ZOOM_IN
|
||||
KeyMap[169] = KEY_UNKNOWN; // AKEYCODE_ZOOM_OUT
|
||||
KeyMap[170] = KEY_UNKNOWN; // AKEYCODE_TV
|
||||
KeyMap[171] = KEY_UNKNOWN; // AKEYCODE_WINDOW
|
||||
KeyMap[172] = KEY_UNKNOWN; // AKEYCODE_GUIDE
|
||||
KeyMap[173] = KEY_UNKNOWN; // AKEYCODE_DVR
|
||||
KeyMap[174] = KEY_UNKNOWN; // AKEYCODE_BOOKMARK
|
||||
KeyMap[175] = KEY_UNKNOWN; // AKEYCODE_CAPTIONS
|
||||
KeyMap[176] = KEY_UNKNOWN; // AKEYCODE_SETTINGS
|
||||
KeyMap[177] = KEY_UNKNOWN; // AKEYCODE_TV_POWER
|
||||
KeyMap[178] = KEY_UNKNOWN; // AKEYCODE_TV_INPUT
|
||||
KeyMap[179] = KEY_UNKNOWN; // AKEYCODE_STB_POWER
|
||||
KeyMap[180] = KEY_UNKNOWN; // AKEYCODE_STB_INPUT
|
||||
KeyMap[181] = KEY_UNKNOWN; // AKEYCODE_AVR_POWER
|
||||
KeyMap[182] = KEY_UNKNOWN; // AKEYCODE_AVR_INPUT
|
||||
KeyMap[183] = KEY_UNKNOWN; // AKEYCODE_PROG_RED
|
||||
KeyMap[184] = KEY_UNKNOWN; // AKEYCODE_PROG_GREEN
|
||||
KeyMap[185] = KEY_UNKNOWN; // AKEYCODE_PROG_YELLOW
|
||||
KeyMap[186] = KEY_UNKNOWN; // AKEYCODE_PROG_BLUE
|
||||
KeyMap[187] = KEY_UNKNOWN; // AKEYCODE_APP_SWITCH
|
||||
KeyMap[188] = KEY_UNKNOWN; // AKEYCODE_BUTTON_1
|
||||
KeyMap[189] = KEY_UNKNOWN; // AKEYCODE_BUTTON_2
|
||||
KeyMap[190] = KEY_UNKNOWN; // AKEYCODE_BUTTON_3
|
||||
KeyMap[191] = KEY_UNKNOWN; // AKEYCODE_BUTTON_4
|
||||
KeyMap[192] = KEY_UNKNOWN; // AKEYCODE_BUTTON_5
|
||||
KeyMap[193] = KEY_UNKNOWN; // AKEYCODE_BUTTON_6
|
||||
KeyMap[194] = KEY_UNKNOWN; // AKEYCODE_BUTTON_7
|
||||
KeyMap[195] = KEY_UNKNOWN; // AKEYCODE_BUTTON_8
|
||||
KeyMap[196] = KEY_UNKNOWN; // AKEYCODE_BUTTON_9
|
||||
KeyMap[197] = KEY_UNKNOWN; // AKEYCODE_BUTTON_10
|
||||
KeyMap[198] = KEY_UNKNOWN; // AKEYCODE_BUTTON_11
|
||||
KeyMap[199] = KEY_UNKNOWN; // AKEYCODE_BUTTON_12
|
||||
KeyMap[200] = KEY_UNKNOWN; // AKEYCODE_BUTTON_13
|
||||
KeyMap[201] = KEY_UNKNOWN; // AKEYCODE_BUTTON_14
|
||||
KeyMap[202] = KEY_UNKNOWN; // AKEYCODE_BUTTON_15
|
||||
KeyMap[203] = KEY_UNKNOWN; // AKEYCODE_BUTTON_16
|
||||
KeyMap[204] = KEY_UNKNOWN; // AKEYCODE_LANGUAGE_SWITCH
|
||||
KeyMap[205] = KEY_UNKNOWN; // AKEYCODE_MANNER_MODE
|
||||
KeyMap[206] = KEY_UNKNOWN; // AKEYCODE_3D_MODE
|
||||
KeyMap[207] = KEY_UNKNOWN; // AKEYCODE_CONTACTS
|
||||
KeyMap[208] = KEY_UNKNOWN; // AKEYCODE_CALENDAR
|
||||
KeyMap[209] = KEY_UNKNOWN; // AKEYCODE_MUSIC
|
||||
KeyMap[210] = KEY_UNKNOWN; // AKEYCODE_CALCULATOR
|
||||
KeyMap[211] = KEY_UNKNOWN; // AKEYCODE_ZENKAKU_HANKAKU
|
||||
KeyMap[212] = KEY_UNKNOWN; // AKEYCODE_EISU
|
||||
KeyMap[213] = KEY_UNKNOWN; // AKEYCODE_MUHENKAN
|
||||
KeyMap[214] = KEY_UNKNOWN; // AKEYCODE_HENKAN
|
||||
KeyMap[215] = KEY_UNKNOWN; // AKEYCODE_KATAKANA_HIRAGANA
|
||||
KeyMap[216] = KEY_UNKNOWN; // AKEYCODE_YEN
|
||||
KeyMap[217] = KEY_UNKNOWN; // AKEYCODE_RO
|
||||
KeyMap[218] = KEY_UNKNOWN; // AKEYCODE_KANA
|
||||
KeyMap[219] = KEY_UNKNOWN; // AKEYCODE_ASSIST
|
||||
KeyMap[220] = KEY_UNKNOWN; // AKEYCODE_BRIGHTNESS_DOWN
|
||||
KeyMap[221] = KEY_UNKNOWN; // AKEYCODE_BRIGHTNESS_UP ,
|
||||
KeyMap[222] = KEY_UNKNOWN; // AKEYCODE_MEDIA_AUDIO_TRACK
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::activateAccelerometer(float updateInterval)
|
||||
{
|
||||
if (!isAccelerometerAvailable())
|
||||
return false;
|
||||
|
||||
ASensorEventQueue_enableSensor(SensorEventQueue, Accelerometer);
|
||||
ASensorEventQueue_setEventRate(SensorEventQueue, Accelerometer, (int32_t)(updateInterval*1000.f*1000.f)); // in microseconds
|
||||
|
||||
os::Printer::log("Activated accelerometer", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::deactivateAccelerometer()
|
||||
{
|
||||
if (Accelerometer)
|
||||
{
|
||||
ASensorEventQueue_disableSensor(SensorEventQueue, Accelerometer);
|
||||
Accelerometer = 0;
|
||||
os::Printer::log("Deactivated accelerometer", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isAccelerometerActive()
|
||||
{
|
||||
return (Accelerometer != 0);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isAccelerometerAvailable()
|
||||
{
|
||||
if (!Accelerometer)
|
||||
Accelerometer = ASensorManager_getDefaultSensor(SensorManager, ASENSOR_TYPE_ACCELEROMETER);
|
||||
|
||||
return (Accelerometer != 0);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::activateGyroscope(float updateInterval)
|
||||
{
|
||||
if (!isGyroscopeAvailable())
|
||||
return false;
|
||||
|
||||
ASensorEventQueue_enableSensor(SensorEventQueue, Gyroscope);
|
||||
ASensorEventQueue_setEventRate(SensorEventQueue, Gyroscope, (int32_t)(updateInterval*1000.f*1000.f)); // in microseconds
|
||||
|
||||
os::Printer::log("Activated gyroscope", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::deactivateGyroscope()
|
||||
{
|
||||
if (Gyroscope)
|
||||
{
|
||||
ASensorEventQueue_disableSensor(SensorEventQueue, Gyroscope);
|
||||
Gyroscope = 0;
|
||||
os::Printer::log("Deactivated gyroscope", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isGyroscopeActive()
|
||||
{
|
||||
return (Gyroscope != 0);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isGyroscopeAvailable()
|
||||
{
|
||||
if (!Gyroscope)
|
||||
Gyroscope = ASensorManager_getDefaultSensor(SensorManager, ASENSOR_TYPE_GYROSCOPE);
|
||||
|
||||
return (Gyroscope != 0);
|
||||
}
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
107
source/Irrlicht/Android/CIrrDeviceAndroid.h
Normal file
107
source/Irrlicht/Android/CIrrDeviceAndroid.h
Normal file
@ -0,0 +1,107 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_IRR_DEVICE_ANDROID_H_INCLUDED__
|
||||
#define __C_IRR_DEVICE_ANDROID_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "IImagePresenter.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
#include <android/sensor.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
class CIrrDeviceAndroid : public CIrrDeviceStub, video::IImagePresenter
|
||||
{
|
||||
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 present(video::IImage* surface, void* windowId, core::rect<s32>* srcClip);
|
||||
|
||||
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_
|
||||
#endif // __C_IRR_DEVICE_ANDROID_H_INCLUDED__
|
63
source/Irrlicht/Android/CKeyEventWrapper.cpp
Normal file
63
source/Irrlicht/Android/CKeyEventWrapper.cpp
Normal file
@ -0,0 +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_
|
43
source/Irrlicht/Android/CKeyEventWrapper.h
Normal file
43
source/Irrlicht/Android/CKeyEventWrapper.h
Normal file
@ -0,0 +1,43 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_IRR_KEY_EVENT_WRAPPER_H_INCLUDED__
|
||||
#define __C_IRR_KEY_EVENT_WRAPPER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#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_
|
||||
#endif // __C_IRR_KEY_EVENT_WRAPPER_H_INCLUDED__
|
342
source/Irrlicht/Android/jni/Android.mk
Executable file
342
source/Irrlicht/Android/jni/Android.mk
Executable file
@ -0,0 +1,342 @@
|
||||
LOCAL_PATH := $(call my-dir)/../..
|
||||
IRRLICHT_LIB_PATH := $(LOCAL_PATH)/../../lib/Android
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := Irrlicht
|
||||
IRRLICHT_LIB_NAME := lib$(LOCAL_MODULE).a
|
||||
|
||||
LOCAL_CFLAGS := -Wall -pipe -fno-exceptions -fno-rtti -fstrict-aliasing
|
||||
|
||||
ifndef NDEBUG
|
||||
LOCAL_CFLAGS += -g -D_DEBUG
|
||||
else
|
||||
LOCAL_CFLAGS += -fexpensive-optimizations -O3
|
||||
endif
|
||||
|
||||
LOCAL_C_INCLUDES := ../../../include
|
||||
LOCAL_C_INCLUDES += ../zlib ../jpeglib ../libpng
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
Android/CIrrDeviceAndroid.cpp \
|
||||
Android/CAndroidAssetReader.cpp \
|
||||
Android/CAndroidAssetFileArchive.cpp \
|
||||
Android/CKeyEventWrapper.cpp \
|
||||
aesGladman/aescrypt.cpp \
|
||||
aesGladman/aeskey.cpp \
|
||||
aesGladman/aestab.cpp \
|
||||
aesGladman/fileenc.cpp \
|
||||
aesGladman/hmac.cpp \
|
||||
aesGladman/prng.cpp \
|
||||
aesGladman/pwd2key.cpp \
|
||||
aesGladman/sha1.cpp \
|
||||
aesGladman/sha2.cpp \
|
||||
C3DSMeshFileLoader.cpp \
|
||||
CAnimatedMeshHalfLife.cpp \
|
||||
CAnimatedMeshMD2.cpp \
|
||||
CAnimatedMeshMD3.cpp \
|
||||
CAnimatedMeshSceneNode.cpp \
|
||||
CAttributes.cpp \
|
||||
CB3DMeshFileLoader.cpp \
|
||||
CB3DMeshWriter.cpp \
|
||||
CBillboardSceneNode.cpp \
|
||||
CBoneSceneNode.cpp \
|
||||
CBSPMeshFileLoader.cpp \
|
||||
CBurningShader_Raster_Reference.cpp \
|
||||
CCameraSceneNode.cpp \
|
||||
CColladaFileLoader.cpp \
|
||||
CColladaMeshWriter.cpp \
|
||||
CColorConverter.cpp \
|
||||
CCSMLoader.cpp \
|
||||
CCubeSceneNode.cpp \
|
||||
CD3D9Driver.cpp \
|
||||
CD3D9HLSLMaterialRenderer.cpp \
|
||||
CD3D9NormalMapRenderer.cpp \
|
||||
CD3D9ParallaxMapRenderer.cpp \
|
||||
CD3D9ShaderMaterialRenderer.cpp \
|
||||
CD3D9Texture.cpp \
|
||||
CDefaultGUIElementFactory.cpp \
|
||||
CDefaultSceneNodeAnimatorFactory.cpp \
|
||||
CDefaultSceneNodeFactory.cpp \
|
||||
CDepthBuffer.cpp \
|
||||
CDMFLoader.cpp \
|
||||
CDummyTransformationSceneNode.cpp \
|
||||
CEmptySceneNode.cpp \
|
||||
CFileList.cpp \
|
||||
CFileSystem.cpp \
|
||||
CFPSCounter.cpp \
|
||||
leakHunter.cpp \
|
||||
CGeometryCreator.cpp \
|
||||
CGUIButton.cpp \
|
||||
CGUICheckBox.cpp \
|
||||
CGUIColorSelectDialog.cpp \
|
||||
CGUIComboBox.cpp \
|
||||
CGUIContextMenu.cpp \
|
||||
CGUIEditBox.cpp \
|
||||
CGUIEnvironment.cpp \
|
||||
CGUIFileOpenDialog.cpp \
|
||||
CGUIFont.cpp \
|
||||
CGUIImage.cpp \
|
||||
CGUIImageList.cpp \
|
||||
CGUIInOutFader.cpp \
|
||||
CGUIListBox.cpp \
|
||||
CGUIMenu.cpp \
|
||||
CGUIMeshViewer.cpp \
|
||||
CGUIMessageBox.cpp \
|
||||
CGUIModalScreen.cpp \
|
||||
CGUIScrollBar.cpp \
|
||||
CGUISkin.cpp \
|
||||
CGUISpinBox.cpp \
|
||||
CGUISpriteBank.cpp \
|
||||
CGUIStaticText.cpp \
|
||||
CGUITabControl.cpp \
|
||||
CGUITable.cpp \
|
||||
CGUIToolBar.cpp \
|
||||
CGUITreeView.cpp \
|
||||
CGUIWindow.cpp \
|
||||
CGUIProfiler.cpp \
|
||||
CImage.cpp \
|
||||
CImageLoaderBMP.cpp \
|
||||
CImageLoaderDDS.cpp \
|
||||
CImageLoaderJPG.cpp \
|
||||
CImageLoaderPCX.cpp \
|
||||
CImageLoaderPNG.cpp \
|
||||
CImageLoaderPPM.cpp \
|
||||
CImageLoaderPSD.cpp \
|
||||
CImageLoaderRGB.cpp \
|
||||
CImageLoaderTGA.cpp \
|
||||
CImageLoaderWAL.cpp \
|
||||
CImageWriterBMP.cpp \
|
||||
CImageWriterJPG.cpp \
|
||||
CImageWriterPCX.cpp \
|
||||
CImageWriterPNG.cpp \
|
||||
CImageWriterPPM.cpp \
|
||||
CImageWriterPSD.cpp \
|
||||
CImageWriterTGA.cpp \
|
||||
CImageLoaderPVR.cpp \
|
||||
CIrrDeviceConsole.cpp \
|
||||
CIrrDeviceFB.cpp \
|
||||
CIrrDeviceLinux.cpp \
|
||||
CIrrDeviceSDL.cpp \
|
||||
CIrrDeviceStub.cpp \
|
||||
CIrrDeviceWin32.cpp \
|
||||
CIrrMeshFileLoader.cpp \
|
||||
CIrrMeshWriter.cpp \
|
||||
CLightSceneNode.cpp \
|
||||
CLimitReadFile.cpp \
|
||||
CLMTSMeshFileLoader.cpp \
|
||||
CLogger.cpp \
|
||||
CLWOMeshFileLoader.cpp \
|
||||
CMD2MeshFileLoader.cpp \
|
||||
CMD3MeshFileLoader.cpp \
|
||||
CMemoryFile.cpp \
|
||||
CMeshCache.cpp \
|
||||
CMeshManipulator.cpp \
|
||||
CMeshSceneNode.cpp \
|
||||
CMeshTextureLoader.cpp \
|
||||
CMetaTriangleSelector.cpp \
|
||||
CMountPointReader.cpp \
|
||||
CMS3DMeshFileLoader.cpp \
|
||||
CMY3DMeshFileLoader.cpp \
|
||||
CNPKReader.cpp \
|
||||
CNullDriver.cpp \
|
||||
COBJMeshFileLoader.cpp \
|
||||
COBJMeshWriter.cpp \
|
||||
COCTLoader.cpp \
|
||||
COctreeSceneNode.cpp \
|
||||
COctreeTriangleSelector.cpp \
|
||||
CEGLManager.cpp \
|
||||
COGLES2Driver.cpp \
|
||||
COGLES2ExtensionHandler.cpp \
|
||||
COGLES2MaterialRenderer.cpp \
|
||||
COGLES2FixedPipelineRenderer.cpp \
|
||||
COGLES2NormalMapRenderer.cpp \
|
||||
COGLES2ParallaxMapRenderer.cpp \
|
||||
COGLES2Renderer2D.cpp \
|
||||
COGLESDriver.cpp \
|
||||
COGLESExtensionHandler.cpp \
|
||||
COgreMeshFileLoader.cpp \
|
||||
COpenGLCacheHandler.cpp \
|
||||
COpenGLDriver.cpp \
|
||||
COpenGLExtensionHandler.cpp \
|
||||
COpenGLNormalMapRenderer.cpp \
|
||||
COpenGLParallaxMapRenderer.cpp \
|
||||
COpenGLShaderMaterialRenderer.cpp \
|
||||
COpenGLSLMaterialRenderer.cpp \
|
||||
COSOperator.cpp \
|
||||
CPakReader.cpp \
|
||||
CParticleAnimatedMeshSceneNodeEmitter.cpp \
|
||||
CParticleAttractionAffector.cpp \
|
||||
CParticleBoxEmitter.cpp \
|
||||
CParticleCylinderEmitter.cpp \
|
||||
CParticleFadeOutAffector.cpp \
|
||||
CParticleGravityAffector.cpp \
|
||||
CParticleMeshEmitter.cpp \
|
||||
CParticlePointEmitter.cpp \
|
||||
CParticleRingEmitter.cpp \
|
||||
CParticleRotationAffector.cpp \
|
||||
CParticleScaleAffector.cpp \
|
||||
CParticleSphereEmitter.cpp \
|
||||
CParticleSystemSceneNode.cpp \
|
||||
CPLYMeshFileLoader.cpp \
|
||||
CPLYMeshWriter.cpp \
|
||||
CProfiler.cpp \
|
||||
CQ3LevelMesh.cpp \
|
||||
CQuake3ShaderSceneNode.cpp \
|
||||
CReadFile.cpp \
|
||||
CSceneCollisionManager.cpp \
|
||||
CSceneLoaderIrr.cpp \
|
||||
CSceneManager.cpp \
|
||||
CSceneNodeAnimatorCameraFPS.cpp \
|
||||
CSceneNodeAnimatorCameraMaya.cpp \
|
||||
CSceneNodeAnimatorCollisionResponse.cpp \
|
||||
CSceneNodeAnimatorDelete.cpp \
|
||||
CSceneNodeAnimatorFlyCircle.cpp \
|
||||
CSceneNodeAnimatorFlyStraight.cpp \
|
||||
CSceneNodeAnimatorFollowSpline.cpp \
|
||||
CSceneNodeAnimatorRotation.cpp \
|
||||
CSceneNodeAnimatorTexture.cpp \
|
||||
CShadowVolumeSceneNode.cpp \
|
||||
CSkinnedMesh.cpp \
|
||||
CSkyBoxSceneNode.cpp \
|
||||
CSkyDomeSceneNode.cpp \
|
||||
CSMFMeshFileLoader.cpp \
|
||||
CSoftwareDriver.cpp \
|
||||
CSoftwareDriver2.cpp \
|
||||
CSoftwareTexture.cpp \
|
||||
CSoftwareTexture2.cpp \
|
||||
CSphereSceneNode.cpp \
|
||||
CSTLMeshFileLoader.cpp \
|
||||
CSTLMeshWriter.cpp \
|
||||
CTarReader.cpp \
|
||||
CTerrainSceneNode.cpp \
|
||||
CTerrainTriangleSelector.cpp \
|
||||
CTextSceneNode.cpp \
|
||||
CTRFlat.cpp \
|
||||
CTRFlatWire.cpp \
|
||||
CTRGouraud.cpp \
|
||||
CTRGouraud2.cpp \
|
||||
CTRGouraudAlpha2.cpp \
|
||||
CTRGouraudAlphaNoZ2.cpp \
|
||||
CTRGouraudWire.cpp \
|
||||
CTriangleBBSelector.cpp \
|
||||
CTriangleSelector.cpp \
|
||||
CTRNormalMap.cpp \
|
||||
CTRStencilShadow.cpp \
|
||||
CTRTextureBlend.cpp \
|
||||
CTRTextureDetailMap2.cpp \
|
||||
CTRTextureFlat.cpp \
|
||||
CTRTextureFlatWire.cpp \
|
||||
CTRTextureGouraud.cpp \
|
||||
CTRTextureGouraud2.cpp \
|
||||
CTRTextureGouraudAdd.cpp \
|
||||
CTRTextureGouraudAdd2.cpp \
|
||||
CTRTextureGouraudAddNoZ2.cpp \
|
||||
CTRTextureGouraudAlpha.cpp \
|
||||
CTRTextureGouraudAlphaNoZ.cpp \
|
||||
CTRTextureGouraudNoZ.cpp \
|
||||
CTRTextureGouraudNoZ2.cpp \
|
||||
CTRTextureGouraudVertexAlpha2.cpp \
|
||||
CTRTextureGouraudWire.cpp \
|
||||
CTRTextureLightMap2_Add.cpp \
|
||||
CTRTextureLightMap2_M1.cpp \
|
||||
CTRTextureLightMap2_M2.cpp \
|
||||
CTRTextureLightMap2_M4.cpp \
|
||||
CTRTextureLightMapGouraud2_M4.cpp \
|
||||
CTRTextureWire2.cpp \
|
||||
CVideoModeList.cpp \
|
||||
CVolumeLightSceneNode.cpp \
|
||||
CWADReader.cpp \
|
||||
CWaterSurfaceSceneNode.cpp \
|
||||
CWriteFile.cpp \
|
||||
CXMeshFileLoader.cpp \
|
||||
CXMLReader.cpp \
|
||||
CXMLWriter.cpp \
|
||||
CZBuffer.cpp \
|
||||
CZipReader.cpp \
|
||||
IBurningShader.cpp \
|
||||
Irrlicht.cpp \
|
||||
irrXML.cpp \
|
||||
os.cpp \
|
||||
bzip2/blocksort.c \
|
||||
bzip2/bzcompress.c \
|
||||
bzip2/bzlib.c \
|
||||
bzip2/crctable.c \
|
||||
bzip2/decompress.c \
|
||||
bzip2/huffman.c \
|
||||
bzip2/randtable.c \
|
||||
jpeglib/jaricom.c \
|
||||
jpeglib/jcapimin.c \
|
||||
jpeglib/jcapistd.c \
|
||||
jpeglib/jcarith.c \
|
||||
jpeglib/jccoefct.c \
|
||||
jpeglib/jccolor.c \
|
||||
jpeglib/jcdctmgr.c \
|
||||
jpeglib/jchuff.c \
|
||||
jpeglib/jcinit.c \
|
||||
jpeglib/jcmainct.c \
|
||||
jpeglib/jcmarker.c \
|
||||
jpeglib/jcmaster.c \
|
||||
jpeglib/jcomapi.c \
|
||||
jpeglib/jcparam.c \
|
||||
jpeglib/jcprepct.c \
|
||||
jpeglib/jcsample.c \
|
||||
jpeglib/jctrans.c \
|
||||
jpeglib/jdapimin.c \
|
||||
jpeglib/jdapistd.c \
|
||||
jpeglib/jdarith.c \
|
||||
jpeglib/jdatadst.c \
|
||||
jpeglib/jdatasrc.c \
|
||||
jpeglib/jdcoefct.c \
|
||||
jpeglib/jdcolor.c \
|
||||
jpeglib/jddctmgr.c \
|
||||
jpeglib/jdhuff.c \
|
||||
jpeglib/jdinput.c \
|
||||
jpeglib/jdmainct.c \
|
||||
jpeglib/jdmarker.c \
|
||||
jpeglib/jdmaster.c \
|
||||
jpeglib/jdmerge.c \
|
||||
jpeglib/jdpostct.c \
|
||||
jpeglib/jdsample.c \
|
||||
jpeglib/jdtrans.c \
|
||||
jpeglib/jerror.c \
|
||||
jpeglib/jfdctflt.c \
|
||||
jpeglib/jfdctfst.c \
|
||||
jpeglib/jfdctint.c \
|
||||
jpeglib/jidctflt.c \
|
||||
jpeglib/jidctfst.c \
|
||||
jpeglib/jidctint.c \
|
||||
jpeglib/jmemmgr.c \
|
||||
jpeglib/jmemnobs.c \
|
||||
jpeglib/jquant1.c \
|
||||
jpeglib/jquant2.c \
|
||||
jpeglib/jutils.c \
|
||||
libpng/png.c \
|
||||
libpng/pngerror.c \
|
||||
libpng/pngget.c \
|
||||
libpng/pngmem.c \
|
||||
libpng/pngpread.c \
|
||||
libpng/pngread.c \
|
||||
libpng/pngrio.c \
|
||||
libpng/pngrtran.c \
|
||||
libpng/pngrutil.c \
|
||||
libpng/pngset.c \
|
||||
libpng/pngtrans.c \
|
||||
libpng/pngwio.c \
|
||||
libpng/pngwrite.c \
|
||||
libpng/pngwtran.c \
|
||||
libpng/pngwutil.c \
|
||||
lzma/LzmaDec.c \
|
||||
zlib/adler32.c zlib/crc32.c zlib/gzclose.c zlib/gzread.c zlib/infback.c zlib/inflate.c zlib/trees.c zlib/zutil.c\
|
||||
zlib/compress.c zlib/deflate.c zlib/gzlib.c zlib/gzwrite.c zlib/inffast.c zlib/inftrees.c zlib/uncompr.c
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
$(call import-module,android/native_app_glue)
|
||||
|
||||
all: $(IRRLICHT_LIB_PATH)
|
||||
$(IRRLICHT_LIB_PATH) : $(TARGET_OUT)/$(IRRLICHT_LIB_NAME)
|
||||
cp $< $@
|
||||
|
2
source/Irrlicht/Android/jni/Application.mk
Normal file
2
source/Irrlicht/Android/jni/Application.mk
Normal file
@ -0,0 +1,2 @@
|
||||
APP_PLATFORM := android-10
|
||||
APP_MODULES := Irrlicht
|
1075
source/Irrlicht/BuiltInFont.h
Normal file
1075
source/Irrlicht/BuiltInFont.h
Normal file
File diff suppressed because it is too large
Load Diff
1371
source/Irrlicht/C3DSMeshFileLoader.cpp
Normal file
1371
source/Irrlicht/C3DSMeshFileLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
166
source/Irrlicht/C3DSMeshFileLoader.h
Normal file
166
source/Irrlicht/C3DSMeshFileLoader.h
Normal file
@ -0,0 +1,166 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_3DS_MESH_FILE_LOADER_H_INCLUDED__
|
||||
#define __C_3DS_MESH_FILE_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrString.h"
|
||||
#include "SMesh.h"
|
||||
#include "matrix4.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Meshloader capable of loading 3ds meshes.
|
||||
class C3DSMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
C3DSMeshFileLoader(ISceneManager* smgr, io::IFileSystem* fs);
|
||||
|
||||
//! destructor
|
||||
virtual ~C3DSMeshFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_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.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
||||
struct ChunkHeader
|
||||
{
|
||||
u16 id;
|
||||
s32 length;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
struct ChunkData
|
||||
{
|
||||
ChunkData() : read(0) {}
|
||||
|
||||
ChunkHeader header;
|
||||
s32 read;
|
||||
};
|
||||
|
||||
struct SCurrentMaterial
|
||||
{
|
||||
void clear() {
|
||||
Material=video::SMaterial();
|
||||
Name="";
|
||||
Filename[0]="";
|
||||
Filename[1]="";
|
||||
Filename[2]="";
|
||||
Filename[3]="";
|
||||
Filename[4]="";
|
||||
Strength[0]=0.f;
|
||||
Strength[1]=0.f;
|
||||
Strength[2]=0.f;
|
||||
Strength[3]=0.f;
|
||||
Strength[4]=0.f;
|
||||
}
|
||||
|
||||
video::SMaterial Material;
|
||||
core::stringc Name;
|
||||
core::stringc Filename[5];
|
||||
f32 Strength[5];
|
||||
};
|
||||
|
||||
struct SMaterialGroup
|
||||
{
|
||||
SMaterialGroup() : faceCount(0), faces(0) {};
|
||||
|
||||
SMaterialGroup(const SMaterialGroup& o)
|
||||
{
|
||||
*this = o;
|
||||
}
|
||||
|
||||
~SMaterialGroup()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
delete [] faces;
|
||||
faces = 0;
|
||||
faceCount = 0;
|
||||
}
|
||||
|
||||
void operator =(const SMaterialGroup& o)
|
||||
{
|
||||
MaterialName = o.MaterialName;
|
||||
faceCount = o.faceCount;
|
||||
faces = new u16[faceCount];
|
||||
for (u16 i=0; i<faceCount; ++i)
|
||||
faces[i] = o.faces[i];
|
||||
}
|
||||
|
||||
core::stringc MaterialName;
|
||||
u16 faceCount;
|
||||
u16* faces;
|
||||
};
|
||||
|
||||
bool readChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readMaterialChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readFrameChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readTrackChunk(io::IReadFile* file, ChunkData& data,
|
||||
IMeshBuffer* mb, const core::vector3df& pivot);
|
||||
bool readObjectChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readPercentageChunk(io::IReadFile* file, ChunkData* chunk, f32& percentage);
|
||||
bool readColorChunk(io::IReadFile* file, ChunkData* chunk, video::SColor& out);
|
||||
|
||||
void readChunkData(io::IReadFile* file, ChunkData& data);
|
||||
void readString(io::IReadFile* file, ChunkData& data, core::stringc& out);
|
||||
void readVertices(io::IReadFile* file, ChunkData& data);
|
||||
void readIndices(io::IReadFile* file, ChunkData& data);
|
||||
void readMaterialGroup(io::IReadFile* file, ChunkData& data);
|
||||
void readTextureCoords(io::IReadFile* file, ChunkData& data);
|
||||
|
||||
void composeObject(io::IReadFile* file, const core::stringc& name);
|
||||
void loadMaterials(io::IReadFile* file);
|
||||
void cleanUp();
|
||||
|
||||
scene::ISceneManager* SceneManager;
|
||||
io::IFileSystem* FileSystem;
|
||||
|
||||
f32* Vertices;
|
||||
u16* Indices;
|
||||
u32* SmoothingGroups;
|
||||
core::array<u16> TempIndices;
|
||||
f32* TCoords;
|
||||
u16 CountVertices;
|
||||
u16 CountFaces; // = CountIndices/4
|
||||
u16 CountTCoords;
|
||||
core::array<SMaterialGroup> MaterialGroups;
|
||||
|
||||
SCurrentMaterial CurrentMaterial;
|
||||
core::array<SCurrentMaterial> Materials;
|
||||
core::array<core::stringc> MeshBufferNames;
|
||||
core::matrix4 TransformationMatrix;
|
||||
|
||||
SMesh* Mesh;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1679
source/Irrlicht/CAnimatedMeshHalfLife.cpp
Normal file
1679
source/Irrlicht/CAnimatedMeshHalfLife.cpp
Normal file
File diff suppressed because it is too large
Load Diff
630
source/Irrlicht/CAnimatedMeshHalfLife.h
Normal file
630
source/Irrlicht/CAnimatedMeshHalfLife.h
Normal file
@ -0,0 +1,630 @@
|
||||
// Copyright (C) 2002-2012 Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_HALFLIFE_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_HALFLIFE_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMesh.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
#include "IMeshLoader.h"
|
||||
#include "SMesh.h"
|
||||
#include "IReadFile.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
// STUDIO MODELS, Copyright (c) 1998, Valve LLC. All rights reserved.
|
||||
#define MAXSTUDIOTRIANGLES 20000 // TODO: tune this
|
||||
#define MAXSTUDIOVERTS 2048 // TODO: tune this
|
||||
#define MAXSTUDIOSEQUENCES 256 // total animation sequences
|
||||
#define MAXSTUDIOSKINS 100 // total textures
|
||||
#define MAXSTUDIOSRCBONES 512 // bones allowed at source movement
|
||||
#define MAXSTUDIOBONES 128 // total bones actually used
|
||||
#define MAXSTUDIOMODELS 32 // sub-models per model
|
||||
#define MAXSTUDIOBODYPARTS 32
|
||||
#define MAXSTUDIOGROUPS 4
|
||||
#define MAXSTUDIOANIMATIONS 512 // per sequence
|
||||
#define MAXSTUDIOMESHES 256
|
||||
#define MAXSTUDIOEVENTS 1024
|
||||
#define MAXSTUDIOPIVOTS 256
|
||||
#define MAXSTUDIOCONTROLLERS 8
|
||||
|
||||
typedef f32 vec3_hl[3]; // x,y,z
|
||||
typedef f32 vec4_hl[4]; // x,y,z,w
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
||||
struct SHalflifeHeader
|
||||
{
|
||||
c8 id[4];
|
||||
s32 version;
|
||||
|
||||
c8 name[64];
|
||||
s32 length;
|
||||
|
||||
vec3_hl eyeposition; // ideal eye position
|
||||
vec3_hl min; // ideal movement hull size
|
||||
vec3_hl max;
|
||||
|
||||
vec3_hl bbmin; // clipping bounding box
|
||||
vec3_hl bbmax;
|
||||
|
||||
s32 flags;
|
||||
|
||||
u32 numbones; // bones
|
||||
u32 boneindex;
|
||||
|
||||
u32 numbonecontrollers; // bone controllers
|
||||
u32 bonecontrollerindex;
|
||||
|
||||
u32 numhitboxes; // complex bounding boxes
|
||||
u32 hitboxindex;
|
||||
|
||||
u32 numseq; // animation sequences
|
||||
u32 seqindex;
|
||||
|
||||
u32 numseqgroups; // demand loaded sequences
|
||||
u32 seqgroupindex;
|
||||
|
||||
u32 numtextures; // raw textures
|
||||
u32 textureindex;
|
||||
u32 texturedataindex;
|
||||
|
||||
u32 numskinref; // replaceable textures
|
||||
u32 numskinfamilies;
|
||||
u32 skinindex;
|
||||
|
||||
u32 numbodyparts;
|
||||
u32 bodypartindex;
|
||||
|
||||
u32 numattachments; // queryable attachable points
|
||||
u32 attachmentindex;
|
||||
|
||||
s32 soundtable;
|
||||
s32 soundindex;
|
||||
s32 soundgroups;
|
||||
s32 soundgroupindex;
|
||||
|
||||
s32 numtransitions; // animation node to animation node transition graph
|
||||
s32 transitionindex;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// header for demand loaded sequence group data
|
||||
struct studioseqhdr_t
|
||||
{
|
||||
s32 id;
|
||||
s32 version;
|
||||
|
||||
c8 name[64];
|
||||
s32 length;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// bones
|
||||
struct SHalflifeBone
|
||||
{
|
||||
c8 name[32]; // bone name for symbolic links
|
||||
s32 parent; // parent bone
|
||||
s32 flags; // ??
|
||||
s32 bonecontroller[6]; // bone controller index, -1 == none
|
||||
f32 value[6]; // default DoF values
|
||||
f32 scale[6]; // scale for delta DoF values
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// bone controllers
|
||||
struct SHalflifeBoneController
|
||||
{
|
||||
s32 bone; // -1 == 0
|
||||
s32 type; // X, Y, Z, XR, YR, ZR, M
|
||||
f32 start;
|
||||
f32 end;
|
||||
s32 rest; // byte index value at rest
|
||||
s32 index; // 0-3 user set controller, 4 mouth
|
||||
} PACK_STRUCT;
|
||||
|
||||
// intersection boxes
|
||||
struct SHalflifeBBox
|
||||
{
|
||||
s32 bone;
|
||||
s32 group; // intersection group
|
||||
vec3_hl bbmin; // bounding box
|
||||
vec3_hl bbmax;
|
||||
} PACK_STRUCT;
|
||||
|
||||
#ifndef ZONE_H
|
||||
// NOTE: this was a void*, but that crashes on 64bit.
|
||||
// I have found no mdl format desc, so not sure what it's meant to be, but s32 at least works.
|
||||
typedef s32 cache_user_t;
|
||||
#endif
|
||||
|
||||
// demand loaded sequence groups
|
||||
struct SHalflifeSequenceGroup
|
||||
{
|
||||
c8 label[32]; // textual name
|
||||
c8 name[64]; // file name
|
||||
cache_user_t cache; // cache index pointer
|
||||
s32 data; // hack for group 0
|
||||
} PACK_STRUCT;
|
||||
|
||||
// sequence descriptions
|
||||
struct SHalflifeSequence
|
||||
{
|
||||
c8 label[32]; // sequence label
|
||||
|
||||
f32 fps; // frames per second
|
||||
s32 flags; // looping/non-looping flags
|
||||
|
||||
s32 activity;
|
||||
s32 actweight;
|
||||
|
||||
s32 numevents;
|
||||
s32 eventindex;
|
||||
|
||||
s32 numframes; // number of frames per sequence
|
||||
|
||||
u32 numpivots; // number of foot pivots
|
||||
u32 pivotindex;
|
||||
|
||||
s32 motiontype;
|
||||
s32 motionbone;
|
||||
vec3_hl linearmovement;
|
||||
s32 automoveposindex;
|
||||
s32 automoveangleindex;
|
||||
|
||||
vec3_hl bbmin; // per sequence bounding box
|
||||
vec3_hl bbmax;
|
||||
|
||||
s32 numblends;
|
||||
s32 animindex; // SHalflifeAnimOffset pointer relative to start of sequence group data
|
||||
// [blend][bone][X, Y, Z, XR, YR, ZR]
|
||||
|
||||
s32 blendtype[2]; // X, Y, Z, XR, YR, ZR
|
||||
f32 blendstart[2]; // starting value
|
||||
f32 blendend[2]; // ending value
|
||||
s32 blendparent;
|
||||
|
||||
s32 seqgroup; // sequence group for demand loading
|
||||
|
||||
s32 entrynode; // transition node at entry
|
||||
s32 exitnode; // transition node at exit
|
||||
s32 nodeflags; // transition rules
|
||||
|
||||
s32 nextseq; // auto advancing sequences
|
||||
} PACK_STRUCT;
|
||||
|
||||
// events
|
||||
struct mstudioevent_t
|
||||
{
|
||||
s32 frame;
|
||||
s32 event;
|
||||
s32 type;
|
||||
c8 options[64];
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// pivots
|
||||
struct mstudiopivot_t
|
||||
{
|
||||
vec3_hl org; // pivot point
|
||||
s32 start;
|
||||
s32 end;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// attachment
|
||||
struct SHalflifeAttachment
|
||||
{
|
||||
c8 name[32];
|
||||
s32 type;
|
||||
s32 bone;
|
||||
vec3_hl org; // attachment point
|
||||
vec3_hl vectors[3];
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct SHalflifeAnimOffset
|
||||
{
|
||||
u16 offset[6];
|
||||
} PACK_STRUCT;
|
||||
|
||||
// animation frames
|
||||
union SHalflifeAnimationFrame
|
||||
{
|
||||
struct {
|
||||
u8 valid;
|
||||
u8 total;
|
||||
} PACK_STRUCT num;
|
||||
s16 value;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// body part index
|
||||
struct SHalflifeBody
|
||||
{
|
||||
c8 name[64];
|
||||
u32 nummodels;
|
||||
u32 base;
|
||||
u32 modelindex; // index into models array
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// skin info
|
||||
struct SHalflifeTexture
|
||||
{
|
||||
c8 name[64];
|
||||
s32 flags;
|
||||
s32 width;
|
||||
s32 height;
|
||||
s32 index;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// skin families
|
||||
// short index[skinfamilies][skinref]
|
||||
|
||||
// studio models
|
||||
struct SHalflifeModel
|
||||
{
|
||||
c8 name[64];
|
||||
s32 type;
|
||||
|
||||
f32 boundingradius;
|
||||
|
||||
u32 nummesh;
|
||||
u32 meshindex;
|
||||
|
||||
u32 numverts; // number of unique vertices
|
||||
u32 vertinfoindex; // vertex bone info
|
||||
u32 vertindex; // vertex vec3_hl
|
||||
u32 numnorms; // number of unique surface normals
|
||||
u32 norminfoindex; // normal bone info
|
||||
u32 normindex; // normal vec3_hl
|
||||
|
||||
u32 numgroups; // deformation groups
|
||||
u32 groupindex;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// meshes
|
||||
struct SHalflifeMesh
|
||||
{
|
||||
u32 numtris;
|
||||
u32 triindex;
|
||||
u32 skinref;
|
||||
u32 numnorms; // per mesh normals
|
||||
u32 normindex; // normal vec3_hl
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
// lighting options
|
||||
#define STUDIO_NF_FLATSHADE 0x0001
|
||||
#define STUDIO_NF_CHROME 0x0002
|
||||
#define STUDIO_NF_FULLBRIGHT 0x0004
|
||||
|
||||
// motion flags
|
||||
#define STUDIO_X 0x0001
|
||||
#define STUDIO_Y 0x0002
|
||||
#define STUDIO_Z 0x0004
|
||||
#define STUDIO_XR 0x0008
|
||||
#define STUDIO_YR 0x0010
|
||||
#define STUDIO_ZR 0x0020
|
||||
#define STUDIO_LX 0x0040
|
||||
#define STUDIO_LY 0x0080
|
||||
#define STUDIO_LZ 0x0100
|
||||
#define STUDIO_AX 0x0200
|
||||
#define STUDIO_AY 0x0400
|
||||
#define STUDIO_AZ 0x0800
|
||||
#define STUDIO_AXR 0x1000
|
||||
#define STUDIO_AYR 0x2000
|
||||
#define STUDIO_AZR 0x4000
|
||||
#define STUDIO_TYPES 0x7FFF
|
||||
#define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance
|
||||
|
||||
// sequence flags
|
||||
#define STUDIO_LOOPING 0x0001
|
||||
|
||||
// bone flags
|
||||
#define STUDIO_HAS_NORMALS 0x0001
|
||||
#define STUDIO_HAS_VERTICES 0x0002
|
||||
#define STUDIO_HAS_BBOX 0x0004
|
||||
#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them
|
||||
|
||||
#define RAD_TO_STUDIO (32768.0/M_PI)
|
||||
#define STUDIO_TO_RAD (M_PI/32768.0)
|
||||
|
||||
/*!
|
||||
Textureatlas
|
||||
Combine Source Images with arbitrary size and bithdepth to an Image with 2^n size
|
||||
borders from the source images are copied around for allowing filtering ( bilinear, mipmap )
|
||||
*/
|
||||
struct STextureAtlas
|
||||
{
|
||||
STextureAtlas ()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
virtual ~STextureAtlas ()
|
||||
{
|
||||
release ();
|
||||
}
|
||||
|
||||
void release ();
|
||||
void addSource ( const c8 * name, video::IImage * image );
|
||||
void create ( u32 pixelborder, video::E_TEXTURE_CLAMP texmode );
|
||||
void getScale ( core::vector2df &scale );
|
||||
void getTranslation ( const c8 * name, core::vector2di &pos );
|
||||
|
||||
struct TextureAtlasEntry
|
||||
{
|
||||
io::path name;
|
||||
u32 width;
|
||||
u32 height;
|
||||
|
||||
core::vector2di pos;
|
||||
|
||||
video::IImage * image;
|
||||
|
||||
bool operator < ( const TextureAtlasEntry & other )
|
||||
{
|
||||
return height > other.height;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
core::array < TextureAtlasEntry > atlas;
|
||||
video::IImage * Master;
|
||||
};
|
||||
|
||||
|
||||
//! Possible types of Animation Type
|
||||
enum E_ANIMATION_TYPE
|
||||
{
|
||||
//! No Animation
|
||||
EAMT_STILL,
|
||||
//! From Start to End, then Stop ( Limited Line )
|
||||
EAMT_WAYPOINT,
|
||||
//! Linear Cycling Animation ( Sawtooth )
|
||||
EAMT_LOOPING,
|
||||
//! Linear bobbing ( Triangle )
|
||||
EAMT_PINGPONG
|
||||
};
|
||||
|
||||
//! Names for Animation Type
|
||||
const c8* const MeshAnimationTypeNames[] =
|
||||
{
|
||||
"still",
|
||||
"waypoint",
|
||||
"looping",
|
||||
"pingpong",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
//! Data for holding named Animation Info
|
||||
struct KeyFrameInterpolation
|
||||
{
|
||||
core::stringc Name; // Name of the current Animation/Bone
|
||||
E_ANIMATION_TYPE AnimationType; // Type of Animation ( looping, usw..)
|
||||
|
||||
f32 CurrentFrame; // Current Frame
|
||||
s32 NextFrame; // Frame which will be used next. For blending
|
||||
|
||||
s32 StartFrame; // Absolute Frame where the current animation start
|
||||
s32 Frames; // Relative Frames how much Frames this animation have
|
||||
s32 LoopingFrames; // How much of Frames sould be looped
|
||||
s32 EndFrame; // Absolute Frame where the current animation ends End = start + frames - 1
|
||||
|
||||
f32 FramesPerSecond; // Speed in Frames/Seconds the animation is played
|
||||
f32 RelativeSpeed; // Factor Original fps is modified
|
||||
|
||||
u32 BeginTime; // Animation started at this thime
|
||||
u32 EndTime; // Animation end at this time
|
||||
u32 LastTime; // Last Keyframe was done at this time
|
||||
|
||||
KeyFrameInterpolation ( const c8 * name = "", s32 start = 0, s32 frames = 0, s32 loopingframes = 0,
|
||||
f32 fps = 0.f, f32 relativefps = 1.f )
|
||||
: Name ( name ), AnimationType ( loopingframes ? EAMT_LOOPING : EAMT_WAYPOINT),
|
||||
CurrentFrame ( (f32) start ), NextFrame ( start ), StartFrame ( start ),
|
||||
Frames ( frames ), LoopingFrames ( loopingframes ), EndFrame ( start + frames - 1 ),
|
||||
FramesPerSecond ( fps ), RelativeSpeed ( relativefps ),
|
||||
BeginTime ( 0 ), EndTime ( 0 ), LastTime ( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
// linear search
|
||||
bool operator == ( const KeyFrameInterpolation & other ) const
|
||||
{
|
||||
return Name.equals_ignore_case ( other.Name );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! a List holding named Animations
|
||||
typedef core::array < KeyFrameInterpolation > IAnimationList;
|
||||
|
||||
//! a List holding named Skins
|
||||
typedef core::array < core::stringc > ISkinList;
|
||||
|
||||
|
||||
// Current Model per Body
|
||||
struct SubModel
|
||||
{
|
||||
core::stringc name;
|
||||
u32 startBuffer;
|
||||
u32 endBuffer;
|
||||
u32 state;
|
||||
};
|
||||
|
||||
struct BodyPart
|
||||
{
|
||||
core::stringc name;
|
||||
u32 defaultModel;
|
||||
core::array < SubModel > model;
|
||||
};
|
||||
//! a List holding named Models and SubModels
|
||||
typedef core::array < BodyPart > IBodyList;
|
||||
|
||||
|
||||
class CAnimatedMeshHalfLife : public IAnimatedMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshHalfLife();
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshHalfLife();
|
||||
|
||||
//! loads a Halflife mdl file
|
||||
bool loadModelFile( io::IReadFile* file, ISceneManager * smgr );
|
||||
|
||||
//IAnimatedMesh
|
||||
virtual u32 getFrameCount() const _IRR_OVERRIDE_;
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) _IRR_OVERRIDE_;
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const _IRR_OVERRIDE_;
|
||||
void renderModel ( u32 param, video::IVideoDriver * driver, const core::matrix4 &absoluteTransformation);
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const _IRR_OVERRIDE_;
|
||||
//! returns pointer to a mesh buffer
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const _IRR_OVERRIDE_;
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const _IRR_OVERRIDE_;
|
||||
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) _IRR_OVERRIDE_;
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) _IRR_OVERRIDE_;
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) _IRR_OVERRIDE_;
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox(const core::aabbox3df& box) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
virtual f32 getAnimationSpeed() const _IRR_OVERRIDE_
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
virtual void setAnimationSpeed(f32 fps) _IRR_OVERRIDE_
|
||||
{
|
||||
FramesPerSecond=fps;
|
||||
}
|
||||
|
||||
//! Get the Animation List
|
||||
IAnimationList* getAnimList () { return &AnimList; }
|
||||
|
||||
//! Return the named Body List of this Animated Mesh
|
||||
IBodyList *getBodyList() { return &BodyList; }
|
||||
|
||||
private:
|
||||
|
||||
// KeyFrame Animation List
|
||||
IAnimationList AnimList;
|
||||
// Sum of all sequences
|
||||
u32 FrameCount;
|
||||
|
||||
// Named meshes of the Body
|
||||
IBodyList BodyList;
|
||||
|
||||
//! return a Mesh per frame
|
||||
SMesh* MeshIPol;
|
||||
|
||||
ISceneManager *SceneManager;
|
||||
|
||||
SHalflifeHeader *Header;
|
||||
SHalflifeHeader *TextureHeader;
|
||||
bool OwnTexModel; // do we have a modelT.mdl ?
|
||||
SHalflifeHeader *AnimationHeader[32]; // sequences named model01.mdl, model02.mdl
|
||||
|
||||
void initData ();
|
||||
SHalflifeHeader * loadModel( io::IReadFile* file, const io::path &filename );
|
||||
bool postLoadModel( const io::path &filename );
|
||||
|
||||
u32 SequenceIndex; // sequence index
|
||||
f32 CurrentFrame; // Current Frame
|
||||
f32 FramesPerSecond;
|
||||
|
||||
#define MOUTH_CONTROLLER 4
|
||||
u8 BoneController[4 + 1 ]; // bone controllers + mouth position
|
||||
u8 Blending[2]; // animation blending
|
||||
|
||||
vec4_hl BoneAdj;
|
||||
f32 SetController( s32 controllerIndex, f32 value );
|
||||
|
||||
u32 SkinGroupSelection; // skin group selection
|
||||
u32 SetSkin( u32 value );
|
||||
|
||||
void initModel();
|
||||
void dumpModelInfo(u32 level) const;
|
||||
|
||||
void ExtractBbox(s32 sequence, core::aabbox3df &box) const;
|
||||
|
||||
void setUpBones ();
|
||||
SHalflifeAnimOffset * getAnim( SHalflifeSequence *seq );
|
||||
void slerpBones( vec4_hl q1[], vec3_hl pos1[], vec4_hl q2[], vec3_hl pos2[], f32 s );
|
||||
void calcRotations ( vec3_hl *pos, vec4_hl *q, SHalflifeSequence *seq, SHalflifeAnimOffset *anim, f32 f );
|
||||
|
||||
void calcBoneAdj();
|
||||
void calcBoneQuaternion(const s32 frame, const SHalflifeBone *bone, SHalflifeAnimOffset *anim, const u32 j, f32& angle1, f32& angle2) const;
|
||||
void calcBonePosition(const s32 frame, f32 s, const SHalflifeBone *bone, SHalflifeAnimOffset *anim, f32 *pos ) const;
|
||||
|
||||
void buildVertices ();
|
||||
|
||||
io::path TextureBaseName;
|
||||
|
||||
#define HL_TEXTURE_ATLAS
|
||||
|
||||
#ifdef HL_TEXTURE_ATLAS
|
||||
STextureAtlas TextureAtlas;
|
||||
// video::ITexture *TextureMaster;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! Meshloader capable of loading HalfLife Model files
|
||||
class CHalflifeMDLMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CHalflifeMDLMeshFileLoader( 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") */
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_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.
|
||||
*/
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
scene::ISceneManager* SceneManager;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
465
source/Irrlicht/CAnimatedMeshMD2.cpp
Normal file
465
source/Irrlicht/CAnimatedMeshMD2.cpp
Normal file
@ -0,0 +1,465 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
|
||||
|
||||
#include "CAnimatedMeshMD2.h"
|
||||
#include "SColor.h"
|
||||
#include "irrMath.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
const s32 MD2_FRAME_SHIFT = 2;
|
||||
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT);
|
||||
|
||||
const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162;
|
||||
|
||||
static const f32 Q2_VERTEX_NORMAL_TABLE[Q2_VERTEX_NORMAL_TABLE_SIZE][3] = {
|
||||
{-0.525731f, 0.000000f, 0.850651f},
|
||||
{-0.442863f, 0.238856f, 0.864188f},
|
||||
{-0.295242f, 0.000000f, 0.955423f},
|
||||
{-0.309017f, 0.500000f, 0.809017f},
|
||||
{-0.162460f, 0.262866f, 0.951056f},
|
||||
{0.000000f, 0.000000f, 1.000000f},
|
||||
{0.000000f, 0.850651f, 0.525731f},
|
||||
{-0.147621f, 0.716567f, 0.681718f},
|
||||
{0.147621f, 0.716567f, 0.681718f},
|
||||
{0.000000f, 0.525731f, 0.850651f},
|
||||
{0.309017f, 0.500000f, 0.809017f},
|
||||
{0.525731f, 0.000000f, 0.850651f},
|
||||
{0.295242f, 0.000000f, 0.955423f},
|
||||
{0.442863f, 0.238856f, 0.864188f},
|
||||
{0.162460f, 0.262866f, 0.951056f},
|
||||
{-0.681718f, 0.147621f, 0.716567f},
|
||||
{-0.809017f, 0.309017f, 0.500000f},
|
||||
{-0.587785f, 0.425325f, 0.688191f},
|
||||
{-0.850651f, 0.525731f, 0.000000f},
|
||||
{-0.864188f, 0.442863f, 0.238856f},
|
||||
{-0.716567f, 0.681718f, 0.147621f},
|
||||
{-0.688191f, 0.587785f, 0.425325f},
|
||||
{-0.500000f, 0.809017f, 0.309017f},
|
||||
{-0.238856f, 0.864188f, 0.442863f},
|
||||
{-0.425325f, 0.688191f, 0.587785f},
|
||||
{-0.716567f, 0.681718f, -0.147621f},
|
||||
{-0.500000f, 0.809017f, -0.309017f},
|
||||
{-0.525731f, 0.850651f, 0.000000f},
|
||||
{0.000000f, 0.850651f, -0.525731f},
|
||||
{-0.238856f, 0.864188f, -0.442863f},
|
||||
{0.000000f, 0.955423f, -0.295242f},
|
||||
{-0.262866f, 0.951056f, -0.162460f},
|
||||
{0.000000f, 1.000000f, 0.000000f},
|
||||
{0.000000f, 0.955423f, 0.295242f},
|
||||
{-0.262866f, 0.951056f, 0.162460f},
|
||||
{0.238856f, 0.864188f, 0.442863f},
|
||||
{0.262866f, 0.951056f, 0.162460f},
|
||||
{0.500000f, 0.809017f, 0.309017f},
|
||||
{0.238856f, 0.864188f, -0.442863f},
|
||||
{0.262866f, 0.951056f, -0.162460f},
|
||||
{0.500000f, 0.809017f, -0.309017f},
|
||||
{0.850651f, 0.525731f, 0.000000f},
|
||||
{0.716567f, 0.681718f, 0.147621f},
|
||||
{0.716567f, 0.681718f, -0.147621f},
|
||||
{0.525731f, 0.850651f, 0.000000f},
|
||||
{0.425325f, 0.688191f, 0.587785f},
|
||||
{0.864188f, 0.442863f, 0.238856f},
|
||||
{0.688191f, 0.587785f, 0.425325f},
|
||||
{0.809017f, 0.309017f, 0.500000f},
|
||||
{0.681718f, 0.147621f, 0.716567f},
|
||||
{0.587785f, 0.425325f, 0.688191f},
|
||||
{0.955423f, 0.295242f, 0.000000f},
|
||||
{1.000000f, 0.000000f, 0.000000f},
|
||||
{0.951056f, 0.162460f, 0.262866f},
|
||||
{0.850651f, -0.525731f, 0.000000f},
|
||||
{0.955423f, -0.295242f, 0.000000f},
|
||||
{0.864188f, -0.442863f, 0.238856f},
|
||||
{0.951056f, -0.162460f, 0.262866f},
|
||||
{0.809017f, -0.309017f, 0.500000f},
|
||||
{0.681718f, -0.147621f, 0.716567f},
|
||||
{0.850651f, 0.000000f, 0.525731f},
|
||||
{0.864188f, 0.442863f, -0.238856f},
|
||||
{0.809017f, 0.309017f, -0.500000f},
|
||||
{0.951056f, 0.162460f, -0.262866f},
|
||||
{0.525731f, 0.000000f, -0.850651f},
|
||||
{0.681718f, 0.147621f, -0.716567f},
|
||||
{0.681718f, -0.147621f, -0.716567f},
|
||||
{0.850651f, 0.000000f, -0.525731f},
|
||||
{0.809017f, -0.309017f, -0.500000f},
|
||||
{0.864188f, -0.442863f, -0.238856f},
|
||||
{0.951056f, -0.162460f, -0.262866f},
|
||||
{0.147621f, 0.716567f, -0.681718f},
|
||||
{0.309017f, 0.500000f, -0.809017f},
|
||||
{0.425325f, 0.688191f, -0.587785f},
|
||||
{0.442863f, 0.238856f, -0.864188f},
|
||||
{0.587785f, 0.425325f, -0.688191f},
|
||||
{0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.147621f, 0.716567f, -0.681718f},
|
||||
{-0.309017f, 0.500000f, -0.809017f},
|
||||
{0.000000f, 0.525731f, -0.850651f},
|
||||
{-0.525731f, 0.000000f, -0.850651f},
|
||||
{-0.442863f, 0.238856f, -0.864188f},
|
||||
{-0.295242f, 0.000000f, -0.955423f},
|
||||
{-0.162460f, 0.262866f, -0.951056f},
|
||||
{0.000000f, 0.000000f, -1.000000f},
|
||||
{0.295242f, 0.000000f, -0.955423f},
|
||||
{0.162460f, 0.262866f, -0.951056f},
|
||||
{-0.442863f, -0.238856f, -0.864188f},
|
||||
{-0.309017f, -0.500000f, -0.809017f},
|
||||
{-0.162460f, -0.262866f, -0.951056f},
|
||||
{0.000000f, -0.850651f, -0.525731f},
|
||||
{-0.147621f, -0.716567f, -0.681718f},
|
||||
{0.147621f, -0.716567f, -0.681718f},
|
||||
{0.000000f, -0.525731f, -0.850651f},
|
||||
{0.309017f, -0.500000f, -0.809017f},
|
||||
{0.442863f, -0.238856f, -0.864188f},
|
||||
{0.162460f, -0.262866f, -0.951056f},
|
||||
{0.238856f, -0.864188f, -0.442863f},
|
||||
{0.500000f, -0.809017f, -0.309017f},
|
||||
{0.425325f, -0.688191f, -0.587785f},
|
||||
{0.716567f, -0.681718f, -0.147621f},
|
||||
{0.688191f, -0.587785f, -0.425325f},
|
||||
{0.587785f, -0.425325f, -0.688191f},
|
||||
{0.000000f, -0.955423f, -0.295242f},
|
||||
{0.000000f, -1.000000f, 0.000000f},
|
||||
{0.262866f, -0.951056f, -0.162460f},
|
||||
{0.000000f, -0.850651f, 0.525731f},
|
||||
{0.000000f, -0.955423f, 0.295242f},
|
||||
{0.238856f, -0.864188f, 0.442863f},
|
||||
{0.262866f, -0.951056f, 0.162460f},
|
||||
{0.500000f, -0.809017f, 0.309017f},
|
||||
{0.716567f, -0.681718f, 0.147621f},
|
||||
{0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.238856f, -0.864188f, -0.442863f},
|
||||
{-0.500000f, -0.809017f, -0.309017f},
|
||||
{-0.262866f, -0.951056f, -0.162460f},
|
||||
{-0.850651f, -0.525731f, 0.000000f},
|
||||
{-0.716567f, -0.681718f, -0.147621f},
|
||||
{-0.716567f, -0.681718f, 0.147621f},
|
||||
{-0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.500000f, -0.809017f, 0.309017f},
|
||||
{-0.238856f, -0.864188f, 0.442863f},
|
||||
{-0.262866f, -0.951056f, 0.162460f},
|
||||
{-0.864188f, -0.442863f, 0.238856f},
|
||||
{-0.809017f, -0.309017f, 0.500000f},
|
||||
{-0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.681718f, -0.147621f, 0.716567f},
|
||||
{-0.442863f, -0.238856f, 0.864188f},
|
||||
{-0.587785f, -0.425325f, 0.688191f},
|
||||
{-0.309017f, -0.500000f, 0.809017f},
|
||||
{-0.147621f, -0.716567f, 0.681718f},
|
||||
{-0.425325f, -0.688191f, 0.587785f},
|
||||
{-0.162460f, -0.262866f, 0.951056f},
|
||||
{0.442863f, -0.238856f, 0.864188f},
|
||||
{0.162460f, -0.262866f, 0.951056f},
|
||||
{0.309017f, -0.500000f, 0.809017f},
|
||||
{0.147621f, -0.716567f, 0.681718f},
|
||||
{0.000000f, -0.525731f, 0.850651f},
|
||||
{0.425325f, -0.688191f, 0.587785f},
|
||||
{0.587785f, -0.425325f, 0.688191f},
|
||||
{0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.955423f, 0.295242f, 0.000000f},
|
||||
{-0.951056f, 0.162460f, 0.262866f},
|
||||
{-1.000000f, 0.000000f, 0.000000f},
|
||||
{-0.850651f, 0.000000f, 0.525731f},
|
||||
{-0.955423f, -0.295242f, 0.000000f},
|
||||
{-0.951056f, -0.162460f, 0.262866f},
|
||||
{-0.864188f, 0.442863f, -0.238856f},
|
||||
{-0.951056f, 0.162460f, -0.262866f},
|
||||
{-0.809017f, 0.309017f, -0.500000f},
|
||||
{-0.864188f, -0.442863f, -0.238856f},
|
||||
{-0.951056f, -0.162460f, -0.262866f},
|
||||
{-0.809017f, -0.309017f, -0.500000f},
|
||||
{-0.681718f, 0.147621f, -0.716567f},
|
||||
{-0.681718f, -0.147621f, -0.716567f},
|
||||
{-0.850651f, 0.000000f, -0.525731f},
|
||||
{-0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.587785f, 0.425325f, -0.688191f},
|
||||
{-0.425325f, 0.688191f, -0.587785f},
|
||||
{-0.425325f, -0.688191f, -0.587785f},
|
||||
{-0.587785f, -0.425325f, -0.688191f},
|
||||
{-0.688191f, -0.587785f, -0.425325f},
|
||||
};
|
||||
|
||||
struct SMD2AnimationType
|
||||
{
|
||||
s32 begin;
|
||||
s32 end;
|
||||
s32 fps;
|
||||
};
|
||||
|
||||
static const SMD2AnimationType MD2AnimationTypeList[21] =
|
||||
{
|
||||
{ 0, 39, 9}, // STAND
|
||||
{ 40, 45, 10}, // RUN
|
||||
{ 46, 53, 10}, // ATTACK
|
||||
{ 54, 57, 7}, // PAIN_A
|
||||
{ 58, 61, 7}, // PAIN_B
|
||||
{ 62, 65, 7}, // PAIN_C
|
||||
{ 66, 71, 7}, // JUMP
|
||||
{ 72, 83, 7}, // FLIP
|
||||
{ 84, 94, 7}, // SALUTE
|
||||
{ 95, 111, 10}, // FALLBACK
|
||||
{112, 122, 7}, // WAVE
|
||||
{123, 134, 6}, // POINT
|
||||
{135, 153, 10}, // CROUCH_STAND
|
||||
{154, 159, 7}, // CROUCH_WALK
|
||||
{160, 168, 10}, // CROUCH_ATTACK
|
||||
{169, 172, 7}, // CROUCH_PAIN
|
||||
{173, 177, 5}, // CROUCH_DEATH
|
||||
{178, 183, 7}, // DEATH_FALLBACK
|
||||
{184, 189, 7}, // DEATH_FALLFORWARD
|
||||
{190, 197, 7}, // DEATH_FALLBACKSLOW
|
||||
{198, 198, 5}, // BOOM
|
||||
};
|
||||
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshMD2::CAnimatedMeshMD2()
|
||||
: InterpolationBuffer(0), InterpolationFirstFrame(-1), InterpolationSecondFrame(-1), InterpolationFrameDiv(0.f)
|
||||
, FrameList(0), FrameCount(0), FramesPerSecond((f32)(MD2AnimationTypeList[0].fps << MD2_FRAME_SHIFT))
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IAnimatedMesh::setDebugName("CAnimatedMeshMD2 IAnimatedMesh");
|
||||
IMesh::setDebugName("CAnimatedMeshMD2 IMesh");
|
||||
#endif
|
||||
InterpolationBuffer = new SMeshBuffer;
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CAnimatedMeshMD2::~CAnimatedMeshMD2()
|
||||
{
|
||||
delete [] FrameList;
|
||||
if (InterpolationBuffer)
|
||||
InterpolationBuffer->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
|
||||
u32 CAnimatedMeshMD2::getFrameCount() const
|
||||
{
|
||||
return FrameCount<<MD2_FRAME_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
|
||||
IMesh* CAnimatedMeshMD2::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
if ((u32)frame > getFrameCount())
|
||||
frame = (frame % getFrameCount());
|
||||
|
||||
if (startFrameLoop == -1 && endFrameLoop == -1)
|
||||
{
|
||||
startFrameLoop = 0;
|
||||
endFrameLoop = getFrameCount();
|
||||
}
|
||||
|
||||
updateInterpolationBuffer(frame, startFrameLoop, endFrameLoop);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of mesh buffers. MD2 meshes only have one buffer
|
||||
u32 CAnimatedMeshMD2::getMeshBufferCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(u32 nr) const
|
||||
{
|
||||
if (nr == 0)
|
||||
return InterpolationBuffer;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(const video::SMaterial &material) const
|
||||
{
|
||||
if (InterpolationBuffer->Material == material)
|
||||
return InterpolationBuffer;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// updates the interpolation buffer
|
||||
void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
u32 firstFrame, secondFrame;
|
||||
f32 div;
|
||||
|
||||
// TA: resolve missing ipol in loop between end-start
|
||||
|
||||
if (endFrameLoop - startFrameLoop == 0)
|
||||
{
|
||||
firstFrame = frame>>MD2_FRAME_SHIFT;
|
||||
secondFrame = frame>>MD2_FRAME_SHIFT;
|
||||
div = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// key frames
|
||||
u32 s = startFrameLoop >> MD2_FRAME_SHIFT;
|
||||
u32 e = endFrameLoop >> MD2_FRAME_SHIFT;
|
||||
|
||||
firstFrame = frame >> MD2_FRAME_SHIFT;
|
||||
secondFrame = core::if_c_a_else_b(firstFrame + 1 > e, s, firstFrame + 1);
|
||||
|
||||
firstFrame = core::s32_min(FrameCount - 1, firstFrame);
|
||||
secondFrame = core::s32_min(FrameCount - 1, secondFrame);
|
||||
|
||||
//div = (frame % (1<<MD2_FRAME_SHIFT)) / (f32)(1<<MD2_FRAME_SHIFT);
|
||||
frame &= (1<<MD2_FRAME_SHIFT) - 1;
|
||||
div = frame * MD2_FRAME_SHIFT_RECIPROCAL;
|
||||
}
|
||||
|
||||
if ( firstFrame != InterpolationFirstFrame || secondFrame != InterpolationSecondFrame || div != InterpolationFrameDiv )
|
||||
{
|
||||
InterpolationFirstFrame = firstFrame;
|
||||
InterpolationSecondFrame = secondFrame;
|
||||
InterpolationFrameDiv = div;
|
||||
|
||||
video::S3DVertex* target = static_cast<video::S3DVertex*>(InterpolationBuffer->getVertices());
|
||||
SMD2Vert* first = FrameList[firstFrame].pointer();
|
||||
SMD2Vert* second = FrameList[secondFrame].pointer();
|
||||
|
||||
// interpolate both frames
|
||||
const u32 count = FrameList[firstFrame].size();
|
||||
for (u32 i=0; i<count; ++i)
|
||||
{
|
||||
const core::vector3df one = core::vector3df(f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X,
|
||||
f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y,
|
||||
f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z);
|
||||
const core::vector3df two = core::vector3df(f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X,
|
||||
f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y,
|
||||
f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z);
|
||||
target->Pos = two.getInterpolated(one, div);
|
||||
const core::vector3df n1(
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][1]);
|
||||
const core::vector3df n2(
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][1]);
|
||||
target->Normal = n2.getInterpolated(n1, div);
|
||||
++target;
|
||||
++first;
|
||||
++second;
|
||||
}
|
||||
|
||||
//update bounding box
|
||||
InterpolationBuffer->setBoundingBox(BoxList[secondFrame].getInterpolated(BoxList[firstFrame], div));
|
||||
InterpolationBuffer->setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! sets a flag of all contained materials to a new value
|
||||
void CAnimatedMeshMD2::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
|
||||
{
|
||||
InterpolationBuffer->Material.setFlag(flag, newvalue);
|
||||
}
|
||||
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
void CAnimatedMeshMD2::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
|
||||
E_BUFFER_TYPE buffer)
|
||||
{
|
||||
InterpolationBuffer->setHardwareMappingHint(newMappingHint, buffer);
|
||||
}
|
||||
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
void CAnimatedMeshMD2::setDirty(E_BUFFER_TYPE buffer)
|
||||
{
|
||||
InterpolationBuffer->setDirty(buffer);
|
||||
}
|
||||
|
||||
|
||||
//! returns an axis aligned bounding box
|
||||
const core::aabbox3d<f32>& CAnimatedMeshMD2::getBoundingBox() const
|
||||
{
|
||||
return InterpolationBuffer->BoundingBox;
|
||||
}
|
||||
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
void CAnimatedMeshMD2::setBoundingBox(const core::aabbox3df& box)
|
||||
{
|
||||
InterpolationBuffer->BoundingBox = box;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
E_ANIMATED_MESH_TYPE CAnimatedMeshMD2::getMeshType() const
|
||||
{
|
||||
return EAMT_MD2;
|
||||
}
|
||||
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
|
||||
s32& outBegin, s32& outEnd, s32& outFPS) const
|
||||
{
|
||||
if (l < 0 || l >= EMAT_COUNT)
|
||||
return;
|
||||
|
||||
outBegin = MD2AnimationTypeList[l].begin << MD2_FRAME_SHIFT;
|
||||
outEnd = MD2AnimationTypeList[l].end << MD2_FRAME_SHIFT;
|
||||
|
||||
// correct to anim between last->first frame
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = MD2AnimationTypeList[l].fps << MD2_FRAME_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
bool CAnimatedMeshMD2::getFrameLoop(const c8* name,
|
||||
s32& outBegin, s32&outEnd, s32& outFPS) const
|
||||
{
|
||||
for (u32 i=0; i < AnimationData.size(); ++i)
|
||||
{
|
||||
if (AnimationData[i].name == name)
|
||||
{
|
||||
outBegin = AnimationData[i].begin << MD2_FRAME_SHIFT;
|
||||
outEnd = AnimationData[i].end << MD2_FRAME_SHIFT;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = AnimationData[i].fps << MD2_FRAME_SHIFT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! Returns amount of md2 animations in this file.
|
||||
s32 CAnimatedMeshMD2::getAnimationCount() const
|
||||
{
|
||||
return AnimationData.size();
|
||||
}
|
||||
|
||||
|
||||
//! Returns name of md2 animation.
|
||||
const c8* CAnimatedMeshMD2::getAnimationName(s32 nr) const
|
||||
{
|
||||
if ((u32)nr >= AnimationData.size())
|
||||
return 0;
|
||||
|
||||
return AnimationData[nr].name.c_str();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_MD2_LOADER_
|
158
source/Irrlicht/CAnimatedMeshMD2.h
Normal file
158
source/Irrlicht/CAnimatedMeshMD2.h
Normal file
@ -0,0 +1,158 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_MD2_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_MD2_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMeshMD2.h"
|
||||
#include "IMesh.h"
|
||||
#include "CMeshBuffer.h"
|
||||
#include "IReadFile.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CAnimatedMeshMD2 : public IAnimatedMeshMD2
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshMD2();
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshMD2();
|
||||
|
||||
//! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh.
|
||||
virtual u32 getFrameCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
virtual f32 getAnimationSpeed() const _IRR_OVERRIDE_
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
virtual void setAnimationSpeed(f32 fps) _IRR_OVERRIDE_
|
||||
{
|
||||
FramesPerSecond=fps;
|
||||
}
|
||||
|
||||
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
/** \param material: material to search for
|
||||
\return Returns the pointer to the mesh buffer or
|
||||
NULL if there is no such mesh buffer. */
|
||||
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns an axis aligned bounding box
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox( const core::aabbox3df& box) _IRR_OVERRIDE_;
|
||||
|
||||
//! sets a flag of all contained materials to a new value
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) _IRR_OVERRIDE_;
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) _IRR_OVERRIDE_;
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
virtual void getFrameLoop(EMD2_ANIMATION_TYPE,
|
||||
s32& outBegin, s32& outEnd, s32& outFps) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
virtual bool getFrameLoop(const c8* name,
|
||||
s32& outBegin, s32& outEnd, s32& outFps) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns amount of md2 animations in this file.
|
||||
virtual s32 getAnimationCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns name of md2 animation.
|
||||
//! \param nr: Zero based index of animation.
|
||||
virtual const c8* getAnimationName(s32 nr) const _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
//
|
||||
// exposed for loader
|
||||
//
|
||||
|
||||
//! the buffer that contains the most recent animation
|
||||
SMeshBuffer* InterpolationBuffer;
|
||||
|
||||
//! Frames used to calculate InterpolationBuffer
|
||||
u32 InterpolationFirstFrame, InterpolationSecondFrame;
|
||||
f32 InterpolationFrameDiv;
|
||||
|
||||
//! named animations
|
||||
struct SAnimationData
|
||||
{
|
||||
core::stringc name;
|
||||
s32 begin;
|
||||
s32 end;
|
||||
s32 fps;
|
||||
};
|
||||
|
||||
//! scale and translations for keyframes
|
||||
struct SKeyFrameTransform
|
||||
{
|
||||
core::vector3df scale;
|
||||
core::vector3df translate;
|
||||
};
|
||||
|
||||
//! md2 vertex data
|
||||
struct SMD2Vert
|
||||
{
|
||||
core::vector3d<u8> Pos;
|
||||
u8 NormalIdx;
|
||||
};
|
||||
|
||||
//! keyframe transformations
|
||||
core::array<SKeyFrameTransform> FrameTransforms;
|
||||
|
||||
//! keyframe vertex data
|
||||
core::array<SMD2Vert> *FrameList;
|
||||
|
||||
//! bounding boxes for each keyframe
|
||||
core::array<core::aabbox3d<f32> > BoxList;
|
||||
|
||||
//! named animations
|
||||
core::array< SAnimationData > AnimationData;
|
||||
|
||||
u32 FrameCount;
|
||||
|
||||
private:
|
||||
|
||||
//! updates the interpolation buffer
|
||||
void updateInterpolationBuffer(s32 frame, s32 startFrame, s32 endFrame);
|
||||
|
||||
f32 FramesPerSecond;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
468
source/Irrlicht/CAnimatedMeshMD3.cpp
Normal file
468
source/Irrlicht/CAnimatedMeshMD3.cpp
Normal file
@ -0,0 +1,468 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
|
||||
|
||||
#include "CAnimatedMeshMD3.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
||||
//! General properties of a single animation frame.
|
||||
struct SMD3Frame
|
||||
{
|
||||
f32 mins[3]; // bounding box per frame
|
||||
f32 maxs[3];
|
||||
f32 position[3]; // position of bounding box
|
||||
f32 radius; // radius of bounding sphere
|
||||
c8 creator[16]; // name of frame
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
//! An attachment point for another MD3 model.
|
||||
struct SMD3Tag
|
||||
{
|
||||
c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part.
|
||||
f32 position[3]; //relative position of tag
|
||||
f32 rotationMatrix[9]; //3x3 rotation direction of tag
|
||||
} PACK_STRUCT;
|
||||
|
||||
//!Shader
|
||||
struct SMD3Shader
|
||||
{
|
||||
c8 name[64]; // name of shader
|
||||
s32 shaderIndex;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
|
||||
//! Constructor
|
||||
CAnimatedMeshMD3::CAnimatedMeshMD3()
|
||||
:Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f)//, FramesPerSecond(25.f)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CAnimatedMeshMD3");
|
||||
#endif
|
||||
|
||||
Mesh = new SMD3Mesh();
|
||||
MeshIPol = new SMesh();
|
||||
setInterpolationShift(0, 0);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CAnimatedMeshMD3::~CAnimatedMeshMD3()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
if (MeshIPol)
|
||||
MeshIPol->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
|
||||
u32 CAnimatedMeshMD3::getFrameCount() const
|
||||
{
|
||||
return Mesh->MD3Header.numFrames << IPolShift;
|
||||
}
|
||||
|
||||
|
||||
//! Rendering Hint
|
||||
void CAnimatedMeshMD3::setInterpolationShift(u32 shift, u32 loopMode)
|
||||
{
|
||||
IPolShift = shift;
|
||||
LoopMode = loopMode;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
u32 CAnimatedMeshMD3::getMeshBufferCount() const
|
||||
{
|
||||
return MeshIPol->getMeshBufferCount();
|
||||
}
|
||||
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(u32 nr) const
|
||||
{
|
||||
return MeshIPol->getMeshBuffer(nr);
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(const video::SMaterial &material) const
|
||||
{
|
||||
return MeshIPol->getMeshBuffer(material);
|
||||
}
|
||||
|
||||
|
||||
void CAnimatedMeshMD3::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
|
||||
{
|
||||
MeshIPol->setMaterialFlag(flag, newvalue);
|
||||
}
|
||||
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
void CAnimatedMeshMD3::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
|
||||
E_BUFFER_TYPE buffer)
|
||||
{
|
||||
MeshIPol->setHardwareMappingHint(newMappingHint, buffer);
|
||||
}
|
||||
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer)
|
||||
{
|
||||
MeshIPol->setDirty(buffer);
|
||||
}
|
||||
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
void CAnimatedMeshMD3::setBoundingBox(const core::aabbox3df& box)
|
||||
{
|
||||
MeshIPol->setBoundingBox(box);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail.
|
||||
SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
if (0 == Mesh)
|
||||
return 0;
|
||||
|
||||
getMesh(frame, detailLevel, startFrameLoop, endFrameLoop);
|
||||
return &TagListIPol;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail.
|
||||
IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
if (0 == Mesh)
|
||||
return 0;
|
||||
|
||||
//! check if we have the mesh in our private cache
|
||||
SCacheInfo candidate(frame, startFrameLoop, endFrameLoop);
|
||||
if (candidate == Current)
|
||||
return MeshIPol;
|
||||
|
||||
startFrameLoop = core::s32_max(0, startFrameLoop >> IPolShift);
|
||||
endFrameLoop = core::if_c_a_else_b(endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift);
|
||||
|
||||
const u32 mask = 1 << IPolShift;
|
||||
|
||||
s32 frameA;
|
||||
s32 frameB;
|
||||
f32 iPol;
|
||||
|
||||
if (LoopMode)
|
||||
{
|
||||
// correct frame to "pixel center"
|
||||
frame -= mask >> 1;
|
||||
|
||||
// interpolation
|
||||
iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask));
|
||||
|
||||
// wrap anim
|
||||
frame >>= IPolShift;
|
||||
frameA = core::if_c_a_else_b(frame < startFrameLoop, endFrameLoop, frame);
|
||||
frameB = core::if_c_a_else_b(frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// correct frame to "pixel center"
|
||||
frame -= mask >> 1;
|
||||
|
||||
iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask));
|
||||
|
||||
// clamp anim
|
||||
frame >>= IPolShift;
|
||||
frameA = core::s32_clamp(frame, startFrameLoop, endFrameLoop);
|
||||
frameB = core::s32_min(frameA + 1, endFrameLoop);
|
||||
}
|
||||
|
||||
// build current vertex
|
||||
for (u32 i = 0; i!= Mesh->Buffer.size(); ++i)
|
||||
{
|
||||
buildVertexArray(frameA, frameB, iPol,
|
||||
Mesh->Buffer[i],
|
||||
(SMeshBufferLightMap*) MeshIPol->getMeshBuffer(i));
|
||||
}
|
||||
MeshIPol->recalculateBoundingBox();
|
||||
|
||||
// build current tags
|
||||
buildTagArray(frameA, frameB, iPol);
|
||||
|
||||
Current = candidate;
|
||||
return MeshIPol;
|
||||
}
|
||||
|
||||
|
||||
//! create a Irrlicht MeshBuffer for a MD3 MeshBuffer
|
||||
IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source,
|
||||
io::IFileSystem* fs, video::IVideoDriver * driver)
|
||||
{
|
||||
SMeshBufferLightMap * dest = new SMeshBufferLightMap();
|
||||
dest->Vertices.set_used(source->MeshHeader.numVertices);
|
||||
dest->Indices.set_used(source->Indices.size());
|
||||
|
||||
u32 i;
|
||||
|
||||
// fill in static face info
|
||||
for (i = 0; i < source->Indices.size(); i += 3)
|
||||
{
|
||||
dest->Indices[i + 0] = (u16) source->Indices[i + 0];
|
||||
dest->Indices[i + 1] = (u16) source->Indices[i + 1];
|
||||
dest->Indices[i + 2] = (u16) source->Indices[i + 2];
|
||||
}
|
||||
|
||||
// fill in static vertex info
|
||||
for (i = 0; i!= (u32)source->MeshHeader.numVertices; ++i)
|
||||
{
|
||||
video::S3DVertex2TCoords &v = dest->Vertices[i];
|
||||
v.Color = 0xFFFFFFFF;
|
||||
v.TCoords.X = source->Tex[i].u;
|
||||
v.TCoords.Y = source->Tex[i].v;
|
||||
v.TCoords2.X = 0.f;
|
||||
v.TCoords2.Y = 0.f;
|
||||
}
|
||||
|
||||
// load static texture
|
||||
u32 pos = 0;
|
||||
quake3::tTexArray textureArray;
|
||||
quake3::getTextures(textureArray, source->Shader, pos, fs, driver);
|
||||
dest->Material.MaterialType = video::EMT_SOLID;
|
||||
dest->Material.setTexture(0, textureArray[0]);
|
||||
dest->Material.Lighting = false;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
//! build final mesh's vertices from frames frameA and frameB with linear interpolation.
|
||||
void CAnimatedMeshMD3::buildVertexArray(u32 frameA, u32 frameB, f32 interpolate,
|
||||
const SMD3MeshBuffer* source,
|
||||
SMeshBufferLightMap* dest)
|
||||
{
|
||||
const u32 frameOffsetA = frameA * source->MeshHeader.numVertices;
|
||||
const u32 frameOffsetB = frameB * source->MeshHeader.numVertices;
|
||||
const f32 scale = (1.f/ 64.f);
|
||||
|
||||
for (s32 i = 0; i != source->MeshHeader.numVertices; ++i)
|
||||
{
|
||||
video::S3DVertex2TCoords &v = dest->Vertices [ i ];
|
||||
|
||||
const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ];
|
||||
const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ];
|
||||
|
||||
// position
|
||||
v.Pos.X = scale * (vA.position[0] + interpolate * (vB.position[0] - vA.position[0]));
|
||||
v.Pos.Y = scale * (vA.position[2] + interpolate * (vB.position[2] - vA.position[2]));
|
||||
v.Pos.Z = scale * (vA.position[1] + interpolate * (vB.position[1] - vA.position[1]));
|
||||
|
||||
// normal
|
||||
const core::vector3df nA(quake3::getMD3Normal(vA.normal[0], vA.normal[1]));
|
||||
const core::vector3df nB(quake3::getMD3Normal(vB.normal[0], vB.normal[1]));
|
||||
|
||||
v.Normal.X = nA.X + interpolate * (nB.X - nA.X);
|
||||
v.Normal.Y = nA.Z + interpolate * (nB.Z - nA.Z);
|
||||
v.Normal.Z = nA.Y + interpolate * (nB.Y - nA.Y);
|
||||
}
|
||||
|
||||
dest->recalculateBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! build final mesh's tag from frames frameA and frameB with linear interpolation.
|
||||
void CAnimatedMeshMD3::buildTagArray(u32 frameA, u32 frameB, f32 interpolate)
|
||||
{
|
||||
const u32 frameOffsetA = frameA * Mesh->MD3Header.numTags;
|
||||
const u32 frameOffsetB = frameB * Mesh->MD3Header.numTags;
|
||||
|
||||
for (s32 i = 0; i != Mesh->MD3Header.numTags; ++i)
|
||||
{
|
||||
SMD3QuaternionTag &d = TagListIPol [ i ];
|
||||
|
||||
const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i];
|
||||
const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i];
|
||||
|
||||
// rotation
|
||||
d.rotation.slerp(qA.rotation, qB.rotation, interpolate);
|
||||
|
||||
// position
|
||||
d.position.X = qA.position.X + interpolate * (qB.position.X - qA.position.X);
|
||||
d.position.Y = qA.position.Y + interpolate * (qB.position.Y - qA.position.Y);
|
||||
d.position.Z = qA.position.Z + interpolate * (qB.position.Z - qA.position.Z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
loads a model
|
||||
*/
|
||||
bool CAnimatedMeshMD3::loadModelFile(u32 modelIndex, io::IReadFile* file,
|
||||
io::IFileSystem* fs, video::IVideoDriver* driver)
|
||||
{
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
//! Check MD3Header
|
||||
{
|
||||
file->read(&Mesh->MD3Header, sizeof(SMD3Header));
|
||||
|
||||
if (strncmp("IDP3", Mesh->MD3Header.headerID, 4))
|
||||
{
|
||||
os::Printer::log("MD3 Loader: invalid header");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//! store model name
|
||||
Mesh->Name = file->getFileName();
|
||||
|
||||
u32 i;
|
||||
|
||||
//! Frame Data (ignore)
|
||||
#if 0
|
||||
SMD3Frame frameImport;
|
||||
file->seek(Mesh->MD3Header.frameStart);
|
||||
for (i = 0; i != Mesh->MD3Header.numFrames; ++i)
|
||||
{
|
||||
file->read(&frameImport, sizeof(frameImport));
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Tag Data
|
||||
const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames;
|
||||
|
||||
SMD3Tag import;
|
||||
|
||||
file->seek(Mesh->MD3Header.tagStart);
|
||||
Mesh->TagList.set_used(totalTags);
|
||||
for (i = 0; i != totalTags; ++i)
|
||||
{
|
||||
file->read(&import, sizeof(import));
|
||||
|
||||
SMD3QuaternionTag &exp = Mesh->TagList[i];
|
||||
|
||||
//! tag name
|
||||
exp.Name = import.Name;
|
||||
|
||||
//! position
|
||||
exp.position.X = import.position[0];
|
||||
exp.position.Y = import.position[2];
|
||||
exp.position.Z = import.position[1];
|
||||
|
||||
//! construct quaternion from a RH 3x3 Matrix
|
||||
exp.rotation.set(import.rotationMatrix[7],
|
||||
0.f,
|
||||
-import.rotationMatrix[6],
|
||||
1 + import.rotationMatrix[8]);
|
||||
exp.rotation.normalize();
|
||||
}
|
||||
|
||||
//! Meshes
|
||||
u32 offset = Mesh->MD3Header.tagEnd;
|
||||
|
||||
for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i)
|
||||
{
|
||||
//! construct a new mesh buffer
|
||||
SMD3MeshBuffer * buf = new SMD3MeshBuffer();
|
||||
|
||||
// !read mesh header info
|
||||
SMD3MeshHeader &meshHeader = buf->MeshHeader;
|
||||
|
||||
//! read mesh info
|
||||
file->seek(offset);
|
||||
file->read(&meshHeader, sizeof(SMD3MeshHeader));
|
||||
|
||||
//! prepare memory
|
||||
buf->Vertices.set_used(meshHeader.numVertices * Mesh->MD3Header.numFrames);
|
||||
buf->Indices.set_used(meshHeader.numTriangles * 3);
|
||||
buf->Tex.set_used(meshHeader.numVertices);
|
||||
|
||||
//! read skins (shaders). should be 1 per meshbuffer
|
||||
SMD3Shader skin;
|
||||
file->seek(offset + buf->MeshHeader.offset_shaders);
|
||||
for (s32 g = 0; g != buf->MeshHeader.numShader; ++g)
|
||||
{
|
||||
file->read(&skin, sizeof(skin));
|
||||
|
||||
io::path name;
|
||||
cutFilenameExtension(name, skin.name);
|
||||
name.replace('\\', '/');
|
||||
buf->Shader = name;
|
||||
}
|
||||
|
||||
//! read texture coordinates
|
||||
file->seek(offset + buf->MeshHeader.offset_st);
|
||||
file->read(buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord));
|
||||
|
||||
//! read vertices
|
||||
file->seek(offset + meshHeader.vertexStart);
|
||||
file->read(buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex));
|
||||
|
||||
//! read indices
|
||||
file->seek(offset + meshHeader.offset_triangles);
|
||||
file->read(buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face));
|
||||
|
||||
//! store meshBuffer
|
||||
Mesh->Buffer.push_back(buf);
|
||||
|
||||
offset += meshHeader.offset_end;
|
||||
}
|
||||
|
||||
// Init Mesh Interpolation
|
||||
for (i = 0; i != Mesh->Buffer.size(); ++i)
|
||||
{
|
||||
IMeshBuffer * buffer = createMeshBuffer(Mesh->Buffer[i], fs, driver);
|
||||
MeshIPol->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
MeshIPol->recalculateBoundingBox();
|
||||
|
||||
// Init Tag Interpolation
|
||||
for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i)
|
||||
{
|
||||
TagListIPol.push_back(Mesh->TagList[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh()
|
||||
{
|
||||
return Mesh;
|
||||
}
|
||||
|
||||
|
||||
//! Returns an axis aligned bounding box
|
||||
const core::aabbox3d<f32>& CAnimatedMeshMD3::getBoundingBox() const
|
||||
{
|
||||
return MeshIPol->BoundingBox;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
E_ANIMATED_MESH_TYPE CAnimatedMeshMD3::getMeshType() const
|
||||
{
|
||||
return EAMT_MD3;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_MD3_LOADER_
|
135
source/Irrlicht/CAnimatedMeshMD3.h
Normal file
135
source/Irrlicht/CAnimatedMeshMD3.h
Normal file
@ -0,0 +1,135 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_MD3_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_MD3_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMeshMD3.h"
|
||||
#include "IReadFile.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
#include "SMesh.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "IQ3Shader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CAnimatedMeshMD3 : public IAnimatedMeshMD3
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshMD3();
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshMD3();
|
||||
|
||||
//! loads a quake3 md3 file
|
||||
bool loadModelFile(u32 modelIndex, io::IReadFile* file,
|
||||
io::IFileSystem* fs, video::IVideoDriver* driver);
|
||||
|
||||
// IAnimatedMeshMD3
|
||||
virtual void setInterpolationShift(u32 shift, u32 loopMode) _IRR_OVERRIDE_;
|
||||
virtual SMD3Mesh* getOriginalMesh() _IRR_OVERRIDE_;
|
||||
virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) _IRR_OVERRIDE_;
|
||||
|
||||
//IAnimatedMesh
|
||||
virtual u32 getFrameCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
virtual f32 getAnimationSpeed() const _IRR_OVERRIDE_
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
virtual void setAnimationSpeed(f32 fps) _IRR_OVERRIDE_
|
||||
{
|
||||
FramesPerSecond=fps;
|
||||
}
|
||||
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel,
|
||||
s32 startFrameLoop, s32 endFrameLoop) _IRR_OVERRIDE_;
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
virtual IMeshBuffer* getMeshBuffer(const video::SMaterial &material) const _IRR_OVERRIDE_;
|
||||
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) _IRR_OVERRIDE_;
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox(const core::aabbox3df& box) _IRR_OVERRIDE_;
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) _IRR_OVERRIDE_;
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
//! animates one frame
|
||||
inline void Animate(u32 frame);
|
||||
|
||||
video::SMaterial Material;
|
||||
|
||||
//! hold original compressed MD3 Info
|
||||
SMD3Mesh *Mesh;
|
||||
|
||||
u32 IPolShift;
|
||||
u32 LoopMode;
|
||||
f32 Scaling;
|
||||
|
||||
//! Cache Info
|
||||
struct SCacheInfo
|
||||
{
|
||||
SCacheInfo(s32 frame=-1, s32 start=-1, s32 end=-1 ) :
|
||||
Frame(frame), startFrameLoop(start),
|
||||
endFrameLoop(end)
|
||||
{}
|
||||
|
||||
bool operator == ( const SCacheInfo &other ) const
|
||||
{
|
||||
return 0 == memcmp ( this, &other, sizeof ( SCacheInfo ) );
|
||||
}
|
||||
s32 Frame;
|
||||
s32 startFrameLoop;
|
||||
s32 endFrameLoop;
|
||||
};
|
||||
SCacheInfo Current;
|
||||
|
||||
//! return a Mesh per frame
|
||||
SMesh* MeshIPol;
|
||||
SMD3QuaternionTagList TagListIPol;
|
||||
|
||||
IMeshBuffer* createMeshBuffer(const SMD3MeshBuffer* source,
|
||||
io::IFileSystem* fs, video::IVideoDriver* driver);
|
||||
|
||||
void buildVertexArray(u32 frameA, u32 frameB, f32 interpolate,
|
||||
const SMD3MeshBuffer* source,
|
||||
SMeshBufferLightMap* dest);
|
||||
|
||||
void buildTagArray(u32 frameA, u32 frameB, f32 interpolate);
|
||||
f32 FramesPerSecond;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1126
source/Irrlicht/CAnimatedMeshSceneNode.cpp
Normal file
1126
source/Irrlicht/CAnimatedMeshSceneNode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
223
source/Irrlicht/CAnimatedMeshSceneNode.h
Normal file
223
source/Irrlicht/CAnimatedMeshSceneNode.h
Normal file
@ -0,0 +1,223 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#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.
|
||||
virtual void setCurrentFrame(f32 frame) _IRR_OVERRIDE_;
|
||||
|
||||
//! frame
|
||||
virtual void OnRegisterSceneNode() _IRR_OVERRIDE_;
|
||||
|
||||
//! OnAnimate() is called just before rendering the whole scene.
|
||||
virtual void OnAnimate(u32 timeMs) _IRR_OVERRIDE_;
|
||||
|
||||
//! renders the node.
|
||||
virtual void render() _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_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
|
||||
virtual bool setFrameLoop(s32 begin, s32 end) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets looping mode which is on by default. If set to false,
|
||||
//! animations will not be looped.
|
||||
virtual void setLoopMode(bool playAnimationLooped) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the current loop mode
|
||||
virtual bool getLoopMode() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a callback interface which will be called if an animation
|
||||
//! playback has ended. Set this to 0 to disable the callback again.
|
||||
virtual void setAnimationEndCallback(IAnimationEndCallBack* callback=0) _IRR_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
|
||||
virtual void setAnimationSpeed(f32 framesPerSecond) _IRR_OVERRIDE_;
|
||||
|
||||
//! gets the speed with which the animation is played
|
||||
virtual f32 getAnimationSpeed() const _IRR_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.
|
||||
virtual video::SMaterial& getMaterial(u32 i) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates shadow volume scene node as child of this node
|
||||
//! and returns a pointer to it.
|
||||
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
|
||||
s32 id, bool zfailmethod=true, f32 infinity=1000.0f) _IRR_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.
|
||||
virtual IBoneSceneNode* getJointNode(const c8* jointName) _IRR_OVERRIDE_;
|
||||
|
||||
//! same as getJointNode(const c8* jointName), but based on id
|
||||
virtual IBoneSceneNode* getJointNode(u32 jointID) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets joint count.
|
||||
virtual u32 getJointCount() const _IRR_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.
|
||||
virtual bool removeChild(ISceneNode* child) _IRR_OVERRIDE_;
|
||||
|
||||
//! Starts a MD2 animation.
|
||||
virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim) _IRR_OVERRIDE_;
|
||||
|
||||
//! Starts a special MD2 animation.
|
||||
virtual bool setMD2Animation(const c8* animationName) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the current displayed frame number.
|
||||
virtual f32 getFrameNr() const _IRR_OVERRIDE_;
|
||||
//! Returns the current start frame number.
|
||||
virtual s32 getStartFrame() const _IRR_OVERRIDE_;
|
||||
//! Returns the current end frame number.
|
||||
virtual s32 getEndFrame() const _IRR_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. */
|
||||
virtual void setReadOnlyMaterials(bool readonly) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
|
||||
virtual bool isReadOnlyMaterials() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a new mesh
|
||||
virtual void setMesh(IAnimatedMesh* mesh) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the current mesh
|
||||
virtual IAnimatedMesh* getMesh(void) _IRR_OVERRIDE_ { return Mesh; }
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_ANIMATED_MESH; }
|
||||
|
||||
// returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh,
|
||||
// or the absolutetransformation if it's a normal scenenode
|
||||
const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) _IRR_OVERRIDE_;
|
||||
|
||||
//! updates the absolute position based on the relative and the parents position
|
||||
virtual void updateAbsolutePosition() _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
//! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
|
||||
virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode) _IRR_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
|
||||
virtual void setTransitionTime(f32 Time) _IRR_OVERRIDE_;
|
||||
|
||||
//! updates the joint positions of this mesh
|
||||
virtual void animateJoints(bool CalculateAbsolutePositions=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
||||
virtual void setRenderFromIdentity( bool On ) _IRR_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. */
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) _IRR_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;
|
||||
|
||||
IShadowVolumeSceneNode* Shadow;
|
||||
|
||||
core::array<IBoneSceneNode* > JointChildSceneNodes;
|
||||
core::array<core::matrix4> PretransitingSave;
|
||||
|
||||
// Quake3 Model
|
||||
struct SMD3Special : public virtual IReferenceCounted
|
||||
{
|
||||
core::stringc Tagname;
|
||||
SMD3QuaternionTagList AbsoluteTagList;
|
||||
|
||||
SMD3Special & operator = (const SMD3Special & copyMe)
|
||||
{
|
||||
Tagname = copyMe.Tagname;
|
||||
AbsoluteTagList = copyMe.AbsoluteTagList;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
SMD3Special *MD3Special;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
2093
source/Irrlicht/CAttributeImpl.h
Normal file
2093
source/Irrlicht/CAttributeImpl.h
Normal file
File diff suppressed because it is too large
Load Diff
1658
source/Irrlicht/CAttributes.cpp
Normal file
1658
source/Irrlicht/CAttributes.cpp
Normal file
File diff suppressed because it is too large
Load Diff
738
source/Irrlicht/CAttributes.h
Normal file
738
source/Irrlicht/CAttributes.h
Normal file
@ -0,0 +1,738 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_ATTRIBUTES_H_INCLUDED__
|
||||
#define __C_ATTRIBUTES_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#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.
|
||||
virtual u32 getAttributeCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns attribute name by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const c8* getAttributeName(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the type of an attribute
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual E_ATTRIBUTE_TYPE getAttributeType(const c8* attributeName) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns attribute type by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual E_ATTRIBUTE_TYPE getAttributeType(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the type string of the attribute
|
||||
//! \param attributeName: String for the attribute type
|
||||
//! \param defaultNotFound Value returned when attributeName was not found
|
||||
virtual const wchar_t* getAttributeTypeString(const c8* attributeName, const wchar_t* defaultNotFound = L"unknown") const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the type string of the attribute by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const wchar_t* getAttributeTypeString(s32 index, const wchar_t* defaultNotFound = L"unknown") const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if an attribute with a name exists
|
||||
virtual bool existsAttribute(const c8* attributeName) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns attribute index from name, -1 if not found
|
||||
virtual s32 findAttribute(const c8* attributeName) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Removes all attributes
|
||||
virtual void clear() _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes from a xml file.
|
||||
//! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'.
|
||||
//! IF set to false, the first appearing list attributes are read.
|
||||
virtual bool read(io::IXMLReader* reader, bool readCurrentElementOnly=false,
|
||||
const wchar_t* nonDefaultElementName = 0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Write these attributes into a xml file
|
||||
virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* nonDefaultElementName=0) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Integer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as integer
|
||||
virtual void addInt(const c8* attributeName, s32 value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
virtual void setAttribute(const c8* attributeName, s32 value) _IRR_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()
|
||||
virtual s32 getAttributeAsInt(const c8* attributeName, irr::s32 defaultNotFound=0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual s32 getAttributeAsInt(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
virtual void setAttribute(s32 index, s32 value) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
Float Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as float
|
||||
virtual void addFloat(const c8* attributeName, f32 value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a attribute as float value
|
||||
virtual void setAttribute(const c8* attributeName, f32 value) _IRR_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()
|
||||
virtual f32 getAttributeAsFloat(const c8* attributeName, irr::f32 defaultNotFound=0.f) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual f32 getAttributeAsFloat(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as float value
|
||||
virtual void setAttribute(s32 index, f32 value) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
String Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as string
|
||||
virtual void addString(const c8* attributeName, const c8* value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const c8* value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \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()
|
||||
//! or defaultNotFound if attribute is not set.
|
||||
virtual core::stringc getAttributeAsString(const c8* attributeName, const core::stringc& defaultNotFound=core::stringc()) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param target: Buffer where the string is copied to.
|
||||
virtual void getAttributeAsString(const c8* attributeName, c8* target) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns attribute value as string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::stringc getAttributeAsString(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual void setAttribute(s32 index, const c8* value) _IRR_OVERRIDE_;
|
||||
|
||||
// wide strings
|
||||
|
||||
//! Adds an attribute as string
|
||||
virtual void addString(const c8* attributeName, const wchar_t* value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const wchar_t* value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \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()
|
||||
//! or defaultNotFound if attribute is not set.
|
||||
virtual core::stringw getAttributeAsStringW(const c8* attributeName, const core::stringw& defaultNotFound = core::stringw()) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param target: Buffer where the string is copied to.
|
||||
virtual void getAttributeAsStringW(const c8* attributeName, wchar_t* target) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns attribute value as string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::stringw getAttributeAsStringW(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual void setAttribute(s32 index, const wchar_t* value) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
Binary Data Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as binary data
|
||||
virtual void addBinary(const c8* attributeName, void* data, s32 dataSizeInBytes) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as binary data
|
||||
virtual void setAttribute(const c8* attributeName, void* data, s32 dataSizeInBytes) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as binary data
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void getAttributeAsBinaryData(const c8* attributeName, void* outData, s32 maxSizeInBytes) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as binary data
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void getAttributeAsBinaryData(s32 index, void* outData, s32 maxSizeInBytes) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as binary data
|
||||
virtual void setAttribute(s32 index, void* data, s32 dataSizeInBytes) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Array Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as wide string array
|
||||
virtual void addArray(const c8* attributeName, const core::array<core::stringw>& value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute value as a wide string array.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const core::array<core::stringw>& value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as an array of wide strings.
|
||||
//! \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()
|
||||
//! or defaultNotFound if attribute is not set.
|
||||
virtual core::array<core::stringw> getAttributeAsArray(const c8* attributeName, const core::array<core::stringw>& defaultNotFound = core::array<core::stringw>()) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns attribute value as an array of wide strings by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::array<core::stringw> getAttributeAsArray(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as an array of wide strings
|
||||
virtual void setAttribute(s32 index, const core::array<core::stringw>& value) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
Bool Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as bool
|
||||
virtual void addBool(const c8* attributeName, bool value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
virtual void setAttribute(const c8* attributeName, bool value) _IRR_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()
|
||||
virtual bool getAttributeAsBool(const c8* attributeName, bool defaultNotFound=false) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual bool getAttributeAsBool(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
virtual void setAttribute(s32 index, bool value) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
Enumeration Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as enum
|
||||
virtual void addEnum(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals) _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds an attribute as enum
|
||||
virtual void addEnum(const c8* attributeName, s32 enumValue, const c8* const* enumerationLiterals) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as enumeration
|
||||
virtual void setAttribute(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \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()
|
||||
virtual const c8* getAttributeAsEnumeration(const c8* attributeName, const c8* defaultNotFound = 0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param enumerationLiteralsToUse: Use these enumeration literals to get the index value instead of the set ones.
|
||||
//! This is useful when the attribute list maybe was read from an xml file, and only contains the enumeration string, but
|
||||
//! no information about its index.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual s32 getAttributeAsEnumeration(const c8* attributeName, const c8* const* enumerationLiteralsToUse, s32 defaultNotFound ) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual s32 getAttributeAsEnumeration(s32 index, const c8* const* enumerationLiteralsToUse, s32 defaultNotFound) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const c8* getAttributeAsEnumeration(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the list of enumeration literals of an enumeration attribute
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array<core::stringc>& outLiterals) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the list of enumeration literals of an enumeration attribute
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array<core::stringc>& outLiterals) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as enumeration
|
||||
virtual void setAttribute(s32 index, const c8* enumValue, const c8* const* enumerationLiterals) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
SColor Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as color
|
||||
virtual void addColor(const c8* attributeName, video::SColor value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a attribute as color
|
||||
virtual void setAttribute(const c8* attributeName, video::SColor color) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as color
|
||||
//! \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()
|
||||
virtual video::SColor getAttributeAsColor(const c8* attributeName, const video::SColor& defaultNotFound = video::SColor(0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as color
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::SColor getAttributeAsColor(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as color
|
||||
virtual void setAttribute(s32 index, video::SColor color) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
SColorf Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as floating point color
|
||||
virtual void addColorf(const c8* attributeName, video::SColorf value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a attribute as floating point color
|
||||
virtual void setAttribute(const c8* attributeName, video::SColorf color) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as floating point color
|
||||
//! \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()
|
||||
virtual video::SColorf getAttributeAsColorf(const c8* attributeName, const video::SColorf& defaultNotFound = video::SColorf(0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as floating point color
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::SColorf getAttributeAsColorf(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as floating point color
|
||||
virtual void setAttribute(s32 index, video::SColorf color) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Vector3d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d vector
|
||||
virtual void addVector3d(const c8* attributeName, const core::vector3df& value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a attribute as 3d vector
|
||||
virtual void setAttribute(const c8* attributeName, const core::vector3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \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()
|
||||
virtual core::vector3df getAttributeAsVector3d(const c8* attributeName, const core::vector3df& defaultNotFound=core::vector3df(0,0,0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::vector3df getAttributeAsVector3d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as vector
|
||||
virtual void setAttribute(s32 index, const core::vector3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Vector2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 2d vector
|
||||
virtual void addVector2d(const c8* attributeName, const core::vector2df& value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a attribute as 2d vector
|
||||
virtual void setAttribute(const c8* attributeName, const core::vector2df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as 2d vector
|
||||
//! \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()
|
||||
virtual core::vector2df getAttributeAsVector2d(const c8* attributeName, const core::vector2df& defaultNotFound=core::vector2df(0,0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::vector2df getAttributeAsVector2d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as vector
|
||||
virtual void setAttribute(s32 index, const core::vector2df& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Position2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 2d position
|
||||
virtual void addPosition2d(const c8* attributeName, const core::position2di& value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a attribute as 2d position
|
||||
virtual void setAttribute(const c8* attributeName, const core::position2di& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as position
|
||||
//! \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()
|
||||
virtual core::position2di getAttributeAsPosition2d(const c8* attributeName, const core::position2di& defaultNotFound=core::position2di(0,0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as position
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::position2di getAttributeAsPosition2d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as 2d position
|
||||
virtual void setAttribute(s32 index, const core::position2di& v) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
Rectangle Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as rectangle
|
||||
virtual void addRect(const c8* attributeName, const core::rect<s32>& value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as rectangle
|
||||
virtual void setAttribute(const c8* attributeName, const core::rect<s32>& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as rectangle
|
||||
//! \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()
|
||||
virtual core::rect<s32> getAttributeAsRect(const c8* attributeName, const core::rect<s32>& defaultNotFound = core::rect<s32>()) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as rectangle
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::rect<s32> getAttributeAsRect(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as rectangle
|
||||
virtual void setAttribute(s32 index, const core::rect<s32>& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Dimension2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as dimension2d
|
||||
virtual void addDimension2d(const c8* attributeName, const core::dimension2d<u32>& value) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as dimension2d
|
||||
virtual void setAttribute(const c8* attributeName, const core::dimension2d<u32>& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as dimension2d
|
||||
//! \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()
|
||||
virtual core::dimension2d<u32> getAttributeAsDimension2d(const c8* attributeName, const core::dimension2d<u32>& defaultNotFound = core::dimension2d<u32>()) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as dimension2d
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::dimension2d<u32> getAttributeAsDimension2d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as dimension2d
|
||||
virtual void setAttribute(s32 index, const core::dimension2d<u32>& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
matrix attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as matrix
|
||||
virtual void addMatrix(const c8* attributeName, const core::matrix4& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as matrix
|
||||
virtual void setAttribute(const c8* attributeName, const core::matrix4& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a matrix4
|
||||
//! \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()
|
||||
virtual core::matrix4 getAttributeAsMatrix(const c8* attributeName, const core::matrix4& defaultNotFound=core::matrix4()) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as matrix
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::matrix4 getAttributeAsMatrix(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as matrix
|
||||
virtual void setAttribute(s32 index, const core::matrix4& v) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
quaternion attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as quaternion
|
||||
virtual void addQuaternion(const c8* attributeName, const core::quaternion& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as quaternion
|
||||
virtual void setAttribute(const c8* attributeName, const core::quaternion& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a quaternion
|
||||
//! \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()
|
||||
virtual core::quaternion getAttributeAsQuaternion(const c8* attributeName, const core::quaternion& defaultNotFound=core::quaternion(0,1,0, 0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as quaternion
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::quaternion getAttributeAsQuaternion(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as quaternion
|
||||
virtual void setAttribute(s32 index, const core::quaternion& v) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
3d bounding box
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as axis aligned bounding box
|
||||
virtual void addBox3d(const c8* attributeName, const core::aabbox3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as axis aligned bounding box
|
||||
virtual void setAttribute(const c8* attributeName, const core::aabbox3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a axis aligned bounding box
|
||||
//! \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()
|
||||
virtual core::aabbox3df getAttributeAsBox3d(const c8* attributeName, const core::aabbox3df& defaultNotFound=core::aabbox3df(0,0,0, 0,0,0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as axis aligned bounding box
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::aabbox3df getAttributeAsBox3d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as axis aligned bounding box
|
||||
virtual void setAttribute(s32 index, const core::aabbox3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
|
||||
plane
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d plane
|
||||
virtual void addPlane3d(const c8* attributeName, const core::plane3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as 3d plane
|
||||
virtual void setAttribute(const c8* attributeName, const core::plane3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a 3d plane
|
||||
//! \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()
|
||||
virtual core::plane3df getAttributeAsPlane3d(const c8* attributeName, const core::plane3df& defaultNotFound=core::plane3df(0,0,0, 0,1,0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as 3d plane
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::plane3df getAttributeAsPlane3d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as 3d plane
|
||||
virtual void setAttribute(s32 index, const core::plane3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
3d triangle
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d triangle
|
||||
virtual void addTriangle3d(const c8* attributeName, const core::triangle3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as 3d triangle
|
||||
virtual void setAttribute(const c8* attributeName, const core::triangle3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a 3d triangle
|
||||
//! \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()
|
||||
virtual core::triangle3df getAttributeAsTriangle3d(const c8* attributeName, const core::triangle3df& defaultNotFound = core::triangle3df(core::vector3df(0,0,0), core::vector3df(0,0,0), core::vector3df(0,0,0))) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as 3d triangle
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::triangle3df getAttributeAsTriangle3d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as 3d triangle
|
||||
virtual void setAttribute(s32 index, const core::triangle3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
line 2d
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as a 2d line
|
||||
virtual void addLine2d(const c8* attributeName, const core::line2df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as a 2d line
|
||||
virtual void setAttribute(const c8* attributeName, const core::line2df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a 2d line
|
||||
//! \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()
|
||||
virtual core::line2df getAttributeAsLine2d(const c8* attributeName, const core::line2df& defaultNotFound = core::line2df(0,0, 0,0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a 2d line
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::line2df getAttributeAsLine2d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as a 2d line
|
||||
virtual void setAttribute(s32 index, const core::line2df& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
line 3d
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as a 3d line
|
||||
virtual void addLine3d(const c8* attributeName, const core::line3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as a 3d line
|
||||
virtual void setAttribute(const c8* attributeName, const core::line3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a 3d line
|
||||
//! \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()
|
||||
virtual core::line3df getAttributeAsLine3d(const c8* attributeName, const core::line3df& defaultNotFound=core::line3df(0,0,0, 0,0,0)) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as a 3d line
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::line3df getAttributeAsLine3d(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as a 3d line
|
||||
virtual void setAttribute(s32 index, const core::line3df& v) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Texture Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as texture reference
|
||||
virtual void addTexture(const c8* attributeName, video::ITexture* texture, const io::path& filename = "") _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as texture reference
|
||||
virtual void setAttribute(const c8* attributeName, video::ITexture* texture, const io::path& filename = "") _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as texture reference
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param defaultNotFound Value returned when attributeName was not found
|
||||
virtual video::ITexture* getAttributeAsTexture(const c8* attributeName, video::ITexture* defaultNotFound=0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as texture reference
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::ITexture* getAttributeAsTexture(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as texture reference
|
||||
virtual void setAttribute(s32 index, video::ITexture* texture, const io::path& filename = "") _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
User Pointer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as user pointer
|
||||
virtual void addUserPointer(const c8* attributeName, void* userPointer) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as user pointer
|
||||
virtual void setAttribute(const c8* attributeName, void* userPointer) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as user pointer
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param defaultNotFound Value returned when attributeName was not found
|
||||
virtual void* getAttributeAsUserPointer(const c8* attributeName, void* defaultNotFound = 0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets an attribute as user pointer
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void* getAttributeAsUserPointer(s32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an attribute as user pointer
|
||||
virtual void setAttribute(s32 index, void* userPointer) _IRR_OVERRIDE_;
|
||||
|
||||
protected:
|
||||
|
||||
void readAttributeFromXML(const io::IXMLReader* reader);
|
||||
|
||||
core::array<IAttribute*> Attributes;
|
||||
|
||||
IAttribute* getAttributeP(const c8* attributeName) const;
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1106
source/Irrlicht/CB3DMeshFileLoader.cpp
Normal file
1106
source/Irrlicht/CB3DMeshFileLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
91
source/Irrlicht/CB3DMeshFileLoader.h
Normal file
91
source/Irrlicht/CB3DMeshFileLoader.h
Normal file
@ -0,0 +1,91 @@
|
||||
// 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
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifndef __C_B3D_MESH_LOADER_H_INCLUDED__
|
||||
#define __C_B3D_MESH_LOADER_H_INCLUDED__
|
||||
|
||||
#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")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_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.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_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 loadTextures(SB3dMaterial& material) const;
|
||||
|
||||
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;
|
||||
|
||||
ISceneManager* SceneManager;
|
||||
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
|
||||
|
||||
#endif // __C_B3D_MESH_LOADER_H_INCLUDED__
|
||||
|
648
source/Irrlicht/CB3DMeshWriter.cpp
Normal file
648
source/Irrlicht/CB3DMeshWriter.cpp
Normal file
@ -0,0 +1,648 @@
|
||||
// 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
|
||||
|
||||
// TODO: replace printf's by logging messages
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_B3D_WRITER_
|
||||
|
||||
#include "CB3DMeshWriter.h"
|
||||
#include "os.h"
|
||||
#include "ISkinnedMesh.h"
|
||||
#include "IMeshBuffer.h"
|
||||
#include "IWriteFile.h"
|
||||
#include "ITexture.h"
|
||||
#include "irrMap.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
using namespace core;
|
||||
using namespace video;
|
||||
|
||||
CB3DMeshWriter::CB3DMeshWriter()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CB3DMeshWriter");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of the mesh writer
|
||||
EMESH_WRITER_TYPE CB3DMeshWriter::getType() const
|
||||
{
|
||||
return EMWT_B3D;
|
||||
}
|
||||
|
||||
|
||||
//! writes a mesh
|
||||
bool CB3DMeshWriter::writeMesh(io::IWriteFile* file, IMesh* const mesh, s32 flags)
|
||||
{
|
||||
if (!file || !mesh)
|
||||
return false;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Printer::log("B3D export does not support big-endian systems.", ELL_ERROR);
|
||||
return false;
|
||||
#endif
|
||||
|
||||
Size = 0;
|
||||
file->write("BB3D", 4);
|
||||
file->write(&Size, sizeof(u32)); // Updated later once known.
|
||||
|
||||
int version = 1;
|
||||
write(file, &version, sizeof(int));
|
||||
|
||||
//
|
||||
|
||||
const u32 numBeshBuffers = mesh->getMeshBufferCount();
|
||||
array<SB3dTexture> texs;
|
||||
map<ITexture *, u32> tex2id; // TODO: texture pointer as key not sufficient as same texture can have several id's
|
||||
u32 texsizes = 0;
|
||||
for (u32 i = 0; i < numBeshBuffers; i++)
|
||||
{
|
||||
const IMeshBuffer * const mb = mesh->getMeshBuffer(i);
|
||||
const SMaterial &mat = mb->getMaterial();
|
||||
|
||||
for (u32 j = 0; j < MATERIAL_MAX_TEXTURES; j++)
|
||||
{
|
||||
if (mat.getTexture(j))
|
||||
{
|
||||
SB3dTexture t;
|
||||
t.TextureName = core::stringc(mat.getTexture(j)->getName().getPath());
|
||||
|
||||
// TODO: need some description of Blitz3D texture-flags to figure this out. But Blend should likely depend on material-type.
|
||||
t.Flags = j == 2 ? 65536 : 1;
|
||||
t.Blend = 2;
|
||||
|
||||
// TODO: evaluate texture matrix
|
||||
t.Xpos = 0;
|
||||
t.Ypos = 0;
|
||||
t.Xscale = 1;
|
||||
t.Yscale = 1;
|
||||
t.Angle = 0;
|
||||
|
||||
texs.push_back(t);
|
||||
texsizes += 7*4 + t.TextureName.size() + 1;
|
||||
tex2id[mat.getTexture(j)] = texs.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write(file, "TEXS", 4);
|
||||
write(file, &texsizes, 4);
|
||||
|
||||
u32 numTexture = texs.size();
|
||||
for (u32 i = 0; i < numTexture; i++)
|
||||
{
|
||||
write(file, texs[i].TextureName.c_str(), texs[i].TextureName.size() + 1);
|
||||
write(file, &texs[i].Flags, 7*4);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const u32 brushsize = (7 * 4 + 1) * numBeshBuffers + numBeshBuffers * 4 * MATERIAL_MAX_TEXTURES + 4;
|
||||
write(file, "BRUS", 4);
|
||||
write(file, &brushsize, 4);
|
||||
u32 brushcheck = Size;
|
||||
const u32 usedtex = MATERIAL_MAX_TEXTURES;
|
||||
write(file, &usedtex, 4);
|
||||
|
||||
for (u32 i = 0; i < numBeshBuffers; i++)
|
||||
{
|
||||
const IMeshBuffer * const mb = mesh->getMeshBuffer(i);
|
||||
const SMaterial &mat = mb->getMaterial();
|
||||
|
||||
write(file, "", 1);
|
||||
|
||||
float f = 1;
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
|
||||
f = 0;
|
||||
write(file, &f, 4);
|
||||
|
||||
u32 tmp = 1;
|
||||
write(file, &tmp, 4);
|
||||
tmp = 0;
|
||||
write(file, &tmp, 4);
|
||||
|
||||
for (u32 j = 0; j < MATERIAL_MAX_TEXTURES; j++)
|
||||
{
|
||||
if (mat.getTexture(j))
|
||||
{
|
||||
const u32 id = tex2id[mat.getTexture(j)];
|
||||
write(file, &id, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int id = -1;
|
||||
write(file, &id, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check brushsize
|
||||
brushcheck = Size - brushcheck;
|
||||
if (brushcheck != brushsize)
|
||||
{
|
||||
printf("Failed in brush size calculation, size %u advanced %u\n",
|
||||
brushsize, brushcheck);
|
||||
}
|
||||
|
||||
write(file, "NODE", 4);
|
||||
|
||||
// Calculate node size
|
||||
u32 nodesize = 41 + 8 + 4 + 8;
|
||||
u32 bonesSize = 0;
|
||||
|
||||
if(ISkinnedMesh *skinnedMesh = getSkinned(mesh))
|
||||
{
|
||||
if (!skinnedMesh->isStatic())
|
||||
{
|
||||
bonesSize += 20;
|
||||
}
|
||||
|
||||
const core::array<ISkinnedMesh::SJoint*> rootJoints = getRootJoints(skinnedMesh);
|
||||
for (u32 i = 0; i < rootJoints.size(); i++)
|
||||
{
|
||||
bonesSize += getJointChunkSize(skinnedMesh, rootJoints[i]);
|
||||
}
|
||||
nodesize += bonesSize;
|
||||
|
||||
// -------------------
|
||||
|
||||
}
|
||||
|
||||
// VERT data
|
||||
nodesize += 12;
|
||||
|
||||
const u32 texcoords = getUVlayerCount(mesh);
|
||||
for (u32 i = 0; i < numBeshBuffers; i++)
|
||||
{
|
||||
nodesize += 8 + 4;
|
||||
const IMeshBuffer * const mb = mesh->getMeshBuffer(i);
|
||||
|
||||
nodesize += mb->getVertexCount() * 10 * 4;
|
||||
|
||||
nodesize += mb->getVertexCount() * texcoords * 2 * 4;
|
||||
nodesize += mb->getIndexCount() * 4;
|
||||
}
|
||||
write(file, &nodesize, 4);
|
||||
u32 nodecheck = Size;
|
||||
|
||||
// Node
|
||||
write(file, "", 1);
|
||||
float f = 0;
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
|
||||
f = 1;
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
|
||||
write(file, &f, 4);
|
||||
f = 0;
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
write(file, &f, 4);
|
||||
|
||||
// Mesh
|
||||
write(file, "MESH", 4);
|
||||
const u32 meshsize = nodesize - 41 - 8 - bonesSize;
|
||||
write(file, &meshsize, 4);
|
||||
s32 brushID = -1;
|
||||
write(file, &brushID, 4);
|
||||
|
||||
|
||||
|
||||
// Verts
|
||||
write(file, "VRTS", 4);
|
||||
u32 vertsize = 12;
|
||||
|
||||
for (u32 i = 0; i < numBeshBuffers; i++)
|
||||
{
|
||||
const IMeshBuffer * const mb = mesh->getMeshBuffer(i);
|
||||
|
||||
vertsize += mb->getVertexCount() * 10 * 4 +
|
||||
mb->getVertexCount() * texcoords * 2 * 4;
|
||||
}
|
||||
write(file, &vertsize, 4);
|
||||
u32 vertcheck = Size;
|
||||
|
||||
int flagsB3D = 3;
|
||||
write(file, &flagsB3D, 4);
|
||||
|
||||
write(file, &texcoords, 4);
|
||||
flagsB3D = 2;
|
||||
write(file, &flagsB3D, 4);
|
||||
|
||||
for (u32 i = 0; i < numBeshBuffers; i++)
|
||||
{
|
||||
const IMeshBuffer * const mb = mesh->getMeshBuffer(i);
|
||||
irr::u32 numVertices = mb->getVertexCount();
|
||||
for (u32 j = 0; j < numVertices; j++)
|
||||
{
|
||||
const vector3df &pos = mb->getPosition(j);
|
||||
write(file, &pos.X, 4);
|
||||
write(file, &pos.Y, 4);
|
||||
write(file, &pos.Z, 4);
|
||||
|
||||
const vector3df &n = mb->getNormal(j);
|
||||
write(file, &n.X, 4);
|
||||
write(file, &n.Y, 4);
|
||||
write(file, &n.Z, 4);
|
||||
|
||||
const u32 zero = 0;
|
||||
switch (mb->getVertexType())
|
||||
{
|
||||
case EVT_STANDARD:
|
||||
{
|
||||
S3DVertex *v = (S3DVertex *) mb->getVertices();
|
||||
const SColorf col(v[j].Color);
|
||||
write(file, &col.r, 4);
|
||||
write(file, &col.g, 4);
|
||||
write(file, &col.b, 4);
|
||||
write(file, &col.a, 4);
|
||||
|
||||
write(file, &v[j].TCoords.X, 4);
|
||||
write(file, &v[j].TCoords.Y, 4);
|
||||
if (texcoords == 2)
|
||||
{
|
||||
write(file, &zero, 4);
|
||||
write(file, &zero, 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EVT_2TCOORDS:
|
||||
{
|
||||
S3DVertex2TCoords *v = (S3DVertex2TCoords *) mb->getVertices();
|
||||
const SColorf col(v[j].Color);
|
||||
write(file, &col.r, 4);
|
||||
write(file, &col.g, 4);
|
||||
write(file, &col.b, 4);
|
||||
write(file, &col.a, 4);
|
||||
|
||||
write(file, &v[j].TCoords.X, 4);
|
||||
write(file, &v[j].TCoords.Y, 4);
|
||||
write(file, &v[j].TCoords2.X, 4);
|
||||
write(file, &v[j].TCoords2.Y, 4);
|
||||
}
|
||||
break;
|
||||
case EVT_TANGENTS:
|
||||
{
|
||||
S3DVertexTangents *v = (S3DVertexTangents *) mb->getVertices();
|
||||
const SColorf col(v[j].Color);
|
||||
write(file, &col.r, 4);
|
||||
write(file, &col.g, 4);
|
||||
write(file, &col.b, 4);
|
||||
write(file, &col.a, 4);
|
||||
|
||||
write(file, &v[j].TCoords.X, 4);
|
||||
write(file, &v[j].TCoords.Y, 4);
|
||||
if (texcoords == 2)
|
||||
{
|
||||
write(file, &zero, 4);
|
||||
write(file, &zero, 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check vertsize
|
||||
vertcheck = Size - vertcheck;
|
||||
if (vertcheck != vertsize)
|
||||
{
|
||||
printf("Failed in vertex size calculation, size %u advanced %u\n",
|
||||
vertsize, vertcheck);
|
||||
}
|
||||
|
||||
u32 currentMeshBufferIndex = 0;
|
||||
// Tris
|
||||
for (u32 i = 0; i < numBeshBuffers; i++)
|
||||
{
|
||||
const IMeshBuffer * const mb = mesh->getMeshBuffer(i);
|
||||
write(file, "TRIS", 4);
|
||||
const u32 trisize = 4 + mb->getIndexCount() * 4;
|
||||
write(file, &trisize, 4);
|
||||
|
||||
u32 tricheck = Size;
|
||||
|
||||
write(file, &i, 4);
|
||||
|
||||
u32 numIndices = mb->getIndexCount();
|
||||
const u16 * const idx = (u16 *) mb->getIndices();
|
||||
for (u32 j = 0; j < numIndices; j += 3)
|
||||
{
|
||||
u32 tmp = idx[j] + currentMeshBufferIndex;
|
||||
write(file, &tmp, sizeof(u32));
|
||||
|
||||
tmp = idx[j + 1] + currentMeshBufferIndex;
|
||||
write(file, &tmp, sizeof(u32));
|
||||
|
||||
tmp = idx[j + 2] + currentMeshBufferIndex;
|
||||
write(file, &tmp, sizeof(u32));
|
||||
}
|
||||
|
||||
// Check that tris calculation was ok
|
||||
tricheck = Size - tricheck;
|
||||
if (tricheck != trisize)
|
||||
{
|
||||
printf("Failed in tris size calculation, size %u advanced %u\n",
|
||||
trisize, tricheck);
|
||||
}
|
||||
|
||||
currentMeshBufferIndex += mb->getVertexCount();
|
||||
}
|
||||
|
||||
if(ISkinnedMesh *skinnedMesh = getSkinned(mesh))
|
||||
{
|
||||
// Write animation data
|
||||
if (!skinnedMesh->isStatic())
|
||||
{
|
||||
write(file, "ANIM", 4);
|
||||
|
||||
const u32 animsize = 12;
|
||||
write(file, &animsize, 4);
|
||||
|
||||
const u32 flags = 0;
|
||||
const u32 frames = skinnedMesh->getFrameCount();
|
||||
const f32 fps = skinnedMesh->getAnimationSpeed();
|
||||
|
||||
write(file, &flags, 4);
|
||||
write(file, &frames, 4);
|
||||
write(file, &fps, 4);
|
||||
}
|
||||
|
||||
// Write joints
|
||||
core::array<ISkinnedMesh::SJoint*> rootJoints = getRootJoints(skinnedMesh);
|
||||
|
||||
for (u32 i = 0; i < rootJoints.size(); i++)
|
||||
{
|
||||
writeJointChunk(file, skinnedMesh, rootJoints[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that node calculation was ok
|
||||
nodecheck = Size - nodecheck;
|
||||
if (nodecheck != nodesize)
|
||||
{
|
||||
printf("Failed in node size calculation, size %u advanced %u\n",
|
||||
nodesize, nodecheck);
|
||||
}
|
||||
file->seek(4);
|
||||
file->write(&Size, 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CB3DMeshWriter::writeJointChunk(io::IWriteFile* file, ISkinnedMesh* mesh , ISkinnedMesh::SJoint* joint)
|
||||
{
|
||||
// Node
|
||||
write(file, "NODE", 4);
|
||||
|
||||
// Calculate node size
|
||||
u32 nodesize = getJointChunkSize(mesh, joint);
|
||||
nodesize -= 8; // The declaration + size of THIS chunk shouldn't be added to the size
|
||||
|
||||
write(file, &nodesize, 4);
|
||||
|
||||
|
||||
core::stringc name = joint->Name;
|
||||
write(file, name.c_str(), name.size());
|
||||
write(file, "", 1);
|
||||
|
||||
core::vector3df pos = joint->Animatedposition;
|
||||
// Position
|
||||
write(file, &pos.X, 4);
|
||||
write(file, &pos.Y, 4);
|
||||
write(file, &pos.Z, 4);
|
||||
|
||||
// Scale
|
||||
core::vector3df scale = joint->Animatedscale;
|
||||
if (scale == core::vector3df(0, 0, 0))
|
||||
scale = core::vector3df(1, 1, 1);
|
||||
|
||||
write(file, &scale.X, 4);
|
||||
write(file, &scale.Y, 4);
|
||||
write(file, &scale.Z, 4);
|
||||
|
||||
// Rotation
|
||||
core::quaternion quat = joint->Animatedrotation;
|
||||
write(file, &quat.W, 4);
|
||||
write(file, &quat.X, 4);
|
||||
write(file, &quat.Y, 4);
|
||||
write(file, &quat.Z, 4);
|
||||
|
||||
// Bone
|
||||
write(file, "BONE", 4);
|
||||
u32 bonesize = 8 * joint->Weights.size();
|
||||
write(file, &bonesize, 4);
|
||||
|
||||
// Skinning ------------------
|
||||
for (u32 i = 0; i < joint->Weights.size(); i++)
|
||||
{
|
||||
const u32 vertexID = joint->Weights[i].vertex_id;
|
||||
const u32 bufferID = joint->Weights[i].buffer_id;
|
||||
const f32 weight = joint->Weights[i].strength;
|
||||
|
||||
u32 b3dVertexID = vertexID;
|
||||
for (u32 j = 0; j < bufferID; j++)
|
||||
{
|
||||
b3dVertexID += mesh->getMeshBuffer(j)->getVertexCount();
|
||||
}
|
||||
|
||||
write(file, &b3dVertexID, 4);
|
||||
write(file, &weight, 4);
|
||||
}
|
||||
// ---------------------------
|
||||
|
||||
// Animation keys
|
||||
if (joint->PositionKeys.size())
|
||||
{
|
||||
write(file, "KEYS", 4);
|
||||
u32 keysSize = 4 * joint->PositionKeys.size() * 4; // X, Y and Z pos + frame
|
||||
keysSize += 4; // Flag to define the type of the key
|
||||
write(file, &keysSize, 4);
|
||||
|
||||
u32 flag = 1; // 1 = flag for position keys
|
||||
write(file, &flag, 4);
|
||||
|
||||
for (u32 i = 0; i < joint->PositionKeys.size(); i++)
|
||||
{
|
||||
const s32 frame = static_cast<s32>(joint->PositionKeys[i].frame);
|
||||
const core::vector3df pos = joint->PositionKeys[i].position;
|
||||
|
||||
write (file, &frame, 4);
|
||||
|
||||
write (file, &pos.X, 4);
|
||||
write (file, &pos.Y, 4);
|
||||
write (file, &pos.Z, 4);
|
||||
|
||||
}
|
||||
}
|
||||
if (joint->RotationKeys.size())
|
||||
{
|
||||
write(file, "KEYS", 4);
|
||||
u32 keysSize = 4 * joint->RotationKeys.size() * 5; // W, X, Y and Z rot + frame
|
||||
keysSize += 4; // Flag
|
||||
write(file, &keysSize, 4);
|
||||
|
||||
u32 flag = 4;
|
||||
write(file, &flag, 4);
|
||||
|
||||
for (u32 i = 0; i < joint->RotationKeys.size(); i++)
|
||||
{
|
||||
const s32 frame = static_cast<s32>(joint->RotationKeys[i].frame);
|
||||
const core::quaternion rot = joint->RotationKeys[i].rotation;
|
||||
|
||||
write (file, &frame, 4);
|
||||
|
||||
write (file, &rot.W, 4);
|
||||
write (file, &rot.X, 4);
|
||||
write (file, &rot.Y, 4);
|
||||
write (file, &rot.Z, 4);
|
||||
}
|
||||
}
|
||||
if (joint->ScaleKeys.size())
|
||||
{
|
||||
write(file, "KEYS", 4);
|
||||
u32 keysSize = 4 * joint->ScaleKeys.size() * 4; // X, Y and Z scale + frame
|
||||
keysSize += 4; // Flag
|
||||
write(file, &keysSize, 4);
|
||||
|
||||
u32 flag = 2;
|
||||
write(file, &flag, 4);
|
||||
|
||||
for (u32 i = 0; i < joint->ScaleKeys.size(); i++)
|
||||
{
|
||||
const s32 frame = static_cast<s32>(joint->ScaleKeys[i].frame);
|
||||
const core::vector3df scale = joint->ScaleKeys[i].scale;
|
||||
|
||||
write (file, &frame, 4);
|
||||
|
||||
write (file, &scale.X, 4);
|
||||
write (file, &scale.Y, 4);
|
||||
write (file, &scale.Z, 4);
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < joint->Children.size(); i++)
|
||||
{
|
||||
writeJointChunk(file, mesh, joint->Children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ISkinnedMesh* CB3DMeshWriter::getSkinned (IMesh *mesh)
|
||||
{
|
||||
if (mesh->getMeshType() == EAMT_SKINNED)
|
||||
{
|
||||
return static_cast<ISkinnedMesh*>(mesh);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 CB3DMeshWriter::getJointChunkSize(const ISkinnedMesh* mesh, ISkinnedMesh::SJoint* joint)
|
||||
{
|
||||
u32 chunkSize = 8 + 40; // Chunk declaration + chunk data
|
||||
chunkSize += joint->Name.size() + 1; // the NULL character at the end of the string
|
||||
|
||||
u32 boneSize = joint->Weights.size() * 8; // vertex_id + weight = 8 bits per weight block
|
||||
boneSize += 8; // declaration + size of he BONE chunk
|
||||
|
||||
u32 keysSize = 0;
|
||||
if (joint->PositionKeys.size() != 0)
|
||||
{
|
||||
keysSize += 8; // KEYS + chunk size
|
||||
keysSize += 4; // flags
|
||||
|
||||
keysSize += (joint->PositionKeys.size() * 16);
|
||||
}
|
||||
if (joint->RotationKeys.size() != 0)
|
||||
{
|
||||
keysSize += 8; // KEYS + chunk size
|
||||
keysSize += 4; // flags
|
||||
|
||||
keysSize += (joint->RotationKeys.size() * 20);
|
||||
}
|
||||
if (joint->ScaleKeys.size() != 0)
|
||||
{
|
||||
keysSize += 8; // KEYS + chunk size
|
||||
keysSize += 4; // flags
|
||||
|
||||
keysSize += (joint->ScaleKeys.size() * 16);
|
||||
}
|
||||
|
||||
chunkSize += boneSize;
|
||||
chunkSize += keysSize;
|
||||
|
||||
for (u32 i = 0; i < joint->Children.size(); ++i)
|
||||
{
|
||||
chunkSize += (getJointChunkSize(mesh, joint->Children[i]));
|
||||
}
|
||||
return chunkSize;
|
||||
}
|
||||
|
||||
core::array<ISkinnedMesh::SJoint*> CB3DMeshWriter::getRootJoints(const ISkinnedMesh* mesh)
|
||||
{
|
||||
core::array<ISkinnedMesh::SJoint*> roots;
|
||||
|
||||
core::array<ISkinnedMesh::SJoint*> allJoints = mesh->getAllJoints();
|
||||
for (u32 i = 0; i < allJoints.size(); i++)
|
||||
{
|
||||
bool isRoot = true;
|
||||
ISkinnedMesh::SJoint* testedJoint = allJoints[i];
|
||||
for (u32 j = 0; j < allJoints.size(); j++)
|
||||
{
|
||||
ISkinnedMesh::SJoint* testedJoint2 = allJoints[j];
|
||||
for (u32 k = 0; k < testedJoint2->Children.size(); k++)
|
||||
{
|
||||
if (testedJoint == testedJoint2->Children[k])
|
||||
isRoot = false;
|
||||
}
|
||||
}
|
||||
if (isRoot)
|
||||
roots.push_back(testedJoint);
|
||||
}
|
||||
|
||||
return roots;
|
||||
}
|
||||
|
||||
u32 CB3DMeshWriter::getUVlayerCount(IMesh* mesh)
|
||||
{
|
||||
const u32 numBeshBuffers = mesh->getMeshBufferCount();
|
||||
for (u32 i = 0; i < numBeshBuffers; i++)
|
||||
{
|
||||
const IMeshBuffer * const mb = mesh->getMeshBuffer(i);
|
||||
|
||||
if (mb->getVertexType() == EVT_2TCOORDS)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CB3DMeshWriter::write(io::IWriteFile* file, const void *ptr, const u32 bytes)
|
||||
{
|
||||
file->write(ptr, bytes);
|
||||
Size += bytes;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_B3D_WRITER_
|
||||
|
52
source/Irrlicht/CB3DMeshWriter.h
Normal file
52
source/Irrlicht/CB3DMeshWriter.h
Normal file
@ -0,0 +1,52 @@
|
||||
// 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
|
||||
|
||||
#ifndef __IRR_B3D_MESH_WRITER_H_INCLUDED__
|
||||
#define __IRR_B3D_MESH_WRITER_H_INCLUDED__
|
||||
|
||||
#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
|
||||
virtual EMESH_WRITER_TYPE getType() const _IRR_OVERRIDE_;
|
||||
|
||||
//! writes a mesh
|
||||
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
u32 Size;
|
||||
|
||||
void writeJointChunk(io::IWriteFile* file, ISkinnedMesh* mesh , ISkinnedMesh::SJoint* joint);
|
||||
u32 getJointChunkSize(const ISkinnedMesh* mesh, ISkinnedMesh::SJoint* joint);
|
||||
core::array<ISkinnedMesh::SJoint*> getRootJoints(const ISkinnedMesh* mesh);
|
||||
|
||||
u32 getUVlayerCount(IMesh *mesh);
|
||||
ISkinnedMesh* getSkinned (IMesh *mesh);
|
||||
|
||||
void write(io::IWriteFile* file, const void *ptr, const u32 bytes);
|
||||
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
107
source/Irrlicht/CBSPMeshFileLoader.cpp
Normal file
107
source/Irrlicht/CBSPMeshFileLoader.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
|
||||
|
||||
#include "CBSPMeshFileLoader.h"
|
||||
#include "CQ3LevelMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Constructor
|
||||
CBSPMeshFileLoader::CBSPMeshFileLoader(scene::ISceneManager* smgr,
|
||||
io::IFileSystem* fs)
|
||||
: FileSystem(fs), SceneManager(smgr)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBSPMeshFileLoader");
|
||||
#endif
|
||||
|
||||
if (FileSystem)
|
||||
FileSystem->grab();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CBSPMeshFileLoader::~CBSPMeshFileLoader()
|
||||
{
|
||||
if (FileSystem)
|
||||
FileSystem->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
bool CBSPMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "bsp", "shader", "cfg" );
|
||||
}
|
||||
|
||||
|
||||
//! 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* CBSPMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
s32 type = core::isFileExtension ( file->getFileName(), "bsp", "shader", "cfg" );
|
||||
CQ3LevelMesh* q = 0;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case 1:
|
||||
q = new CQ3LevelMesh(FileSystem, SceneManager, LoadParam);
|
||||
|
||||
// determine real shaders in LoadParam
|
||||
if ( 0 == LoadParam.loadAllShaders )
|
||||
{
|
||||
q->getShader("scripts/common.shader");
|
||||
q->getShader("scripts/sfx.shader");
|
||||
q->getShader("scripts/gfx.shader");
|
||||
q->getShader("scripts/liquid.shader");
|
||||
q->getShader("scripts/models.shader");
|
||||
q->getShader("scripts/walls.shader");
|
||||
//q->getShader("scripts/sky.shader");
|
||||
}
|
||||
|
||||
if ( q->loadFile(file) )
|
||||
return q;
|
||||
|
||||
q->drop();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam);
|
||||
q->getShader( file );
|
||||
return q;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// load quake 3 loading parameter
|
||||
if ( file->getFileName() == "levelparameter.cfg" )
|
||||
{
|
||||
file->read ( &LoadParam, sizeof ( LoadParam ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam);
|
||||
q->getConfiguration( file );
|
||||
return q;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_BSP_LOADER_
|
||||
|
52
source/Irrlicht/CBSPMeshFileLoader.h
Normal file
52
source/Irrlicht/CBSPMeshFileLoader.h
Normal file
@ -0,0 +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
|
||||
|
||||
#ifndef __C_BSP_MESH_FILE_LOADER_H_INCLUDED__
|
||||
#define __C_BSP_MESH_FILE_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IQ3Shader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Meshloader capable of loading Quake 3 BSP files and shaders
|
||||
class CBSPMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CBSPMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
|
||||
|
||||
//! destructor
|
||||
virtual ~CBSPMeshFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_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.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
io::IFileSystem* FileSystem;
|
||||
scene::ISceneManager* SceneManager;
|
||||
|
||||
quake3::Q3LevelLoadParameter LoadParam;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
321
source/Irrlicht/CBillboardSceneNode.cpp
Normal file
321
source/Irrlicht/CBillboardSceneNode.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_BILLBOARD_SCENENODE_
|
||||
#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.
|
||||
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 avg = (Size.Width + Size.Height)/6;
|
||||
BBoxSafe.MinEdge.set(-avg,-avg,-avg);
|
||||
BBoxSafe.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
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 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6;
|
||||
BBoxSafe.MinEdge.set(-avg,-avg,-avg);
|
||||
BBoxSafe.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IBillboardSceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addFloat("Width", Size.Width);
|
||||
out->addFloat("TopEdgeWidth", TopEdgeWidth);
|
||||
out->addFloat("Height", Size.Height);
|
||||
out->addColor("Shade_Top", Buffer->Vertices[1].Color);
|
||||
out->addColor("Shade_Down", Buffer->Vertices[0].Color);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
IBillboardSceneNode::deserializeAttributes(in, options);
|
||||
|
||||
Size.Width = in->getAttributeAsFloat("Width");
|
||||
Size.Height = in->getAttributeAsFloat("Height");
|
||||
|
||||
if (in->existsAttribute("TopEdgeWidth"))
|
||||
{
|
||||
TopEdgeWidth = in->getAttributeAsFloat("TopEdgeWidth");
|
||||
if (Size.Width != TopEdgeWidth)
|
||||
setSize(Size.Height, Size.Width, TopEdgeWidth);
|
||||
}
|
||||
else
|
||||
setSize(Size);
|
||||
Buffer->Vertices[1].Color = in->getAttributeAsColor("Shade_Top");
|
||||
Buffer->Vertices[0].Color = in->getAttributeAsColor("Shade_Down");
|
||||
Buffer->Vertices[2].Color = Buffer->Vertices[1].Color;
|
||||
Buffer->Vertices[3].Color = Buffer->Vertices[0].Color;
|
||||
}
|
||||
|
||||
|
||||
//! 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
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_BILLBOARD_SCENENODE_
|
112
source/Irrlicht/CBillboardSceneNode.h
Normal file
112
source/Irrlicht/CBillboardSceneNode.h
Normal file
@ -0,0 +1,112 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#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
|
||||
virtual void OnRegisterSceneNode() _IRR_OVERRIDE_;
|
||||
|
||||
//! render
|
||||
virtual void render() _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
|
||||
//! sets the size of the billboard
|
||||
virtual void setSize(const core::dimension2d<f32>& size) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the widths of the top and bottom edges of the billboard independently.
|
||||
virtual void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth) _IRR_OVERRIDE_;
|
||||
|
||||
//! gets the size of the billboard
|
||||
virtual const core::dimension2d<f32>& getSize() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
virtual void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const _IRR_OVERRIDE_;
|
||||
|
||||
virtual video::SMaterial& getMaterial(u32 i) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
virtual void setColor(const video::SColor& overallColor) _IRR_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) _IRR_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 _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the real boundingbox used by the billboard (which depends on the active camera)
|
||||
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_BILLBOARD; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) _IRR_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
|
||||
|
||||
#endif
|
||||
|
1422
source/Irrlicht/CBlit.h
Normal file
1422
source/Irrlicht/CBlit.h
Normal file
File diff suppressed because it is too large
Load Diff
129
source/Irrlicht/CBoneSceneNode.cpp
Normal file
129
source/Irrlicht/CBoneSceneNode.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
|
||||
#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)
|
||||
{
|
||||
// animate this node with all animators
|
||||
|
||||
ISceneNodeAnimatorList::Iterator ait = Animators.begin();
|
||||
for (; ait != Animators.end(); ++ait)
|
||||
(*ait)->animateNode(this, timeMs);
|
||||
|
||||
// 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::ConstIterator it = Node->getChildren().begin();
|
||||
for (; it != Node->getChildren().end(); ++it)
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( (*it) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( this );
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IBoneSceneNode::serializeAttributes(out, options);
|
||||
out->addInt("BoneIndex", BoneIndex);
|
||||
out->addEnum("AnimationMode", AnimationMode, BoneAnimationModeNames);
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
BoneIndex = in->getAttributeAsInt("BoneIndex");
|
||||
AnimationMode = (E_BONE_ANIMATION_MODE)in->getAttributeAsEnumeration("AnimationMode", BoneAnimationModeNames);
|
||||
// for legacy files (before 1.5)
|
||||
const core::stringc boneName = in->getAttributeAsString("BoneName");
|
||||
setName(boneName);
|
||||
IBoneSceneNode::deserializeAttributes(in, options);
|
||||
// TODO: add/replace bone in parent with bone from mesh
|
||||
}
|
||||
|
||||
|
||||
} // namespace scene
|
||||
} // namespace irr
|
||||
|
||||
#endif
|
||||
|
79
source/Irrlicht/CBoneSceneNode.h
Normal file
79
source/Irrlicht/CBoneSceneNode.h
Normal file
@ -0,0 +1,79 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
// 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
|
||||
virtual u32 getBoneIndex() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the animation mode of the bone. Returns true if successful.
|
||||
virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the current animation mode of the bone
|
||||
virtual E_BONE_ANIMATION_MODE getAnimationMode() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
//virtual core::matrix4 getRelativeTransformation() const _IRR_OVERRIDE_;
|
||||
*/
|
||||
|
||||
virtual void OnAnimate(u32 timeMs) _IRR_OVERRIDE_;
|
||||
|
||||
virtual void updateAbsolutePositionOfAllChildren() _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! How the relative transformation of the bone is used
|
||||
virtual void setSkinningSpace(E_BONE_SKINNING_SPACE space) _IRR_OVERRIDE_
|
||||
{
|
||||
SkinningSpace=space;
|
||||
}
|
||||
|
||||
virtual E_BONE_SKINNING_SPACE getSkinningSpace() const _IRR_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
|
||||
|
||||
#endif
|
||||
|
1141
source/Irrlicht/CBurningShader_Raster_Reference.cpp
Normal file
1141
source/Irrlicht/CBurningShader_Raster_Reference.cpp
Normal file
File diff suppressed because it is too large
Load Diff
859
source/Irrlicht/CCSMLoader.cpp
Normal file
859
source/Irrlicht/CCSMLoader.cpp
Normal file
@ -0,0 +1,859 @@
|
||||
// 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 written by Saurav Mohapatra and modified by Nikolaus Gebhardt.
|
||||
// See CCSMLoader.h for details.
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
|
||||
|
||||
#include "CCSMLoader.h"
|
||||
#include "CMeshTextureLoader.h"
|
||||
#include "os.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IReadFile.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IAttributes.h"
|
||||
#include "SMesh.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "SAnimatedMesh.h"
|
||||
#include "SMeshBufferLightMap.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _IRR_DEBUG_CSM_LOADER_
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
//
|
||||
// the CSM data types
|
||||
//
|
||||
struct color_rgb_t
|
||||
{
|
||||
s32 red;
|
||||
s32 green;
|
||||
s32 blue;
|
||||
|
||||
color_rgb_t() : red(0), green(0), blue(0) {}
|
||||
void clear() { red=0; green=0; blue=0; }
|
||||
video::SColor toSColor() const { return video::SColor(255, red, green, blue); }
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// A Binary File Reader
|
||||
//
|
||||
struct BinaryFileReader
|
||||
{
|
||||
BinaryFileReader(io::IReadFile* pFile) : file(pFile) { }
|
||||
|
||||
size_t readBuffer(void* buffer, s32 len)
|
||||
{
|
||||
return file->read(buffer,len);
|
||||
}
|
||||
|
||||
s32 readLong();
|
||||
f32 readFloat();
|
||||
|
||||
void readString(core::stringc &str);
|
||||
void readVec3f(core::vector3df* v);
|
||||
void readVec2f(core::vector2df* v);
|
||||
void readColorRGB(color_rgb_t* color);
|
||||
|
||||
io::IReadFile *file;
|
||||
};
|
||||
|
||||
//
|
||||
// The file header
|
||||
//
|
||||
class Header
|
||||
{
|
||||
public:
|
||||
|
||||
enum E_CSM_VERSION
|
||||
{
|
||||
VERSION_4 = 4,
|
||||
VERSION_4_1 = 5
|
||||
};
|
||||
|
||||
Header(){ clear(); }
|
||||
|
||||
s32 getVersion() const { return version; }
|
||||
void clear(){ version = 0; }
|
||||
void load(BinaryFileReader* pReader)
|
||||
{
|
||||
version = pReader->readLong();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
s32 version;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// The groups
|
||||
//
|
||||
class Group
|
||||
{
|
||||
public:
|
||||
|
||||
Group(){ clear(); }
|
||||
~Group(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
s32 getFlags() const { return flags; }
|
||||
s32 getParentGroupID() const { return parentGroup; }
|
||||
const core::stringc& getProperties() const { return props; }
|
||||
video::SColor getColor() const { return color.toSColor(); }
|
||||
|
||||
private:
|
||||
|
||||
s32 flags;
|
||||
s32 parentGroup;
|
||||
core::stringc props;
|
||||
color_rgb_t color;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// The visgroups
|
||||
//
|
||||
class VisGroup
|
||||
{
|
||||
public:
|
||||
|
||||
VisGroup(){ clear(); }
|
||||
~VisGroup(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
s32 getFlags() const{ return flags; }
|
||||
const core::stringc& getName() const{ return name; }
|
||||
video::SColor getColor() const{ return color.toSColor(); }
|
||||
|
||||
private:
|
||||
|
||||
core::stringc name;
|
||||
s32 flags;
|
||||
color_rgb_t color;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Lightmaps
|
||||
//
|
||||
class LightMap
|
||||
{
|
||||
public:
|
||||
|
||||
LightMap() : pixelData(0){ clear(); }
|
||||
~LightMap(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
s32 getWidth() const{ return width; }
|
||||
s32 getHeight() const{ return height; }
|
||||
s32* getPixelData() const{ return pixelData; }
|
||||
|
||||
private:
|
||||
|
||||
s32 width;
|
||||
s32 height;
|
||||
s32* pixelData;
|
||||
};
|
||||
|
||||
struct Triangle
|
||||
{
|
||||
s32 a,b,c;
|
||||
};
|
||||
|
||||
|
||||
struct Line
|
||||
{
|
||||
s32 a,b;
|
||||
};
|
||||
|
||||
|
||||
class Vertex
|
||||
{
|
||||
public:
|
||||
|
||||
Vertex(){ clear(); }
|
||||
~Vertex(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
const core::vector3df& getPosition() const { return position; }
|
||||
const core::vector3df& getNormal() const { return normal; }
|
||||
video::SColor getColor() const { return color.toSColor(); }
|
||||
const core::vector3df& getTextureCoordinates() const { return texCoords; }
|
||||
const core::vector3df& getLightMapCoordinates() const { return lmapCoords; }
|
||||
|
||||
private:
|
||||
|
||||
core::vector3df position;
|
||||
core::vector3df normal;
|
||||
color_rgb_t color;
|
||||
core::vector3df texCoords;
|
||||
core::vector3df lmapCoords;
|
||||
};
|
||||
|
||||
|
||||
class Surface
|
||||
{
|
||||
public:
|
||||
|
||||
Surface() { clear(); }
|
||||
~Surface(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader *pReader);
|
||||
|
||||
s32 getFlags() const{ return flags; }
|
||||
const core::stringc& getTextureName() const{ return textureName; }
|
||||
s32 getLightMapId() const{ return lightMapId; }
|
||||
const core::vector2df* getUVOffset() const{ return &uvOffset; }
|
||||
const core::vector2df* getUVScale() const{ return &uvScale; }
|
||||
f32 getUVRotation() const{ return uvRotation; }
|
||||
|
||||
u32 getVertexCount() const{ return vertices.size(); }
|
||||
const Vertex& getVertexAt(const s32 index) const{ return vertices[index]; }
|
||||
|
||||
u32 getTriangleCount() const{ return triangles.size(); }
|
||||
const Triangle& getTriangleAt(const s32 index) const{ return triangles[index]; }
|
||||
|
||||
private:
|
||||
|
||||
s32 flags;
|
||||
core::stringc textureName;
|
||||
s32 lightMapId;
|
||||
core::vector2df uvOffset;
|
||||
core::vector2df uvScale;
|
||||
f32 uvRotation;
|
||||
core::array<Vertex> vertices;
|
||||
core::array<Triangle> triangles;
|
||||
core::array<Line> lines;
|
||||
};
|
||||
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
|
||||
Mesh(){ clear(); }
|
||||
~Mesh(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader, bool bReadVisGroups);
|
||||
|
||||
s32 getFlags() const { return flags; }
|
||||
s32 getGroupID() const { return groupId; }
|
||||
const core::stringc& getProperties() const { return props; }
|
||||
video::SColor getColor() const { return color.toSColor(); }
|
||||
const core::vector3df* getPosition() const { return &position; }
|
||||
s32 getVisgroupID() const { return visgroupId; }
|
||||
s32 getSurfaceCount() const { return surfaces.size(); }
|
||||
const Surface* getSurfaceAt(const s32 index) const { return surfaces[index]; }
|
||||
|
||||
private:
|
||||
|
||||
s32 flags;
|
||||
s32 groupId;
|
||||
core::stringc props;
|
||||
color_rgb_t color;
|
||||
core::vector3df position;
|
||||
s32 visgroupId;
|
||||
|
||||
core::array<Surface*> surfaces;
|
||||
};
|
||||
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
|
||||
Entity() { clear(); }
|
||||
~Entity() { clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
s32 getVisgroupID() const { return visgroupId; }
|
||||
s32 getGroupID() const { return groupId; }
|
||||
const core::stringc& getProperties() const { return props; }
|
||||
const core::vector3df* getPosition() const { return &position; }
|
||||
|
||||
private:
|
||||
|
||||
s32 visgroupId;
|
||||
s32 groupId;
|
||||
core::stringc props;
|
||||
core::vector3df position;
|
||||
};
|
||||
|
||||
|
||||
class CameraData
|
||||
{
|
||||
public:
|
||||
|
||||
CameraData(){ clear(); }
|
||||
~CameraData(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
const core::vector3df* getPosition(){ return &position; }
|
||||
f32 getPitch(){ return pitch; }
|
||||
f32 getYaw(){ return yaw; }
|
||||
|
||||
private:
|
||||
|
||||
core::vector3df position;
|
||||
f32 pitch;
|
||||
f32 yaw;
|
||||
};
|
||||
|
||||
//
|
||||
// A CSM File
|
||||
//
|
||||
class CSMFile
|
||||
{
|
||||
public:
|
||||
|
||||
CSMFile(){ clear(); }
|
||||
~CSMFile(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
const Header* getHeader() const{ return &header; }
|
||||
|
||||
u32 getGroupCount() const{ return groups.size(); }
|
||||
const Group* getGroupAt(const s32 index) const{ return groups[index]; }
|
||||
|
||||
u32 getVisGroupCount() const{ return visgroups.size(); }
|
||||
const VisGroup* getVisGroupAt(const s32 index) const{ return visgroups[index]; }
|
||||
|
||||
u32 getLightMapCount() const{ return lightmaps.size(); }
|
||||
const LightMap* getLightMapAt(const s32 index) const { return lightmaps[index]; }
|
||||
|
||||
u32 getMeshCount() const{ return meshes.size(); }
|
||||
const Mesh* getMeshAt(const s32 index) const{ return meshes[index]; }
|
||||
|
||||
u32 getEntityCount() const{ return entities.size(); }
|
||||
const Entity* getEntityAt(const s32 index) const{ return entities[index]; }
|
||||
|
||||
const CameraData* getCameraData() const{ return &cameraData; }
|
||||
|
||||
private:
|
||||
|
||||
Header header;
|
||||
core::array<Group*> groups;
|
||||
core::array<VisGroup*> visgroups;
|
||||
core::array<LightMap*> lightmaps;
|
||||
core::array<Mesh*> meshes;
|
||||
core::array<Entity*> entities;
|
||||
CameraData cameraData;
|
||||
};
|
||||
|
||||
CCSMLoader::CCSMLoader(scene::ISceneManager* manager, io::IFileSystem* fs)
|
||||
: FileSystem(fs), SceneManager(manager)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCSMLoader");
|
||||
#endif
|
||||
|
||||
TextureLoader = new CMeshTextureLoader( FileSystem, SceneManager->getVideoDriver() );
|
||||
}
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
bool CCSMLoader::isALoadableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "csm" );
|
||||
}
|
||||
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
IAnimatedMesh* CCSMLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
if ( getMeshTextureLoader() )
|
||||
getMeshTextureLoader()->setMeshFile(file);
|
||||
|
||||
scene::IMesh* m = createCSMMesh(file);
|
||||
|
||||
if (!m)
|
||||
return 0;
|
||||
|
||||
SAnimatedMesh* am = new SAnimatedMesh();
|
||||
am->Type = EAMT_CSM;
|
||||
am->addMesh(m);
|
||||
m->drop();
|
||||
|
||||
am->recalculateBoundingBox();
|
||||
return am;
|
||||
}
|
||||
|
||||
scene::IMesh* CCSMLoader::createCSMMesh(io::IReadFile* file)
|
||||
{
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
BinaryFileReader reader(file);
|
||||
CSMFile csmFile;
|
||||
csmFile.load(&reader);
|
||||
|
||||
return createIrrlichtMesh(&csmFile, file->getFileName());
|
||||
}
|
||||
|
||||
|
||||
scene::IMesh* CCSMLoader::createIrrlichtMesh(const CSMFile* csmFile, const io::path& lmprefix)
|
||||
{
|
||||
if ( getMeshTextureLoader() )
|
||||
{
|
||||
if ( SceneManager->getParameters()->existsAttribute(CSM_TEXTURE_PATH) )
|
||||
getMeshTextureLoader()->setTexturePath( SceneManager->getParameters()->getAttributeAsString(CSM_TEXTURE_PATH) );
|
||||
}
|
||||
|
||||
scene::SMesh *pMesh = new scene::SMesh();
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
|
||||
for(u32 l = 0; l<csmFile->getLightMapCount(); l++)
|
||||
{
|
||||
const LightMap* lmap = csmFile->getLightMapAt(l);
|
||||
|
||||
io::path lmapName = lmprefix;
|
||||
lmapName += "LMAP_";
|
||||
lmapName += io::path(l+1);
|
||||
os::Printer::log("CCSMLoader loading light map", lmapName.c_str());
|
||||
|
||||
video::IImage* lmapImg = driver->createImageFromData(
|
||||
video::ECF_A8R8G8B8,
|
||||
core::dimension2d<u32>(lmap->getWidth(),lmap->getHeight()),
|
||||
lmap->getPixelData());
|
||||
|
||||
driver->addTexture(lmapName.c_str(), lmapImg);
|
||||
lmapImg->drop();
|
||||
}
|
||||
|
||||
for(u32 m = 0; m<csmFile->getMeshCount(); m++)
|
||||
{
|
||||
const Mesh* mshPtr = csmFile->getMeshAt(m);
|
||||
|
||||
for(s32 s = 0; s < mshPtr->getSurfaceCount(); s++)
|
||||
{
|
||||
const Surface* surface = mshPtr->getSurfaceAt(s);
|
||||
|
||||
video::ITexture* texture = getMeshTextureLoader() ? getMeshTextureLoader()->getTexture(surface->getTextureName()) : NULL;
|
||||
|
||||
// same lightmap name as above where they are created
|
||||
io::path lmapName = lmprefix;
|
||||
lmapName += "LMAP_";
|
||||
lmapName += io::path(surface->getLightMapId());
|
||||
|
||||
scene::SMeshBufferLightMap *buffer = new scene::SMeshBufferLightMap();
|
||||
buffer->Material.setTexture(0, texture);
|
||||
if (surface->getLightMapId())
|
||||
{
|
||||
buffer->Material.setTexture(1, driver->getTexture(lmapName));
|
||||
buffer->Material.Lighting = false;
|
||||
buffer->Material.MaterialType = video::EMT_LIGHTMAP_ADD;
|
||||
}
|
||||
|
||||
buffer->Vertices.reallocate(surface->getVertexCount());
|
||||
for(u32 v = 0; v < surface->getVertexCount(); ++v)
|
||||
{
|
||||
const Vertex& vtxPtr = surface->getVertexAt(v);
|
||||
video::S3DVertex2TCoords vtx;
|
||||
vtx.Pos = vtxPtr.getPosition();
|
||||
vtx.Normal = vtxPtr.getPosition();
|
||||
vtx.Color=vtxPtr.getColor();
|
||||
vtx.TCoords.set(vtxPtr.getTextureCoordinates().X, 1.f-vtxPtr.getTextureCoordinates().Y);
|
||||
vtx.TCoords2.set(vtxPtr.getLightMapCoordinates().X, 1.f-vtxPtr.getLightMapCoordinates().Y);
|
||||
|
||||
buffer->Vertices.push_back(vtx);
|
||||
}
|
||||
|
||||
buffer->Indices.reallocate(surface->getTriangleCount()*3);
|
||||
for(u32 t = 0; t < surface->getTriangleCount(); ++t)
|
||||
{
|
||||
const Triangle& tri = surface->getTriangleAt(t);
|
||||
buffer->Indices.push_back(tri.c);
|
||||
buffer->Indices.push_back(tri.b);
|
||||
buffer->Indices.push_back(tri.a);
|
||||
}
|
||||
|
||||
buffer->recalculateBoundingBox();
|
||||
pMesh->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
}
|
||||
|
||||
pMesh->recalculateBoundingBox();
|
||||
return pMesh;
|
||||
}
|
||||
|
||||
void Group::clear()
|
||||
{
|
||||
color.clear();
|
||||
flags = 0;
|
||||
parentGroup = 0;
|
||||
props = "";
|
||||
}
|
||||
|
||||
void Group::load(BinaryFileReader* pReader)
|
||||
{
|
||||
flags = pReader->readLong();
|
||||
parentGroup = pReader->readLong();
|
||||
pReader->readString(props);
|
||||
pReader->readColorRGB(&color);
|
||||
}
|
||||
|
||||
void VisGroup::clear()
|
||||
{
|
||||
color.clear();
|
||||
flags = 0;
|
||||
name = "";
|
||||
}
|
||||
|
||||
void VisGroup::load(BinaryFileReader* pReader)
|
||||
{
|
||||
pReader->readString(name);
|
||||
flags = pReader->readLong();
|
||||
pReader->readColorRGB(&color);
|
||||
}
|
||||
|
||||
void LightMap::clear()
|
||||
{
|
||||
delete[] pixelData;
|
||||
pixelData = 0;
|
||||
width = height = 0;
|
||||
}
|
||||
|
||||
void LightMap::load(BinaryFileReader* pReader)
|
||||
{
|
||||
width = pReader->readLong();
|
||||
height = pReader->readLong();
|
||||
pixelData = new s32[width * height];
|
||||
pReader->readBuffer(pixelData, width * height * sizeof(s32));
|
||||
}
|
||||
|
||||
void Mesh::clear()
|
||||
{
|
||||
flags = 0;
|
||||
groupId = 0;
|
||||
visgroupId = 0;
|
||||
props = "";
|
||||
color.clear();
|
||||
position.set(0,0,0);
|
||||
|
||||
for(u32 s = 0; s < surfaces.size(); s++)
|
||||
{
|
||||
delete surfaces[s];
|
||||
}
|
||||
surfaces.clear();
|
||||
}
|
||||
|
||||
void Mesh::load(BinaryFileReader* pReader, bool bReadVisGroups)
|
||||
{
|
||||
flags = pReader->readLong();
|
||||
groupId = pReader->readLong();
|
||||
pReader->readString(props);
|
||||
pReader->readColorRGB(&color);
|
||||
pReader->readVec3f(&position);
|
||||
if(bReadVisGroups)
|
||||
visgroupId = pReader->readLong();
|
||||
else
|
||||
visgroupId = 0;
|
||||
|
||||
s32 count = pReader->readLong();
|
||||
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
Surface* surf = new Surface();
|
||||
surf->load(pReader);
|
||||
surfaces.push_back(surf);
|
||||
}
|
||||
}
|
||||
|
||||
void Surface::clear()
|
||||
{
|
||||
flags = 0;
|
||||
lightMapId = 0;
|
||||
textureName = "";
|
||||
uvOffset.set(0.0f,0.0f);
|
||||
uvScale.set(0.0f,0.0f);
|
||||
uvRotation = 0.0f;
|
||||
triangles.clear();
|
||||
lines.clear();
|
||||
vertices.clear();
|
||||
}
|
||||
|
||||
void Surface::load(BinaryFileReader* pReader)
|
||||
{
|
||||
flags = pReader->readLong();
|
||||
pReader->readString(textureName);
|
||||
textureName.replace('\\', '/');
|
||||
|
||||
lightMapId = pReader->readLong();
|
||||
pReader->readVec2f(&uvOffset);
|
||||
pReader->readVec2f(&uvScale);
|
||||
uvRotation = pReader->readFloat();
|
||||
s32 vtxCount = pReader->readLong();
|
||||
s32 triCount = pReader->readLong();
|
||||
s32 lineCount = pReader->readLong();
|
||||
|
||||
for(s32 v = 0; v < vtxCount; v++)
|
||||
{
|
||||
vertices.push_back(Vertex());
|
||||
vertices.getLast().load(pReader);
|
||||
}
|
||||
|
||||
for(s32 t = 0; t < triCount; t++)
|
||||
{
|
||||
Triangle tri;
|
||||
pReader->readBuffer(&tri, sizeof(tri));
|
||||
triangles.push_back(tri);
|
||||
}
|
||||
|
||||
for(s32 l = 0; l < lineCount; l++)
|
||||
{
|
||||
Line line;
|
||||
pReader->readBuffer(&line,sizeof(line));
|
||||
lines.push_back(line);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Vertex::clear()
|
||||
{
|
||||
position.set(0,0,0);
|
||||
normal.set(0,0,0);
|
||||
color.clear();
|
||||
texCoords.set(0,0,0);
|
||||
lmapCoords.set(0,0,0);
|
||||
}
|
||||
|
||||
void Vertex::load(BinaryFileReader* pReader)
|
||||
{
|
||||
pReader->readVec3f(&position);
|
||||
pReader->readVec3f(&normal);
|
||||
pReader->readColorRGB(&color);
|
||||
pReader->readVec3f(&texCoords);
|
||||
pReader->readVec3f(&lmapCoords);
|
||||
}
|
||||
|
||||
void Entity::clear()
|
||||
{
|
||||
visgroupId = groupId = 0;
|
||||
props = "";
|
||||
position.set(0,0,0);
|
||||
}
|
||||
|
||||
void Entity::load(BinaryFileReader* pReader)
|
||||
{
|
||||
visgroupId = pReader->readLong();
|
||||
groupId = pReader->readLong();
|
||||
pReader->readString(props);
|
||||
pReader->readVec3f(&position);
|
||||
}
|
||||
|
||||
void CameraData::clear()
|
||||
{
|
||||
position.set(0,0,0);
|
||||
pitch = 0;
|
||||
yaw = 0;
|
||||
}
|
||||
|
||||
void CameraData::load(BinaryFileReader* pReader)
|
||||
{
|
||||
pReader->readVec3f(&position);
|
||||
pitch = pReader->readFloat();
|
||||
yaw = pReader->readFloat();
|
||||
}
|
||||
|
||||
void CSMFile::clear()
|
||||
{
|
||||
header.clear();
|
||||
cameraData.clear();
|
||||
|
||||
u32 x =0;
|
||||
for( x= 0; x < groups.size(); x++)
|
||||
delete groups[x];
|
||||
|
||||
groups.clear();
|
||||
|
||||
for(x= 0; x < visgroups.size(); x++)
|
||||
delete visgroups[x];
|
||||
|
||||
visgroups.clear();
|
||||
|
||||
for(x= 0; x < lightmaps.size(); x++)
|
||||
delete lightmaps[x];
|
||||
|
||||
lightmaps.clear();
|
||||
|
||||
for(x= 0; x < meshes.size(); x++)
|
||||
delete meshes[x];
|
||||
|
||||
meshes.clear();
|
||||
|
||||
for(x= 0; x < entities.size(); x++)
|
||||
delete entities[x];
|
||||
|
||||
entities.clear();
|
||||
}
|
||||
|
||||
void CSMFile::load(BinaryFileReader* pReader)
|
||||
{
|
||||
clear();
|
||||
|
||||
header.load(pReader);
|
||||
|
||||
//groups
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("CSM Version", core::stringc(header.getVersion()).c_str());
|
||||
os::Printer::log("Loading groups. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
groups.reallocate(count);
|
||||
for (s32 i = 0; i < count; i++)
|
||||
{
|
||||
Group* grp = new Group();
|
||||
grp->load(pReader);
|
||||
groups.push_back(grp);
|
||||
}
|
||||
}
|
||||
const bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1);
|
||||
|
||||
if (bHasVGroups)
|
||||
{
|
||||
//visgroups
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading visgroups. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
visgroups.reallocate(count);
|
||||
for (s32 i = 0; i < count; i++)
|
||||
{
|
||||
VisGroup* grp = new VisGroup();
|
||||
grp->load(pReader);
|
||||
visgroups.push_back(grp);
|
||||
}
|
||||
}
|
||||
|
||||
//lightmaps
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading lightmaps. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
lightmaps.reallocate(count);
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
LightMap* lm = new LightMap();
|
||||
lm->load(pReader);
|
||||
lightmaps.push_back(lm);
|
||||
}
|
||||
}
|
||||
|
||||
//meshes
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading meshes. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
meshes.reallocate(count);
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
Mesh* mesh = new Mesh();
|
||||
mesh->load(pReader,bHasVGroups);
|
||||
meshes.push_back(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
//entities
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading entitites. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
entities.reallocate(count);
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
Entity* ent = new Entity();
|
||||
ent->load(pReader);
|
||||
entities.push_back(ent);
|
||||
}
|
||||
}
|
||||
|
||||
//camera data
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading camera data.");
|
||||
#endif
|
||||
cameraData.load(pReader);
|
||||
}
|
||||
|
||||
s32 BinaryFileReader::readLong()
|
||||
{
|
||||
int ret = 0;
|
||||
readBuffer(&ret,sizeof(int));
|
||||
#ifdef __BIG_ENDIAN__
|
||||
ret = os::Byteswap::byteswap(ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
f32 BinaryFileReader::readFloat()
|
||||
{
|
||||
float ret = 0;
|
||||
readBuffer(&ret,sizeof(float));
|
||||
#ifdef __BIG_ENDIAN__
|
||||
ret = os::Byteswap::byteswap(ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BinaryFileReader::readString(core::stringc &str)
|
||||
{
|
||||
str = "";
|
||||
c8 c;
|
||||
readBuffer(&c,sizeof(char));
|
||||
while(c != 0)
|
||||
{
|
||||
str += c;
|
||||
readBuffer(&c,sizeof(char));
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryFileReader::readVec3f(core::vector3df* v)
|
||||
{
|
||||
v->X = readFloat();
|
||||
v->Y = readFloat();
|
||||
v->Z = readFloat();
|
||||
}
|
||||
|
||||
void BinaryFileReader::readVec2f(core::vector2df* v)
|
||||
{
|
||||
v->X = readFloat();
|
||||
v->Y = readFloat();
|
||||
}
|
||||
|
||||
void BinaryFileReader::readColorRGB(color_rgb_t* color)
|
||||
{
|
||||
readBuffer(color,sizeof(color_rgb_t));
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_CSM_LOADER_
|
81
source/Irrlicht/CCSMLoader.h
Normal file
81
source/Irrlicht/CCSMLoader.h
Normal file
@ -0,0 +1,81 @@
|
||||
// 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 Loader has been originally written by Saurav Mohapatra. I (Nikolaus Gebhardt)
|
||||
// modified some minor things and integrated it into Irrlicht 0.9. Thanks a lot
|
||||
// to Saurav Mohapatra for his work on this and that he gave me his permission to
|
||||
// add it into Irrlicht.
|
||||
// I did some changes to Saurav Mohapatra's loader, so I'm writing this down here:
|
||||
// - Replaced all dependencies to STL and stdio with irr:: methods/constructs.
|
||||
// - Moved everything into namespace irr::scene
|
||||
// - Replaced logging with Irrlicht's internal logger.
|
||||
// - Removed dependency to IrrlichtDevice
|
||||
// - Moved all internal structures into CCSMLoader.cpp
|
||||
// - Made the texture root parameter dependent on a ISceneManager string parameter
|
||||
// - removed exceptions
|
||||
// - Implemented CCCSMLoader as IMeshLoader
|
||||
// - Fixed some problems with memory leaks
|
||||
// - Fixed bounding box calculation
|
||||
//
|
||||
// The original readme of this file looks like this:
|
||||
//
|
||||
// This component provides a loader for the Cartography shop 4.x .csm maps for Irrlicht Engine.
|
||||
// This is a part of the M_TRIX Project.
|
||||
// This is licensed under the ZLib/LibPNG license
|
||||
// The IrrCSM library is written by Saurav Mohapatra.
|
||||
//
|
||||
// Features
|
||||
//
|
||||
// The IrrCSM library features the following capabilities
|
||||
//
|
||||
// * Loads the .csm 4.0 and 4.1 files transparently
|
||||
// * Presents the loaded file as irr::scene::IAnimatedMesh for easy creation of IOctreeSceneNode
|
||||
// * Loads the textures given the correct texture root. hence map and textures can be in separate directories
|
||||
//
|
||||
// For more information go to http://www.geocities.com/standard_template/irrcsm/downloads.html
|
||||
|
||||
#ifndef __CSM_LOADER_H_INCLUDED__
|
||||
#define __CSM_LOADER_H_INCLUDED__
|
||||
|
||||
#include "irrArray.h"
|
||||
#include "IMesh.h"
|
||||
#include "irrString.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IMeshLoader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class CSMFile;
|
||||
class ISceneManager;
|
||||
|
||||
class CCSMLoader : public scene::IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
CCSMLoader(ISceneManager* manager, io::IFileSystem* fs);
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_OVERRIDE_;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
scene::IMesh* createCSMMesh(io::IReadFile* file);
|
||||
|
||||
scene::IMesh* createIrrlichtMesh(const CSMFile* csmFile, const io::path& lmprefix);
|
||||
|
||||
io::IFileSystem* FileSystem;
|
||||
scene::ISceneManager* SceneManager;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
401
source/Irrlicht/CCameraSceneNode.cpp
Normal file
401
source/Irrlicht/CCameraSceneNode.cpp
Normal file
@ -0,0 +1,401 @@
|
||||
// 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),
|
||||
HasD3DStyleProjectionMatrix(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCameraSceneNode");
|
||||
#endif
|
||||
|
||||
// set default projection
|
||||
Fovy = core::PI / 2.5f; // Field of view, in radians.
|
||||
|
||||
const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0;
|
||||
if (d)
|
||||
{
|
||||
Aspect = (f32)d->getCurrentRenderTargetSize().Width /
|
||||
(f32)d->getCurrentRenderTargetSize().Height;
|
||||
HasD3DStyleProjectionMatrix = d->getDriverType() != video::EDT_OPENGL;
|
||||
}
|
||||
else
|
||||
Aspect = 4.0f / 3.0f; // Aspect ratio.
|
||||
|
||||
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)
|
||||
{
|
||||
if (!InputReceiverEnabled)
|
||||
return false;
|
||||
|
||||
// send events to event receiving animators
|
||||
|
||||
ISceneNodeAnimatorList::Iterator ait = Animators.begin();
|
||||
|
||||
for (; ait != Animators.end(); ++ait)
|
||||
if ((*ait)->isEventReceiverEnabled() && (*ait)->OnEvent(event))
|
||||
return true;
|
||||
|
||||
// if nobody processed the event, return false
|
||||
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, HasD3DStyleProjectionMatrix);
|
||||
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
|
||||
{
|
||||
// NOTE: We deliberately don't return the boundingbox of the ViewArea. People can access that already.
|
||||
// We want to prevent cameras from having their bounding box colliding in the SceneCollisionManager.
|
||||
// If another boundingbox is ever necessary then please move BoundingBox to ICameraSceneNode and make it accessible (via a setter or an enum with options).
|
||||
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, HasD3DStyleProjectionMatrix);
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
ICameraSceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addVector3d("Target", Target);
|
||||
out->addVector3d("UpVector", UpVector);
|
||||
out->addFloat("Fovy", Fovy);
|
||||
out->addFloat("Aspect", Aspect);
|
||||
out->addFloat("ZNear", ZNear);
|
||||
out->addFloat("ZFar", ZFar);
|
||||
out->addBool("Binding", TargetAndRotationAreBound);
|
||||
out->addBool("ReceiveInput", InputReceiverEnabled);
|
||||
}
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
ICameraSceneNode::deserializeAttributes(in, options);
|
||||
|
||||
Target = in->getAttributeAsVector3d("Target");
|
||||
UpVector = in->getAttributeAsVector3d("UpVector");
|
||||
Fovy = in->getAttributeAsFloat("Fovy");
|
||||
Aspect = in->getAttributeAsFloat("Aspect");
|
||||
ZNear = in->getAttributeAsFloat("ZNear");
|
||||
ZFar = in->getAttributeAsFloat("ZFar");
|
||||
TargetAndRotationAreBound = in->getAttributeAsBool("Binding");
|
||||
if ( in->findAttribute("ReceiveInput") )
|
||||
InputReceiverEnabled = in->getAttributeAsBool("ReceiveInput");
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
recalculateViewArea();
|
||||
}
|
||||
|
||||
|
||||
//! 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
|
||||
|
179
source/Irrlicht/CCameraSceneNode.h
Normal file
179
source/Irrlicht/CCameraSceneNode.h
Normal file
@ -0,0 +1,179 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_CAMERA_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_CAMERA_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#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(). */
|
||||
virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the current projection matrix of the camera
|
||||
//! \return Returns the current projection matrix of the camera.
|
||||
virtual const core::matrix4& getProjectionMatrix() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the current view matrix of the camera
|
||||
//! \return Returns the current view matrix of the camera.
|
||||
virtual const core::matrix4& getViewMatrix() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a custom view matrix affector.
|
||||
/** \param affector: The affector matrix. */
|
||||
virtual void setViewMatrixAffector(const core::matrix4& affector) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the custom view matrix affector.
|
||||
virtual const core::matrix4& getViewMatrixAffector() const _IRR_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.
|
||||
virtual bool OnEvent(const SEvent& event) _IRR_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. */
|
||||
virtual void setTarget(const core::vector3df& pos) _IRR_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. */
|
||||
virtual void setRotation(const core::vector3df& rotation) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the current look at target of the camera
|
||||
/** \return The current look at target of the camera */
|
||||
virtual const core::vector3df& getTarget() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the up vector of the camera.
|
||||
//! \param pos: New upvector of the camera.
|
||||
virtual void setUpVector(const core::vector3df& pos) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the up vector of the camera.
|
||||
//! \return Returns the up vector of the camera.
|
||||
virtual const core::vector3df& getUpVector() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets distance from the camera to the near plane.
|
||||
//! \return Value of the near plane of the camera.
|
||||
virtual f32 getNearValue() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the distance from the camera to the far plane.
|
||||
//! \return Value of the far plane of the camera.
|
||||
virtual f32 getFarValue() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the aspect ratio of the camera.
|
||||
//! \return The aspect ratio of the camera.
|
||||
virtual f32 getAspectRatio() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the field of view of the camera.
|
||||
//! \return Field of view of the camera
|
||||
virtual f32 getFOV() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the value of the near clipping plane. (default: 1.0f)
|
||||
virtual void setNearValue(f32 zn) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the value of the far clipping plane (default: 2000.0f)
|
||||
virtual void setFarValue(f32 zf) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the aspect ratio (default: 4.0f / 3.0f)
|
||||
virtual void setAspectRatio(f32 aspect) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the field of view (Default: PI / 3.5f)
|
||||
virtual void setFOV(f32 fovy) _IRR_OVERRIDE_;
|
||||
|
||||
//! PreRender event
|
||||
virtual void OnRegisterSceneNode() _IRR_OVERRIDE_;
|
||||
|
||||
//! Render
|
||||
virtual void render() _IRR_OVERRIDE_;
|
||||
|
||||
//! Update
|
||||
virtual void updateMatrices() _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the view area.
|
||||
virtual const SViewFrustum* getViewFrustum() const _IRR_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.
|
||||
virtual void setInputReceiverEnabled(bool enabled) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if the input receiver of the camera is currently enabled.
|
||||
virtual bool isInputReceiverEnabled() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_CAMERA; }
|
||||
|
||||
//! Binds the camera scene node's rotation to its target position and vice versa, or unbinds them.
|
||||
virtual void bindTargetAndRotation(bool bound) _IRR_OVERRIDE_;
|
||||
|
||||
//! Queries if the camera scene node's rotation and its target position are bound together.
|
||||
virtual bool getTargetAndRotationBinding(void) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) _IRR_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;
|
||||
|
||||
bool HasD3DStyleProjectionMatrix; // true: projection from 0 to w; false: -w to w
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
3008
source/Irrlicht/CColladaFileLoader.cpp
Normal file
3008
source/Irrlicht/CColladaFileLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
410
source/Irrlicht/CColladaFileLoader.h
Normal file
410
source/Irrlicht/CColladaFileLoader.h
Normal file
@ -0,0 +1,410 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
|
||||
#define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "irrString.h"
|
||||
#include "SMesh.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrMap.h"
|
||||
#include "CAttributes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
//#define COLLADA_READER_DEBUG
|
||||
#endif
|
||||
|
||||
class IColladaPrefab;
|
||||
|
||||
enum ECOLLADA_PARAM_NAME
|
||||
{
|
||||
ECPN_COLOR = 0,
|
||||
ECPN_AMBIENT,
|
||||
ECPN_DIFFUSE,
|
||||
ECPN_SPECULAR,
|
||||
ECPN_SHININESS,
|
||||
ECPN_TRANSPARENCY,
|
||||
ECPN_YFOV,
|
||||
ECPN_ZNEAR,
|
||||
ECPN_ZFAR,
|
||||
|
||||
ECPN_COUNT
|
||||
};
|
||||
|
||||
enum ECOLLADA_PARAM_TYPE
|
||||
{
|
||||
ECPT_FLOAT = 0,
|
||||
ECPT_FLOAT2,
|
||||
ECPT_FLOAT3,
|
||||
ECPT_FLOAT4,
|
||||
|
||||
ECPT_COUNT
|
||||
};
|
||||
|
||||
//! Collada Parameter
|
||||
struct SColladaParam
|
||||
{
|
||||
SColladaParam()
|
||||
: Name(ECPN_COUNT), Type(ECPT_COUNT)
|
||||
{
|
||||
for (int i=0; i<4; ++i) Floats[i] = 0;
|
||||
}
|
||||
|
||||
ECOLLADA_PARAM_NAME Name;
|
||||
ECOLLADA_PARAM_TYPE Type;
|
||||
|
||||
f32 Floats[4];
|
||||
};
|
||||
|
||||
enum ECOLLADA_INPUT_SEMANTIC
|
||||
{
|
||||
ECIS_POSITION = 0,
|
||||
ECIS_VERTEX,
|
||||
ECIS_NORMAL,
|
||||
ECIS_TEXCOORD,
|
||||
ECIS_UV,
|
||||
ECIS_TANGENT,
|
||||
ECIS_IMAGE,
|
||||
ECIS_TEXTURE,
|
||||
ECIS_COLOR,
|
||||
|
||||
ECIS_COUNT
|
||||
};
|
||||
|
||||
//! Collada Input
|
||||
struct SColladaInput
|
||||
{
|
||||
SColladaInput()
|
||||
: Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1)
|
||||
{
|
||||
}
|
||||
|
||||
ECOLLADA_INPUT_SEMANTIC Semantic;
|
||||
core::stringc Source;
|
||||
f32* Data;
|
||||
u32 Offset;
|
||||
u32 Set;
|
||||
u32 Stride;
|
||||
};
|
||||
|
||||
//! Collada images
|
||||
struct SColladaImage
|
||||
{
|
||||
core::stringc Id;
|
||||
core::stringc Source;
|
||||
core::dimension2du Dimension;
|
||||
bool SourceIsFilename;
|
||||
};
|
||||
|
||||
|
||||
//! Collada texture
|
||||
struct SColladaTexture
|
||||
{
|
||||
video::ITexture* Texture;
|
||||
core::stringc Id;
|
||||
};
|
||||
|
||||
|
||||
//! Collada material
|
||||
struct SColladaMaterial
|
||||
{
|
||||
video::SMaterial Mat;
|
||||
core::stringc Id;
|
||||
core::stringc InstanceEffectId;
|
||||
f32 Transparency;
|
||||
|
||||
inline bool operator< (const SColladaMaterial & other) const
|
||||
{
|
||||
return Id < other.Id;
|
||||
}
|
||||
};
|
||||
|
||||
//! Collada effect (materials, shaders, and programs)
|
||||
struct SColladaEffect
|
||||
{
|
||||
core::stringc Id;
|
||||
f32 Transparency;
|
||||
core::array<core::stringc> Textures;
|
||||
video::SMaterial Mat;
|
||||
// TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct.
|
||||
io::IAttributes * Parameters;
|
||||
|
||||
inline bool operator< (const SColladaEffect & other) const
|
||||
{
|
||||
return Id < other.Id;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct SNumberArray // for storing float and int arrays
|
||||
{
|
||||
core::stringc Name;
|
||||
core::array<f32> Data;
|
||||
};
|
||||
|
||||
struct SAccessor
|
||||
{
|
||||
SAccessor()
|
||||
: Count(0), Offset(0), Stride(1) {}
|
||||
// I don't store the source of the accessor here because I assume
|
||||
// it to use the array of the source this accessor is located in.
|
||||
|
||||
int Count;
|
||||
int Offset;
|
||||
int Stride;
|
||||
|
||||
core::array<SColladaParam> Parameters; // parameters defining the accessor
|
||||
};
|
||||
|
||||
struct SSource
|
||||
{
|
||||
core::stringc Id;
|
||||
SNumberArray Array;
|
||||
core::array<SAccessor> Accessors;
|
||||
};
|
||||
|
||||
class CScenePrefab;
|
||||
|
||||
//! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht.
|
||||
class CColladaFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
|
||||
|
||||
//! destructor
|
||||
virtual ~CColladaFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_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.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
//! skips an (unknown) section in the collada document
|
||||
void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping);
|
||||
|
||||
//! reads the <COLLADA> section and its content
|
||||
void readColladaSection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <library> section and its content
|
||||
void readLibrarySection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <visual_scene> element and stores it as a prefab
|
||||
void readVisualScene(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <scene> section and its content
|
||||
void readSceneSection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <asset> section and its content
|
||||
void readAssetSection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <node> section and its content
|
||||
//! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab
|
||||
void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0);
|
||||
|
||||
//! reads a <lookat> element and its content and creates a matrix from it
|
||||
core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <matrix> element and its content and creates a matrix from it
|
||||
core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <perspective> element and its content and creates a matrix from it
|
||||
core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <rotate> element and its content and creates a matrix from it
|
||||
core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <skew> element and its content and creates a matrix from it
|
||||
core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <boundingbox> element and its content and stores it in bbox
|
||||
void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox);
|
||||
|
||||
//! reads a <scale> element and its content and creates a matrix from it
|
||||
core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <translate> element and its content and creates a matrix from it
|
||||
core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <color> element
|
||||
video::SColorf readColorNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <float> element
|
||||
f32 readFloatNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <instance> node
|
||||
void readInstanceNode(io::IXMLReaderUTF8* reader,
|
||||
scene::ISceneNode* parent, scene::ISceneNode** outNode,
|
||||
CScenePrefab* p=0, const core::stringc& type=core::stringc());
|
||||
|
||||
//! creates a scene node from Prefabs (with name given in 'url')
|
||||
void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0,
|
||||
CScenePrefab* p=0, const core::stringc& url="",
|
||||
const core::stringc& type=core::stringc());
|
||||
|
||||
//! reads a <light> element and stores it as prefab
|
||||
void readLightPrefab(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <camera> element and stores it as prefab
|
||||
void readCameraPrefab(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <image> element and stores it in the image section
|
||||
void readImage(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <texture> element and stores it in the texture section
|
||||
void readTexture(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <material> element and stores it in the material section
|
||||
void readMaterial(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <effect> element and stores it in the effects section
|
||||
void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0);
|
||||
|
||||
//! reads a <geometry> element and stores it as mesh if possible
|
||||
void readGeometry(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! parses a float from a char pointer and moves the pointer to
|
||||
//! the end of the parsed float
|
||||
inline f32 readFloat(const c8** p);
|
||||
|
||||
//! parses an int from a char pointer and moves the pointer to
|
||||
//! the end of the parsed float
|
||||
inline s32 readInt(const c8** p);
|
||||
|
||||
//! places pointer to next begin of a token
|
||||
void findNextNoneWhiteSpace(const c8** p);
|
||||
|
||||
//! reads floats from inside of xml element until end of xml element
|
||||
void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count);
|
||||
|
||||
//! reads ints from inside of xml element until end of xml element
|
||||
void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count);
|
||||
|
||||
//! clears all loaded data
|
||||
void clearData();
|
||||
|
||||
//! parses all collada parameters inside an element and stores them in ColladaParameters
|
||||
void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
|
||||
|
||||
//! returns a collada parameter or none if not found
|
||||
SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name);
|
||||
|
||||
//! parses all collada inputs inside an element and stores them in Inputs. Reads
|
||||
//! until first tag which is not an input tag or the end of the parent is reached
|
||||
void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
|
||||
|
||||
//! reads a collada input tag and adds it to the input parameter
|
||||
void readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs);
|
||||
|
||||
//! returns a collada input or none if not found
|
||||
SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input);
|
||||
|
||||
//! read Collada Id, uses id or name if id is missing
|
||||
core::stringc readId(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! changes the XML URI into an internal id
|
||||
void uriToId(core::stringc& str);
|
||||
|
||||
//! reads a polygons section and creates a mesh from it
|
||||
void readPolygonSection(io::IXMLReaderUTF8* reader,
|
||||
core::array<SSource>& sources, scene::SMesh* mesh,
|
||||
const core::stringc& geometryId);
|
||||
|
||||
//! finds a material, possible instancing it
|
||||
const SColladaMaterial * findMaterial(const core::stringc & materialName);
|
||||
|
||||
//! reads and bind materials as given by the symbol->target bind mapping
|
||||
void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);
|
||||
|
||||
//! create an Irrlicht texture from the SColladaImage
|
||||
video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect);
|
||||
|
||||
//! read a parameter and value
|
||||
void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters);
|
||||
|
||||
//! Flip z axis in matrix around to convert between right-handed and left-handed coordinate system.
|
||||
//! Note that function is symmetric (no difference if called before or after a transpose).
|
||||
core::matrix4 flipZAxis(const core::matrix4& m);
|
||||
|
||||
//! replace escape characters with the unescaped ones
|
||||
void unescape(irr::core::stringc& uri);
|
||||
|
||||
scene::ISceneManager* SceneManager;
|
||||
io::IFileSystem* FileSystem;
|
||||
|
||||
scene::IAnimatedMesh* DummyMesh;
|
||||
core::stringc CurrentlyLoadingMesh;
|
||||
|
||||
scene::IAnimatedMesh* FirstLoadedMesh;
|
||||
io::path FirstLoadedMeshName;
|
||||
s32 LoadedMeshCount;
|
||||
u32 Version;
|
||||
bool FlipAxis;
|
||||
|
||||
core::array<IColladaPrefab*> Prefabs;
|
||||
core::array<SColladaParam> ColladaParameters;
|
||||
core::array<SColladaImage> Images;
|
||||
core::array<SColladaTexture> Textures;
|
||||
core::array<SColladaMaterial> Materials;
|
||||
core::array<SColladaInput> Inputs;
|
||||
core::array<SColladaEffect> Effects;
|
||||
//! meshbuffer reference ("geomid/matname") -> index into MeshesToBind
|
||||
core::map<core::stringc,u32> MaterialsToBind;
|
||||
//! Array of buffers for each material binding
|
||||
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
|
||||
|
||||
bool CreateInstances;
|
||||
|
||||
struct EscapeCharacterURL
|
||||
{
|
||||
EscapeCharacterURL(irr::c8 c, const irr::c8* e)
|
||||
: Character(c)
|
||||
{
|
||||
Escape = e;
|
||||
}
|
||||
|
||||
irr::c8 Character; // unescaped (like ' ')
|
||||
irr::core::stringc Escape; // escaped (like '%20')
|
||||
};
|
||||
irr::core::array<EscapeCharacterURL> EscapeCharsAnyURI;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! following class is for holding and createing instances of library objects,
|
||||
//! named prefabs in this loader.
|
||||
class IColladaPrefab : public virtual IReferenceCounted
|
||||
{
|
||||
public:
|
||||
//! creates an instance of this prefab
|
||||
virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr) = 0;
|
||||
|
||||
//! returns id of this prefab
|
||||
virtual const core::stringc& getId() = 0;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
2309
source/Irrlicht/CColladaMeshWriter.cpp
Normal file
2309
source/Irrlicht/CColladaMeshWriter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
282
source/Irrlicht/CColladaMeshWriter.h
Normal file
282
source/Irrlicht/CColladaMeshWriter.h
Normal file
@ -0,0 +1,282 @@
|
||||
// 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
|
||||
|
||||
#ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
|
||||
#define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
|
||||
|
||||
#include "IColladaMeshWriter.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "irrMap.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IXMLWriter.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
class IFileSystem;
|
||||
}
|
||||
|
||||
namespace scene
|
||||
{
|
||||
//! Callback interface for properties which can be used to influence collada writing
|
||||
// (Implementer note: keep namespace labels here to make it easier for users copying this one)
|
||||
class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties
|
||||
{
|
||||
public:
|
||||
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
|
||||
virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Which texture index should be used when writing the texture of the given sampler color.
|
||||
virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Return which color from Irrlicht should be used for the color requested by collada
|
||||
virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Return custom colors for certain color types requested by collada.
|
||||
virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Return the settings for transparence
|
||||
virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Transparency value for that material.
|
||||
virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reflectivity value for that material
|
||||
virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Return index of refraction for that material
|
||||
virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Should node be used in scene export? By default all visible nodes are exported.
|
||||
virtual bool isExportable(const irr::scene::ISceneNode * node) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0.
|
||||
virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node) _IRR_OVERRIDE_;
|
||||
|
||||
//! Return if the node has it's own material overwriting the mesh-materials
|
||||
virtual bool useNodeMaterial(const scene::ISceneNode* node) const _IRR_OVERRIDE_;
|
||||
};
|
||||
|
||||
class CColladaMeshWriterNames : public virtual IColladaMeshWriterNames
|
||||
{
|
||||
public:
|
||||
CColladaMeshWriterNames(IColladaMeshWriter * writer);
|
||||
virtual irr::core::stringc nameForMesh(const scene::IMesh* mesh, int instance) _IRR_OVERRIDE_;
|
||||
virtual irr::core::stringc nameForNode(const scene::ISceneNode* node) _IRR_OVERRIDE_;
|
||||
virtual irr::core::stringc nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) _IRR_OVERRIDE_;
|
||||
protected:
|
||||
irr::core::stringc nameForPtr(const void* ptr) const;
|
||||
private:
|
||||
IColladaMeshWriter * ColladaMeshWriter;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! class to write meshes, implementing a COLLADA (.dae, .xml) writer
|
||||
/** This writer implementation has been originally developed for irrEdit and then
|
||||
merged out to the Irrlicht Engine */
|
||||
class CColladaMeshWriter : public IColladaMeshWriter
|
||||
{
|
||||
public:
|
||||
|
||||
CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs);
|
||||
virtual ~CColladaMeshWriter();
|
||||
|
||||
//! Returns the type of the mesh writer
|
||||
virtual EMESH_WRITER_TYPE getType() const _IRR_OVERRIDE_;
|
||||
|
||||
//! writes a scene starting with the given node
|
||||
virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root, int writeRoot) _IRR_OVERRIDE_;
|
||||
|
||||
//! writes a mesh
|
||||
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) _IRR_OVERRIDE_;
|
||||
|
||||
// Restrict the characters of oldString a set of allowed characters in xs:NCName and add the prefix.
|
||||
virtual irr::core::stringc toNCName(const irr::core::stringc& oldString, const irr::core::stringc& prefix=irr::core::stringc("_NC_")) const _IRR_OVERRIDE_;
|
||||
|
||||
//! After export you can find out which name had been used for writing the geometry for this node.
|
||||
virtual const irr::core::stringc* findGeometryNameForNode(ISceneNode* node) _IRR_OVERRIDE_;
|
||||
|
||||
protected:
|
||||
|
||||
void reset();
|
||||
bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const;
|
||||
void writeUv(const irr::core::vector2df& vec);
|
||||
void writeVector(const irr::core::vector3df& vec);
|
||||
void writeColor(const irr::video::SColorf& colorf, bool writeAlpha=true);
|
||||
inline irr::core::stringc toString(const irr::video::ECOLOR_FORMAT format) const;
|
||||
inline irr::core::stringc toString(const irr::video::E_TEXTURE_CLAMP clamp) const;
|
||||
inline irr::core::stringc toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const;
|
||||
inline irr::core::stringc toRef(const irr::core::stringc& source) const;
|
||||
bool isCamera(const scene::ISceneNode* node) const;
|
||||
irr::core::stringc nameForMesh(const scene::IMesh* mesh, int instance) const;
|
||||
irr::core::stringc nameForNode(const scene::ISceneNode* node) const;
|
||||
irr::core::stringc nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
|
||||
irr::core::stringc nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const;
|
||||
irr::core::stringc findCachedMaterialName(const irr::video::SMaterial& material) const;
|
||||
irr::core::stringc minTexfilterToString(bool bilinear, bool trilinear) const;
|
||||
irr::core::stringc magTexfilterToString(bool bilinear, bool trilinear) const;
|
||||
irr::core::stringc pathToURI(const irr::io::path& path) const;
|
||||
inline bool isXmlNameStartChar(c8 c) const;
|
||||
inline bool isXmlNameChar(c8 c) const;
|
||||
s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
|
||||
video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType);
|
||||
void writeAsset();
|
||||
void makeMeshNames(irr::scene::ISceneNode * node);
|
||||
void writeNodeMaterials(irr::scene::ISceneNode * node);
|
||||
void writeNodeEffects(irr::scene::ISceneNode * node);
|
||||
void writeNodeLights(irr::scene::ISceneNode * node);
|
||||
void writeNodeCameras(irr::scene::ISceneNode * node);
|
||||
void writeAllMeshGeometries();
|
||||
void writeSceneNode(irr::scene::ISceneNode * node);
|
||||
void writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringc> * materialNamesOut=0);
|
||||
void writeMeshEffects(scene::IMesh* mesh);
|
||||
void writeMaterialEffect(const irr::core::stringc& materialname, const video::SMaterial & material);
|
||||
void writeMeshGeometry(const irr::core::stringc& meshname, scene::IMesh* mesh);
|
||||
void writeMeshInstanceGeometry(const irr::core::stringc& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0);
|
||||
void writeMaterial(const irr::core::stringc& materialname);
|
||||
void writeLightInstance(const irr::core::stringc& lightName);
|
||||
void writeCameraInstance(const irr::core::stringc& cameraName);
|
||||
void writeLibraryImages();
|
||||
void writeColorFx(const video::SMaterial & material, const c8 * colorname, E_COLLADA_COLOR_SAMPLER cs, const c8* attr1Name=0, const c8* attr1Value=0);
|
||||
void writeAmbientLightElement(const video::SColorf & col);
|
||||
void writeColorElement(const video::SColor & col, bool writeAlpha=true);
|
||||
void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
|
||||
void writeTextureSampler(s32 textureIdx);
|
||||
void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
|
||||
void writeNode(const c8 * nodeName, const c8 * content);
|
||||
void writeFloatElement(irr::f32 value);
|
||||
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
|
||||
void writeScaleElement(const irr::core::vector3df& scale);
|
||||
void writeTranslateElement(const irr::core::vector3df& translate);
|
||||
void writeLookAtElement(const irr::core::vector3df& eyePos, const irr::core::vector3df& targetPos, const irr::core::vector3df& upVector);
|
||||
void writeMatrixElement(const irr::core::matrix4& matrix);
|
||||
|
||||
struct SComponentGlobalStartPos
|
||||
{
|
||||
SComponentGlobalStartPos() : PosStartIndex(0),
|
||||
NormalStartIndex(0),
|
||||
TCoord0StartIndex(0),
|
||||
TCoord1StartIndex(0)
|
||||
{ }
|
||||
|
||||
u32 PosStartIndex;
|
||||
u32 NormalStartIndex;
|
||||
u32 TCoord0StartIndex;
|
||||
u32 TCoord1StartIndex;
|
||||
};
|
||||
|
||||
io::IFileSystem* FileSystem;
|
||||
video::IVideoDriver* VideoDriver;
|
||||
io::IXMLWriterUTF8* Writer;
|
||||
core::array<video::ITexture*> LibraryImages;
|
||||
io::path Directory;
|
||||
|
||||
// Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings.
|
||||
struct SGeometryMeshMaterials
|
||||
{
|
||||
bool equals(const core::array<irr::core::stringc>& names) const
|
||||
{
|
||||
if ( names.size() != MaterialNames.size() )
|
||||
return false;
|
||||
for ( irr::u32 i=0; i<MaterialNames.size(); ++i )
|
||||
if ( names[i] != MaterialNames[i] )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
irr::core::stringc GeometryName; // replacing the usual ColladaMesh::Name
|
||||
core::array<irr::core::stringc> MaterialNames; // Material names exported for this instance
|
||||
core::array<const ISceneNode*> MaterialOwners; // Nodes using this specific mesh-material combination
|
||||
};
|
||||
|
||||
// Check per mesh-ptr if stuff has been written for this mesh already
|
||||
struct SColladaMesh
|
||||
{
|
||||
SColladaMesh() : MaterialsWritten(false), EffectsWritten(false)
|
||||
{
|
||||
}
|
||||
|
||||
SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array<irr::core::stringc> materialNames)
|
||||
{
|
||||
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
|
||||
{
|
||||
if ( GeometryMeshMaterials[i].equals(materialNames) )
|
||||
return &(GeometryMeshMaterials[i]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const irr::core::stringc& findGeometryNameForNode(const ISceneNode* node) const
|
||||
{
|
||||
if ( GeometryMeshMaterials.size() < 2 )
|
||||
return Name;
|
||||
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
|
||||
{
|
||||
if ( GeometryMeshMaterials[i].MaterialOwners.linear_search(node) >= 0 )
|
||||
return GeometryMeshMaterials[i].GeometryName;
|
||||
}
|
||||
return Name; // (shouldn't get here usually)
|
||||
}
|
||||
|
||||
irr::core::stringc Name;
|
||||
bool MaterialsWritten; // just an optimization doing that here in addition to the MaterialsWritten map
|
||||
bool EffectsWritten; // just an optimization doing that here in addition to the EffectsWritten map
|
||||
|
||||
core::array<SGeometryMeshMaterials> GeometryMeshMaterials;
|
||||
};
|
||||
typedef core::map<IMesh*, SColladaMesh>::Node MeshNode;
|
||||
core::map<IMesh*, SColladaMesh> Meshes;
|
||||
|
||||
// structure for the lights library
|
||||
struct SColladaLight
|
||||
{
|
||||
SColladaLight() {}
|
||||
irr::core::stringc Name;
|
||||
};
|
||||
typedef core::map<ISceneNode*, SColladaLight>::Node LightNode;
|
||||
core::map<ISceneNode*, SColladaLight> LightNodes;
|
||||
|
||||
// structure for the camera library
|
||||
typedef core::map<ISceneNode*, irr::core::stringc>::Node CameraNode;
|
||||
core::map<ISceneNode*, irr::core::stringc> CameraNodes;
|
||||
|
||||
// Check per name if stuff has been written already
|
||||
// TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht
|
||||
core::map<irr::core::stringc, bool> MaterialsWritten;
|
||||
core::map<irr::core::stringc, bool> EffectsWritten;
|
||||
|
||||
// Cache material names
|
||||
struct MaterialName
|
||||
{
|
||||
MaterialName(const irr::video::SMaterial & material, const irr::core::stringc& name)
|
||||
: Material(material), Name(name)
|
||||
{}
|
||||
irr::video::SMaterial Material;
|
||||
irr::core::stringc Name;
|
||||
};
|
||||
irr::core::array< MaterialName > MaterialNameCache;
|
||||
|
||||
irr::core::stringc WriteBuffer; // use for writing short strings to avoid regular memory allocations
|
||||
|
||||
struct EscapeCharacterURL
|
||||
{
|
||||
EscapeCharacterURL(irr::c8 c, const irr::c8* e)
|
||||
: Character(c)
|
||||
{
|
||||
Escape = e;
|
||||
}
|
||||
|
||||
irr::c8 Character; // unescaped (like ' ')
|
||||
irr::core::stringc Escape; // escaped (like '%20')
|
||||
};
|
||||
irr::core::array<EscapeCharacterURL> EscapeCharsAnyURI;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
830
source/Irrlicht/CColorConverter.cpp
Normal file
830
source/Irrlicht/CColorConverter.cpp
Normal file
@ -0,0 +1,830 @@
|
||||
// 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 "CColorConverter.h"
|
||||
#include "SColor.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! converts a monochrome bitmap to A1R5G5B5 data
|
||||
void CColorConverter::convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
s32 shift = 7;
|
||||
if (flip)
|
||||
out -= width;
|
||||
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = *in>>shift & 0x01 ? (s16)0xffff : (s16)0x8000;
|
||||
|
||||
if ((--shift)<0) // 8 pixel done
|
||||
{
|
||||
shift=7;
|
||||
++in;
|
||||
}
|
||||
}
|
||||
|
||||
if (shift != 7) // width did not fill last byte
|
||||
++in;
|
||||
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts a 4 bit palettized image to A1R5G5B5
|
||||
void CColorConverter::convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out || !palette)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width*height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
s32 shift = 4;
|
||||
if (flip)
|
||||
out -= width;
|
||||
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)((*in >> shift) & 0xf)]);
|
||||
|
||||
if (shift==0)
|
||||
{
|
||||
shift = 4;
|
||||
++in;
|
||||
}
|
||||
else
|
||||
shift = 0;
|
||||
}
|
||||
|
||||
if (shift == 0) // odd width
|
||||
++in;
|
||||
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts a 8 bit palettized image into A1R5G5B5
|
||||
void CColorConverter::convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out || !palette)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width; // one line back
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)(*in)]);
|
||||
++in;
|
||||
}
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
void CColorConverter::convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out )
|
||||
return;
|
||||
|
||||
const s32 lineWidth = 3 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth; // one line back
|
||||
for (s32 x=0; x< lineWidth; x += 3)
|
||||
{
|
||||
if ( palette )
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
out[x+0] = palette[ (in[0] << 2 ) + 0];
|
||||
out[x+1] = palette[ (in[0] << 2 ) + 1];
|
||||
out[x+2] = palette[ (in[0] << 2 ) + 2];
|
||||
#else
|
||||
out[x+0] = palette[ (in[0] << 2 ) + 2];
|
||||
out[x+1] = palette[ (in[0] << 2 ) + 1];
|
||||
out[x+2] = palette[ (in[0] << 2 ) + 0];
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
out[x+0] = in[0];
|
||||
out[x+1] = in[0];
|
||||
out[x+2] = in[0];
|
||||
}
|
||||
++in;
|
||||
}
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
void CColorConverter::convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out )
|
||||
return;
|
||||
|
||||
const u32 lineWidth = 4 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
u32 x;
|
||||
u32 c;
|
||||
for (u32 y=0; y < (u32) height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth; // one line back
|
||||
|
||||
if ( palette )
|
||||
{
|
||||
for (x=0; x < (u32) width; x += 1)
|
||||
{
|
||||
c = in[x];
|
||||
((u32*)out)[x] = ((u32*)palette)[ c ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x=0; x < (u32) width; x += 1)
|
||||
{
|
||||
c = in[x];
|
||||
#ifdef __BIG_ENDIAN__
|
||||
((u32*)out)[x] = c << 24 | c << 16 | c << 8 | 0x000000FF;
|
||||
#else
|
||||
((u32*)out)[x] = 0xFF000000 | c << 16 | c << 8 | c;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += width + linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts 16bit data to 16bit data
|
||||
void CColorConverter::convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (s32 x=0; x<width; ++x)
|
||||
out[x]=os::Byteswap::byteswap(in[x]);
|
||||
#else
|
||||
memcpy(out, in, width*sizeof(s16));
|
||||
#endif
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! copies R8G8B8 24bit data to 24bit data
|
||||
void CColorConverter::convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad, bool flip, bool bgr)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
const s32 lineWidth = 3 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth;
|
||||
if (bgr)
|
||||
{
|
||||
for (s32 x=0; x<lineWidth; x+=3)
|
||||
{
|
||||
out[x+0] = in[x+2];
|
||||
out[x+1] = in[x+1];
|
||||
out[x+2] = in[x+0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(out,in,lineWidth);
|
||||
}
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += lineWidth;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! 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.
|
||||
void CColorConverter::convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight)
|
||||
{
|
||||
if (!newWidth || !newHeight)
|
||||
return;
|
||||
|
||||
// note: this is very very slow. (i didn't want to write a fast version.
|
||||
// but hopefully, nobody wants to convert surfaces every frame.
|
||||
|
||||
f32 sourceXStep = (f32)currentWidth / (f32)newWidth;
|
||||
f32 sourceYStep = (f32)currentHeight / (f32)newHeight;
|
||||
f32 sy;
|
||||
s32 t;
|
||||
|
||||
for (s32 x=0; x<newWidth; ++x)
|
||||
{
|
||||
sy = 0.0f;
|
||||
|
||||
for (s32 y=0; y<newHeight; ++y)
|
||||
{
|
||||
t = in[(s32)(((s32)sy)*currentWidth + x*sourceXStep)];
|
||||
t = (((t >> 15)&0x1)<<31) | (((t >> 10)&0x1F)<<19) |
|
||||
(((t >> 5)&0x1F)<<11) | (t&0x1F)<<3;
|
||||
out[(s32)(y*newWidth + x)] = t;
|
||||
|
||||
sy+=sourceYStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! copies X8R8G8B8 32 bit data
|
||||
void CColorConverter::convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (s32 x=0; x<width; ++x)
|
||||
out[x]=os::Byteswap::byteswap(in[x]);
|
||||
#else
|
||||
memcpy(out, in, width*sizeof(s32));
|
||||
#endif
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = (*sB & 0x7c00) >> 7;
|
||||
dB[1] = (*sB & 0x03e0) >> 2;
|
||||
dB[0] = (*sB & 0x1f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = (*sB & 0x7c00) >> 7;
|
||||
dB[1] = (*sB & 0x03e0) >> 2;
|
||||
dB[2] = (*sB & 0x1f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR5G5B5A1(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
const u16* sB = (const u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = (*sB<<1)|(*sB>>15);
|
||||
++sB; ++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A1R5G5B5toA8R8G8B8(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 2);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A1R5G5B5toR5G6B5(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
// sB[3] is alpha
|
||||
dB[0] = sB[2];
|
||||
dB[1] = sB[1];
|
||||
dB[2] = sB[0];
|
||||
|
||||
sB += 4;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
// sB[3] is alpha
|
||||
dB[0] = sB[0];
|
||||
dB[1] = sB[1];
|
||||
dB[2] = sB[2];
|
||||
|
||||
sB += 4;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 4);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u32* sB = (u32*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A8R8G8B8toA1R5G5B5(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA1B5G5R5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[0] >> 3;
|
||||
s32 g = sB[1] >> 3;
|
||||
s32 b = sB[2] >> 3;
|
||||
s32 a = sB[3] >> 3;
|
||||
|
||||
dB[0] = (a << 15) | (r << 10) | (g << 5) | (b);
|
||||
|
||||
sB += 4;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[2] >> 3;
|
||||
s32 g = sB[1] >> 2;
|
||||
s32 b = sB[0] >> 3;
|
||||
|
||||
dB[0] = (r << 11) | (g << 5) | (b);
|
||||
|
||||
sB += 4;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
u8 r = sB[2] & 0xe0;
|
||||
u8 g = (sB[1] & 0xe0) >> 3;
|
||||
u8 b = (sB[0] & 0xc0) >> 6;
|
||||
|
||||
dB[0] = (r | g | b);
|
||||
|
||||
sB += 4;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 3);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8* )sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = 0xff000000 | (sB[0]<<16) | (sB[1]<<8) | sB[2];
|
||||
|
||||
sB += 3;
|
||||
++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[0] >> 3;
|
||||
s32 g = sB[1] >> 3;
|
||||
s32 b = sB[2] >> 3;
|
||||
|
||||
dB[0] = (0x8000) | (r << 10) | (g << 5) | (b);
|
||||
|
||||
sB += 3;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8* )sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = 0xff000000 | (sB[2]<<16) | (sB[1]<<8) | sB[0];
|
||||
|
||||
sB += 3;
|
||||
++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR8G8B8A8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
const u32* sB = (const u32*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB++ = (*sB<<8) | (*sB>>24);
|
||||
++sB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA8B8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
const u32* sB = (const u32*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB++ = (*sB&0xff00ff00)|((*sB&0x00ff0000)>>16)|((*sB&0x000000ff)<<16);
|
||||
++sB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = sB[3];
|
||||
dB[1] = sB[2];
|
||||
dB[2] = sB[1];
|
||||
dB[3] = sB[0];
|
||||
|
||||
sB += 4;
|
||||
dB += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = sB[0];
|
||||
dB[1] = sB[1];
|
||||
dB[0] = sB[2];
|
||||
|
||||
sB += 3;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[0] >> 3;
|
||||
s32 g = sB[1] >> 2;
|
||||
s32 b = sB[2] >> 3;
|
||||
|
||||
dB[0] = (r << 11) | (g << 5) | (b);
|
||||
|
||||
sB += 3;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 2);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = (*sB & 0xf800) >> 8;
|
||||
dB[1] = (*sB & 0x07e0) >> 3;
|
||||
dB[2] = (*sB & 0x001f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = (*sB & 0xf800) >> 8;
|
||||
dB[1] = (*sB & 0x07e0) >> 3;
|
||||
dB[0] = (*sB & 0x001f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = R5G6B5toA8R8G8B8(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = R5G6B5toA1R5G5B5(*sB++);
|
||||
}
|
||||
|
||||
bool CColorConverter::canConvertFormat(ECOLOR_FORMAT sourceFormat, ECOLOR_FORMAT destFormat)
|
||||
{
|
||||
switch (sourceFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
switch (destFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
case ECF_A8R8G8B8:
|
||||
case ECF_R8G8B8:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
switch (destFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
case ECF_A8R8G8B8:
|
||||
case ECF_R8G8B8:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
switch (destFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
case ECF_A8R8G8B8:
|
||||
case ECF_R8G8B8:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
switch (destFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
case ECF_A8R8G8B8:
|
||||
case ECF_R8G8B8:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CColorConverter::convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN,
|
||||
void* dP, ECOLOR_FORMAT dF)
|
||||
{
|
||||
// please also update can_convert_viaFormat when adding new conversions
|
||||
switch (sF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_A1R5G5B5toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_A1R5G5B5toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_A1R5G5B5toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_A1R5G5B5toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_R5G6B5toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_R5G6B5toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_R5G6B5toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_R5G6B5toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_A8R8G8B8toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_A8R8G8B8toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_A8R8G8B8toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_A8R8G8B8toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_R8G8B8toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_R8G8B8toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_R8G8B8toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_R8G8B8toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
101
source/Irrlicht/CColorConverter.h
Normal file
101
source/Irrlicht/CColorConverter.h
Normal file
@ -0,0 +1,101 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_COLOR_CONVERTER_H_INCLUDED__
|
||||
#define __C_COLOR_CONVERTER_H_INCLUDED__
|
||||
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
246
source/Irrlicht/CCubeSceneNode.cpp
Normal file
246
source/Irrlicht/CCubeSceneNode.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_CUBE_SCENENODE_
|
||||
#include "CCubeSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "os.h"
|
||||
#ifdef _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
|
||||
#include "CShadowVolumeSceneNode.h"
|
||||
#else
|
||||
#include "IShadowVolumeSceneNode.h"
|
||||
#endif // _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
/*
|
||||
011 111
|
||||
/6,8------/5 y
|
||||
/ | / | ^ z
|
||||
/ | / | | /
|
||||
010 3,9-------2 | |/
|
||||
| 7- - -10,4 101 *---->x
|
||||
| / | /
|
||||
|/ | /
|
||||
0------11,1/
|
||||
000 100
|
||||
*/
|
||||
|
||||
//! constructor
|
||||
CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id, const core::vector3df& position,
|
||||
const core::vector3df& rotation, const core::vector3df& scale)
|
||||
: IMeshSceneNode(parent, mgr, id, position, rotation, scale),
|
||||
Mesh(0), Shadow(0), Size(size)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCubeSceneNode");
|
||||
#endif
|
||||
|
||||
setSize();
|
||||
}
|
||||
|
||||
|
||||
CCubeSceneNode::~CCubeSceneNode()
|
||||
{
|
||||
if (Shadow)
|
||||
Shadow->drop();
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
}
|
||||
|
||||
|
||||
void CCubeSceneNode::setSize()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size));
|
||||
}
|
||||
|
||||
|
||||
//! renders the node.
|
||||
void CCubeSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
|
||||
if (Shadow)
|
||||
Shadow->updateShadowVolumes();
|
||||
|
||||
// for debug purposes only:
|
||||
video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial();
|
||||
|
||||
// overwrite half transparency
|
||||
if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
|
||||
mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
|
||||
driver->setMaterial(mat);
|
||||
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
|
||||
|
||||
// for debug purposes only:
|
||||
if (DebugDataVisible)
|
||||
{
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
m.AntiAliasing=0;
|
||||
driver->setMaterial(m);
|
||||
|
||||
if (DebugDataVisible & scene::EDS_BBOX)
|
||||
{
|
||||
driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255));
|
||||
}
|
||||
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
|
||||
{
|
||||
driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(),
|
||||
video::SColor(255,190,128,128));
|
||||
}
|
||||
if (DebugDataVisible & scene::EDS_NORMALS)
|
||||
{
|
||||
// draw normals
|
||||
const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH);
|
||||
const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR);
|
||||
const u32 count = Mesh->getMeshBufferCount();
|
||||
|
||||
for (u32 i=0; i != count; ++i)
|
||||
{
|
||||
driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor);
|
||||
}
|
||||
}
|
||||
|
||||
// show mesh
|
||||
if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
|
||||
{
|
||||
m.Wireframe = true;
|
||||
driver->setMaterial(m);
|
||||
|
||||
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Mesh->getMeshBuffer(0)->getBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
bool CCubeSceneNode::removeChild(ISceneNode* child)
|
||||
{
|
||||
if (child && Shadow == child)
|
||||
{
|
||||
Shadow->drop();
|
||||
Shadow = 0;
|
||||
}
|
||||
|
||||
return ISceneNode::removeChild(child);
|
||||
}
|
||||
|
||||
|
||||
//! Creates shadow volume scene node as child of this node
|
||||
//! and returns a pointer to it.
|
||||
IShadowVolumeSceneNode* CCubeSceneNode::addShadowVolumeSceneNode(
|
||||
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
|
||||
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
|
||||
return 0;
|
||||
|
||||
if (!shadowMesh)
|
||||
shadowMesh = Mesh; // if null is given, use the mesh of node
|
||||
|
||||
if (Shadow)
|
||||
Shadow->drop();
|
||||
|
||||
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
|
||||
return Shadow;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CCubeSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! returns the material based on the zero based index i.
|
||||
video::SMaterial& CCubeSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Mesh->getMeshBuffer(0)->getMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
u32 CCubeSceneNode::getMaterialCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
ISceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addFloat("Size", Size);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
f32 newSize = in->getAttributeAsFloat("Size");
|
||||
newSize = core::max_(newSize, 0.0001f);
|
||||
if (newSize != Size)
|
||||
{
|
||||
Size = newSize;
|
||||
setSize();
|
||||
}
|
||||
|
||||
ISceneNode::deserializeAttributes(in, options);
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent,
|
||||
newManager, ID, RelativeTranslation);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->getMaterial(0) = getMaterial(0);
|
||||
nb->Shadow = Shadow;
|
||||
if ( nb->Shadow )
|
||||
nb->Shadow->grab();
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_CUBE_SCENENODE_
|
93
source/Irrlicht/CCubeSceneNode.h
Normal file
93
source/Irrlicht/CCubeSceneNode.h
Normal file
@ -0,0 +1,93 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_CUBE_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_CUBE_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IMeshSceneNode.h"
|
||||
#include "SMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class CCubeSceneNode : public IMeshSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CCubeSceneNode(f32 size, 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));
|
||||
|
||||
virtual ~CCubeSceneNode();
|
||||
|
||||
virtual void OnRegisterSceneNode() _IRR_OVERRIDE_;
|
||||
|
||||
//! renders the node.
|
||||
virtual void render() _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_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.
|
||||
virtual video::SMaterial& getMaterial(u32 i) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_CUBE; }
|
||||
|
||||
//! Creates shadow volume scene node as child of this node
|
||||
//! and returns a pointer to it.
|
||||
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
|
||||
s32 id, bool zfailmethod=true, f32 infinity=10000.0f) _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a new mesh to display
|
||||
virtual void setMesh(IMesh* mesh) _IRR_OVERRIDE_ {}
|
||||
|
||||
//! Returns the current mesh
|
||||
virtual IMesh* getMesh(void) _IRR_OVERRIDE_ { return Mesh; }
|
||||
|
||||
//! 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. */
|
||||
virtual void setReadOnlyMaterials(bool readonly) _IRR_OVERRIDE_ {}
|
||||
|
||||
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
|
||||
virtual bool isReadOnlyMaterials() const _IRR_OVERRIDE_ { return false; }
|
||||
|
||||
//! 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.
|
||||
virtual bool removeChild(ISceneNode* child) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
void setSize();
|
||||
|
||||
IMesh* Mesh;
|
||||
IShadowVolumeSceneNode* Shadow;
|
||||
f32 Size;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
3793
source/Irrlicht/CD3D9Driver.cpp
Normal file
3793
source/Irrlicht/CD3D9Driver.cpp
Normal file
File diff suppressed because it is too large
Load Diff
507
source/Irrlicht/CD3D9Driver.h
Normal file
507
source/Irrlicht/CD3D9Driver.h
Normal file
@ -0,0 +1,507 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
#define __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#ifdef _IRR_WINDOWS_
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "CNullDriver.h"
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class CD3D9CallBridge;
|
||||
class CD3D9RenderTarget;
|
||||
class CD3D9Texture;
|
||||
|
||||
class CD3D9Driver : public CNullDriver, IMaterialRendererServices
|
||||
{
|
||||
public:
|
||||
|
||||
friend class CD3D9CallBridge;
|
||||
friend class CD3D9RenderTarget;
|
||||
friend class CD3D9Texture;
|
||||
|
||||
//! constructor
|
||||
CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D9Driver();
|
||||
|
||||
virtual bool beginScene(u16 clearFlag, SColor clearColor = SColor(255,0,0,0), f32 clearDepth = 1.f, u8 clearStencil = 0,
|
||||
const SExposedVideoData& videoData = SExposedVideoData(), core::rect<s32>* sourceRect = 0) _IRR_OVERRIDE_;
|
||||
|
||||
virtual bool endScene() _IRR_OVERRIDE_;
|
||||
|
||||
//! queries the features of the driver, returns true if feature is available
|
||||
virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const _IRR_OVERRIDE_;
|
||||
|
||||
//! sets transformation
|
||||
virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) _IRR_OVERRIDE_;
|
||||
|
||||
//! sets a material
|
||||
virtual void setMaterial(const SMaterial& material) _IRR_OVERRIDE_;
|
||||
|
||||
virtual bool setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor = SColor(255,0,0,0),
|
||||
f32 clearDepth = 1.f, u8 clearStencil = 0) _IRR_OVERRIDE_;
|
||||
|
||||
//! sets a viewport
|
||||
virtual void setViewPort(const core::rect<s32>& area) _IRR_OVERRIDE_;
|
||||
|
||||
//! gets the area of the current viewport
|
||||
virtual const core::rect<s32>& getViewPort() const _IRR_OVERRIDE_;
|
||||
|
||||
struct SHWBufferLink_d3d9 : public SHWBufferLink
|
||||
{
|
||||
SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer):
|
||||
SHWBufferLink(_MeshBuffer),
|
||||
vertexBuffer(0), indexBuffer(0),
|
||||
vertexBufferSize(0), indexBufferSize(0) {}
|
||||
|
||||
IDirect3DVertexBuffer9* vertexBuffer;
|
||||
IDirect3DIndexBuffer9* indexBuffer;
|
||||
|
||||
u32 vertexBufferSize;
|
||||
u32 indexBufferSize;
|
||||
};
|
||||
|
||||
bool updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
bool updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
|
||||
//! updates hardware buffer if needed
|
||||
virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer) _IRR_OVERRIDE_;
|
||||
|
||||
//! Create hardware buffer from mesh
|
||||
virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb) _IRR_OVERRIDE_;
|
||||
|
||||
//! Delete hardware buffer (only some drivers can)
|
||||
virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draw hardware buffer
|
||||
virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer) _IRR_OVERRIDE_;
|
||||
|
||||
//! Create occlusion query.
|
||||
/** Use node for identification and mesh for occlusion test. */
|
||||
virtual void addOcclusionQuery(scene::ISceneNode* node,
|
||||
const scene::IMesh* mesh=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Remove occlusion query.
|
||||
virtual void removeOcclusionQuery(scene::ISceneNode* node) _IRR_OVERRIDE_;
|
||||
|
||||
//! Run occlusion query. Draws mesh stored in query.
|
||||
/** If the mesh shall not be rendered visible, use
|
||||
overrideMaterial to disable the color and depth buffer. */
|
||||
virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false) _IRR_OVERRIDE_;
|
||||
|
||||
//! Update occlusion query. Retrieves results from GPU.
|
||||
/** If the query shall not block, set the flag to false.
|
||||
Update might not occur in this case, though */
|
||||
virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! Return query result.
|
||||
/** Return value is the number of visible pixels/fragments.
|
||||
The value is a safe approximation, i.e. can be larger then the
|
||||
actual value of pixels. */
|
||||
virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Create render target.
|
||||
virtual IRenderTarget* addRenderTarget() _IRR_OVERRIDE_;
|
||||
|
||||
//! draws a vertex primitive list
|
||||
virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType) _IRR_OVERRIDE_;
|
||||
|
||||
//! draws a vertex primitive list in 2d
|
||||
virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType) _IRR_OVERRIDE_;
|
||||
|
||||
//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draws a part of the texture into the rectangle.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draws a set of 2d images, using a color and the alpha channel of the texture.
|
||||
virtual void draw2DImageBatch(const video::ITexture* texture,
|
||||
const core::array<core::position2d<s32> >& positions,
|
||||
const core::array<core::rect<s32> >& sourceRects,
|
||||
const core::rect<s32>* clipRect=0,
|
||||
SColor color=SColor(255,255,255,255),
|
||||
bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_;
|
||||
|
||||
//!Draws an 2d rectangle with a gradient.
|
||||
virtual void draw2DRectangle(const core::rect<s32>& pos,
|
||||
SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
|
||||
const core::rect<s32>* clip) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draws a 2d line.
|
||||
virtual void draw2DLine(const core::position2d<s32>& start,
|
||||
const core::position2d<s32>& end,
|
||||
SColor color=SColor(255,255,255,255)) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draws a pixel.
|
||||
virtual void drawPixel(u32 x, u32 y, const SColor & color) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draws a 3d line.
|
||||
virtual void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, SColor color = SColor(255,255,255,255)) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draws a 3d box.
|
||||
virtual void draw3DBox( const core::aabbox3d<f32>& box, SColor color = SColor(255,255,255,255 ) ) _IRR_OVERRIDE_;
|
||||
|
||||
//! initialises the Direct3D API
|
||||
bool initDriver(HWND hwnd, bool pureSoftware);
|
||||
|
||||
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
|
||||
//! driver, it would return "Direct3D8.1".
|
||||
virtual const wchar_t* getName() const _IRR_OVERRIDE_;
|
||||
|
||||
//! deletes all dynamic lights there are
|
||||
virtual void deleteAllDynamicLights() _IRR_OVERRIDE_;
|
||||
|
||||
//! adds a dynamic light, returning an index to the light
|
||||
//! \param light: the light data to use to create the light
|
||||
//! \return An index to the light, or -1 if an error occurs
|
||||
virtual s32 addDynamicLight(const SLight& light) _IRR_OVERRIDE_;
|
||||
|
||||
//! Turns a dynamic light on or off
|
||||
//! \param lightIndex: the index returned by addDynamicLight
|
||||
//! \param turnOn: true to turn the light on, false to turn it off
|
||||
virtual void turnLightOn(s32 lightIndex, bool turnOn) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the maximal amount of dynamic lights the device can handle
|
||||
virtual u32 getMaximalDynamicLightAmount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the dynamic ambient light color. The default color is
|
||||
//! (0,0,0,0) which means it is dark.
|
||||
//! \param color: New color of the ambient light.
|
||||
virtual void setAmbientLight(const SColorf& color) _IRR_OVERRIDE_;
|
||||
|
||||
//! Draws a shadow volume into the stencil buffer.
|
||||
virtual void drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail=true, u32 debugDataVisible=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Fills the stencil shadow with color.
|
||||
virtual void drawStencilShadow(bool clearStencilBuffer=false,
|
||||
video::SColor leftUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor leftDownEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightDownEdge = video::SColor(0,0,0,0)) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the maximum amount of primitives (mostly vertices) which
|
||||
//! the device is able to render with one drawIndexedTriangleList
|
||||
//! call.
|
||||
virtual u32 getMaximalPrimitiveCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the fog mode.
|
||||
virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start,
|
||||
f32 end, f32 density, bool pixelFog, bool rangeFog) _IRR_OVERRIDE_;
|
||||
|
||||
//! Only used by the internal engine. Used to notify the driver that
|
||||
//! the window was resized.
|
||||
virtual void OnResize(const core::dimension2d<u32>& size) _IRR_OVERRIDE_;
|
||||
|
||||
//! Can be called by an IMaterialRenderer to make its work easier.
|
||||
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns type of video driver
|
||||
virtual E_DRIVER_TYPE getDriverType() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the transformation set by setTransform
|
||||
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get a vertex shader constant index.
|
||||
virtual s32 getVertexShaderConstantID(const c8* name) _IRR_OVERRIDE_;
|
||||
|
||||
//! Get a pixel shader constant index.
|
||||
virtual s32 getPixelShaderConstantID(const c8* name) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a vertex shader constant.
|
||||
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a pixel shader constant.
|
||||
virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a constant for the vertex shader based on an index.
|
||||
virtual bool setVertexShaderConstant(s32 index, const f32* floats, int count) _IRR_OVERRIDE_;
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVertexShaderConstant(s32 index, const s32* ints, int count) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets a constant for the pixel shader based on an index.
|
||||
virtual bool setPixelShaderConstant(s32 index, const f32* floats, int count) _IRR_OVERRIDE_;
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setPixelShaderConstant(s32 index, const s32* ints, int count) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns a pointer to the IVideoDriver interface. (Implementation for
|
||||
//! IMaterialRendererServices)
|
||||
virtual IVideoDriver* getVideoDriver() _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a render target texture.
|
||||
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a render target texture for a cubemap
|
||||
ITexture* addRenderTargetTextureCubemap(const irr::u32 sideLen,
|
||||
const io::path& name, const ECOLOR_FORMAT format) _IRR_OVERRIDE_;
|
||||
|
||||
virtual void clearBuffers(u16 flag, SColor color = SColor(255,0,0,0), f32 depth = 1.f, u8 stencil = 0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns an image created from the last rendered frame.
|
||||
virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) _IRR_OVERRIDE_;
|
||||
|
||||
//! Set/unset a clipping plane.
|
||||
virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false) _IRR_OVERRIDE_;
|
||||
|
||||
//! Enable/disable a clipping plane.
|
||||
virtual void enableClipPlane(u32 index, bool enable) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the graphics card vendor name.
|
||||
virtual core::stringc getVendorInfo() _IRR_OVERRIDE_ {return VendorName;}
|
||||
|
||||
//! Enable the 2d override material
|
||||
virtual void enableMaterial2D(bool enable=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! Check if the driver was recently reset.
|
||||
virtual bool checkDriverReset() _IRR_OVERRIDE_ {return DriverWasReset;}
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer. */
|
||||
virtual ECOLOR_FORMAT getColorFormat() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the maximum texture size supported.
|
||||
virtual core::dimension2du getMaxTextureSize() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Check if the driver supports creating textures with the given color format
|
||||
virtual bool queryTextureFormat(ECOLOR_FORMAT format) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Used by some SceneNodes to check if a material should be rendered in the transparent render pass
|
||||
virtual bool needsTransparentRenderPass(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer as D3D color value. */
|
||||
D3DFORMAT getD3DColorFormat() const;
|
||||
|
||||
//! Get D3D color format from Irrlicht color format.
|
||||
D3DFORMAT getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const;
|
||||
|
||||
//! Get Irrlicht color format from D3D color format.
|
||||
ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format) const;
|
||||
|
||||
//! Get D3D blending factor.
|
||||
u32 getD3DBlend(E_BLEND_FACTOR factor) const;
|
||||
|
||||
//! Get D3D modulate.
|
||||
u32 getD3DModulate(E_MODULATE_FUNC func) const;
|
||||
|
||||
//! Get bridge calls.
|
||||
CD3D9CallBridge* getBridgeCalls() const;
|
||||
|
||||
private:
|
||||
|
||||
//! enumeration for rendering modes such as 2d and 3d for minimizing the switching of renderStates.
|
||||
enum E_RENDER_MODE
|
||||
{
|
||||
ERM_NONE = 0, // no render state has been set yet.
|
||||
ERM_2D, // 2d drawing rendermode
|
||||
ERM_3D, // 3d rendering mode
|
||||
ERM_STENCIL_FILL, // stencil fill mode
|
||||
ERM_SHADOW_VOLUME_ZFAIL, // stencil volume draw mode
|
||||
ERM_SHADOW_VOLUME_ZPASS // stencil volume draw mode
|
||||
};
|
||||
|
||||
//! sets right vertex shader
|
||||
void setVertexShader(video::E_VERTEX_TYPE newType);
|
||||
|
||||
//! sets the needed renderstates
|
||||
bool setRenderStates3DMode();
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilFillMode(bool alpha);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible);
|
||||
|
||||
//! sets the current Texture
|
||||
bool setActiveTexture(u32 stage, const video::ITexture* texture);
|
||||
|
||||
//! resets the device
|
||||
bool reset();
|
||||
|
||||
//! Try to get back a lost device
|
||||
bool retrieveDevice(int numTries, int msSleepBetweenTries=100);
|
||||
|
||||
virtual ITexture* createDeviceDependentTexture(const io::path& name, IImage* image) _IRR_OVERRIDE_;
|
||||
|
||||
virtual ITexture* createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image) _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, using pixel and/or
|
||||
//! vertex shaders to render geometry.
|
||||
s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
E_MATERIAL_TYPE baseMaterial, s32 userData) _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, based on a high level shading
|
||||
//! language.
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8* geometryShaderProgram,
|
||||
const c8* geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack* callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) _IRR_OVERRIDE_;
|
||||
|
||||
void createMaterialRenderers();
|
||||
|
||||
void draw2D3DVertexPrimitiveList(const void* vertices,
|
||||
u32 vertexCount, const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType, bool is3D);
|
||||
|
||||
D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp);
|
||||
|
||||
inline D3DCOLORVALUE colorToD3D(const SColor& col)
|
||||
{
|
||||
const f32 f = 1.0f / 255.0f;
|
||||
D3DCOLORVALUE v;
|
||||
v.r = col.getRed() * f;
|
||||
v.g = col.getGreen() * f;
|
||||
v.b = col.getBlue() * f;
|
||||
v.a = col.getAlpha() * f;
|
||||
return v;
|
||||
}
|
||||
|
||||
CD3D9CallBridge* BridgeCalls;
|
||||
|
||||
E_RENDER_MODE CurrentRenderMode;
|
||||
D3DPRESENT_PARAMETERS present;
|
||||
|
||||
SMaterial Material, LastMaterial;
|
||||
bool ResetRenderStates; // bool to make all renderstates be reseted if set.
|
||||
bool Transformation3DChanged;
|
||||
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
|
||||
bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES];
|
||||
core::matrix4 Matrices[ETS_COUNT]; // matrices of the 3d mode we need to restore when we switch back from the 2d mode.
|
||||
|
||||
HINSTANCE D3DLibrary;
|
||||
IDirect3D9* pID3D;
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
|
||||
IDirect3DSurface9* BackBufferSurface;
|
||||
IDirect3DSurface9* DepthStencilSurface;
|
||||
|
||||
core::array<bool> ActiveRenderTarget;
|
||||
|
||||
HWND WindowId;
|
||||
core::rect<s32>* SceneSourceRect;
|
||||
|
||||
D3DCAPS9 Caps;
|
||||
|
||||
SIrrlichtCreationParameters Params;
|
||||
|
||||
E_VERTEX_TYPE LastVertexType;
|
||||
|
||||
core::stringc VendorName;
|
||||
u16 VendorID;
|
||||
|
||||
u32 MaxTextureUnits;
|
||||
u32 MaxFixedPipelineTextureUnits;
|
||||
u32 MaxUserClipPlanes;
|
||||
f32 MaxLightDistance;
|
||||
s32 LastSetLight;
|
||||
|
||||
enum E_CACHE_2D_ATTRIBUTES
|
||||
{
|
||||
EC2D_ALPHA = 0x1,
|
||||
EC2D_TEXTURE = 0x2,
|
||||
EC2D_ALPHA_CHANNEL = 0x4
|
||||
};
|
||||
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
D3DFORMAT D3DColorFormat;
|
||||
bool DeviceLost;
|
||||
bool DriverWasReset;
|
||||
bool OcclusionQuerySupport;
|
||||
bool AlphaToCoverageSupport;
|
||||
};
|
||||
|
||||
//! This bridge between Irrlicht pseudo D3D9 calls
|
||||
//! and true D3D9 calls.
|
||||
|
||||
class CD3D9CallBridge
|
||||
{
|
||||
public:
|
||||
CD3D9CallBridge(IDirect3DDevice9* p, CD3D9Driver* driver);
|
||||
|
||||
// Reset to default state.
|
||||
|
||||
void reset();
|
||||
|
||||
// Blending calls.
|
||||
|
||||
void setBlendOperation(DWORD mode);
|
||||
|
||||
void setBlendFunc(DWORD source, DWORD destination);
|
||||
|
||||
void setBlendFuncSeparate(DWORD sourceRGB, DWORD destinationRGB, DWORD sourceAlpha, DWORD destinationAlpha);
|
||||
|
||||
void setBlend(bool enable);
|
||||
|
||||
private:
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
|
||||
DWORD BlendOperation;
|
||||
DWORD BlendSourceRGB;
|
||||
DWORD BlendDestinationRGB;
|
||||
DWORD BlendSourceAlpha;
|
||||
DWORD BlendDestinationAlpha;
|
||||
bool Blend;
|
||||
bool BlendSeparate;
|
||||
|
||||
bool FeatureBlendSeparate;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#endif // __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
416
source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp
Normal file
416
source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp
Normal file
@ -0,0 +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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9HLSLMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver, s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, callback, baseMaterial, userData),
|
||||
VSConstantsTable(0), PSConstantsTable(0)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9HLSLMaterialRenderer");
|
||||
#endif
|
||||
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// now create shaders
|
||||
|
||||
if (vsCompileTarget < 0 || vsCompileTarget > EVST_COUNT)
|
||||
{
|
||||
os::Printer::log("Invalid HLSL vertex shader compilation target", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!createHLSLVertexShader(vertexShaderProgram,
|
||||
vertexShaderEntryPointName, VERTEX_SHADER_TYPE_NAMES[vsCompileTarget]))
|
||||
return;
|
||||
|
||||
if (!createHLSLPixelShader(pixelShaderProgram,
|
||||
pixelShaderEntryPointName, PIXEL_SHADER_TYPE_NAMES[psCompileTarget]))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9HLSLMaterialRenderer::~CD3D9HLSLMaterialRenderer()
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->Release();
|
||||
|
||||
if (PSConstantsTable)
|
||||
PSConstantsTable->Release();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!vertexShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
size_t dataLen_t = strlen(vertexShaderProgram);
|
||||
UINT dataLen = (UINT)dataLen_t;
|
||||
if ( dataLen != dataLen_t )
|
||||
return false;
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
vertexShaderProgram,
|
||||
dataLen,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
0, // no flags
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emit some debug information to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.vsh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vertexShaderProgram, strlen(vertexShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL vertex shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreateVertexShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl vertex shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!pixelShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
DWORD flags = 0;
|
||||
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
if (Driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0) || Driver->queryFeature(video::EVDF_VERTEX_SHADER_3_0))
|
||||
// this one's for newer DX SDKs which don't support ps_1_x anymore
|
||||
// instead they'll silently compile 1_x as 2_x when using this flag
|
||||
flags |= D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY;
|
||||
#endif
|
||||
#if defined(_IRR_D3D_USE_LEGACY_HLSL_COMPILER) && defined(D3DXSHADER_USE_LEGACY_D3DX9_31_DLL)
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
else
|
||||
#endif
|
||||
flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
|
||||
#endif
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
size_t dataLen_t = strlen(pixelShaderProgram);
|
||||
UINT dataLen = (UINT)dataLen_t;
|
||||
if ( dataLen != dataLen_t )
|
||||
return false;
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
pixelShaderProgram,
|
||||
dataLen,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emit some debug information to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.psh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pixelShaderProgram, strlen(pixelShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags | D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL pixel shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl pixel shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
s32 CD3D9HLSLMaterialRenderer::getVariableID(bool vertexShader, const c8* name)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return -1;
|
||||
|
||||
D3DXCONSTANTTABLE_DESC tblDesc;
|
||||
if (!FAILED(tbl->GetDesc(&tblDesc)))
|
||||
{
|
||||
for (u32 i = 0; i < tblDesc.Constants; ++i)
|
||||
{
|
||||
D3DXHANDLE curConst = tbl->GetConstant(NULL, i);
|
||||
D3DXCONSTANT_DESC constDesc;
|
||||
UINT ucount = 1;
|
||||
|
||||
if (!FAILED(tbl->GetConstantDesc(curConst, &constDesc, &ucount)))
|
||||
if(strcmp(name, constDesc.Name) == 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
core::stringc s = "HLSL Variable to get ID not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, s32 index,
|
||||
const f32* floats, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (index < 0 || !tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstant(NULL, index);
|
||||
if (!hndl)
|
||||
return false;
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetFloatArray(pID3DDevice, hndl, floats, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting float array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, s32 index,
|
||||
const s32* ints, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (index < 0 || !tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstant(NULL, index);
|
||||
if (!hndl)
|
||||
return false;
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetIntArray(pID3DDevice, hndl, ints, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting int array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->SetDefaults(pID3DDevice);
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table)
|
||||
{
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
// print out constant names
|
||||
D3DXCONSTANTTABLE_DESC tblDesc;
|
||||
HRESULT hr = table->GetDesc(&tblDesc);
|
||||
if (!FAILED(hr))
|
||||
{
|
||||
for (int i=0; i<(int)tblDesc.Constants; ++i)
|
||||
{
|
||||
D3DXCONSTANT_DESC d;
|
||||
UINT n = 1;
|
||||
D3DXHANDLE cHndl = table->GetConstant(NULL, i);
|
||||
if (!FAILED(table->GetConstantDesc(cHndl, &d, &n)))
|
||||
{
|
||||
core::stringc s = " '";
|
||||
s += d.Name;
|
||||
s += "' Registers:[begin:";
|
||||
s += (int)d.RegisterIndex;
|
||||
s += ", count:";
|
||||
s += (int)d.RegisterCount;
|
||||
s += "]";
|
||||
os::Printer::log(s.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
84
source/Irrlicht/CD3D9HLSLMaterialRenderer.h
Normal file
84
source/Irrlicht/CD3D9HLSLMaterialRenderer.h
Normal file
@ -0,0 +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
|
||||
|
||||
#ifndef __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IGPUProgrammingServices.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders via HLSL with D3D9
|
||||
class CD3D9HLSLMaterialRenderer : public CD3D9ShaderMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9HLSLMaterialRenderer();
|
||||
|
||||
virtual s32 getVariableID(bool vertexShader, const c8* name);
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param index: Index of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, s32 index, const f32* floats, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, s32 index, const s32* ints, int count);
|
||||
|
||||
bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) _IRR_OVERRIDE_;
|
||||
|
||||
protected:
|
||||
|
||||
bool createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
bool createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
void printHLSLVariables(LPD3DXCONSTANTTABLE table);
|
||||
|
||||
LPD3DXCONSTANTTABLE VSConstantsTable;
|
||||
LPD3DXCONSTANTTABLE PSConstantsTable;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
577
source/Irrlicht/CD3D9MaterialRenderer.h
Normal file
577
source/Irrlicht/CD3D9MaterialRenderer.h
Normal file
@ -0,0 +1,577 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
#include "CD3D9Driver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
D3DMATRIX UnitMatrixD3D9;
|
||||
D3DMATRIX SphereMapMatrixD3D9;
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2);
|
||||
}
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
}
|
||||
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2);
|
||||
}
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//! Base class for all internal D3D9 material renderers
|
||||
class CD3D9MaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, CD3D9Driver* driver)
|
||||
: pID3DDevice(d3ddev), Driver(driver)
|
||||
{
|
||||
}
|
||||
|
||||
virtual s32 getVariableID(bool vertexShader, const c8* name)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param index: Index of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, s32 index, const f32* floats, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, s32 index, const s32* ints, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
CD3D9Driver* Driver;
|
||||
};
|
||||
|
||||
|
||||
//! Solid material renderer
|
||||
class CD3D9MaterialRenderer_SOLID : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
}
|
||||
};
|
||||
|
||||
//! Generic Texture Blend
|
||||
class CD3D9MaterialRenderer_ONETEXTURE_BLEND : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
// if (material.MaterialType != lastMaterial.MaterialType ||
|
||||
// material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
|
||||
// resetAllRenderstates)
|
||||
{
|
||||
E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact;
|
||||
E_MODULATE_FUNC modulate;
|
||||
u32 alphaSource;
|
||||
unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam);
|
||||
|
||||
Driver->getBridgeCalls()->setBlend(true);
|
||||
Driver->getBridgeCalls()->setBlendFuncSeparate(Driver->getD3DBlend(srcRGBFact), Driver->getD3DBlend(dstRGBFact),
|
||||
Driver->getD3DBlend(srcAlphaFact), Driver->getD3DBlend(dstAlphaFact));
|
||||
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, Driver->getD3DModulate(modulate), D3DTA_DIFFUSE);
|
||||
|
||||
if (textureBlendFunc_hasAlpha(srcRGBFact) || textureBlendFunc_hasAlpha(dstRGBFact) ||
|
||||
textureBlendFunc_hasAlpha(srcAlphaFact) || textureBlendFunc_hasAlpha(dstAlphaFact))
|
||||
{
|
||||
if (alphaSource==EAS_VERTEX_COLOR)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
}
|
||||
else if (alphaSource==EAS_TEXTURE)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
Driver->getBridgeCalls()->setBlend(false);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
/** The scene management needs to know this for being able to sort the
|
||||
materials by opaque and transparent.
|
||||
The return value could be optimized, but we'd need to know the
|
||||
MaterialTypeParam for it. */
|
||||
virtual bool isTransparent() const _IRR_OVERRIDE_
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Solid 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent add color material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
Driver->getBridgeCalls()->setBlend(true);
|
||||
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_ONE, D3DBLEND_INVSRCCOLOR);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
Driver->getBridgeCalls()->setBlend(false);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const _IRR_OVERRIDE_
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent vertex alpha material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
Driver->getBridgeCalls()->setBlend(true);
|
||||
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
Driver->getBridgeCalls()->setBlend(false);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const _IRR_OVERRIDE_
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
Driver->getBridgeCalls()->setBlend(true);
|
||||
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|
||||
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f));
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
Driver->getBridgeCalls()->setBlend(false);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const _IRR_OVERRIDE_
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
// 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const _IRR_OVERRIDE_
|
||||
{
|
||||
return false; // this material is not really transparent because it does no blending.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! material renderer for all kinds of lightmaps
|
||||
class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING)
|
||||
{
|
||||
// with lighting
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE,
|
||||
(material.MaterialType == EMT_LIGHTMAP_ADD)?
|
||||
D3DTOP_ADD:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)?
|
||||
D3DTOP_MODULATE4X:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)?
|
||||
D3DTOP_MODULATE2X:
|
||||
D3DTOP_MODULATE,
|
||||
D3DTA_CURRENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! material renderer for detail maps
|
||||
class CD3D9MaterialRenderer_DETAIL_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! sphere map material renderer
|
||||
class CD3D9MaterialRenderer_SPHERE_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, CD3D9Driver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
Driver->getBridgeCalls()->setBlend(true);
|
||||
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
|
||||
{
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9);
|
||||
Driver->getBridgeCalls()->setBlend(false);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const _IRR_OVERRIDE_
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
306
source/Irrlicht/CD3D9NormalMapRenderer.cpp
Normal file
306
source/Irrlicht/CD3D9NormalMapRenderer.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9NormalMapRenderer.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// 1.1 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_NORMAL_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius<75> \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius<75> \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - lightpos1\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - lightpos2\n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x<> + r2.y<> + r2.z<> \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x<> + r3.y<> + r3.z<> \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader
|
||||
const char D3D9_NORMAL_MAP_PSH_1_1[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
"ps.1.1 \n"\
|
||||
"tex t0 ; sample color map \n"\
|
||||
"tex t1 ; sample normal map\n"\
|
||||
"texcoord t2 ; fetch light vector 1\n"\
|
||||
"texcoord t3 ; fetch light vector 2\n"\
|
||||
"\n"\
|
||||
"dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\
|
||||
"mul r0, r0, v0 ; luminance1 * light color 1 \n"\
|
||||
"\n"\
|
||||
"dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\
|
||||
"mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\
|
||||
"\n"\
|
||||
"mul r0.xyz, t0, r0 ; total luminance * base color\n"\
|
||||
"+mov r0.a, v0.a ; write interpolated vertex alpha value \n"\
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
// Higher-quality normal map pixel shader (requires PS 2.0)
|
||||
// uses per-pixel normalization for improved accuracy
|
||||
const char D3D9_NORMAL_MAP_PSH_2_0[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
|
||||
"ps_2_0 \n"\
|
||||
"def c0, 0, 0, 0, 0\n"\
|
||||
"def c1, 1.0, 1.0, 1.0, 1.0\n"\
|
||||
"def c2, 2.0, 2.0, 2.0, 2.0\n"\
|
||||
"def c3, -.5, -.5, -.5, -.5\n"\
|
||||
"dcl t0\n"\
|
||||
"dcl t1\n"\
|
||||
"dcl t2\n"\
|
||||
"dcl t3\n"\
|
||||
"dcl v1\n"\
|
||||
"dcl v0\n"\
|
||||
"dcl_2d s0\n"\
|
||||
"dcl_2d s1\n"\
|
||||
|
||||
"texld r0, t0, s0 ; sample color map into r0 \n"\
|
||||
"texld r4, t0, s1 ; sample normal map into r4\n"\
|
||||
"add r4, r4, c3 ; bias the normal vector\n"\
|
||||
"add r5, t2, c3 ; bias the light 1 vector into r5\n"\
|
||||
"add r6, t3, c3 ; bias the light 2 vector into r6\n"\
|
||||
|
||||
"nrm r1, r4 ; normalize the normal vector into r1\n"\
|
||||
"nrm r2, r5 ; normalize the light1 vector into r2\n"\
|
||||
"nrm r3, r6 ; normalize the light2 vector into r3\n"\
|
||||
|
||||
"dp3 r2, r2, r1 ; let r2 = normal DOT light 1 vector\n"\
|
||||
"max r2, r2, c0 ; clamp result to positive numbers\n"\
|
||||
"mul r2, r2, v0 ; let r2 = luminance1 * light color 1 \n"\
|
||||
|
||||
"dp3 r3, r3, r1 ; let r3 = normal DOT light 2 vector\n"\
|
||||
"max r3, r3, c0 ; clamp result to positive numbers\n"\
|
||||
|
||||
"mad r2, r3, v1, r2 ; let r2 = (luminance2 * light color 2) + (luminance2 * light color 1) \n"\
|
||||
|
||||
"mul r2, r2, r0 ; let r2 = total luminance * base color\n"\
|
||||
"mov r2.w, v0.w ; write interpolated vertex alpha value \n"\
|
||||
|
||||
"mov oC0, r2 ; copy r2 to the output register \n"\
|
||||
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
CD3D9NormalMapRenderer::CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9NormalMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basically, this thing simply compiles the hardcoded shaders
|
||||
// if the hardware is able to do them, otherwise it maps to the
|
||||
// base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled normal map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9NormalMapRenderer* nmr = (video::CD3D9NormalMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compile shaders on our own
|
||||
if (driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0))
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_2_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_1_1);
|
||||
}
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9NormalMapRenderer::~CD3D9NormalMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9NormalMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
56
source/Irrlicht/CD3D9NormalMapRenderer.h
Normal file
56
source/Irrlicht/CD3D9NormalMapRenderer.h
Normal file
@ -0,0 +1,56 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps
|
||||
class CD3D9NormalMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9NormalMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData) _IRR_OVERRIDE_;
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
409
source/Irrlicht/CD3D9ParallaxMapRenderer.cpp
Normal file
409
source/Irrlicht/CD3D9ParallaxMapRenderer.cpp
Normal file
@ -0,0 +1,409 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ParallaxMapRenderer.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
//#define SHADER_EXTERNAL_DEBUG
|
||||
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
#include "CReadFile.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// 1.1/1.4 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_PARALLAX_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c4: Eye position \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius<75> \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius<75> \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"def c96, -1, 1, 1, 1 ; somewhere I've got a bug. flipping the vectors with this fixes it. \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - light1 pos\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - light2 pos\n"\
|
||||
"add r1, -c4, r4 ; eye - vtxpos \n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light1 vector with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light2 vector with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"dp3 r10.x, r5, r1 ; transform the eye vector with U, V, W\n"\
|
||||
"dp3 r10.y, r6, r1 \n"\
|
||||
"dp3 r10.z, r7, r1 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
";mul r8, r8, c96 \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
";mul r9, r9, c96 \n"\
|
||||
"dp3 r10.w, r10, r10 ; normalize eye vector (r10)\n"\
|
||||
"rsq r10.w, r10.w \n"\
|
||||
"mul r10, r10, r10.w \n"\
|
||||
"mul r10, r10, c96 \n"\
|
||||
"\n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"mad oT4.xyz, r10.xyz, c95, c95 ; move eye vector from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x<> + r2.y<> + r2.z<> \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x<> + r3.y<> + r3.z<> \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 1.4
|
||||
const char D3D9_PARALLAX_MAP_PSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.1.4 \n"\
|
||||
" \n"\
|
||||
";def c6, 0.02f, 0.02f, 0.02f, 0.0f ; scale factor, now set in callback \n"\
|
||||
"def c5, 0.5f, 0.5f, 0.5f, 0.0f ; for specular division \n"\
|
||||
" \n"\
|
||||
"texld r1, t1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"texcrd r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"texcrd r0.xyz, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
";mul r3, r1_bx2.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to reduce swimming effect: \n"\
|
||||
"mul r3, r1_bx2.wwww, r1_bx2.zzzz ; (nh,nh,nh,nh) = (h,h,h,h) * (n.z,n.z,n.z,n.z,) \n"\
|
||||
"mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
"mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"phase \n"\
|
||||
" \n"\
|
||||
"texld r0, r2 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2 ; sample normal map \n"\
|
||||
"texcrd r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"texcrd r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r5, r1_bx2, r2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r5, r5, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1_bx2, r3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r5 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"+mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 2.0
|
||||
const char D3D9_PARALLAX_MAP_PSH_20[] =
|
||||
";Irrlicht Engine D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
" \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.2.0 \n"\
|
||||
" \n"\
|
||||
"dcl_2d s0 ; Declare the s0 register to be the sampler for stage 0 \n"\
|
||||
"dcl t0.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl t1.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl_2d s1 ; Declare the s1 register to be the sampler for stage 1 \n"\
|
||||
" \n"\
|
||||
"dcl t2.xyz ; \n"\
|
||||
"dcl t3.xyz ; \n"\
|
||||
"dcl t4.xyz ; \n"\
|
||||
"dcl v0.xyzw; \n"\
|
||||
"dcl v1.xyzw; \n"\
|
||||
" \n"\
|
||||
"def c0, -1.0f, -1.0f, -1.0f, -1.0f ; for _bx2 emulation \n"\
|
||||
"def c1, 2.0f, 2.0f, 2.0f, 2.0f ; for _bx2 emulation \n"\
|
||||
"mov r11, c1; \n"\
|
||||
" \n"\
|
||||
"texld r1, t1, s1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"mov r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"mov r0.xy, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mul r3, r1.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r4.xyz, r4, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mad r2.xy, r3, r4, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to avoid swimming: \n"\
|
||||
";mul r3, r1_bx2.wwww, r1_bx2.zzzz ; r3 = (h,h,h,h) * (n.z, n.z, n.z, n.z,) \n"\
|
||||
";mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"texld r0, r2, s0 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2, s1 ; sample normal map \n"\
|
||||
"mov r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"mov r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
"mad r2.xyz, r2, r11, c0; \n"\
|
||||
"mad r3.xyz, r3, r11, c0; \n"\
|
||||
" \n"\
|
||||
"dp3_sat r2, r1, r2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r2, r2, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1, r3 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r2 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"mov oC0, r0; \n"\
|
||||
"\n";
|
||||
|
||||
CD3D9ParallaxMapRenderer::CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial),
|
||||
CurrentScale(0.0f)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ParallaxMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basically, this thing simply compiles these hardcoded shaders if the
|
||||
// hardware is able to do them, otherwise it maps to the base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled parallax map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9ParallaxMapRenderer* nmr = (video::CD3D9ParallaxMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
|
||||
// quickly load shader from external file
|
||||
io::CReadFile* file = new io::CReadFile("parallax.psh");
|
||||
s32 sz = file->getSize();
|
||||
char* s = new char[sz+1];
|
||||
file->read(s, sz);
|
||||
s[sz] = 0;
|
||||
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, s);
|
||||
|
||||
delete [] s;
|
||||
file->drop();
|
||||
|
||||
#else
|
||||
|
||||
// compile shaders on our own
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, D3D9_PARALLAX_MAP_PSH);
|
||||
|
||||
#endif // SHADER_EXTERNAL_DEBUG
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9ParallaxMapRenderer::~CD3D9ParallaxMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
bool CD3D9ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Parallax map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
CD3D9ShaderMaterialRenderer::OnSetMaterial(material, lastMaterial,
|
||||
resetAllRenderstates, services);
|
||||
|
||||
CurrentScale = material.MaterialTypeParam;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9ParallaxMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9ParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set eye position
|
||||
|
||||
// The viewpoint is at (0., 0., 0.) in eye space.
|
||||
// Turning this into a vector [0 0 0 1] and multiply it by
|
||||
// the inverse of the view matrix, the resulting vector is the
|
||||
// object space location of the camera.
|
||||
|
||||
f32 floats[4] = {0,0,0,1};
|
||||
core::matrix4 minv = driver->getTransform(video::ETS_VIEW);
|
||||
minv.makeInverse();
|
||||
minv.multiplyWith1x4Matrix(floats);
|
||||
services->setVertexShaderConstant(floats, 4, 1);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj;
|
||||
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
const u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
f32 c96[] = {-1, 1, 1, 1};
|
||||
services->setVertexShaderConstant(c96, 96, 1);
|
||||
|
||||
// set scale factor
|
||||
f32 factor = 0.02f; // default value
|
||||
if (CurrentScale != 0)
|
||||
factor = CurrentScale;
|
||||
|
||||
f32 c6[] = {factor, factor, factor, 0};
|
||||
services->setPixelShaderConstant(c6, 6, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
63
source/Irrlicht/CD3D9ParallaxMapRenderer.h
Normal file
63
source/Irrlicht/CD3D9ParallaxMapRenderer.h
Normal file
@ -0,0 +1,63 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps using parallax mapping
|
||||
class CD3D9ParallaxMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9ParallaxMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData) _IRR_OVERRIDE_;
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const _IRR_OVERRIDE_;
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material) _IRR_OVERRIDE_ { }
|
||||
virtual void OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
f32 CurrentScale;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
281
source/Irrlicht/CD3D9RenderTarget.cpp
Normal file
281
source/Irrlicht/CD3D9RenderTarget.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
// Copyright (C) 2015 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CD3D9RenderTarget.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "IImage.h"
|
||||
#include "irrMath.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#include "CD3D9Driver.h"
|
||||
#include "CD3D9Texture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
CD3D9RenderTarget::CD3D9RenderTarget(CD3D9Driver* driver) : DepthStencilSurface(0), Driver(driver)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9RenderTarget");
|
||||
#endif
|
||||
|
||||
DriverType = EDT_DIRECT3D9;
|
||||
Size = Driver->getScreenSize();
|
||||
}
|
||||
|
||||
CD3D9RenderTarget::~CD3D9RenderTarget()
|
||||
{
|
||||
for (u32 i = 0; i < Surface.size(); ++i)
|
||||
{
|
||||
if (Surface[i])
|
||||
Surface[i]->Release();
|
||||
}
|
||||
|
||||
if (DepthStencilSurface)
|
||||
DepthStencilSurface->Release();
|
||||
|
||||
for (u32 i = 0; i < Texture.size(); ++i)
|
||||
{
|
||||
if (Texture[i])
|
||||
Texture[i]->drop();
|
||||
}
|
||||
|
||||
if (DepthStencil)
|
||||
DepthStencil->drop();
|
||||
}
|
||||
|
||||
void CD3D9RenderTarget::setTexture(const core::array<ITexture*>& texture, ITexture* depthStencil, const core::array<E_CUBE_SURFACE>& cubeSurfaces)
|
||||
{
|
||||
bool needSizeUpdate = false;
|
||||
|
||||
// Set color attachments.
|
||||
if ((Texture != texture) || (CubeSurfaces != cubeSurfaces))
|
||||
{
|
||||
needSizeUpdate = true;
|
||||
CubeSurfaces = cubeSurfaces; // TODO: we can probably avoid some memory allocating/de-allocating if _only_ CubeSurfaces change.
|
||||
|
||||
if (texture.size() > Driver->ActiveRenderTarget.size())
|
||||
{
|
||||
core::stringc message = "This GPU supports up to ";
|
||||
message += Driver->ActiveRenderTarget.size();
|
||||
message += " textures per render target.";
|
||||
|
||||
os::Printer::log(message.c_str(), ELL_WARNING);
|
||||
}
|
||||
|
||||
const u32 size = core::min_(texture.size(), static_cast<u32>(Driver->ActiveRenderTarget.size()));
|
||||
|
||||
for (u32 i = 0; i < Surface.size(); ++i)
|
||||
{
|
||||
if (Surface[i])
|
||||
Surface[i]->Release();
|
||||
}
|
||||
|
||||
Surface.set_used(size);
|
||||
|
||||
core::array<ITexture*> prevTextures(Texture);
|
||||
|
||||
Texture.set_used(size);
|
||||
|
||||
for (u32 i = 0; i < size; ++i)
|
||||
{
|
||||
CD3D9Texture* currentTexture = (texture[i] && texture[i]->getDriverType() == DriverType) ? static_cast<CD3D9Texture*>(texture[i]) : 0;
|
||||
|
||||
IDirect3DTexture9* textureID = 0;
|
||||
IDirect3DCubeTexture9* cubeTextureId = 0;
|
||||
UINT level = 0; // no support for rendering to to other mip-levels so far
|
||||
|
||||
if (currentTexture)
|
||||
{
|
||||
if (currentTexture->getType() == ETT_2D)
|
||||
textureID = currentTexture->getDX9Texture();
|
||||
else if ( currentTexture->getType() == ETT_CUBEMAP )
|
||||
cubeTextureId = currentTexture->getDX9CubeTexture();
|
||||
}
|
||||
|
||||
if (textureID)
|
||||
{
|
||||
Texture[i] = texture[i];
|
||||
Texture[i]->grab();
|
||||
|
||||
IDirect3DSurface9* currentSurface = 0;
|
||||
textureID->GetSurfaceLevel(level, ¤tSurface);
|
||||
|
||||
Surface[i] = currentSurface;
|
||||
}
|
||||
else if ( cubeTextureId )
|
||||
{
|
||||
Texture[i] = texture[i];
|
||||
Texture[i]->grab();
|
||||
|
||||
IDirect3DSurface9* currentSurface = 0;
|
||||
D3DCUBEMAP_FACES face = (D3DCUBEMAP_FACES)CubeSurfaces[i]; // we use same numbering
|
||||
cubeTextureId->GetCubeMapSurface(face, level, ¤tSurface);
|
||||
|
||||
Surface[i] = currentSurface;
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface[i] = 0;
|
||||
Texture[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < prevTextures.size(); ++i)
|
||||
{
|
||||
if (prevTextures[i])
|
||||
prevTextures[i]->drop();
|
||||
}
|
||||
}
|
||||
|
||||
// Set depth and stencil attachments.
|
||||
|
||||
if (DepthStencil != depthStencil)
|
||||
{
|
||||
if (DepthStencilSurface)
|
||||
{
|
||||
DepthStencilSurface->Release();
|
||||
DepthStencilSurface = 0;
|
||||
}
|
||||
|
||||
if (DepthStencil)
|
||||
{
|
||||
DepthStencil->drop();
|
||||
DepthStencil = 0;
|
||||
|
||||
DepthStencilSurface = 0;
|
||||
}
|
||||
|
||||
needSizeUpdate = true;
|
||||
CD3D9Texture* currentTexture = (depthStencil && depthStencil->getDriverType() == DriverType) ? static_cast<CD3D9Texture*>(depthStencil) : 0;
|
||||
|
||||
if (currentTexture)
|
||||
{
|
||||
if (currentTexture->getType() == ETT_2D)
|
||||
{
|
||||
IDirect3DTexture9* textureID = currentTexture->getDX9Texture();
|
||||
if (textureID)
|
||||
{
|
||||
const ECOLOR_FORMAT textureFormat = depthStencil->getColorFormat();
|
||||
if (IImage::isDepthFormat(textureFormat))
|
||||
{
|
||||
DepthStencil = depthStencil;
|
||||
DepthStencil->grab();
|
||||
|
||||
IDirect3DSurface9* currentSurface = 0;
|
||||
textureID->GetSurfaceLevel(0, ¤tSurface);
|
||||
|
||||
DepthStencilSurface = currentSurface;
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("Ignoring depth/stencil texture without depth color format.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
os::Printer::log("This driver doesn't support depth/stencil to cubemaps.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if (needSizeUpdate)
|
||||
{
|
||||
// Set size required for a viewport.
|
||||
|
||||
bool sizeDetected = false;
|
||||
|
||||
for (u32 i = 0; i < Texture.size(); ++i)
|
||||
{
|
||||
if (Texture[i])
|
||||
{
|
||||
Size = Texture[i]->getSize();
|
||||
sizeDetected = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sizeDetected)
|
||||
{
|
||||
if (DepthStencil)
|
||||
Size = DepthStencil->getSize();
|
||||
else
|
||||
Size = Driver->getScreenSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const core::dimension2d<u32>& CD3D9RenderTarget::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
IDirect3DSurface9* CD3D9RenderTarget::getSurface(u32 id) const
|
||||
{
|
||||
return (id < Surface.size()) ? Surface[id] : 0;
|
||||
}
|
||||
|
||||
u32 CD3D9RenderTarget::getSurfaceCount() const
|
||||
{
|
||||
return Surface.size();
|
||||
}
|
||||
|
||||
IDirect3DSurface9* CD3D9RenderTarget::getDepthStencilSurface() const
|
||||
{
|
||||
return DepthStencilSurface;
|
||||
}
|
||||
|
||||
void CD3D9RenderTarget::releaseSurfaces()
|
||||
{
|
||||
for (u32 i = 0; i < Surface.size(); ++i)
|
||||
{
|
||||
if (Surface[i])
|
||||
{
|
||||
Surface[i]->Release();
|
||||
Surface[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (DepthStencilSurface)
|
||||
{
|
||||
DepthStencilSurface->Release();
|
||||
DepthStencilSurface = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CD3D9RenderTarget::generateSurfaces()
|
||||
{
|
||||
for (u32 i = 0; i < Surface.size(); ++i)
|
||||
{
|
||||
if (!Surface[i] && Texture[i])
|
||||
{
|
||||
IDirect3DTexture9* currentTexture = static_cast<CD3D9Texture*>(Texture[i])->getDX9Texture();
|
||||
if ( currentTexture )
|
||||
{
|
||||
IDirect3DSurface9* currentSurface = 0;
|
||||
currentTexture->GetSurfaceLevel(0, ¤tSurface);
|
||||
Surface[i] = currentSurface;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!DepthStencilSurface && DepthStencil)
|
||||
{
|
||||
IDirect3DTexture9* currentTexture = static_cast<CD3D9Texture*>(DepthStencil)->getDX9Texture();
|
||||
if ( currentTexture )
|
||||
{
|
||||
IDirect3DSurface9* currentSurface = 0;
|
||||
currentTexture->GetSurfaceLevel(0, ¤tSurface);
|
||||
DepthStencilSurface = currentSurface;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
60
source/Irrlicht/CD3D9RenderTarget.h
Normal file
60
source/Irrlicht/CD3D9RenderTarget.h
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2015 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_OPEN_GL_RENDER_TARGET_H_INCLUDED__
|
||||
#define __C_OPEN_GL_RENDER_TARGET_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "IRenderTarget.h"
|
||||
|
||||
#include "dimension2d.h"
|
||||
#include "os.h"
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CD3D9Driver;
|
||||
|
||||
class CD3D9RenderTarget : public IRenderTarget
|
||||
{
|
||||
public:
|
||||
CD3D9RenderTarget(CD3D9Driver* driver);
|
||||
virtual ~CD3D9RenderTarget();
|
||||
|
||||
virtual void setTexture(const core::array<ITexture*>& texture, ITexture* depthStencil, const core::array<E_CUBE_SURFACE>& cubeSurfaces) _IRR_OVERRIDE_;
|
||||
|
||||
const core::dimension2d<u32>& getSize() const;
|
||||
|
||||
IDirect3DSurface9* getSurface(u32 id) const;
|
||||
|
||||
u32 getSurfaceCount() const;
|
||||
|
||||
IDirect3DSurface9* getDepthStencilSurface() const;
|
||||
|
||||
void releaseSurfaces();
|
||||
|
||||
void generateSurfaces();
|
||||
|
||||
protected:
|
||||
core::dimension2d<u32> Size;
|
||||
|
||||
core::array<IDirect3DSurface9*> Surface;
|
||||
|
||||
IDirect3DSurface9* DepthStencilSurface;
|
||||
|
||||
CD3D9Driver* Driver;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
539
source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp
Normal file
539
source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp
Normal file
@ -0,0 +1,539 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
|
||||
init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);
|
||||
}
|
||||
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram, const c8* pixelShaderProgram)
|
||||
{
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// create vertex shader
|
||||
if (!createVertexShader(vertexShaderProgram))
|
||||
return;
|
||||
|
||||
// create pixel shader
|
||||
if (!createPixelShader(pixelShaderProgram))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer()
|
||||
{
|
||||
if (CallBack)
|
||||
CallBack->drop();
|
||||
|
||||
if (VertexShader)
|
||||
VertexShader->Release();
|
||||
|
||||
if (PixelShader)
|
||||
PixelShader->Release();
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->drop();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
// call callback to set shader constants
|
||||
if (CallBack && (VertexShader || PixelShader))
|
||||
CallBack->OnSetConstants(service, UserData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (VertexShader)
|
||||
{
|
||||
// save old vertex shader
|
||||
pID3DDevice->GetVertexShader(&OldVertexShader);
|
||||
|
||||
// set new vertex shader
|
||||
if (FAILED(pID3DDevice->SetVertexShader(VertexShader)))
|
||||
os::Printer::log("Could not set vertex shader.", ELL_WARNING);
|
||||
}
|
||||
|
||||
// set new pixel shader
|
||||
if (PixelShader)
|
||||
{
|
||||
if (FAILED(pID3DDevice->SetPixelShader(PixelShader)))
|
||||
os::Printer::log("Could not set pixel shader.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnSetMaterial(material, lastMaterial, resetAllRenderstates, services);
|
||||
|
||||
if (CallBack)
|
||||
CallBack->OnSetMaterial(material);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnUnsetMaterial()
|
||||
{
|
||||
if (VertexShader)
|
||||
pID3DDevice->SetVertexShader(OldVertexShader);
|
||||
|
||||
if (PixelShader)
|
||||
pID3DDevice->SetPixelShader(0);
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnUnsetMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
bool CD3D9ShaderMaterialRenderer::isTransparent() const
|
||||
{
|
||||
return BaseMaterial ? BaseMaterial->isTransparent() : false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh)
|
||||
{
|
||||
if (!pxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, 0, &code, &errors);
|
||||
#else
|
||||
|
||||
// compile shader and emit some debug information to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.psh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pxsh, strlen(pxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Pixel shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create pixel shader.", ELL_ERROR);
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh)
|
||||
{
|
||||
if (!vtxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, 0, &code, &errors);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emit some debug information to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.vsh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vtxsh, strlen(vtxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Vertex shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!code || FAILED(pID3DDevice->CreateVertexShader((DWORD*)code->GetBufferPointer(), &VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create vertex shader.", ELL_ERROR);
|
||||
if (code)
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData,
|
||||
UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// Because Irrlicht needs to be able to start up even without installed d3d dlls, it
|
||||
// needs to load external d3d dlls manually. examples for the dlls are:
|
||||
// SDK dll name D3DX_SDK_VERSION
|
||||
// Summer 2004: no dll 22
|
||||
// February 2005: d3dx9_24.dll 24
|
||||
// April 2005: d3dx9_25.dll 25
|
||||
// June 2005: d3dx9_26.dll 26
|
||||
// August 2005: d3dx9_27.dll 27
|
||||
// October 2005,
|
||||
// December 2005: d3dx9_28.dll 28
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, pInclude,
|
||||
Flags, ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShader signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFunction)GetProcAddress(hMod, "D3DXAssembleShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShaderFromFileA(pSrcFile, pDefines, pInclude, Flags,
|
||||
ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShaderFromFileA signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFromFileFunction)GetProcAddress(hMod, "D3DXAssembleShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShader(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShader
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFunction)GetProcAddress(hMod, "D3DXCompileShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShaderFromFileA
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFromFileFunction)GetProcAddress(hMod, "D3DXCompileShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
108
source/Irrlicht/CD3D9ShaderMaterialRenderer.h
Normal file
108
source/Irrlicht/CD3D9ShaderMaterialRenderer.h
Normal file
@ -0,0 +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
|
||||
|
||||
#ifndef __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3dx9shader.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders with D3D9
|
||||
class CD3D9ShaderMaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9ShaderMaterialRenderer();
|
||||
|
||||
virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services) _IRR_OVERRIDE_;
|
||||
|
||||
virtual void OnUnsetMaterial() _IRR_OVERRIDE_;
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
virtual bool isTransparent() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Access the callback provided by the users when creating shader materials
|
||||
virtual IShaderConstantSetCallBack* getShaderConstantSetCallBack() const _IRR_OVERRIDE_
|
||||
{
|
||||
return CallBack;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData=0);
|
||||
|
||||
void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram);
|
||||
bool createPixelShader(const c8* pxsh);
|
||||
bool createVertexShader(const char* vtxsh);
|
||||
|
||||
HRESULT stubD3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
HRESULT stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
IShaderConstantSetCallBack* CallBack;
|
||||
IMaterialRenderer* BaseMaterial;
|
||||
|
||||
IDirect3DVertexShader9* VertexShader;
|
||||
IDirect3DVertexShader9* OldVertexShader;
|
||||
IDirect3DPixelShader9* PixelShader;
|
||||
s32 UserData;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
758
source/Irrlicht/CD3D9Texture.cpp
Normal file
758
source/Irrlicht/CD3D9Texture.cpp
Normal file
@ -0,0 +1,758 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9Texture.h"
|
||||
#include "CD3D9Driver.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
CD3D9Texture::CD3D9Texture(const io::path& name, const core::array<IImage*>& image, E_TEXTURE_TYPE type, CD3D9Driver* driver)
|
||||
: ITexture(name, type), Driver(driver), InternalFormat(D3DFMT_UNKNOWN), LockReadOnly(false), LockData(0), LockLayer(0),
|
||||
MipLevelLocked(0), HardwareMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
_IRR_DEBUG_BREAK_IF(image.size() == 0)
|
||||
|
||||
Device=driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
DriverType = Driver->getDriverType();
|
||||
HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
|
||||
HardwareMipMaps = Driver->getTextureCreationFlag(ETCF_AUTO_GENERATE_MIP_MAPS) && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);
|
||||
|
||||
getImageValues(image[0]);
|
||||
|
||||
DWORD flags = 0;
|
||||
|
||||
if (HasMipMaps && HardwareMipMaps)
|
||||
{
|
||||
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
|
||||
D3DDISPLAYMODE d3ddm;
|
||||
intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm);
|
||||
|
||||
if (D3D_OK == intf->CheckDeviceFormat(Driver->Params.DisplayAdapter, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, InternalFormat))
|
||||
flags = D3DUSAGE_AUTOGENMIPMAP;
|
||||
else
|
||||
HardwareMipMaps = false;
|
||||
}
|
||||
|
||||
HRESULT hr = 0;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ETT_2D:
|
||||
hr = Device->CreateTexture(Size.Width, Size.Height, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &Texture, NULL);
|
||||
break;
|
||||
case ETT_CUBEMAP:
|
||||
hr = Device->CreateCubeTexture(Size.Width, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &CubeTexture, NULL);
|
||||
break;
|
||||
default:
|
||||
_IRR_DEBUG_BREAK_IF(true)
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Try again with 16-bit format
|
||||
if (InternalFormat == D3DFMT_A8R8G8B8)
|
||||
{
|
||||
InternalFormat = D3DFMT_A1R5G5B5;
|
||||
ColorFormat = ECF_A1R5G5B5;
|
||||
}
|
||||
else if (InternalFormat == D3DFMT_R8G8B8) // (24 bit is usually failing in d3d9, not sure if it's ever supported)
|
||||
{
|
||||
InternalFormat = D3DFMT_R5G6B5;
|
||||
ColorFormat = ECF_R5G6B5;
|
||||
}
|
||||
switch (Type)
|
||||
{
|
||||
case ETT_2D:
|
||||
hr = Device->CreateTexture(Size.Width, Size.Height, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &Texture, NULL);
|
||||
break;
|
||||
case ETT_CUBEMAP:
|
||||
hr = Device->CreateCubeTexture(Size.Width, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &CubeTexture, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
core::array<IImage*> tmpImage = image;
|
||||
bool releaseImageData = false;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (OriginalSize != Size || OriginalColorFormat != ColorFormat)
|
||||
{
|
||||
releaseImageData = true;
|
||||
|
||||
for (u32 i = 0; i < image.size(); ++i)
|
||||
{
|
||||
tmpImage[i] = Driver->createImage(ColorFormat, Size);
|
||||
|
||||
if (image[i]->getDimension() == Size)
|
||||
image[i]->copyTo(tmpImage[i]);
|
||||
else
|
||||
image[i]->copyToScaling(tmpImage[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < tmpImage.size(); ++i)
|
||||
uploadTexture(tmpImage[i]->getData(), 0, i);
|
||||
|
||||
bool autoGenerateRequired = true;
|
||||
|
||||
for (u32 i = 0; i < tmpImage.size(); ++i)
|
||||
{
|
||||
void* mipmapsData = tmpImage[i]->getMipMapsData();
|
||||
|
||||
if (autoGenerateRequired || mipmapsData)
|
||||
regenerateMipMapLevels(mipmapsData, i);
|
||||
|
||||
if (!mipmapsData)
|
||||
autoGenerateRequired = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (hr )
|
||||
{
|
||||
case D3DERR_INVALIDCALL:
|
||||
os::Printer::log("Could not create DIRECT3D9 Texture. D3DERR_INVALIDCALL", ELL_WARNING);
|
||||
break;
|
||||
case D3DERR_OUTOFVIDEOMEMORY:
|
||||
os::Printer::log("Could not create DIRECT3D9 Texture. D3DERR_OUTOFVIDEOMEMORY", ELL_WARNING);
|
||||
break;
|
||||
case E_OUTOFMEMORY:
|
||||
os::Printer::log("Could not create DIRECT3D9 Texture. E_OUTOFMEMORY", ELL_WARNING);
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if (releaseImageData)
|
||||
{
|
||||
for (u32 i = 0; i < tmpImage.size(); ++i)
|
||||
tmpImage[i]->drop();
|
||||
}
|
||||
}
|
||||
|
||||
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name, E_TEXTURE_TYPE type, const ECOLOR_FORMAT format)
|
||||
: ITexture(name, type), Driver(driver), InternalFormat(D3DFMT_UNKNOWN), LockReadOnly(false), LockData(0), LockLayer(0),
|
||||
MipLevelLocked(0), HardwareMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
Device = driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
DriverType = Driver->getDriverType();
|
||||
HasMipMaps = false;
|
||||
IsRenderTarget = true;
|
||||
|
||||
OriginalColorFormat = format;
|
||||
|
||||
if (ECF_UNKNOWN == OriginalColorFormat)
|
||||
ColorFormat = getBestColorFormat(Driver->getColorFormat());
|
||||
else
|
||||
ColorFormat = OriginalColorFormat;
|
||||
|
||||
OriginalSize = size;
|
||||
Size = OriginalSize;
|
||||
|
||||
if (!Driver->queryFeature(EVDF_TEXTURE_NPOT))
|
||||
{
|
||||
Size = Size.getOptimalSize(true, !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
if (Size != OriginalSize)
|
||||
os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);
|
||||
}
|
||||
|
||||
Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;
|
||||
|
||||
InternalFormat = Driver->getD3DFormatFromColorFormat(ColorFormat);
|
||||
|
||||
generateRenderTarget();
|
||||
}
|
||||
|
||||
CD3D9Texture::~CD3D9Texture()
|
||||
{
|
||||
releaseTexture();
|
||||
|
||||
if (Device)
|
||||
Device->Release();
|
||||
}
|
||||
|
||||
void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel, u32 layer, E_TEXTURE_LOCK_FLAGS lockFlags)
|
||||
{
|
||||
if (LockData)
|
||||
return LockData;
|
||||
|
||||
if (IImage::isCompressedFormat(ColorFormat))
|
||||
return 0;
|
||||
|
||||
MipLevelLocked = mipmapLevel;
|
||||
LockReadOnly = (mode == ETLM_READ_ONLY);
|
||||
LockLayer = layer;
|
||||
|
||||
HRESULT hr;
|
||||
D3DLOCKED_RECT rect;
|
||||
|
||||
if (!IsRenderTarget)
|
||||
{
|
||||
if (Texture)
|
||||
{
|
||||
hr = Texture->LockRect(MipLevelLocked, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);
|
||||
}
|
||||
else if (CubeTexture)
|
||||
{
|
||||
_IRR_DEBUG_BREAK_IF(layer > 5)
|
||||
|
||||
hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), MipLevelLocked, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture. Missing internal D3D texture.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!RTTSurface)
|
||||
{
|
||||
// Make RTT surface large enough for all miplevels (including 0)
|
||||
D3DSURFACE_DESC desc;
|
||||
if (Texture)
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
else if (CubeTexture)
|
||||
CubeTexture->GetLevelDesc(0, &desc);
|
||||
hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *surface = 0;
|
||||
if (Texture)
|
||||
hr = Texture->GetSurfaceLevel(MipLevelLocked, &surface);
|
||||
else if (CubeTexture)
|
||||
hr = CubeTexture->GetCubeMapSurface(static_cast<_D3DCUBEMAP_FACES>(layer), MipLevelLocked, &surface);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = Device->GetRenderTargetData(surface, RTTSurface);
|
||||
surface->Release();
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = RTTSurface->LockRect(&rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LockData = rect.pBits;
|
||||
|
||||
return LockData;
|
||||
}
|
||||
|
||||
void CD3D9Texture::unlock()
|
||||
{
|
||||
if (!LockData)
|
||||
return;
|
||||
|
||||
if (!IsRenderTarget)
|
||||
{
|
||||
if (Texture)
|
||||
{
|
||||
Texture->UnlockRect(MipLevelLocked);
|
||||
}
|
||||
else if (CubeTexture)
|
||||
{
|
||||
CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(LockLayer), MipLevelLocked);
|
||||
}
|
||||
}
|
||||
else if (RTTSurface)
|
||||
{
|
||||
RTTSurface->UnlockRect();
|
||||
}
|
||||
|
||||
LockReadOnly = false;
|
||||
LockData = 0;
|
||||
LockLayer = 0;
|
||||
}
|
||||
|
||||
void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)
|
||||
{
|
||||
if (!HasMipMaps || (Size.Width <= 1 && Size.Height <= 1))
|
||||
return;
|
||||
|
||||
if ( HardwareMipMaps )
|
||||
{
|
||||
// Can't update with custom data with those unfortunately
|
||||
// Also MSDN docs don't mention it, but GenerateMipSubLevels only works when AUTOGENMIPMAP is set.
|
||||
// So we can't call this to get hardware mipmaps when not setting AUTOGENMIPMAP.
|
||||
if (Texture)
|
||||
Texture->GenerateMipSubLevels();
|
||||
else if (CubeTexture)
|
||||
CubeTexture->GenerateMipSubLevels();
|
||||
}
|
||||
else if (data)
|
||||
{
|
||||
u32 width = Size.Width;
|
||||
u32 height = Size.Height;
|
||||
u8* tmpData = static_cast<u8*>(data);
|
||||
u32 dataSize = 0;
|
||||
u32 level = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (width > 1)
|
||||
width >>= 1;
|
||||
|
||||
if (height > 1)
|
||||
height >>= 1;
|
||||
|
||||
dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
|
||||
++level;
|
||||
|
||||
uploadTexture(tmpData, level, layer);
|
||||
|
||||
tmpData += dataSize;
|
||||
} while (width != 1 || height != 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
createManualMipMaps(1);
|
||||
}
|
||||
}
|
||||
|
||||
void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
SColor c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
else
|
||||
c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
u16 c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = RGBA16(r,g,b,a);
|
||||
else
|
||||
c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);
|
||||
*(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
SColor c;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
c.set(a, r, g, b);
|
||||
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CD3D9Texture::createManualMipMaps(u32 level)
|
||||
{
|
||||
if (level==0)
|
||||
return true;
|
||||
|
||||
if (!Texture) //Manual mips for CubeTexture not supported yet
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// manual mipmap generation
|
||||
IDirect3DSurface9* upperSurface = 0;
|
||||
IDirect3DSurface9* lowerSurface = 0;
|
||||
|
||||
// get upper level
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
|
||||
if (FAILED(hr) || !upperSurface)
|
||||
{
|
||||
os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get lower level
|
||||
hr = Texture->GetSurfaceLevel(level, &lowerSurface);
|
||||
if (FAILED(hr) || !lowerSurface)
|
||||
{
|
||||
os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);
|
||||
upperSurface->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC upperDesc, lowerDesc;
|
||||
upperSurface->GetDesc(&upperDesc);
|
||||
lowerSurface->GetDesc(&lowerDesc);
|
||||
|
||||
D3DLOCKED_RECT upperlr;
|
||||
D3DLOCKED_RECT lowerlr;
|
||||
|
||||
// lock upper surface
|
||||
if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// lock lower surface
|
||||
if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->UnlockRect();
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (upperDesc.Format != lowerDesc.Format)
|
||||
{
|
||||
os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
|
||||
copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
if (upperDesc.Format == D3DFMT_A8R8G8B8)
|
||||
copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);
|
||||
}
|
||||
|
||||
bool result=true;
|
||||
// unlock
|
||||
if (FAILED(upperSurface->UnlockRect()))
|
||||
result=false;
|
||||
if (FAILED(lowerSurface->UnlockRect()))
|
||||
result=false;
|
||||
|
||||
// release
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
|
||||
if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3))
|
||||
return result; // stop generating levels
|
||||
|
||||
// generate next level
|
||||
return createManualMipMaps(level+1);
|
||||
}
|
||||
|
||||
|
||||
IDirect3DBaseTexture9* CD3D9Texture::getDX9BaseTexture() const
|
||||
{
|
||||
return (Texture) ? static_cast<IDirect3DBaseTexture9*>(Texture) : static_cast<IDirect3DBaseTexture9*>(CubeTexture);
|
||||
}
|
||||
|
||||
IDirect3DTexture9* CD3D9Texture::getDX9Texture() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
IDirect3DCubeTexture9* CD3D9Texture::getDX9CubeTexture() const
|
||||
{
|
||||
return CubeTexture;
|
||||
}
|
||||
|
||||
void CD3D9Texture::releaseTexture()
|
||||
{
|
||||
if (RTTSurface)
|
||||
{
|
||||
if (RTTSurface->Release() == 0)
|
||||
RTTSurface = 0;
|
||||
}
|
||||
|
||||
if (Texture)
|
||||
{
|
||||
if (Texture->Release() == 0)
|
||||
Texture = 0;
|
||||
}
|
||||
|
||||
if (CubeTexture)
|
||||
{
|
||||
if (CubeTexture->Release() == 0)
|
||||
CubeTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CD3D9Texture::generateRenderTarget()
|
||||
{
|
||||
DWORD flags = (IImage::isDepthFormat(ColorFormat)) ? D3DUSAGE_DEPTHSTENCIL : D3DUSAGE_RENDERTARGET;
|
||||
|
||||
HRESULT hr = 0;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ETT_2D:
|
||||
if (!Texture )
|
||||
hr = Device->CreateTexture(Size.Width, Size.Height, 1, flags, InternalFormat, D3DPOOL_DEFAULT, &Texture, NULL);
|
||||
break;
|
||||
case ETT_CUBEMAP:
|
||||
if (!CubeTexture)
|
||||
hr = Device->CreateCubeTexture(Size.Width, 1, flags, InternalFormat, D3DPOOL_DEFAULT, &CubeTexture, NULL);
|
||||
break;
|
||||
default:
|
||||
_IRR_DEBUG_BREAK_IF(true)
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (D3DERR_INVALIDCALL == hr)
|
||||
os::Printer::log("Could not create render target texture", "Invalid Call", irr::ELL_ERROR);
|
||||
else if (D3DERR_OUTOFVIDEOMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Video Memory", irr::ELL_ERROR);
|
||||
else if (E_OUTOFMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Memory", irr::ELL_ERROR);
|
||||
else
|
||||
os::Printer::log("Could not create render target texture", irr::ELL_ERROR);
|
||||
core::stringc params("Width:");
|
||||
params += (unsigned int)Size.Width;
|
||||
params += " Height: ";
|
||||
params += (unsigned int)Size.Height;
|
||||
params += " flag: ";
|
||||
params += (unsigned int)flags;
|
||||
params += " format";
|
||||
params += (unsigned int)InternalFormat;
|
||||
params += " Type: ";
|
||||
params += (unsigned int)Type;
|
||||
os::Printer::log(params.c_str(), irr::ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
ECOLOR_FORMAT CD3D9Texture::getBestColorFormat(ECOLOR_FORMAT format)
|
||||
{
|
||||
// We only try for to adapt "simple" formats
|
||||
ECOLOR_FORMAT destFormat = (format <= ECF_A8R8G8B8) ? ECF_A8R8G8B8 : format;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
|
||||
destFormat = ECF_R5G6B5;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
|
||||
Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
// Note: Using ECF_A8R8G8B8 even when ETCF_ALWAYS_32_BIT is not set as 24 bit textures fail with too many cards
|
||||
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||
destFormat = ECF_A1R5G5B5;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL))
|
||||
{
|
||||
switch (destFormat)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
destFormat = ECF_R5G6B5;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
destFormat = ECF_R8G8B8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return destFormat;
|
||||
}
|
||||
|
||||
void CD3D9Texture::getImageValues(const IImage* image)
|
||||
{
|
||||
OriginalColorFormat = image->getColorFormat();
|
||||
ColorFormat = getBestColorFormat(OriginalColorFormat);
|
||||
|
||||
InternalFormat = Driver->getD3DFormatFromColorFormat(ColorFormat);
|
||||
|
||||
if (IImage::isCompressedFormat(image->getColorFormat()))
|
||||
{
|
||||
HardwareMipMaps = false;
|
||||
}
|
||||
|
||||
OriginalSize = image->getDimension();
|
||||
Size = OriginalSize;
|
||||
|
||||
if (Size.Width == 0 || Size.Height == 0)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for texture.", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
const f32 ratio = (f32)Size.Width / (f32)Size.Height;
|
||||
|
||||
if ((Size.Width > Driver->Caps.MaxTextureWidth) && (ratio >= 1.f))
|
||||
{
|
||||
Size.Width = Driver->Caps.MaxTextureWidth;
|
||||
Size.Height = (u32)(Driver->Caps.MaxTextureWidth / ratio);
|
||||
}
|
||||
else if (Size.Height > Driver->Caps.MaxTextureHeight)
|
||||
{
|
||||
Size.Height = Driver->Caps.MaxTextureHeight;
|
||||
Size.Width = (u32)(Driver->Caps.MaxTextureHeight * ratio);
|
||||
}
|
||||
|
||||
bool needSquare = (!Driver->queryFeature(EVDF_TEXTURE_NSQUARE) || Type == ETT_CUBEMAP);
|
||||
|
||||
Size = Size.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), needSquare, true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;
|
||||
}
|
||||
|
||||
void CD3D9Texture::uploadTexture(void* data, u32 mipmapLevel, u32 layer)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
u32 width = Size.Width >> mipmapLevel;
|
||||
u32 height = Size.Height >> mipmapLevel;
|
||||
|
||||
u32 dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
|
||||
|
||||
HRESULT hr = 0;
|
||||
|
||||
D3DLOCKED_RECT lockRectangle;
|
||||
|
||||
if (Texture)
|
||||
{
|
||||
hr = Texture->LockRect(mipmapLevel, &lockRectangle, 0, 0);
|
||||
}
|
||||
else if (CubeTexture)
|
||||
{
|
||||
_IRR_DEBUG_BREAK_IF(layer > 5)
|
||||
|
||||
hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), mipmapLevel, &lockRectangle, 0, 0);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(lockRectangle.pBits, data, dataSize);
|
||||
|
||||
if (Texture)
|
||||
{
|
||||
hr = Texture->UnlockRect(mipmapLevel);
|
||||
}
|
||||
else if (CubeTexture)
|
||||
{
|
||||
hr = CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(layer), mipmapLevel);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
91
source/Irrlicht/CD3D9Texture.h
Normal file
91
source/Irrlicht/CD3D9Texture.h
Normal file
@ -0,0 +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
|
||||
|
||||
#ifndef __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
#define __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "irrArray.h"
|
||||
#include "ITexture.h"
|
||||
#include "IImage.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CD3D9Driver;
|
||||
|
||||
class CD3D9Texture : public ITexture
|
||||
{
|
||||
public:
|
||||
CD3D9Texture(const io::path& name, const core::array<IImage*>& image, E_TEXTURE_TYPE type, CD3D9Driver* driver);
|
||||
|
||||
CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name, E_TEXTURE_TYPE type, const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
virtual ~CD3D9Texture();
|
||||
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode = ETLM_READ_WRITE, u32 mipmapLevel=0, u32 layer = 0, E_TEXTURE_LOCK_FLAGS lockFlags = ETLF_FLIP_Y_UP_RTT) _IRR_OVERRIDE_;
|
||||
|
||||
virtual void unlock() _IRR_OVERRIDE_;
|
||||
|
||||
virtual void regenerateMipMapLevels(void* data = 0, u32 layer = 0) _IRR_OVERRIDE_;
|
||||
|
||||
IDirect3DBaseTexture9* getDX9BaseTexture() const;
|
||||
IDirect3DTexture9* getDX9Texture() const;
|
||||
IDirect3DCubeTexture9* getDX9CubeTexture() const;
|
||||
|
||||
private:
|
||||
friend class CD3D9Driver;
|
||||
|
||||
void releaseTexture();
|
||||
|
||||
void generateRenderTarget();
|
||||
|
||||
ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format);
|
||||
|
||||
void getImageValues(const IImage* image);
|
||||
|
||||
void uploadTexture(void* data, u32 mipmapLevel, u32 layer);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
bool createManualMipMaps(u32 level);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
|
||||
CD3D9Driver* Driver;
|
||||
|
||||
D3DFORMAT InternalFormat;
|
||||
|
||||
bool LockReadOnly;
|
||||
void* LockData;
|
||||
u32 LockLayer;
|
||||
u32 MipLevelLocked;
|
||||
|
||||
bool HardwareMipMaps;
|
||||
|
||||
IDirect3DDevice9* Device;
|
||||
IDirect3DTexture9* Texture;
|
||||
IDirect3DCubeTexture9* CubeTexture;
|
||||
IDirect3DSurface9* RTTSurface;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
431
source/Irrlicht/CDMFLoader.cpp
Normal file
431
source/Irrlicht/CDMFLoader.cpp
Normal file
@ -0,0 +1,431 @@
|
||||
// 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 originally written by Salvatore Russo.
|
||||
// I (Nikolaus Gebhardt) did some minor modifications and changes to it and
|
||||
// integrated it into Irrlicht.
|
||||
// Thanks a lot to Salvatore for his work on this and that he gave me
|
||||
// his permission to add it into Irrlicht using the zlib license.
|
||||
/*
|
||||
CDMFLoader by Salvatore Russo (September 2005)
|
||||
|
||||
See the header file for additional information including use and distribution rights.
|
||||
*/
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _IRR_DMF_DEBUG_
|
||||
#include "os.h"
|
||||
#endif
|
||||
|
||||
#include "CDMFLoader.h"
|
||||
#include "CMeshTextureLoader.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IAttributes.h"
|
||||
#include "SAnimatedMesh.h"
|
||||
#include "SSkinMeshBuffer.h"
|
||||
#include "irrString.h"
|
||||
#include "irrMath.h"
|
||||
#include "dmfsupport.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
/** Constructor*/
|
||||
CDMFLoader::CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys)
|
||||
: SceneMgr(smgr), FileSystem(filesys)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IReferenceCounted::setDebugName("CDMFLoader");
|
||||
#endif
|
||||
|
||||
TextureLoader = new CMeshTextureLoader( FileSystem, SceneMgr->getVideoDriver() );
|
||||
}
|
||||
|
||||
void CDMFLoader::addMaterialPath(core::stringc& filename, const core::stringc& matPath)
|
||||
{
|
||||
c8 last = matPath.lastChar();
|
||||
if ( last == '/' || last == '\\' )
|
||||
filename = matPath+filename;
|
||||
else
|
||||
{
|
||||
core::stringc matPathSlash(matPath);
|
||||
matPathSlash.append('/');
|
||||
filename = matPathSlash+filename;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**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* CDMFLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
if ( getMeshTextureLoader() )
|
||||
{
|
||||
getMeshTextureLoader()->setMeshFile(file);
|
||||
|
||||
if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) )
|
||||
getMeshTextureLoader()->setTexturePath( SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH) );
|
||||
}
|
||||
|
||||
video::IVideoDriver* driver = SceneMgr->getVideoDriver();
|
||||
|
||||
//Load stringlist
|
||||
StringList dmfRawFile;
|
||||
LoadFromFile(file, dmfRawFile);
|
||||
|
||||
if (dmfRawFile.size()==0)
|
||||
return 0;
|
||||
|
||||
SMesh * mesh = new SMesh();
|
||||
|
||||
u32 i;
|
||||
|
||||
dmfHeader header;
|
||||
|
||||
//load header
|
||||
core::array<dmfMaterial> materiali;
|
||||
if (GetDMFHeader(dmfRawFile, header))
|
||||
{
|
||||
//let's set ambient light
|
||||
SceneMgr->setAmbientLight(header.dmfAmbient);
|
||||
|
||||
//let's create the correct number of materials, vertices and faces
|
||||
dmfVert *verts=new dmfVert[header.numVertices];
|
||||
dmfFace *faces=new dmfFace[header.numFaces];
|
||||
|
||||
//let's get the materials
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str());
|
||||
#endif
|
||||
GetDMFMaterials(dmfRawFile, materiali, header.numMaterials);
|
||||
|
||||
//let's get vertices and faces
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Loading geometry");
|
||||
#endif
|
||||
GetDMFVerticesFaces(dmfRawFile, verts, faces);
|
||||
|
||||
//create a meshbuffer for each material, then we'll remove empty ones
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Creating meshbuffers.");
|
||||
#endif
|
||||
for (i=0; i<header.numMaterials; i++)
|
||||
{
|
||||
//create a new SMeshBufferLightMap for each material
|
||||
SSkinMeshBuffer* buffer = new SSkinMeshBuffer();
|
||||
buffer->Material.MaterialType = video::EMT_LIGHTMAP_LIGHTING;
|
||||
buffer->Material.Wireframe = false;
|
||||
buffer->Material.Lighting = true;
|
||||
mesh->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
|
||||
// Build the mesh buffers
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Adding geometry to mesh.");
|
||||
#endif
|
||||
for (i = 0; i < header.numFaces; i++)
|
||||
{
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Polygon with #vertices", core::stringc(faces[i].numVerts).c_str());
|
||||
#endif
|
||||
if (faces[i].numVerts < 3)
|
||||
continue;
|
||||
|
||||
const core::vector3df normal =
|
||||
core::triangle3df(verts[faces[i].firstVert].pos,
|
||||
verts[faces[i].firstVert+1].pos,
|
||||
verts[faces[i].firstVert+2].pos).getNormal().normalize();
|
||||
|
||||
SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer(
|
||||
faces[i].materialID);
|
||||
|
||||
const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() ||
|
||||
materiali[faces[i].materialID].lightmapName.size();
|
||||
if (use2TCoords && meshBuffer->Vertices_Standard.size())
|
||||
meshBuffer->convertTo2TCoords();
|
||||
const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size();
|
||||
|
||||
// Add this face's verts
|
||||
if (use2TCoords)
|
||||
{
|
||||
// make sure we have the proper type set
|
||||
meshBuffer->VertexType=video::EVT_2TCOORDS;
|
||||
for (u32 v = 0; v < faces[i].numVerts; v++)
|
||||
{
|
||||
const dmfVert& vv = verts[faces[i].firstVert + v];
|
||||
video::S3DVertex2TCoords vert(vv.pos,
|
||||
normal, video::SColor(255,255,255,255), vv.tc, vv.lc);
|
||||
if (materiali[faces[i].materialID].textureBlend==4 &&
|
||||
SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
|
||||
{
|
||||
vert.TCoords.set(vv.tc.X,-vv.tc.Y);
|
||||
}
|
||||
meshBuffer->Vertices_2TCoords.push_back(vert);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 v = 0; v < faces[i].numVerts; v++)
|
||||
{
|
||||
const dmfVert& vv = verts[faces[i].firstVert + v];
|
||||
video::S3DVertex vert(vv.pos,
|
||||
normal, video::SColor(255,255,255,255), vv.tc);
|
||||
if (materiali[faces[i].materialID].textureBlend==4 &&
|
||||
SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
|
||||
{
|
||||
vert.TCoords.set(vv.tc.X,-vv.tc.Y);
|
||||
}
|
||||
meshBuffer->Vertices_Standard.push_back(vert);
|
||||
}
|
||||
}
|
||||
|
||||
// Now add the indices
|
||||
// This weird loop turns convex polygons into triangle strips.
|
||||
// I do it this way instead of a simple fan because it usually
|
||||
// looks a lot better in wireframe, for example.
|
||||
u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center
|
||||
for (u32 v = 0; v < faces[i].numVerts - 2; v++)
|
||||
{
|
||||
if (v & 1) // odd
|
||||
c = h - 1;
|
||||
else // even
|
||||
c = l + 1;
|
||||
|
||||
meshBuffer->Indices.push_back(base + h);
|
||||
meshBuffer->Indices.push_back(base + l);
|
||||
meshBuffer->Indices.push_back(base + c);
|
||||
|
||||
if (v & 1) // odd
|
||||
h--;
|
||||
else // even
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] verts;
|
||||
delete [] faces;
|
||||
}
|
||||
|
||||
// delete all buffers without geometry in it.
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Cleaning meshbuffers.");
|
||||
#endif
|
||||
i = 0;
|
||||
while(i < mesh->MeshBuffers.size())
|
||||
{
|
||||
if (mesh->MeshBuffers[i]->getVertexCount() == 0 ||
|
||||
mesh->MeshBuffers[i]->getIndexCount() == 0)
|
||||
{
|
||||
// Meshbuffer is empty -- drop it
|
||||
mesh->MeshBuffers[i]->drop();
|
||||
mesh->MeshBuffers.erase(i);
|
||||
materiali.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
//load textures and lightmaps in materials.
|
||||
//don't worry if you receive a could not load texture, cause if you don't need
|
||||
//a particular material in your scene it will be loaded and then destroyed.
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Loading textures.");
|
||||
#endif
|
||||
const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS);
|
||||
|
||||
for (i=0; i<mesh->getMeshBufferCount(); i++)
|
||||
{
|
||||
//texture and lightmap
|
||||
video::ITexture *tex = 0;
|
||||
video::ITexture *lig = 0;
|
||||
|
||||
//current buffer to apply material
|
||||
video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial();
|
||||
|
||||
//Primary texture is normal
|
||||
if (materiali[i].textureFlag==0)
|
||||
{
|
||||
if (materiali[i].textureBlend==4)
|
||||
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
|
||||
|
||||
if ( use_mat_dirs )
|
||||
addMaterialPath(materiali[i].textureName, materiali[i].pathName);
|
||||
tex = getMeshTextureLoader() ? getMeshTextureLoader()->getTexture( materiali[i].textureName ) : NULL;
|
||||
}
|
||||
//Primary texture is just a color
|
||||
else if(materiali[i].textureFlag==1)
|
||||
{
|
||||
video::SColor color(axtoi(materiali[i].textureName.c_str()));
|
||||
|
||||
//just for compatibility with older Irrlicht versions
|
||||
//to support transparent materials
|
||||
if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
|
||||
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
|
||||
|
||||
video::IImage *immagine= driver->createImage(video::ECF_A8R8G8B8,
|
||||
core::dimension2d<u32>(8,8));
|
||||
immagine->fill(color);
|
||||
tex = driver->addTexture("", immagine);
|
||||
immagine->drop();
|
||||
|
||||
//to support transparent materials
|
||||
if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
|
||||
{
|
||||
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
//Lightmap is present
|
||||
if (materiali[i].lightmapFlag == 0)
|
||||
{
|
||||
if ( use_mat_dirs )
|
||||
addMaterialPath(materiali[i].lightmapName, materiali[i].pathName);
|
||||
lig = getMeshTextureLoader() ? getMeshTextureLoader()->getTexture(materiali[i].lightmapName) : NULL;
|
||||
}
|
||||
else //no lightmap
|
||||
{
|
||||
mat.MaterialType = video::EMT_SOLID;
|
||||
const f32 mult = 100.0f - header.dmfShadow;
|
||||
mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f);
|
||||
}
|
||||
|
||||
if (materiali[i].textureBlend==4)
|
||||
{
|
||||
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
mat.MaterialTypeParam =
|
||||
SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF);
|
||||
}
|
||||
|
||||
//if texture is present mirror vertically owing to DeleD representation
|
||||
if (tex && header.dmfVersion<1.1)
|
||||
{
|
||||
const core::dimension2d<u32> texsize = tex->getSize();
|
||||
void* pp = tex->lock();
|
||||
if (pp)
|
||||
{
|
||||
const video::ECOLOR_FORMAT format = tex->getColorFormat();
|
||||
if (format == video::ECF_A1R5G5B5)
|
||||
{
|
||||
s16* p = (s16*)pp;
|
||||
s16 tmp=0;
|
||||
for (u32 x=0; x<texsize.Width; x++)
|
||||
for (u32 y=0; y<texsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*texsize.Width + x];
|
||||
p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
|
||||
p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
s32* p = (s32*)pp;
|
||||
s32 tmp=0;
|
||||
for (u32 x=0; x<texsize.Width; x++)
|
||||
for (u32 y=0; y<texsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*texsize.Width + x];
|
||||
p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
|
||||
p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
tex->unlock();
|
||||
tex->regenerateMipMapLevels();
|
||||
}
|
||||
|
||||
//if lightmap is present mirror vertically owing to DeleD rapresentation
|
||||
if (lig && header.dmfVersion<1.1)
|
||||
{
|
||||
const core::dimension2d<u32> ligsize=lig->getSize();
|
||||
void* pp = lig->lock();
|
||||
if (pp)
|
||||
{
|
||||
video::ECOLOR_FORMAT format = lig->getColorFormat();
|
||||
if (format == video::ECF_A1R5G5B5)
|
||||
{
|
||||
s16* p = (s16*)pp;
|
||||
s16 tmp=0;
|
||||
for (u32 x=0; x<ligsize.Width; x++)
|
||||
{
|
||||
for (u32 y=0; y<ligsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*ligsize.Width + x];
|
||||
p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
|
||||
p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
s32* p = (s32*)pp;
|
||||
s32 tmp=0;
|
||||
for (u32 x=0; x<ligsize.Width; x++)
|
||||
{
|
||||
for (u32 y=0; y<ligsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*ligsize.Width + x];
|
||||
p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
|
||||
p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lig->unlock();
|
||||
lig->regenerateMipMapLevels();
|
||||
}
|
||||
|
||||
mat.setTexture(0, tex);
|
||||
mat.setTexture(1, lig);
|
||||
}
|
||||
}
|
||||
|
||||
// create bounding box
|
||||
for (i = 0; i < mesh->MeshBuffers.size(); ++i)
|
||||
{
|
||||
mesh->MeshBuffers[i]->recalculateBoundingBox();
|
||||
}
|
||||
mesh->recalculateBoundingBox();
|
||||
|
||||
// Set up an animated mesh to hold the mesh
|
||||
SAnimatedMesh* AMesh = new SAnimatedMesh();
|
||||
AMesh->Type = EAMT_UNKNOWN;
|
||||
AMesh->addMesh(mesh);
|
||||
AMesh->recalculateBoundingBox();
|
||||
mesh->drop();
|
||||
|
||||
return AMesh;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Tell us if this file is able to be loaded by this class
|
||||
based on the file extension (e.g. ".bsp")
|
||||
\return true if file is loadable.*/
|
||||
bool CDMFLoader::isALoadableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "dmf" );
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DMF_LOADER_
|
||||
|
91
source/Irrlicht/CDMFLoader.h
Normal file
91
source/Irrlicht/CDMFLoader.h
Normal file
@ -0,0 +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
|
||||
//
|
||||
// This file was originally written by Salvatore Russo.
|
||||
// I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated
|
||||
// it into Irrlicht:
|
||||
// - removed STL dependency
|
||||
// - removed log file and replaced it with irrlicht logging
|
||||
// - adapted code formatting a bit to Irrlicht style
|
||||
// - removed memory leaks
|
||||
// Thanks a lot to Salvatore for his work on this and that he gave me
|
||||
// his permission to add it into Irrlicht.
|
||||
|
||||
/*
|
||||
CDMFLoader by Salvatore Russo
|
||||
Version 1.3
|
||||
|
||||
This loader is used to load DMF files in Irrlicht.
|
||||
Look at the documentation for a sample application.
|
||||
|
||||
Parts of this code are from Murphy McCauley COCTLoader just like
|
||||
GetFaceNormal() or indexes creation routines and a routine to add faces. So
|
||||
please refer to COCTLoader.h to know more about rights granted.
|
||||
|
||||
You can use this software as you wish but you must not remove these notes about license nor
|
||||
credits to others for parts of this code.
|
||||
*/
|
||||
|
||||
#ifndef __C_DMF_LOADER_H_INCLUDED__
|
||||
#define __C_DMF_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IReadFile.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "SMesh.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "SAnimatedMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
/** A class to load DeleD mesh files.*/
|
||||
class CDMFLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
/** constructor*/
|
||||
CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys);
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_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.*/
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
/** loads dynamic lights present in this scene.
|
||||
Note that loaded lights from DeleD must have the suffix \b dynamic_ and must be \b pointlight.
|
||||
Irrlicht correctly loads specular color, diffuse color , position and distance of object affected by light.
|
||||
\return number of lights loaded or 0 if loading failed.*/
|
||||
int loadLights(const c8 * filename, ISceneManager* smgr,
|
||||
ISceneNode* parent = 0, s32 base_id = 1000);
|
||||
|
||||
/** loads water plains present in this scene.
|
||||
Note that loaded water plains from DeleD must have the suffix \b water_ and must be \b rectangle (with just 1 rectangular face).
|
||||
Irrlicht correctly loads position and rotation of water plain as well as texture layers.
|
||||
\return number of water plains loaded or 0 if loading failed.*/
|
||||
int loadWaterPlains(const c8 *filename,
|
||||
ISceneManager* smgr,
|
||||
ISceneNode * parent = 0,
|
||||
s32 base_id = 2000,
|
||||
bool mode = true);
|
||||
|
||||
private:
|
||||
void addMaterialPath(core::stringc& filename, const core::stringc& matPath);
|
||||
|
||||
ISceneManager* SceneMgr;
|
||||
io::IFileSystem* FileSystem;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
167
source/Irrlicht/CDefaultGUIElementFactory.cpp
Normal file
167
source/Irrlicht/CDefaultGUIElementFactory.cpp
Normal file
@ -0,0 +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
|
||||
|
||||
#include "CDefaultGUIElementFactory.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUICheckBox.h"
|
||||
#include "IGUIColorSelectDialog.h"
|
||||
#include "IGUIComboBox.h"
|
||||
#include "IGUIContextMenu.h"
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "IGUIInOutFader.h"
|
||||
#include "IGUIImage.h"
|
||||
#include "IGUIListBox.h"
|
||||
#include "IGUIMeshViewer.h"
|
||||
#include "IGUIScrollBar.h"
|
||||
#include "IGUISpinBox.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUITabControl.h"
|
||||
#include "IGUITable.h"
|
||||
#include "IGUIToolbar.h"
|
||||
#include "IGUIWindow.h"
|
||||
#include "IGUITreeView.h"
|
||||
#include "IGUIProfiler.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
CDefaultGUIElementFactory::CDefaultGUIElementFactory(IGUIEnvironment* env)
|
||||
: Environment(env)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultGUIElementFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the gui environment here to prevent cyclic references
|
||||
}
|
||||
|
||||
|
||||
//! adds an element to the env based on its type id
|
||||
IGUIElement* CDefaultGUIElementFactory::addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case EGUIET_BUTTON:
|
||||
return Environment->addButton(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_CHECK_BOX:
|
||||
return Environment->addCheckBox(false, core::rect<s32>(0,0,100,100), parent);
|
||||
case EGUIET_COLOR_SELECT_DIALOG:
|
||||
return Environment->addColorSelectDialog(0,true,parent);
|
||||
case EGUIET_COMBO_BOX:
|
||||
return Environment->addComboBox(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_CONTEXT_MENU:
|
||||
return Environment->addContextMenu(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MENU:
|
||||
return Environment->addMenu(parent);
|
||||
case EGUIET_EDIT_BOX:
|
||||
return Environment->addEditBox(0,core::rect<s32>(0,0,100,100),true, parent);
|
||||
case EGUIET_FILE_OPEN_DIALOG:
|
||||
return Environment->addFileOpenDialog(0,true,parent);
|
||||
case EGUIET_IMAGE:
|
||||
return Environment->addImage(0,core::position2di(0,0), true, parent);
|
||||
case EGUIET_IN_OUT_FADER:
|
||||
return Environment->addInOutFader(0,parent);
|
||||
case EGUIET_LIST_BOX:
|
||||
return Environment->addListBox(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MESH_VIEWER:
|
||||
return Environment->addMeshViewer(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MODAL_SCREEN:
|
||||
return Environment->addModalScreen(parent);
|
||||
case EGUIET_MESSAGE_BOX:
|
||||
return Environment->addMessageBox(0,0,false,0,parent);
|
||||
case EGUIET_SCROLL_BAR:
|
||||
return Environment->addScrollBar(false,core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_STATIC_TEXT:
|
||||
return Environment->addStaticText(0,core::rect<s32>(0,0,100,100),false,true,parent);
|
||||
case EGUIET_TAB:
|
||||
return Environment->addTab(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_TAB_CONTROL:
|
||||
return Environment->addTabControl(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_TABLE:
|
||||
return Environment->addTable(core::rect<s32>(0,0,100,100), parent);
|
||||
case EGUIET_TOOL_BAR:
|
||||
return Environment->addToolBar(parent);
|
||||
case EGUIET_WINDOW:
|
||||
return Environment->addWindow(core::rect<s32>(0,0,100,100),false,0,parent);
|
||||
case EGUIET_SPIN_BOX:
|
||||
return Environment->addSpinBox(L"0.0", core::rect<s32>(0,0,100,100), true, parent);
|
||||
case EGUIET_TREE_VIEW:
|
||||
return Environment->addTreeView(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_PROFILER:
|
||||
return Environment->addProfilerDisplay(core::rect<s32>(0,0,100,100), parent);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! adds an element to the environment based on its type name
|
||||
IGUIElement* CDefaultGUIElementFactory::addGUIElement(const c8* typeName, IGUIElement* parent)
|
||||
{
|
||||
return addGUIElement( getTypeFromName(typeName), parent );
|
||||
}
|
||||
|
||||
|
||||
//! Returns the amount of element types this factory is able to create.
|
||||
s32 CDefaultGUIElementFactory::getCreatableGUIElementTypeCount() const
|
||||
{
|
||||
return EGUIET_COUNT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of a creatable element type.
|
||||
EGUI_ELEMENT_TYPE CDefaultGUIElementFactory::getCreateableGUIElementType(s32 idx) const
|
||||
{
|
||||
if (idx>=0 && idx<EGUIET_COUNT)
|
||||
return (EGUI_ELEMENT_TYPE)idx;
|
||||
|
||||
return EGUIET_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type name of a creatable element type.
|
||||
const c8* CDefaultGUIElementFactory::getCreateableGUIElementTypeName(s32 idx) const
|
||||
{
|
||||
if (idx>=0 && idx<EGUIET_COUNT)
|
||||
return GUIElementTypeNames[idx];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type name of a creatable element type.
|
||||
const c8* CDefaultGUIElementFactory::getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const
|
||||
{
|
||||
// for this factory, type == index
|
||||
|
||||
if (type>=0 && type<EGUIET_COUNT)
|
||||
return GUIElementTypeNames[type];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGUI_ELEMENT_TYPE CDefaultGUIElementFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for ( u32 i=0; GUIElementTypeNames[i]; ++i)
|
||||
if (!strcmp(name, GUIElementTypeNames[i]) )
|
||||
return (EGUI_ELEMENT_TYPE)i;
|
||||
|
||||
return EGUIET_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
70
source/Irrlicht/CDefaultGUIElementFactory.h
Normal file
70
source/Irrlicht/CDefaultGUIElementFactory.h
Normal file
@ -0,0 +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
|
||||
|
||||
#ifndef __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIElementFactory.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIElement;
|
||||
class IGUIEnvironment;
|
||||
|
||||
//! This interface makes it possible to dynamically create gui elements.
|
||||
class CDefaultGUIElementFactory : public IGUIElementFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultGUIElementFactory(IGUIEnvironment* env);
|
||||
|
||||
//! Adds an element to the gui environment based on its type id.
|
||||
/** \param type: Type of the element to add.
|
||||
\param parent: Parent scene node of the new element. A value of 0 adds it to the root.
|
||||
\return Returns pointer to the new element or 0 if unsuccessful. */
|
||||
virtual IGUIElement* addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds a GUI element to the GUI Environment based on its type name.
|
||||
/** \param typeName: Type name of the element to add. Taken from the GUIElementTypeNames c8* array.
|
||||
\param parent: Parent scene node of the new element. A value of 0 adds it to the root.
|
||||
\return Returns pointer to the new element or 0 if unsuccessful. */
|
||||
virtual IGUIElement* addGUIElement(const c8* typeName, IGUIElement* parent=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the amount of GUI element types this factory is able to create.
|
||||
virtual s32 getCreatableGUIElementTypeCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the type of a createable GUI element type based on the index.
|
||||
/** \param idx: Index of the element type in this factory. The value must be equal or greater than 0
|
||||
and lower than getCreatableGUIElementTypeCount(). */
|
||||
virtual EGUI_ELEMENT_TYPE getCreateableGUIElementType(s32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the type name of a createable GUI element type based on the index.
|
||||
/** \param idx: Index of the element type in this factory. The value must be equal or greater than 0
|
||||
and lower than getCreatableGUIElementTypeCount(). */
|
||||
virtual const c8* getCreateableGUIElementTypeName(s32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the type name of a createable GUI element based on its type.
|
||||
/** \param type: Type of the GUI element.
|
||||
\return: Returns the name of the type if this factory can create it, otherwise it returns 0. */
|
||||
virtual const c8* getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
EGUI_ELEMENT_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
IGUIEnvironment* Environment;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
162
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.cpp
Normal file
162
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.cpp
Normal file
@ -0,0 +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 "CDefaultSceneNodeAnimatorFactory.h"
|
||||
#include "CSceneNodeAnimatorCameraFPS.h"
|
||||
#include "CSceneNodeAnimatorCameraMaya.h"
|
||||
#include "ICursorControl.h"
|
||||
#include "ISceneNodeAnimatorCollisionResponse.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Names for scene node types
|
||||
const c8* const SceneNodeAnimatorTypeNames[] =
|
||||
{
|
||||
"flyCircle",
|
||||
"flyStraight",
|
||||
"followSpline",
|
||||
"rotation",
|
||||
"texture",
|
||||
"deletion",
|
||||
"collisionResponse",
|
||||
"cameraFPS",
|
||||
"cameraMaya",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory::CDefaultSceneNodeAnimatorFactory(ISceneManager* mgr, gui::ICursorControl* crs)
|
||||
: Manager(mgr), CursorControl(crs)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultSceneNodeAnimatorFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the scene manager here to prevent cyclic references
|
||||
if (CursorControl)
|
||||
CursorControl->grab();
|
||||
}
|
||||
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory::~CDefaultSceneNodeAnimatorFactory()
|
||||
{
|
||||
if (CursorControl)
|
||||
CursorControl->drop();
|
||||
}
|
||||
|
||||
|
||||
//! creates a scene node animator based on its type id
|
||||
ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target)
|
||||
{
|
||||
scene::ISceneNodeAnimator* anim = 0;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ESNAT_FLY_CIRCLE:
|
||||
anim = Manager->createFlyCircleAnimator(core::vector3df(0,0,0), 10);
|
||||
break;
|
||||
case ESNAT_FLY_STRAIGHT:
|
||||
anim = Manager->createFlyStraightAnimator(core::vector3df(0,0,0), core::vector3df(100,100,100), 10000, true );
|
||||
break;
|
||||
case ESNAT_FOLLOW_SPLINE:
|
||||
{
|
||||
core::array<core::vector3df> points;
|
||||
points.push_back(core::vector3df(0,0,0));
|
||||
points.push_back(core::vector3df(10,5,10));
|
||||
anim = Manager->createFollowSplineAnimator(0, points);
|
||||
}
|
||||
break;
|
||||
case ESNAT_ROTATION:
|
||||
anim = Manager->createRotationAnimator(core::vector3df(0.3f,0,0));
|
||||
break;
|
||||
case ESNAT_TEXTURE:
|
||||
{
|
||||
core::array<video::ITexture*> textures;
|
||||
anim = Manager->createTextureAnimator(textures, 250);
|
||||
}
|
||||
break;
|
||||
case ESNAT_DELETION:
|
||||
anim = Manager->createDeleteAnimator(5000);
|
||||
break;
|
||||
case ESNAT_COLLISION_RESPONSE:
|
||||
anim = Manager->createCollisionResponseAnimator(0, target);
|
||||
break;
|
||||
case ESNAT_CAMERA_FPS:
|
||||
anim = new CSceneNodeAnimatorCameraFPS(CursorControl);
|
||||
break;
|
||||
case ESNAT_CAMERA_MAYA:
|
||||
anim = new CSceneNodeAnimatorCameraMaya(CursorControl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (anim && target)
|
||||
target->addAnimator(anim);
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
|
||||
//! creates a scene node animator based on its type name
|
||||
ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(const c8* typeName, ISceneNode* target)
|
||||
{
|
||||
return createSceneNodeAnimator( getTypeFromName(typeName), target );
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of scene node animator types this factory is able to create
|
||||
u32 CDefaultSceneNodeAnimatorFactory::getCreatableSceneNodeAnimatorTypeCount() const
|
||||
{
|
||||
return ESNAT_COUNT;
|
||||
}
|
||||
|
||||
|
||||
//! returns type of a creatable scene node animator type
|
||||
ESCENE_NODE_ANIMATOR_TYPE CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorType(u32 idx) const
|
||||
{
|
||||
if (idx<ESNAT_COUNT)
|
||||
return (ESCENE_NODE_ANIMATOR_TYPE)idx;
|
||||
else
|
||||
return ESNAT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a creatable scene node animator type
|
||||
const c8* CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorTypeName(u32 idx) const
|
||||
{
|
||||
if (idx<ESNAT_COUNT)
|
||||
return SceneNodeAnimatorTypeNames[idx];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! returns type name of a creatable scene node animator type
|
||||
const c8* CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const
|
||||
{
|
||||
// for this factory: index == type
|
||||
|
||||
if (type<ESNAT_COUNT)
|
||||
return SceneNodeAnimatorTypeNames[type];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ESCENE_NODE_ANIMATOR_TYPE CDefaultSceneNodeAnimatorFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for ( u32 i=0; SceneNodeAnimatorTypeNames[i]; ++i)
|
||||
if (!strcmp(name, SceneNodeAnimatorTypeNames[i]) )
|
||||
return (ESCENE_NODE_ANIMATOR_TYPE)i;
|
||||
|
||||
return ESNAT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
75
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.h
Normal file
75
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.h
Normal file
@ -0,0 +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
|
||||
|
||||
#ifndef __C_DEFAULT_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "ISceneNodeAnimatorFactory.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class ICursorControl;
|
||||
}
|
||||
namespace scene
|
||||
{
|
||||
class ISceneNodeAnimator;
|
||||
class ISceneManager;
|
||||
|
||||
//! Interface making it possible to dynamicly create scene nodes animators
|
||||
class CDefaultSceneNodeAnimatorFactory : public ISceneNodeAnimatorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory(ISceneManager* mgr, gui::ICursorControl* crs);
|
||||
|
||||
virtual ~CDefaultSceneNodeAnimatorFactory();
|
||||
|
||||
//! creates a scene node animator based on its type id
|
||||
/** \param type: Type of the scene node animator to add.
|
||||
\param target: Target scene node of the new animator.
|
||||
\return Returns pointer to the new scene node animator or null if not successful. You need to
|
||||
drop this pointer after calling this, see IReferenceCounted::drop() for details. */
|
||||
virtual ISceneNodeAnimator* createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target) _IRR_OVERRIDE_;
|
||||
|
||||
//! creates a scene node animator based on its type name
|
||||
/** \param typeName: Type of the scene node animator to add.
|
||||
\param target: Target scene node of the new animator.
|
||||
\return Returns pointer to the new scene node animator or null if not successful. You need to
|
||||
drop this pointer after calling this, see IReferenceCounted::drop() for details. */
|
||||
virtual ISceneNodeAnimator* createSceneNodeAnimator(const char* typeName, ISceneNode* target) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns amount of scene node animator types this factory is able to create
|
||||
virtual u32 getCreatableSceneNodeAnimatorTypeCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns type of a creatable scene node animator type
|
||||
/** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeTypeCount() */
|
||||
virtual ESCENE_NODE_ANIMATOR_TYPE getCreateableSceneNodeAnimatorType(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns type name of a creatable scene node animator type
|
||||
/** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeAnimatorTypeCount() */
|
||||
virtual const c8* getCreateableSceneNodeAnimatorTypeName(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns type name of a creatable scene node animator type
|
||||
/** \param type: Type of scene node animator.
|
||||
\return: Returns name of scene node animator type if this factory can create the type, otherwise 0. */
|
||||
virtual const c8* getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
ESCENE_NODE_ANIMATOR_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
ISceneManager* Manager;
|
||||
gui::ICursorControl* CursorControl;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
184
source/Irrlicht/CDefaultSceneNodeFactory.cpp
Normal file
184
source/Irrlicht/CDefaultSceneNodeFactory.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
// 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 "CDefaultSceneNodeFactory.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ITextSceneNode.h"
|
||||
#include "IBillboardTextSceneNode.h"
|
||||
#include "ITerrainSceneNode.h"
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "IParticleSystemSceneNode.h"
|
||||
#include "ILightSceneNode.h"
|
||||
#include "IMeshSceneNode.h"
|
||||
#include "IOctreeSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr)
|
||||
: Manager(mgr)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultSceneNodeFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the scene manager here to prevent cyclic references
|
||||
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CUBE, "cube"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SPHERE, "sphere"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TEXT, "text"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_BILLBOARD_TEXT, "billboardText"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_WATER_SURFACE, "waterSurface"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TERRAIN, "terrain"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_BOX, "skyBox"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_DOME, "skyDome"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SHADOW_VOLUME, "shadowVolume"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octree"));
|
||||
// Legacy support
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octTree"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MESH, "mesh"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_LIGHT, "light"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_EMPTY, "empty"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_DUMMY_TRANSFORMATION, "dummyTransformation"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA, "camera"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_BILLBOARD, "billBoard"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_ANIMATED_MESH, "animatedMesh"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_PARTICLE_SYSTEM, "particleSystem"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_VOLUME_LIGHT, "volumeLight"));
|
||||
// SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MD3_SCENE_NODE, "md3"));
|
||||
|
||||
// legacy, for version <= 1.4.x irr files
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_MAYA, "cameraMaya"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_FPS, "cameraFPS"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_Q3SHADER_SCENE_NODE, "quake3Shader"));
|
||||
}
|
||||
|
||||
|
||||
//! adds a scene node to the scene graph based on its type id
|
||||
ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ESNT_CUBE:
|
||||
return Manager->addCubeSceneNode(10, parent);
|
||||
case ESNT_SPHERE:
|
||||
return Manager->addSphereSceneNode(5, 16, parent);
|
||||
case ESNT_TEXT:
|
||||
return Manager->addTextSceneNode(0, L"example");
|
||||
case ESNT_BILLBOARD_TEXT:
|
||||
return Manager->addBillboardTextSceneNode(0, L"example");
|
||||
case ESNT_WATER_SURFACE:
|
||||
return Manager->addWaterSurfaceSceneNode(0, 2.0f, 300.0f, 10.0f, parent);
|
||||
case ESNT_TERRAIN:
|
||||
return Manager->addTerrainSceneNode("", parent, -1,
|
||||
core::vector3df(0.0f,0.0f,0.0f),
|
||||
core::vector3df(0.0f,0.0f,0.0f),
|
||||
core::vector3df(1.0f,1.0f,1.0f),
|
||||
video::SColor(255,255,255,255),
|
||||
4, ETPS_17, 0, true);
|
||||
case ESNT_SKY_BOX:
|
||||
return Manager->addSkyBoxSceneNode(0,0,0,0,0,0, parent);
|
||||
case ESNT_SKY_DOME:
|
||||
return Manager->addSkyDomeSceneNode(0, 16, 8, 0.9f, 2.0f, 1000.0f, parent);
|
||||
case ESNT_SHADOW_VOLUME:
|
||||
return 0;
|
||||
case ESNT_OCTREE:
|
||||
return Manager->addOctreeSceneNode((IMesh*)0, parent, -1, 128, true);
|
||||
case ESNT_MESH:
|
||||
return Manager->addMeshSceneNode(0, parent, -1, core::vector3df(),
|
||||
core::vector3df(), core::vector3df(1,1,1), true);
|
||||
case ESNT_LIGHT:
|
||||
return Manager->addLightSceneNode(parent);
|
||||
case ESNT_EMPTY:
|
||||
return Manager->addEmptySceneNode(parent);
|
||||
case ESNT_DUMMY_TRANSFORMATION:
|
||||
return Manager->addDummyTransformationSceneNode(parent);
|
||||
case ESNT_CAMERA:
|
||||
return Manager->addCameraSceneNode(parent);
|
||||
case ESNT_CAMERA_MAYA:
|
||||
return Manager->addCameraSceneNodeMaya(parent);
|
||||
case ESNT_CAMERA_FPS:
|
||||
return Manager->addCameraSceneNodeFPS(parent);
|
||||
case ESNT_BILLBOARD:
|
||||
return Manager->addBillboardSceneNode(parent);
|
||||
case ESNT_ANIMATED_MESH:
|
||||
return Manager->addAnimatedMeshSceneNode(0, parent, -1, core::vector3df(),
|
||||
core::vector3df(), core::vector3df(1,1,1), true);
|
||||
case ESNT_PARTICLE_SYSTEM:
|
||||
return Manager->addParticleSystemSceneNode(true, parent);
|
||||
case ESNT_VOLUME_LIGHT:
|
||||
return (ISceneNode*)Manager->addVolumeLightSceneNode(parent);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! adds a scene node to the scene graph based on its type name
|
||||
ISceneNode* CDefaultSceneNodeFactory::addSceneNode(const c8* typeName, ISceneNode* parent)
|
||||
{
|
||||
return addSceneNode( getTypeFromName(typeName), parent );
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of scene node types this factory is able to create
|
||||
u32 CDefaultSceneNodeFactory::getCreatableSceneNodeTypeCount() const
|
||||
{
|
||||
return SupportedSceneNodeTypes.size();
|
||||
}
|
||||
|
||||
|
||||
//! returns type of a creatable scene node type
|
||||
ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getCreateableSceneNodeType(u32 idx) const
|
||||
{
|
||||
if (idx<SupportedSceneNodeTypes.size())
|
||||
return SupportedSceneNodeTypes[idx].Type;
|
||||
else
|
||||
return ESNT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a creatable scene node type
|
||||
const c8* CDefaultSceneNodeFactory::getCreateableSceneNodeTypeName(u32 idx) const
|
||||
{
|
||||
if (idx<SupportedSceneNodeTypes.size())
|
||||
return SupportedSceneNodeTypes[idx].TypeName.c_str();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a creatable scene node type
|
||||
const c8* CDefaultSceneNodeFactory::getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const
|
||||
{
|
||||
for (u32 i=0; i<SupportedSceneNodeTypes.size(); ++i)
|
||||
if (SupportedSceneNodeTypes[i].Type == type)
|
||||
return SupportedSceneNodeTypes[i].TypeName.c_str();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for (u32 i=0; i<SupportedSceneNodeTypes.size(); ++i)
|
||||
if (SupportedSceneNodeTypes[i].TypeName == name)
|
||||
return SupportedSceneNodeTypes[i].Type;
|
||||
|
||||
return ESNT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
80
source/Irrlicht/CDefaultSceneNodeFactory.h
Normal file
80
source/Irrlicht/CDefaultSceneNodeFactory.h
Normal file
@ -0,0 +1,80 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "ISceneNodeFactory.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class ISceneNode;
|
||||
class ISceneManager;
|
||||
|
||||
//! Interface making it possible to dynamicly create scene nodes and animators
|
||||
class CDefaultSceneNodeFactory : public ISceneNodeFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultSceneNodeFactory(ISceneManager* mgr);
|
||||
|
||||
//! adds a scene node to the scene graph based on its type id
|
||||
/** \param type: Type of the scene node to add.
|
||||
\param parent: Parent scene node of the new node, can be null to add the scene node to the root.
|
||||
\return Returns pointer to the new scene node or null if not successful. */
|
||||
virtual ISceneNode* addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! adds a scene node to the scene graph based on its type name
|
||||
/** \param typeName: Type name of the scene node to add.
|
||||
\param parent: Parent scene node of the new node, can be null to add the scene node to the root.
|
||||
\return Returns pointer to the new scene node or null if not successful. */
|
||||
virtual ISceneNode* addSceneNode(const c8* typeName, ISceneNode* parent=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns amount of scene node types this factory is able to create
|
||||
virtual u32 getCreatableSceneNodeTypeCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns type name of a creatable scene node type by index
|
||||
/** \param idx: Index of scene node type in this factory. Must be a value between 0 and
|
||||
uetCreatableSceneNodeTypeCount() */
|
||||
virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns type of a creatable scene node type
|
||||
/** \param idx: Index of scene node type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeTypeCount() */
|
||||
virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns type name of a creatable scene node type
|
||||
/** \param idx: Type of scene node.
|
||||
\return: Returns name of scene node type if this factory can create the type, otherwise 0. */
|
||||
virtual const c8* getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
ESCENE_NODE_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
struct SSceneNodeTypePair
|
||||
{
|
||||
SSceneNodeTypePair(ESCENE_NODE_TYPE type, const c8* name)
|
||||
: Type(type), TypeName(name)
|
||||
{}
|
||||
|
||||
ESCENE_NODE_TYPE Type;
|
||||
core::stringc TypeName;
|
||||
};
|
||||
|
||||
core::array<SSceneNodeTypePair> SupportedSceneNodeTypes;
|
||||
|
||||
ISceneManager* Manager;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
172
source/Irrlicht/CDepthBuffer.cpp
Normal file
172
source/Irrlicht/CDepthBuffer.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#include "SoftwareDriver2_compile_config.h"
|
||||
#include "CDepthBuffer.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CDepthBuffer::CDepthBuffer(const core::dimension2d<u32>& size)
|
||||
: Buffer(0), Size(0,0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDepthBuffer");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! destructor
|
||||
CDepthBuffer::~CDepthBuffer()
|
||||
{
|
||||
delete [] Buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! clears the zbuffer
|
||||
void CDepthBuffer::clear()
|
||||
{
|
||||
|
||||
#ifdef SOFTWARE_DRIVER_2_USE_WBUFFER
|
||||
f32 zMax = 0.f;
|
||||
#else
|
||||
f32 zMax = 1.f;
|
||||
#endif
|
||||
|
||||
u32 zMaxValue;
|
||||
zMaxValue = IR(zMax);
|
||||
|
||||
memset32 ( Buffer, zMaxValue, TotalSize );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
void CDepthBuffer::setSize(const core::dimension2d<u32>& size)
|
||||
{
|
||||
if (size == Size)
|
||||
return;
|
||||
|
||||
Size = size;
|
||||
|
||||
delete [] Buffer;
|
||||
|
||||
Pitch = size.Width * sizeof ( fp24 );
|
||||
TotalSize = Pitch * size.Height;
|
||||
Buffer = new u8[TotalSize];
|
||||
clear ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
const core::dimension2d<u32>& CDepthBuffer::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
//! constructor
|
||||
CStencilBuffer::CStencilBuffer(const core::dimension2d<u32>& size)
|
||||
: Buffer(0), Size(0,0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDepthBuffer");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! destructor
|
||||
CStencilBuffer::~CStencilBuffer()
|
||||
{
|
||||
delete [] Buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! clears the zbuffer
|
||||
void CStencilBuffer::clear()
|
||||
{
|
||||
memset32 ( Buffer, 0, TotalSize );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
void CStencilBuffer::setSize(const core::dimension2d<u32>& size)
|
||||
{
|
||||
if (size == Size)
|
||||
return;
|
||||
|
||||
Size = size;
|
||||
|
||||
delete [] Buffer;
|
||||
|
||||
Pitch = size.Width * sizeof ( u32 );
|
||||
TotalSize = Pitch * size.Height;
|
||||
Buffer = new u8[TotalSize];
|
||||
clear ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
const core::dimension2d<u32>& CStencilBuffer::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! creates a ZBuffer
|
||||
IDepthBuffer* createDepthBuffer(const core::dimension2d<u32>& size)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
return new CDepthBuffer(size);
|
||||
#else
|
||||
return 0;
|
||||
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
}
|
||||
|
||||
|
||||
//! creates a ZBuffer
|
||||
IStencilBuffer* createStencilBuffer(const core::dimension2d<u32>& size)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
return new CStencilBuffer(size);
|
||||
#else
|
||||
return 0;
|
||||
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
}
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
|
94
source/Irrlicht/CDepthBuffer.h
Normal file
94
source/Irrlicht/CDepthBuffer.h
Normal file
@ -0,0 +1,94 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_Z_BUFFER_H_INCLUDED__
|
||||
#define __C_Z_BUFFER_H_INCLUDED__
|
||||
|
||||
#include "IDepthBuffer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CDepthBuffer : public IDepthBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CDepthBuffer(const core::dimension2d<u32>& size);
|
||||
|
||||
//! destructor
|
||||
virtual ~CDepthBuffer();
|
||||
|
||||
//! clears the zbuffer
|
||||
virtual void clear() _IRR_OVERRIDE_;
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
virtual void setSize(const core::dimension2d<u32>& size) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
virtual const core::dimension2d<u32>& getSize() const _IRR_OVERRIDE_;
|
||||
|
||||
//! locks the zbuffer
|
||||
virtual void* lock() _IRR_OVERRIDE_ { return (void*) Buffer; }
|
||||
|
||||
//! unlocks the zbuffer
|
||||
virtual void unlock() _IRR_OVERRIDE_ {}
|
||||
|
||||
//! returns pitch of depthbuffer (in bytes)
|
||||
virtual u32 getPitch() const _IRR_OVERRIDE_ { return Pitch; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
u8* Buffer;
|
||||
core::dimension2d<u32> Size;
|
||||
u32 TotalSize;
|
||||
u32 Pitch;
|
||||
};
|
||||
|
||||
|
||||
class CStencilBuffer : public IStencilBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CStencilBuffer(const core::dimension2d<u32>& size);
|
||||
|
||||
//! destructor
|
||||
virtual ~CStencilBuffer();
|
||||
|
||||
//! clears the zbuffer
|
||||
virtual void clear() _IRR_OVERRIDE_;
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
virtual void setSize(const core::dimension2d<u32>& size) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
virtual const core::dimension2d<u32>& getSize() const _IRR_OVERRIDE_;
|
||||
|
||||
//! locks the zbuffer
|
||||
virtual void* lock() _IRR_OVERRIDE_ { return (void*) Buffer; }
|
||||
|
||||
//! unlocks the zbuffer
|
||||
virtual void unlock() _IRR_OVERRIDE_ {}
|
||||
|
||||
//! returns pitch of depthbuffer (in bytes)
|
||||
virtual u32 getPitch() const _IRR_OVERRIDE_ { return Pitch; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
u8* Buffer;
|
||||
core::dimension2d<u32> Size;
|
||||
u32 TotalSize;
|
||||
u32 Pitch;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
105
source/Irrlicht/CDummyTransformationSceneNode.cpp
Normal file
105
source/Irrlicht/CDummyTransformationSceneNode.cpp
Normal file
@ -0,0 +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
|
62
source/Irrlicht/CDummyTransformationSceneNode.h
Normal file
62
source/Irrlicht/CDummyTransformationSceneNode.h
Normal file
@ -0,0 +1,62 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#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
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns a reference to the current relative transformation matrix.
|
||||
//! This is the matrix, this scene node uses instead of scale, translation
|
||||
//! and rotation.
|
||||
virtual core::matrix4& getRelativeTransformationMatrix() _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the relative transformation of the scene node.
|
||||
virtual core::matrix4 getRelativeTransformation() const _IRR_OVERRIDE_;
|
||||
|
||||
//! does nothing.
|
||||
virtual void render() _IRR_OVERRIDE_ {}
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_DUMMY_TRANSFORMATION; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) _IRR_OVERRIDE_;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// TODO: We can add least add some warnings to find troubles faster until we have
|
||||
// fixed bug id 2318691.
|
||||
virtual const core::vector3df& getScale() const _IRR_OVERRIDE_;
|
||||
virtual void setScale(const core::vector3df& scale) _IRR_OVERRIDE_;
|
||||
virtual const core::vector3df& getRotation() const _IRR_OVERRIDE_;
|
||||
virtual void setRotation(const core::vector3df& rotation) _IRR_OVERRIDE_;
|
||||
virtual const core::vector3df& getPosition() const _IRR_OVERRIDE_;
|
||||
virtual void setPosition(const core::vector3df& newpos) _IRR_OVERRIDE_;
|
||||
|
||||
core::matrix4 RelativeTransformationMatrix;
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
87
source/Irrlicht/CEAGLManager.h
Normal file
87
source/Irrlicht/CEAGLManager.h
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (C) 2015 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#ifndef __C_EAGL_MANAGER_H_INCLUDED__
|
||||
#define __C_EAGL_MANAGER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_EAGL_MANAGER_
|
||||
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "SExposedVideoData.h"
|
||||
#include "IContextManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// EAGL manager.
|
||||
class CEAGLManager : public IContextManager
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
CEAGLManager();
|
||||
|
||||
//! Destructor.
|
||||
virtual ~CEAGLManager();
|
||||
|
||||
// Initialize EAGL.
|
||||
/* This method checks if a view has CAEAGLLayer and grabs it if it does, anyway surface and context
|
||||
aren't create. */
|
||||
bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data);
|
||||
|
||||
// Terminate EAGL.
|
||||
/* Terminate EAGL context. This method break both existed surface and context. */
|
||||
void terminate();
|
||||
|
||||
// Create EAGL surface.
|
||||
/* This method configure CAEAGLLayer. */
|
||||
bool generateSurface();
|
||||
|
||||
// Destroy EAGL surface.
|
||||
/* This method reset CAEAGLLayer states. */
|
||||
void destroySurface();
|
||||
|
||||
// Create EAGL context.
|
||||
/* This method create and activate EAGL context. */
|
||||
bool generateContext();
|
||||
|
||||
// Destroy EAGL context.
|
||||
/* This method destroy EAGL context. */
|
||||
void destroyContext();
|
||||
|
||||
const SExposedVideoData& getContext() const;
|
||||
|
||||
bool activateContext(const SExposedVideoData& videoData);
|
||||
|
||||
// Swap buffers.
|
||||
bool swapBuffers();
|
||||
|
||||
private:
|
||||
SIrrlichtCreationParameters Params;
|
||||
SExposedVideoData Data;
|
||||
|
||||
bool Configured;
|
||||
|
||||
void* DataStorage;
|
||||
|
||||
struct SFrameBuffer
|
||||
{
|
||||
SFrameBuffer() : BufferID(0), ColorBuffer(0), DepthBuffer(0)
|
||||
{
|
||||
}
|
||||
|
||||
u32 BufferID;
|
||||
u32 ColorBuffer;
|
||||
u32 DepthBuffer;
|
||||
};
|
||||
|
||||
SFrameBuffer FrameBuffer;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
273
source/Irrlicht/CEAGLManager.mm
Normal file
273
source/Irrlicht/CEAGLManager.mm
Normal file
@ -0,0 +1,273 @@
|
||||
// Copyright (C) 2015 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Irrlicht.h
|
||||
|
||||
#include "CEAGLManager.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_EAGL_MANAGER_
|
||||
|
||||
#include "irrString.h"
|
||||
#include "os.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_OGLES1_)
|
||||
#include <OpenGLES/ES1/gl.h>
|
||||
#include <OpenGLES/ES1/glext.h>
|
||||
#elif defined(_IRR_COMPILE_WITH_OGLES2_)
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
struct SEAGLManagerDataStorage
|
||||
{
|
||||
SEAGLManagerDataStorage() : Layer(0), Context(0)
|
||||
{
|
||||
}
|
||||
|
||||
CAEAGLLayer* Layer;
|
||||
EAGLContext* Context;
|
||||
};
|
||||
|
||||
CEAGLManager::CEAGLManager() : IContextManager(), Configured(false), DataStorage(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CEAGLManager");
|
||||
#endif
|
||||
|
||||
DataStorage = new SEAGLManagerDataStorage();
|
||||
}
|
||||
|
||||
CEAGLManager::~CEAGLManager()
|
||||
{
|
||||
destroyContext();
|
||||
destroySurface();
|
||||
terminate();
|
||||
|
||||
delete static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
}
|
||||
|
||||
bool CEAGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data)
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
|
||||
if (dataStorage->Layer != nil)
|
||||
return true;
|
||||
|
||||
Params = params;
|
||||
Data = data;
|
||||
|
||||
UIView* view = (__bridge UIView*)data.OpenGLiOS.View;
|
||||
|
||||
if (view == nil || ![[view layer] isKindOfClass:[CAEAGLLayer class]])
|
||||
{
|
||||
os::Printer::log("Could not get EAGL display.");
|
||||
return false;
|
||||
}
|
||||
|
||||
dataStorage->Layer = (CAEAGLLayer*)[view layer];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEAGLManager::terminate()
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
|
||||
[EAGLContext setCurrentContext:0];
|
||||
|
||||
destroySurface();
|
||||
|
||||
if (dataStorage->Layer != nil)
|
||||
dataStorage->Layer = 0;
|
||||
}
|
||||
|
||||
bool CEAGLManager::generateSurface()
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
CAEAGLLayer* layer = dataStorage->Layer;
|
||||
|
||||
if (layer == nil)
|
||||
return false;
|
||||
|
||||
if (Configured)
|
||||
return true;
|
||||
|
||||
NSDictionary* attribs = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithBool:NO],
|
||||
kEAGLDrawablePropertyRetainedBacking,
|
||||
(Params.Bits > 16) ? kEAGLColorFormatRGBA8 : kEAGLColorFormatRGB565,
|
||||
kEAGLDrawablePropertyColorFormat,
|
||||
nil];
|
||||
|
||||
[layer setOpaque:(Params.WithAlphaChannel) ? YES : NO];
|
||||
[layer setDrawableProperties:attribs];
|
||||
|
||||
Configured = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEAGLManager::destroySurface()
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
CAEAGLLayer* layer = dataStorage->Layer;
|
||||
|
||||
if (layer == nil)
|
||||
return;
|
||||
|
||||
[layer setOpaque:NO];
|
||||
[layer setDrawableProperties:nil];
|
||||
|
||||
Configured = false;
|
||||
}
|
||||
|
||||
bool CEAGLManager::generateContext()
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
|
||||
if (dataStorage->Context != nil || !Configured)
|
||||
return false;
|
||||
|
||||
EAGLRenderingAPI OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
|
||||
|
||||
switch (Params.DriverType)
|
||||
{
|
||||
case EDT_OGLES1:
|
||||
OpenGLESVersion = kEAGLRenderingAPIOpenGLES1;
|
||||
break;
|
||||
case EDT_OGLES2:
|
||||
OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dataStorage->Context = [[EAGLContext alloc] initWithAPI:OpenGLESVersion];
|
||||
|
||||
if (dataStorage->Context == nil)
|
||||
{
|
||||
os::Printer::log("Could not create EAGL context.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
Data.OpenGLiOS.Context = (__bridge void*)dataStorage->Context;
|
||||
|
||||
os::Printer::log("EAGL context created with OpenGLESVersion: ", core::stringc(static_cast<int>(OpenGLESVersion)), ELL_DEBUG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEAGLManager::destroyContext()
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
|
||||
[dataStorage->Context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:nil];
|
||||
|
||||
if (FrameBuffer.BufferID != 0)
|
||||
{
|
||||
glDeleteFramebuffersOES(1, &FrameBuffer.BufferID);
|
||||
FrameBuffer.BufferID = 0;
|
||||
}
|
||||
|
||||
if (FrameBuffer.ColorBuffer != 0)
|
||||
{
|
||||
glDeleteRenderbuffersOES(1, &FrameBuffer.ColorBuffer);
|
||||
FrameBuffer.ColorBuffer = 0;
|
||||
}
|
||||
|
||||
if (FrameBuffer.DepthBuffer != 0)
|
||||
{
|
||||
glDeleteRenderbuffersOES(1, &FrameBuffer.DepthBuffer);
|
||||
FrameBuffer.DepthBuffer = 0;
|
||||
}
|
||||
|
||||
[EAGLContext setCurrentContext:0];
|
||||
|
||||
if (dataStorage->Context != nil)
|
||||
dataStorage->Context = 0;
|
||||
|
||||
Data.OpenGLiOS.Context = 0;
|
||||
}
|
||||
|
||||
bool CEAGLManager::activateContext(const SExposedVideoData& videoData)
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
EAGLContext* context = dataStorage->Context;
|
||||
|
||||
bool status = false;
|
||||
|
||||
if (context != nil)
|
||||
{
|
||||
status = ([EAGLContext currentContext] == context || [EAGLContext setCurrentContext:context]);
|
||||
}
|
||||
|
||||
if (status)
|
||||
{
|
||||
if (FrameBuffer.ColorBuffer == 0)
|
||||
{
|
||||
glGenRenderbuffersOES(1, &FrameBuffer.ColorBuffer);
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
|
||||
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:dataStorage->Layer];
|
||||
}
|
||||
|
||||
if (FrameBuffer.DepthBuffer == 0)
|
||||
{
|
||||
GLenum depth = (Params.ZBufferBits >= 24) ? GL_DEPTH_COMPONENT24_OES : GL_DEPTH_COMPONENT16_OES;
|
||||
|
||||
glGenRenderbuffersOES(1, &FrameBuffer.DepthBuffer);
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.DepthBuffer);
|
||||
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depth, Params.WindowSize.Width, Params.WindowSize.Height);
|
||||
}
|
||||
|
||||
if (FrameBuffer.BufferID == 0)
|
||||
{
|
||||
glGenFramebuffersOES(1, &FrameBuffer.BufferID);
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer.BufferID);
|
||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
|
||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, FrameBuffer.DepthBuffer);
|
||||
}
|
||||
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer.BufferID);
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("Could not make EGL context current.");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const SExposedVideoData& CEAGLManager::getContext() const
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
bool CEAGLManager::swapBuffers()
|
||||
{
|
||||
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
|
||||
EAGLContext* context = dataStorage->Context;
|
||||
|
||||
bool status = false;
|
||||
|
||||
if (context != nil && context == [EAGLContext currentContext])
|
||||
{
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
|
||||
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
|
||||
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
662
source/Irrlicht/CEGLManager.cpp
Executable file
662
source/Irrlicht/CEGLManager.cpp
Executable file
@ -0,0 +1,662 @@
|
||||
// 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
|
||||
|
||||
#include "CEGLManager.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_EGL_MANAGER_
|
||||
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
#include "os.h"
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
|
||||
#include <android/native_activity.h>
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
CEGLManager::CEGLManager() : IContextManager(), EglWindow(0), EglDisplay(EGL_NO_DISPLAY),
|
||||
EglSurface(EGL_NO_SURFACE), EglContext(EGL_NO_CONTEXT), EglConfig(0), MajorVersion(0), MinorVersion(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CEGLManager");
|
||||
#endif
|
||||
}
|
||||
|
||||
CEGLManager::~CEGLManager()
|
||||
{
|
||||
destroyContext();
|
||||
destroySurface();
|
||||
terminate();
|
||||
}
|
||||
|
||||
bool CEGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data)
|
||||
{
|
||||
// store new data
|
||||
Params=params;
|
||||
Data=data;
|
||||
|
||||
if (EglWindow != 0 && EglDisplay != EGL_NO_DISPLAY)
|
||||
return true;
|
||||
|
||||
// Window is depend on platform.
|
||||
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
||||
EglWindow = (NativeWindowType)Data.OpenGLWin32.HWnd;
|
||||
Data.OpenGLWin32.HDc = GetDC((HWND)EglWindow);
|
||||
EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLWin32.HDc);
|
||||
#elif defined(_IRR_EMSCRIPTEN_PLATFORM_)
|
||||
EglWindow = 0;
|
||||
EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
|
||||
EglWindow = (NativeWindowType)Data.OpenGLLinux.X11Window;
|
||||
EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLLinux.X11Display);
|
||||
#elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
|
||||
EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window;
|
||||
EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
#elif defined(_IRR_COMPILE_WITH_FB_DEVICE_)
|
||||
EglWindow = (NativeWindowType)Data.OpenGLFB.Window;
|
||||
EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
#endif
|
||||
|
||||
// We must check if EGL display is valid.
|
||||
if (EglDisplay == EGL_NO_DISPLAY)
|
||||
{
|
||||
os::Printer::log("Could not get EGL display.");
|
||||
terminate();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize EGL here.
|
||||
if (!eglInitialize(EglDisplay, &MajorVersion, &MinorVersion))
|
||||
{
|
||||
os::Printer::log("Could not initialize EGL display.");
|
||||
|
||||
EglDisplay = EGL_NO_DISPLAY;
|
||||
terminate();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
os::Printer::log("EGL version", core::stringc(MajorVersion+(MinorVersion*0.1f)).c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEGLManager::terminate()
|
||||
{
|
||||
if (EglWindow == 0 && EglDisplay == EGL_NO_DISPLAY)
|
||||
return;
|
||||
|
||||
if (EglDisplay != EGL_NO_DISPLAY)
|
||||
{
|
||||
// We should unbind current EGL context before terminate EGL.
|
||||
eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
eglTerminate(EglDisplay);
|
||||
EglDisplay = EGL_NO_DISPLAY;
|
||||
}
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
||||
if (Data.OpenGLWin32.HDc)
|
||||
{
|
||||
ReleaseDC((HWND)EglWindow, (HDC)Data.OpenGLWin32.HDc);
|
||||
Data.OpenGLWin32.HDc = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
MajorVersion = 0;
|
||||
MinorVersion = 0;
|
||||
}
|
||||
|
||||
bool CEGLManager::generateSurface()
|
||||
{
|
||||
if (EglDisplay == EGL_NO_DISPLAY)
|
||||
return false;
|
||||
|
||||
if (EglSurface != EGL_NO_SURFACE)
|
||||
return true;
|
||||
|
||||
// We should assign new WindowID on platforms, where WindowID may change at runtime,
|
||||
// at this time only Android support this feature.
|
||||
// this needs an update method instead!
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
|
||||
EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window;
|
||||
#endif
|
||||
|
||||
#if defined(_IRR_EMSCRIPTEN_PLATFORM_)
|
||||
// eglChooseConfig is currently only implemented as stub in emscripten (version 1.37.22 at point of writing)
|
||||
// But the other solution would also be fine as it also only generates a single context so there is not much to choose from.
|
||||
EglConfig = chooseConfig(ECS_IRR_CHOOSE);
|
||||
#else
|
||||
EglConfig = chooseConfig(ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS);
|
||||
#endif
|
||||
|
||||
if ( EglConfig == 0 )
|
||||
{
|
||||
os::Printer::log("Could not get config for EGL display.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
|
||||
EGLint Format = 0;
|
||||
eglGetConfigAttrib(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &Format);
|
||||
|
||||
ANativeWindow_setBuffersGeometry(EglWindow, 0, 0, Format);
|
||||
#endif
|
||||
|
||||
// Now we are able to create EGL surface.
|
||||
EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, EglWindow, 0);
|
||||
|
||||
if (EGL_NO_SURFACE == EglSurface)
|
||||
EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, 0, 0);
|
||||
|
||||
if (EGL_NO_SURFACE == EglSurface)
|
||||
os::Printer::log("Could not create EGL surface.");
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
if (MinorVersion > 1)
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
if (Params.Vsync)
|
||||
eglSwapInterval(EglDisplay, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle)
|
||||
{
|
||||
EGLConfig configResult = 0;
|
||||
|
||||
// Find proper OpenGL BIT.
|
||||
EGLint eglOpenGLBIT = 0;
|
||||
switch (Params.DriverType)
|
||||
{
|
||||
case EDT_OGLES1:
|
||||
eglOpenGLBIT = EGL_OPENGL_ES_BIT;
|
||||
break;
|
||||
case EDT_OGLES2:
|
||||
case EDT_WEBGL1:
|
||||
eglOpenGLBIT = EGL_OPENGL_ES2_BIT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( confStyle == ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS )
|
||||
{
|
||||
EGLint Attribs[] =
|
||||
{
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, Params.WithAlphaChannel ? 1:0,
|
||||
EGL_BUFFER_SIZE, Params.Bits,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_DEPTH_SIZE, Params.ZBufferBits,
|
||||
EGL_STENCIL_SIZE, Params.Stencilbuffer,
|
||||
EGL_SAMPLE_BUFFERS, Params.AntiAlias ? 1:0,
|
||||
EGL_SAMPLES, Params.AntiAlias,
|
||||
#ifdef EGL_VERSION_1_3
|
||||
EGL_RENDERABLE_TYPE, eglOpenGLBIT,
|
||||
#endif
|
||||
EGL_NONE, 0
|
||||
};
|
||||
|
||||
EGLint numConfigs = 0;
|
||||
u32 steps = 5;
|
||||
|
||||
// Choose the best EGL config.
|
||||
// TODO: We should also have a confStyle ECS_EGL_CHOOSE_CLOSEST
|
||||
// which doesn't take first result of eglChooseConfigs,
|
||||
// but the closest to requested parameters. eglChooseConfigs
|
||||
// can return more than 1 result and first one might have
|
||||
// "better" values than requested (more bits per pixel etc).
|
||||
// So this returns the config which can do most, not the
|
||||
// config which is closest to the requested parameters.
|
||||
//
|
||||
while (!eglChooseConfig(EglDisplay, Attribs, &configResult, 1, &numConfigs) || !numConfigs)
|
||||
{
|
||||
switch (steps)
|
||||
{
|
||||
case 5: // samples
|
||||
if (Attribs[19] > 2) // Params.AntiAlias
|
||||
--Attribs[19];
|
||||
else
|
||||
{
|
||||
Attribs[17] = 0; // Params.Stencilbuffer
|
||||
Attribs[19] = 0; // Params.AntiAlias
|
||||
--steps;
|
||||
}
|
||||
break;
|
||||
case 4: // alpha
|
||||
if (Attribs[7]) // Params.WithAlphaChannel
|
||||
{
|
||||
Attribs[7] = 0;
|
||||
|
||||
if (Params.AntiAlias)
|
||||
{
|
||||
Attribs[17] = 1;
|
||||
Attribs[19] = Params.AntiAlias;
|
||||
steps = 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
--steps;
|
||||
break;
|
||||
case 3: // stencil
|
||||
if (Attribs[15]) // Params.Stencilbuffer
|
||||
{
|
||||
Attribs[15] = 0;
|
||||
|
||||
if (Params.AntiAlias)
|
||||
{
|
||||
Attribs[17] = 1;
|
||||
Attribs[19] = Params.AntiAlias;
|
||||
steps = 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
--steps;
|
||||
break;
|
||||
case 2: // depth size
|
||||
if (Attribs[13] > 16) // Params.ZBufferBits
|
||||
{
|
||||
Attribs[13] -= 8;
|
||||
}
|
||||
else
|
||||
--steps;
|
||||
break;
|
||||
case 1: // buffer size
|
||||
if (Attribs[9] > 16) // Params.Bits
|
||||
{
|
||||
Attribs[9] -= 8;
|
||||
}
|
||||
else
|
||||
--steps;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (Params.AntiAlias && !Attribs[17])
|
||||
os::Printer::log("No multisampling.");
|
||||
|
||||
if (Params.WithAlphaChannel && !Attribs[7])
|
||||
os::Printer::log("No alpha.");
|
||||
|
||||
if (Params.Stencilbuffer && !Attribs[15])
|
||||
os::Printer::log("No stencil buffer.");
|
||||
|
||||
if (Params.ZBufferBits > Attribs[13])
|
||||
os::Printer::log("No full depth buffer.");
|
||||
|
||||
if (Params.Bits > Attribs[9])
|
||||
os::Printer::log("No full color buffer.");
|
||||
}
|
||||
else if ( confStyle == ECS_IRR_CHOOSE )
|
||||
{
|
||||
// find number of available configs
|
||||
EGLint numConfigs;
|
||||
if ( eglGetConfigs( EglDisplay, NULL, 0, &numConfigs) == EGL_FALSE )
|
||||
{
|
||||
testEGLError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( numConfigs <= 0 )
|
||||
return 0;
|
||||
|
||||
// Get all available configs.
|
||||
EGLConfig * configs = new EGLConfig[numConfigs];
|
||||
if ( eglGetConfigs( EglDisplay, configs, numConfigs, &numConfigs) == EGL_FALSE )
|
||||
{
|
||||
testEGLError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find the best one.
|
||||
core::array<SConfigRating> ratings((u32)numConfigs);
|
||||
for ( u32 i=0; i < (u32)numConfigs; ++i )
|
||||
{
|
||||
SConfigRating r;
|
||||
r.config = configs[i];
|
||||
r.rating = rateConfig(r.config, eglOpenGLBIT);
|
||||
|
||||
if ( r.rating >= 0 )
|
||||
ratings.push_back(r);
|
||||
}
|
||||
|
||||
if ( ratings.size() > 0 )
|
||||
{
|
||||
ratings.sort();
|
||||
configResult = ratings[0].config;
|
||||
|
||||
if ( ratings[0].rating != 0 )
|
||||
{
|
||||
// This is just to print some log info (it also rates again while doing that, but rating is cheap enough, so that doesn't matter here).
|
||||
rateConfig(ratings[0].config, eglOpenGLBIT, true);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] configs;
|
||||
}
|
||||
|
||||
return configResult;
|
||||
}
|
||||
|
||||
irr::s32 CEGLManager::rateConfig(EGLConfig config, EGLint eglOpenGLBIT, bool log)
|
||||
{
|
||||
// some values must be there or we ignore the config
|
||||
#ifdef EGL_VERSION_1_3
|
||||
EGLint attribRenderableType = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_RENDERABLE_TYPE, &attribRenderableType);
|
||||
if ( attribRenderableType != eglOpenGLBIT )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("EGL_RENDERABLE_TYPE != eglOpenGLBIT");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
EGLint attribSurfaceType = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_SURFACE_TYPE, &attribSurfaceType);
|
||||
if ( attribSurfaceType != EGL_WINDOW_BIT )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("EGL_SURFACE_TYPE!= EGL_WINDOW_BIT");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Generally we give a really bad rating if attributes are worse than requested
|
||||
// We give a slight worse rating if attributes are not exact as requested
|
||||
// And we use some priorities which might make sense (but not really fine-tuned,
|
||||
// so if you think other priorities would be better don't worry about changing the values.
|
||||
int rating = 0;
|
||||
|
||||
EGLint attribBufferSize = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_BUFFER_SIZE, &attribBufferSize);
|
||||
if ( attribBufferSize < Params.Bits )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("No full color buffer.");
|
||||
rating += 100;
|
||||
}
|
||||
if ( attribBufferSize > Params.Bits )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("Larger color buffer.", ELL_DEBUG);
|
||||
++rating;
|
||||
}
|
||||
|
||||
EGLint attribRedSize = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_RED_SIZE, &attribRedSize);
|
||||
if ( attribRedSize < 5 && Params.Bits >= 4 )
|
||||
rating += 100;
|
||||
else if ( attribRedSize < 8 && Params.Bits >= 24)
|
||||
rating += 10;
|
||||
else if ( attribRedSize >= 8 && Params.Bits < 24 )
|
||||
rating ++;
|
||||
EGLint attribGreenSize = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_GREEN_SIZE, &attribGreenSize);
|
||||
if ( attribGreenSize < 5 && Params.Bits >= 4 )
|
||||
rating += 100;
|
||||
else if ( attribGreenSize < 8 && Params.Bits >= 24)
|
||||
rating += 10;
|
||||
else if ( attribGreenSize >= 8 && Params.Bits < 24 )
|
||||
rating ++;
|
||||
EGLint attribBlueSize = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_BLUE_SIZE, &attribBlueSize);
|
||||
if ( attribBlueSize < 5 && Params.Bits >= 4 )
|
||||
rating += 100;
|
||||
else if ( attribBlueSize < 8 && Params.Bits >= 24)
|
||||
rating += 10;
|
||||
else if ( attribBlueSize >= 8 && Params.Bits < 24 )
|
||||
rating ++;
|
||||
|
||||
EGLint attribAlphaSize = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_ALPHA_SIZE, &attribAlphaSize);
|
||||
if ( Params.WithAlphaChannel && attribAlphaSize == 0 )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("No alpha.");
|
||||
rating += 10;
|
||||
}
|
||||
else if ( !Params.WithAlphaChannel && attribAlphaSize > 0 )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("Got alpha (unrequested).", ELL_DEBUG);
|
||||
rating ++;
|
||||
}
|
||||
|
||||
EGLint attribStencilSize = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_STENCIL_SIZE, &attribStencilSize);
|
||||
if ( Params.Stencilbuffer && attribStencilSize == 0 )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("No stencil buffer.");
|
||||
rating += 10;
|
||||
}
|
||||
else if ( !Params.Stencilbuffer && attribStencilSize > 0 )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("Got a stencil buffer (unrequested).", ELL_DEBUG);
|
||||
rating ++;
|
||||
}
|
||||
|
||||
EGLint attribDepthSize = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_DEPTH_SIZE, &attribDepthSize);
|
||||
if ( attribDepthSize < Params.ZBufferBits )
|
||||
{
|
||||
if ( log )
|
||||
{
|
||||
if (attribDepthSize > 0)
|
||||
os::Printer::log("No full depth buffer.");
|
||||
else
|
||||
os::Printer::log("No depth buffer.");
|
||||
}
|
||||
rating += 50;
|
||||
}
|
||||
else if ( attribDepthSize != Params.ZBufferBits )
|
||||
{
|
||||
if ( log )
|
||||
{
|
||||
if ( Params.ZBufferBits == 0 )
|
||||
os::Printer::log("Got a depth buffer (unrequested).", ELL_DEBUG);
|
||||
else
|
||||
os::Printer::log("Got a larger depth buffer.", ELL_DEBUG);
|
||||
}
|
||||
rating ++;
|
||||
}
|
||||
|
||||
EGLint attribSampleBuffers=0, attribSamples = 0;
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_SAMPLE_BUFFERS, &attribSampleBuffers);
|
||||
eglGetConfigAttrib( EglDisplay, config, EGL_SAMPLES, &attribSamples);
|
||||
if ( Params.AntiAlias && attribSampleBuffers == 0 )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("No multisampling.");
|
||||
rating += 20;
|
||||
}
|
||||
else if ( Params.AntiAlias && attribSampleBuffers && attribSamples < Params.AntiAlias )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("Multisampling with less samples than requested.", ELL_DEBUG);
|
||||
rating += 10;
|
||||
}
|
||||
else if ( Params.AntiAlias && attribSampleBuffers && attribSamples > Params.AntiAlias )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("Multisampling with more samples than requested.", ELL_DEBUG);
|
||||
rating += 5;
|
||||
}
|
||||
else if ( !Params.AntiAlias && attribSampleBuffers > 0 )
|
||||
{
|
||||
if ( log )
|
||||
os::Printer::log("Got multisampling (unrequested).", ELL_DEBUG);
|
||||
rating += 3;
|
||||
}
|
||||
|
||||
return rating;
|
||||
}
|
||||
|
||||
void CEGLManager::destroySurface()
|
||||
{
|
||||
if (EglSurface == EGL_NO_SURFACE)
|
||||
return;
|
||||
|
||||
// We should unbind current EGL context before destroy EGL surface.
|
||||
eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
eglDestroySurface(EglDisplay, EglSurface);
|
||||
EglSurface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
bool CEGLManager::generateContext()
|
||||
{
|
||||
if (EglDisplay == EGL_NO_DISPLAY || EglSurface == EGL_NO_SURFACE)
|
||||
return false;
|
||||
|
||||
if (EglContext != EGL_NO_CONTEXT)
|
||||
return true;
|
||||
|
||||
EGLint OpenGLESVersion = 0;
|
||||
|
||||
switch (Params.DriverType)
|
||||
{
|
||||
case EDT_OGLES1:
|
||||
OpenGLESVersion = 1;
|
||||
break;
|
||||
case EDT_OGLES2:
|
||||
case EDT_WEBGL1:
|
||||
OpenGLESVersion = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
EGLint ContextAttrib[] =
|
||||
{
|
||||
#ifdef EGL_VERSION_1_3
|
||||
EGL_CONTEXT_CLIENT_VERSION, OpenGLESVersion,
|
||||
#endif
|
||||
EGL_NONE, 0
|
||||
};
|
||||
|
||||
EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, ContextAttrib);
|
||||
|
||||
if (testEGLError())
|
||||
{
|
||||
os::Printer::log("Could not create EGL context.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
os::Printer::log("EGL context created with OpenGLESVersion: ", core::stringc((int)OpenGLESVersion), ELL_DEBUG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEGLManager::destroyContext()
|
||||
{
|
||||
if (EglContext == EGL_NO_CONTEXT)
|
||||
return;
|
||||
|
||||
// We must unbind current EGL context before destroy it.
|
||||
eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(EglDisplay, EglContext);
|
||||
|
||||
EglContext = EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
bool CEGLManager::activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero)
|
||||
{
|
||||
eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext);
|
||||
|
||||
if (testEGLError())
|
||||
{
|
||||
os::Printer::log("Could not make EGL context current.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const SExposedVideoData& CEGLManager::getContext() const
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
bool CEGLManager::swapBuffers()
|
||||
{
|
||||
return (eglSwapBuffers(EglDisplay, EglSurface)==EGL_TRUE);
|
||||
}
|
||||
|
||||
bool CEGLManager::testEGLError()
|
||||
{
|
||||
#if defined(EGL_VERSION_1_0) && defined(_DEBUG)
|
||||
EGLint status = eglGetError();
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case EGL_SUCCESS:
|
||||
return false;
|
||||
case EGL_NOT_INITIALIZED :
|
||||
os::Printer::log("Not Initialized", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_ACCESS:
|
||||
os::Printer::log("Bad Access", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_ALLOC:
|
||||
os::Printer::log("Bad Alloc", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
os::Printer::log("Bad Attribute", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_CONTEXT:
|
||||
os::Printer::log("Bad Context", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_CONFIG:
|
||||
os::Printer::log("Bad Config", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
os::Printer::log("Bad Current Surface", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_DISPLAY:
|
||||
os::Printer::log("Bad Display", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_SURFACE:
|
||||
os::Printer::log("Bad Surface", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_MATCH:
|
||||
os::Printer::log("Bad Match", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_PARAMETER:
|
||||
os::Printer::log("Bad Parameter", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
os::Printer::log("Bad Native Pixmap", ELL_ERROR);
|
||||
break;
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
os::Printer::log("Bad Native Window", ELL_ERROR);
|
||||
break;
|
||||
case EGL_CONTEXT_LOST:
|
||||
os::Printer::log("Context Lost", ELL_ERROR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
119
source/Irrlicht/CEGLManager.h
Executable file
119
source/Irrlicht/CEGLManager.h
Executable file
@ -0,0 +1,119 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_EGL_MANAGER_H_INCLUDED__
|
||||
#define __C_EGL_MANAGER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_EGL_MANAGER_
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "SExposedVideoData.h"
|
||||
#include "IContextManager.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "libEGL.lib")
|
||||
#endif
|
||||
|
||||
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. */
|
||||
virtual bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data) _IRR_OVERRIDE_;
|
||||
|
||||
// Terminate EGL.
|
||||
/* Terminate EGL context. This method break both existed surface and context. */
|
||||
virtual void terminate() _IRR_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. */
|
||||
virtual bool generateSurface() _IRR_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. */
|
||||
virtual void destroySurface() _IRR_OVERRIDE_;
|
||||
|
||||
// Create EGL context.
|
||||
/* This method create and activate EGL context. */
|
||||
virtual bool generateContext() _IRR_OVERRIDE_;
|
||||
|
||||
// Destroy EGL context.
|
||||
/* This method destroy EGL context. */
|
||||
virtual void destroyContext() _IRR_OVERRIDE_;
|
||||
|
||||
virtual const SExposedVideoData& getContext() const _IRR_OVERRIDE_;
|
||||
|
||||
virtual bool activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero) _IRR_OVERRIDE_;
|
||||
|
||||
// Swap buffers.
|
||||
virtual bool swapBuffers() _IRR_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;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
70
source/Irrlicht/CEmptySceneNode.cpp
Normal file
70
source/Irrlicht/CEmptySceneNode.cpp
Normal file
@ -0,0 +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
|
46
source/Irrlicht/CEmptySceneNode.h
Normal file
46
source/Irrlicht/CEmptySceneNode.h
Normal file
@ -0,0 +1,46 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_EMPTY_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_EMPTY_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#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
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const _IRR_OVERRIDE_;
|
||||
|
||||
//! This method is called just before the rendering process of the whole scene.
|
||||
virtual void OnRegisterSceneNode() _IRR_OVERRIDE_;
|
||||
|
||||
//! does nothing.
|
||||
virtual void render() _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_EMPTY; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
76
source/Irrlicht/CFPSCounter.cpp
Normal file
76
source/Irrlicht/CFPSCounter.cpp
Normal file
@ -0,0 +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
|
||||
|
54
source/Irrlicht/CFPSCounter.h
Normal file
54
source/Irrlicht/CFPSCounter.h
Normal file
@ -0,0 +1,54 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_FPSCOUNTER_H_INCLUDED__
|
||||
#define __C_FPSCOUNTER_H_INCLUDED__
|
||||
|
||||
#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
|
||||
|
||||
|
||||
#endif
|
||||
|
163
source/Irrlicht/CFileList.cpp
Normal file
163
source/Irrlicht/CFileList.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
// 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 "IrrCompileConfig.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
|
||||
|
138
source/Irrlicht/CFileList.h
Normal file
138
source/Irrlicht/CFileList.h
Normal file
@ -0,0 +1,138 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_FILE_LIST_H_INCLUDED__
|
||||
#define __C_FILE_LIST_H_INCLUDED__
|
||||
|
||||
#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 */
|
||||
virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sorts the file list. You should call this after adding any items to the file list
|
||||
virtual void sort() _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the amount of files in the filelist.
|
||||
virtual u32 getFileCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the name of a file in the list, based on an index.
|
||||
virtual const io::path& getFileName(u32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the full name of a file in the list, path included, based on an index.
|
||||
virtual const io::path& getFullFileName(u32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the ID of a file in the file list, based on an index.
|
||||
virtual u32 getID(u32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns true if the file is a directory
|
||||
virtual bool isDirectory(u32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the size of a file
|
||||
virtual u32 getFileSize(u32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the offset of a file
|
||||
virtual u32 getFileOffset(u32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Searches for a file or folder within the list, returns the index
|
||||
virtual s32 findFile(const io::path& filename, bool isFolder) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the base path of the file list
|
||||
virtual const io::path& getPath() const _IRR_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
|
||||
|
||||
|
||||
#endif
|
||||
|
1127
source/Irrlicht/CFileSystem.cpp
Normal file
1127
source/Irrlicht/CFileSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
179
source/Irrlicht/CFileSystem.h
Normal file
179
source/Irrlicht/CFileSystem.h
Normal file
@ -0,0 +1,179 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_FILE_SYSTEM_H_INCLUDED__
|
||||
#define __C_FILE_SYSTEM_H_INCLUDED__
|
||||
|
||||
#include "IFileSystem.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class CZipReader;
|
||||
class CPakReader;
|
||||
class CMountPointReader;
|
||||
|
||||
/*!
|
||||
FileSystem which uses normal files and one zipfile
|
||||
*/
|
||||
class CFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CFileSystem();
|
||||
|
||||
//! destructor
|
||||
virtual ~CFileSystem();
|
||||
|
||||
//! opens a file for read access
|
||||
virtual IReadFile* createAndOpenFile(const io::path& filename) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates an IReadFile interface for accessing memory like a file.
|
||||
virtual IReadFile* createMemoryReadFile(const void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped = false) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates an IReadFile interface for accessing files inside files
|
||||
virtual IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates an IWriteFile interface for accessing memory like a file.
|
||||
virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped=false) _IRR_OVERRIDE_;
|
||||
|
||||
//! Opens a file for write access.
|
||||
virtual IWriteFile* createAndWriteFile(const io::path& filename, bool append=false) _IRR_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) _IRR_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) _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
virtual bool addFileArchive(IFileArchive* archive) _IRR_OVERRIDE_;
|
||||
|
||||
//! move the hirarchy of the filesystem. moves sourceIndex relative up or down
|
||||
virtual bool moveFileArchive(u32 sourceIndex, s32 relative) _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds an external archive loader to the engine.
|
||||
virtual void addArchiveLoader(IArchiveLoader* loader) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the total number of archive loaders added.
|
||||
virtual u32 getArchiveLoaderCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the archive loader by index.
|
||||
virtual IArchiveLoader* getArchiveLoader(u32 index) const _IRR_OVERRIDE_;
|
||||
|
||||
//! gets the file archive count
|
||||
virtual u32 getFileArchiveCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! gets an archive
|
||||
virtual IFileArchive* getFileArchive(u32 index) _IRR_OVERRIDE_;
|
||||
|
||||
//! removes an archive from the file system.
|
||||
virtual bool removeFileArchive(u32 index) _IRR_OVERRIDE_;
|
||||
|
||||
//! removes an archive from the file system.
|
||||
virtual bool removeFileArchive(const io::path& filename) _IRR_OVERRIDE_;
|
||||
|
||||
//! Removes an archive from the file system.
|
||||
virtual bool removeFileArchive(const IFileArchive* archive) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the string of the current working directory
|
||||
virtual const io::path& getWorkingDirectory() _IRR_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\"
|
||||
virtual bool changeWorkingDirectoryTo(const io::path& newDirectory) _IRR_OVERRIDE_;
|
||||
|
||||
//! Converts a relative path to an absolute (unique) path, resolving symbolic links
|
||||
virtual io::path getAbsolutePath(const io::path& filename) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the directory a file is located in.
|
||||
/** \param filename: The file to get the directory from */
|
||||
virtual io::path getFileDir(const io::path& filename) const _IRR_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 */
|
||||
virtual io::path getFileBasename(const io::path& filename, bool keepExtension=true) const _IRR_OVERRIDE_;
|
||||
|
||||
//! flatten a path and file name for example: "/you/me/../." becomes "/you"
|
||||
virtual io::path& flattenFilename( io::path& directory, const io::path& root = "/" ) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the relative filename, relative to the given directory
|
||||
virtual path getRelativeFilename(const path& filename, const path& directory) const _IRR_OVERRIDE_;
|
||||
|
||||
virtual EFileSystemType setFileListSystem(EFileSystemType listType) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a list of files and directories in the current working directory
|
||||
//! and returns it.
|
||||
virtual IFileList* createFileList() _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates an empty filelist
|
||||
virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) _IRR_OVERRIDE_;
|
||||
|
||||
//! determines if a file exists and would be able to be opened.
|
||||
virtual bool existFile(const io::path& filename) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReader* createXMLReader(const io::path& filename) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReader* createXMLReader(IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReaderUTF8* createXMLReaderUTF8(const io::path& filename) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Writer from a file.
|
||||
virtual IXMLWriter* createXMLWriter(const io::path& filename) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Writer from a file.
|
||||
virtual IXMLWriter* createXMLWriter(IWriteFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Writer from a file which will write ASCII/UTF-8 characters (char*).
|
||||
virtual IXMLWriterUTF8* createXMLWriterUTF8(const path& filename) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a XML Writer from a file which will write ASCII/UTF-8 characters (char*).
|
||||
virtual IXMLWriterUTF8* createXMLWriterUTF8(IWriteFile* file) _IRR_OVERRIDE_;
|
||||
|
||||
//! Creates a new empty collection of attributes, usable for serialization and more.
|
||||
virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
// don't expose, needs refactoring
|
||||
bool changeArchivePassword(const path& filename,
|
||||
const core::stringc& password,
|
||||
IFileArchive** archive = 0);
|
||||
|
||||
//! 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
|
||||
|
||||
#endif
|
||||
|
436
source/Irrlicht/CGLXManager.cpp
Normal file
436
source/Irrlicht/CGLXManager.cpp
Normal file
@ -0,0 +1,436 @@
|
||||
// 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 "glext.h"
|
||||
#undef GLX_ARB_get_proc_address // avoid problems with local glxext.h
|
||||
#include "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(&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.X11Window=GlxWin;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLXManager::destroySurface()
|
||||
{
|
||||
if (GlxWin)
|
||||
glXDestroyWindow((Display*)CurrentContext.OpenGLLinux.X11Display, GlxWin);
|
||||
}
|
||||
|
||||
bool CGLXManager::generateContext()
|
||||
{
|
||||
GLXContext context;
|
||||
|
||||
if (glxFBConfig)
|
||||
{
|
||||
if (GlxWin)
|
||||
{
|
||||
// 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.X11Window, (GLXContext)videoData.OpenGLLinux.X11Context))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
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.X11Window, (GLXContext)PrimaryContext.OpenGLLinux.X11Context))
|
||||
{
|
||||
os::Printer::log("Context activation failed.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool CGLXManager::swapBuffers()
|
||||
{
|
||||
glXSwapBuffers((Display*)CurrentContext.OpenGLLinux.X11Display, CurrentContext.OpenGLLinux.X11Window);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
79
source/Irrlicht/CGLXManager.h
Normal file
79
source/Irrlicht/CGLXManager.h
Normal file
@ -0,0 +1,79 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_GLX_MANAGER_H_INCLUDED__
|
||||
#define __C_GLX_MANAGER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#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
|
||||
virtual bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data) _IRR_OVERRIDE_;
|
||||
|
||||
// Terminate
|
||||
virtual void terminate() _IRR_OVERRIDE_;
|
||||
|
||||
// Create surface.
|
||||
virtual bool generateSurface() _IRR_OVERRIDE_;
|
||||
|
||||
// Destroy surface.
|
||||
virtual void destroySurface() _IRR_OVERRIDE_;
|
||||
|
||||
// Create context.
|
||||
virtual bool generateContext() _IRR_OVERRIDE_;
|
||||
|
||||
// Destroy context.
|
||||
virtual void destroyContext() _IRR_OVERRIDE_;
|
||||
|
||||
//! Get current context
|
||||
virtual const SExposedVideoData& getContext() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Change render context, disable old and activate new defined by videoData
|
||||
virtual bool activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero) _IRR_OVERRIDE_;
|
||||
|
||||
// Swap buffers.
|
||||
virtual bool swapBuffers() _IRR_OVERRIDE_;
|
||||
|
||||
XVisualInfo* getVisual() const {return VisualInfo;} // return XVisualInfo
|
||||
|
||||
private:
|
||||
SIrrlichtCreationParameters Params;
|
||||
SExposedVideoData PrimaryContext;
|
||||
SExposedVideoData CurrentContext;
|
||||
XVisualInfo* VisualInfo;
|
||||
void* glxFBConfig; // GLXFBConfig
|
||||
XID GlxWin; // GLXWindow
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
650
source/Irrlicht/CGUIButton.cpp
Normal file
650
source/Irrlicht/CGUIButton.cpp
Normal file
@ -0,0 +1,650 @@
|
||||
// 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 "CGUIButton.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool noclip)
|
||||
: IGUIButton(environment, parent, id, rectangle),
|
||||
SpriteBank(0), OverrideFont(0),
|
||||
OverrideColorEnabled(false), OverrideColor(video::SColor(101,255,255,255)),
|
||||
ClickTime(0), HoverTime(0), FocusTime(0),
|
||||
ClickShiftState(false), ClickControlState(false),
|
||||
IsPushButton(false), Pressed(false),
|
||||
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIButton");
|
||||
#endif
|
||||
setNotClipped(noclip);
|
||||
|
||||
// This element can be tabbed.
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIButton::~CGUIButton()
|
||||
{
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
if (SpriteBank)
|
||||
SpriteBank->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the images should be scaled to fit the button
|
||||
void CGUIButton::setScaleImage(bool scaleImage)
|
||||
{
|
||||
ScaleImage = scaleImage;
|
||||
}
|
||||
|
||||
|
||||
//! Returns whether the button scale the used images
|
||||
bool CGUIButton::isScalingImage() const
|
||||
{
|
||||
return ScaleImage;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the button should use the skin to draw its border
|
||||
void CGUIButton::setDrawBorder(bool border)
|
||||
{
|
||||
DrawBorder = border;
|
||||
}
|
||||
|
||||
|
||||
void CGUIButton::setSpriteBank(IGUISpriteBank* sprites)
|
||||
{
|
||||
if (sprites)
|
||||
sprites->grab();
|
||||
|
||||
if (SpriteBank)
|
||||
SpriteBank->drop();
|
||||
|
||||
SpriteBank = sprites;
|
||||
}
|
||||
|
||||
|
||||
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
|
||||
{
|
||||
ButtonSprites[(u32)state].Index = index;
|
||||
ButtonSprites[(u32)state].Color = color;
|
||||
ButtonSprites[(u32)state].Loop = loop;
|
||||
ButtonSprites[(u32)state].Scale = scale;
|
||||
}
|
||||
|
||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||
s32 CGUIButton::getSpriteIndex(EGUI_BUTTON_STATE state) const
|
||||
{
|
||||
return ButtonSprites[(u32)state].Index;
|
||||
}
|
||||
|
||||
//! Get the sprite color for the given state. Color is only used when a sprite is set.
|
||||
video::SColor CGUIButton::getSpriteColor(EGUI_BUTTON_STATE state) const
|
||||
{
|
||||
return ButtonSprites[(u32)state].Color;
|
||||
}
|
||||
|
||||
//! Returns if the sprite in the given state does loop
|
||||
bool CGUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
|
||||
{
|
||||
return ButtonSprites[(u32)state].Loop;
|
||||
}
|
||||
|
||||
//! Returns if the sprite in the given state is scaled
|
||||
bool CGUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
|
||||
{
|
||||
return ButtonSprites[(u32)state].Scale;
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIButton::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (!isEnabled())
|
||||
return IGUIElement::OnEvent(event);
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(true);
|
||||
else
|
||||
setPressed(!Pressed);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
|
||||
{
|
||||
setPressed(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown && Pressed &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
ClickShiftState = event.KeyInput.Shift;
|
||||
ClickControlState = event.KeyInput.Control;
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.Caller == this)
|
||||
{
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
FocusTime = os::Timer::getTime();
|
||||
}
|
||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
|
||||
{
|
||||
FocusTime = os::Timer::getTime();
|
||||
}
|
||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT)
|
||||
{
|
||||
HoverTime = os::Timer::getTime();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
|
||||
{
|
||||
bool wasPressed = Pressed;
|
||||
|
||||
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) )
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
else
|
||||
{
|
||||
setPressed(!Pressed);
|
||||
}
|
||||
|
||||
if ((!IsPushButton && wasPressed && Parent) ||
|
||||
(IsPushButton && wasPressed != Pressed))
|
||||
{
|
||||
ClickShiftState = event.MouseInput.Shift;
|
||||
ClickControlState = event.MouseInput.Control;
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIButton::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
if (DrawBorder)
|
||||
{
|
||||
if (!Pressed)
|
||||
{
|
||||
skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const core::position2di buttonCenter(AbsoluteRect.getCenter());
|
||||
|
||||
EGUI_BUTTON_IMAGE_STATE imageState = getImageState(Pressed);
|
||||
if ( ButtonImages[(u32)imageState].Texture )
|
||||
{
|
||||
core::position2d<s32> pos(buttonCenter);
|
||||
core::rect<s32> sourceRect(ButtonImages[(u32)imageState].SourceRect);
|
||||
if ( sourceRect.getWidth() == 0 && sourceRect.getHeight() == 0 )
|
||||
sourceRect = core::rect<s32>(core::position2di(0,0), ButtonImages[(u32)imageState].Texture->getOriginalSize());
|
||||
|
||||
pos.X -= sourceRect.getWidth() / 2;
|
||||
pos.Y -= sourceRect.getHeight() / 2;
|
||||
|
||||
if ( Pressed )
|
||||
{
|
||||
// Create a pressed-down effect by moving the image when it looks identical to the unpressed state image
|
||||
EGUI_BUTTON_IMAGE_STATE unpressedState = getImageState(false);
|
||||
if ( unpressedState == imageState || ButtonImages[(u32)imageState] == ButtonImages[(u32)unpressedState] )
|
||||
{
|
||||
pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X);
|
||||
pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y);
|
||||
}
|
||||
}
|
||||
|
||||
driver->draw2DImage(ButtonImages[(u32)imageState].Texture,
|
||||
ScaleImage? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
|
||||
sourceRect, &AbsoluteClippingRect,
|
||||
0, UseAlphaChannel);
|
||||
}
|
||||
|
||||
if (SpriteBank)
|
||||
{
|
||||
core::position2di pos(buttonCenter);
|
||||
if ( Pressed )
|
||||
{
|
||||
pos.X += skin->getSize(EGDS_BUTTON_PRESSED_SPRITE_OFFSET_X);
|
||||
pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_SPRITE_OFFSET_Y);
|
||||
}
|
||||
|
||||
if (isEnabled())
|
||||
{
|
||||
// pressed / unpressed animation
|
||||
EGUI_BUTTON_STATE state = Pressed ? EGBS_BUTTON_DOWN : EGBS_BUTTON_UP;
|
||||
drawSprite(state, ClickTime, pos);
|
||||
|
||||
// focused / unfocused animation
|
||||
state = Environment->hasFocus(this) ? EGBS_BUTTON_FOCUSED : EGBS_BUTTON_NOT_FOCUSED;
|
||||
drawSprite(state, FocusTime, pos);
|
||||
|
||||
// mouse over / off animation
|
||||
state = Environment->getHovered() == this ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF;
|
||||
drawSprite(state, HoverTime, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw disabled
|
||||
drawSprite(EGBS_BUTTON_DISABLED, 0, pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
if (Pressed)
|
||||
{
|
||||
rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X);
|
||||
rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y);
|
||||
}
|
||||
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect,
|
||||
OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
|
||||
true, true, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
|
||||
{
|
||||
u32 stateIdx = (u32)state;
|
||||
|
||||
if (ButtonSprites[stateIdx].Index != -1)
|
||||
{
|
||||
if ( ButtonSprites[stateIdx].Scale )
|
||||
{
|
||||
const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};
|
||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect,
|
||||
&AbsoluteClippingRect, colors,
|
||||
os::Timer::getTime()-startTime, ButtonSprites[stateIdx].Loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
|
||||
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, os::Timer::getTime(),
|
||||
ButtonSprites[stateIdx].Loop, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
|
||||
{
|
||||
// figure state we should have
|
||||
EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED;
|
||||
bool focused = Environment->hasFocus(this);
|
||||
bool mouseOver = static_cast<const IGUIElement*>(Environment->getHovered()) == this; // (static cast for Borland)
|
||||
if (isEnabled())
|
||||
{
|
||||
if ( pressed )
|
||||
{
|
||||
if ( focused && mouseOver )
|
||||
state = EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER;
|
||||
else if ( focused )
|
||||
state = EGBIS_IMAGE_DOWN_FOCUSED;
|
||||
else if ( mouseOver )
|
||||
state = EGBIS_IMAGE_DOWN_MOUSEOVER;
|
||||
else
|
||||
state = EGBIS_IMAGE_DOWN;
|
||||
}
|
||||
else // !pressed
|
||||
{
|
||||
if ( focused && mouseOver )
|
||||
state = EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER;
|
||||
else if ( focused )
|
||||
state = EGBIS_IMAGE_UP_FOCUSED;
|
||||
else if ( mouseOver )
|
||||
state = EGBIS_IMAGE_UP_MOUSEOVER;
|
||||
else
|
||||
state = EGBIS_IMAGE_UP;
|
||||
}
|
||||
}
|
||||
|
||||
// find a compatible state that has images
|
||||
while ( state != EGBIS_IMAGE_UP && !ButtonImages[(u32)state].Texture )
|
||||
{
|
||||
switch ( state )
|
||||
{
|
||||
case EGBIS_IMAGE_UP_FOCUSED:
|
||||
state = EGBIS_IMAGE_UP_MOUSEOVER;
|
||||
break;
|
||||
case EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER:
|
||||
state = EGBIS_IMAGE_UP_FOCUSED;
|
||||
break;
|
||||
case EGBIS_IMAGE_DOWN_MOUSEOVER:
|
||||
state = EGBIS_IMAGE_DOWN;
|
||||
break;
|
||||
case EGBIS_IMAGE_DOWN_FOCUSED:
|
||||
state = EGBIS_IMAGE_DOWN_MOUSEOVER;
|
||||
break;
|
||||
case EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER:
|
||||
state = EGBIS_IMAGE_DOWN_FOCUSED;
|
||||
break;
|
||||
case EGBIS_IMAGE_DISABLED:
|
||||
if ( pressed )
|
||||
state = EGBIS_IMAGE_DOWN;
|
||||
else
|
||||
state = EGBIS_IMAGE_UP;
|
||||
break;
|
||||
default:
|
||||
state = EGBIS_IMAGE_UP;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
||||
void CGUIButton::setOverrideFont(IGUIFont* font)
|
||||
{
|
||||
if (OverrideFont == font)
|
||||
return;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
OverrideFont = font;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->grab();
|
||||
}
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * CGUIButton::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* CGUIButton::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont(EGDF_BUTTON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets another color for the text.
|
||||
void CGUIButton::setOverrideColor(video::SColor color)
|
||||
{
|
||||
OverrideColor = color;
|
||||
OverrideColorEnabled = true;
|
||||
}
|
||||
|
||||
video::SColor CGUIButton::getOverrideColor() const
|
||||
{
|
||||
return OverrideColor;
|
||||
}
|
||||
|
||||
void CGUIButton::enableOverrideColor(bool enable)
|
||||
{
|
||||
OverrideColorEnabled = enable;
|
||||
}
|
||||
|
||||
bool CGUIButton::isOverrideColorEnabled() const
|
||||
{
|
||||
return OverrideColorEnabled;
|
||||
}
|
||||
|
||||
void CGUIButton::setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image, const core::rect<s32>& sourceRect)
|
||||
{
|
||||
if ( state >= EGBIS_COUNT )
|
||||
return;
|
||||
|
||||
if ( image )
|
||||
image->grab();
|
||||
|
||||
u32 stateIdx = (u32)state;
|
||||
if ( ButtonImages[stateIdx].Texture )
|
||||
ButtonImages[stateIdx].Texture->drop();
|
||||
|
||||
ButtonImages[stateIdx].Texture = image;
|
||||
ButtonImages[stateIdx].SourceRect = sourceRect;
|
||||
}
|
||||
|
||||
//! 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 CGUIButton::setIsPushButton(bool isPushButton)
|
||||
{
|
||||
IsPushButton = isPushButton;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the button is currently pressed
|
||||
bool CGUIButton::isPressed() const
|
||||
{
|
||||
return Pressed;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the pressed state of the button if this is a pushbutton
|
||||
void CGUIButton::setPressed(bool pressed)
|
||||
{
|
||||
if (Pressed != pressed)
|
||||
{
|
||||
ClickTime = os::Timer::getTime();
|
||||
Pressed = pressed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Returns whether the button is a push button
|
||||
bool CGUIButton::isPushButton() const
|
||||
{
|
||||
return IsPushButton;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
|
||||
void CGUIButton::setUseAlphaChannel(bool useAlphaChannel)
|
||||
{
|
||||
UseAlphaChannel = useAlphaChannel;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the alpha channel should be used for drawing images on the button
|
||||
bool CGUIButton::isAlphaChannelUsed() const
|
||||
{
|
||||
return UseAlphaChannel;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIButton::isDrawingBorder() const
|
||||
{
|
||||
return DrawBorder;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIButton::serializeAttributes(out,options);
|
||||
|
||||
out->addBool ("PushButton", IsPushButton );
|
||||
if (IsPushButton)
|
||||
out->addBool("Pressed", Pressed);
|
||||
|
||||
for ( u32 i=0; i<(u32)EGBIS_COUNT; ++i )
|
||||
{
|
||||
if ( ButtonImages[i].Texture )
|
||||
{
|
||||
core::stringc name( GUIButtonImageStateNames[i] );
|
||||
out->addTexture(name.c_str(), ButtonImages[i].Texture);
|
||||
name += "Rect";
|
||||
out->addRect(name.c_str(), ButtonImages[i].SourceRect);
|
||||
}
|
||||
}
|
||||
|
||||
out->addBool ("UseAlphaChannel", UseAlphaChannel);
|
||||
out->addBool ("Border", DrawBorder);
|
||||
out->addBool ("ScaleImage", ScaleImage);
|
||||
|
||||
for ( u32 i=0; i<(u32)EGBS_COUNT; ++i )
|
||||
{
|
||||
if ( ButtonSprites[i].Index >= 0 )
|
||||
{
|
||||
core::stringc nameIndex( GUIButtonStateNames[i] );
|
||||
nameIndex += "Index";
|
||||
out->addInt(nameIndex.c_str(), ButtonSprites[i].Index );
|
||||
|
||||
core::stringc nameColor( GUIButtonStateNames[i] );
|
||||
nameColor += "Color";
|
||||
out->addColor(nameColor.c_str(), ButtonSprites[i].Color );
|
||||
|
||||
core::stringc nameLoop( GUIButtonStateNames[i] );
|
||||
nameLoop += "Loop";
|
||||
out->addBool(nameLoop.c_str(), ButtonSprites[i].Loop );
|
||||
|
||||
core::stringc nameScale( GUIButtonStateNames[i] );
|
||||
nameScale += "Scale";
|
||||
out->addBool(nameScale.c_str(), ButtonSprites[i].Scale );
|
||||
}
|
||||
}
|
||||
|
||||
// out->addString ("OverrideFont", OverrideFont);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIButton::deserializeAttributes(in,options);
|
||||
|
||||
IsPushButton = in->getAttributeAsBool("PushButton", IsPushButton);
|
||||
Pressed = IsPushButton ? in->getAttributeAsBool("Pressed", Pressed) : false;
|
||||
|
||||
for ( u32 i=0; i<(u32)EGBIS_COUNT; ++i )
|
||||
{
|
||||
core::stringc nameRect( GUIButtonImageStateNames[i] );
|
||||
nameRect += "Rect";
|
||||
|
||||
setImage((EGUI_BUTTON_IMAGE_STATE)i,
|
||||
in->getAttributeAsTexture(GUIButtonImageStateNames[i], ButtonImages[i].Texture),
|
||||
in->getAttributeAsRect(nameRect.c_str(), ButtonImages[i].SourceRect) );
|
||||
}
|
||||
|
||||
setDrawBorder(in->getAttributeAsBool("Border", DrawBorder));
|
||||
setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel", UseAlphaChannel));
|
||||
setScaleImage(in->getAttributeAsBool("ScaleImage", ScaleImage));
|
||||
|
||||
for ( u32 i=0; i<(u32)EGBS_COUNT; ++i )
|
||||
{
|
||||
core::stringc nameIndex( GUIButtonStateNames[i] );
|
||||
nameIndex += "Index";
|
||||
ButtonSprites[i].Index = in->getAttributeAsInt(nameIndex.c_str(), ButtonSprites[i].Index );
|
||||
|
||||
core::stringc nameColor( GUIButtonStateNames[i] );
|
||||
nameColor += "Color";
|
||||
ButtonSprites[i].Color = in->getAttributeAsColor(nameColor.c_str(), ButtonSprites[i].Color );
|
||||
|
||||
core::stringc nameLoop( GUIButtonStateNames[i] );
|
||||
nameLoop += "Loop";
|
||||
ButtonSprites[i].Loop = in->getAttributeAsBool(nameLoop.c_str(), ButtonSprites[i].Loop );
|
||||
|
||||
core::stringc nameScale( GUIButtonStateNames[i] );
|
||||
nameScale += "Scale";
|
||||
ButtonSprites[i].Scale = in->getAttributeAsBool(nameScale.c_str(), ButtonSprites[i].Scale );
|
||||
}
|
||||
|
||||
// setOverrideFont(in->getAttributeAsString("OverrideFont"));
|
||||
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
253
source/Irrlicht/CGUIButton.h
Normal file
253
source/Irrlicht/CGUIButton.h
Normal file
@ -0,0 +1,253 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_GUI_BUTTON_H_INCLUDED__
|
||||
#define __C_GUI_BUTTON_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#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.
|
||||
virtual bool OnEvent(const SEvent& event) _IRR_OVERRIDE_;
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw() _IRR_OVERRIDE_;
|
||||
|
||||
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
||||
virtual void setOverrideFont(IGUIFont* font=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the override font (if any)
|
||||
virtual IGUIFont* getOverrideFont() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
virtual IGUIFont* getActiveFont() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets another color for the button text.
|
||||
virtual void setOverrideColor(video::SColor color) _IRR_OVERRIDE_;
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor(void) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets if the button text should use the override color or the color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable) _IRR_OVERRIDE_;
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
virtual bool isOverrideColorEnabled(void) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in the given state.
|
||||
virtual void setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image=0, const core::rect<s32>& sourceRect=core::rect<s32>(0,0,0,0)) _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
virtual void setImage(video::ITexture* image=0) _IRR_OVERRIDE_
|
||||
{
|
||||
setImage(EGBIS_IMAGE_UP, image);
|
||||
}
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
virtual void setImage(video::ITexture* image, const core::rect<s32>& pos) _IRR_OVERRIDE_
|
||||
{
|
||||
setImage(EGBIS_IMAGE_UP, image, pos);
|
||||
}
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
virtual void setPressedImage(video::ITexture* image=0) _IRR_OVERRIDE_
|
||||
{
|
||||
setImage(EGBIS_IMAGE_DOWN, image);
|
||||
}
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
virtual void setPressedImage(video::ITexture* image, const core::rect<s32>& pos) _IRR_OVERRIDE_
|
||||
{
|
||||
setImage(EGBIS_IMAGE_DOWN, image, pos);
|
||||
}
|
||||
|
||||
//! Sets the sprite bank used by the button
|
||||
virtual void setSpriteBank(IGUISpriteBank* bank=0) _IRR_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) _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||
virtual s32 getSpriteIndex(EGUI_BUTTON_STATE state) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the sprite color for the given state. Color is only used when a sprite is set.
|
||||
virtual video::SColor getSpriteColor(EGUI_BUTTON_STATE state) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if the sprite in the given state does loop
|
||||
virtual bool getSpriteLoop(EGUI_BUTTON_STATE state) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if the sprite in the given state is scaled
|
||||
virtual bool getSpriteScale(EGUI_BUTTON_STATE state) const _IRR_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.
|
||||
virtual void setIsPushButton(bool isPushButton=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! Checks whether the button is a push button
|
||||
virtual bool isPushButton() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the pressed state of the button if this is a pushbutton
|
||||
virtual void setPressed(bool pressed=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if the button is currently pressed
|
||||
virtual bool isPressed() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets if the button should use the skin to draw its border
|
||||
virtual void setDrawBorder(bool border=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! Checks if the button face and border are being drawn
|
||||
virtual bool isDrawingBorder() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
|
||||
virtual void setUseAlphaChannel(bool useAlphaChannel=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! Checks if the alpha channel should be used for drawing images on the button
|
||||
virtual bool isAlphaChannelUsed() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets if the button should scale the button images to fit
|
||||
virtual void setScaleImage(bool scaleImage=true) _IRR_OVERRIDE_;
|
||||
|
||||
//! Checks whether the button scales the used images
|
||||
virtual bool isScalingImage() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get if the shift key was pressed in last EGET_BUTTON_CLICKED event
|
||||
virtual bool getClickShiftState() const _IRR_OVERRIDE_
|
||||
{
|
||||
return ClickShiftState;
|
||||
}
|
||||
|
||||
//! Get if the control key was pressed in last EGET_BUTTON_CLICKED event
|
||||
virtual bool getClickControlState() const _IRR_OVERRIDE_
|
||||
{
|
||||
return ClickControlState;
|
||||
}
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) _IRR_OVERRIDE_;
|
||||
|
||||
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
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_BUTTON_H_INCLUDED__
|
||||
|
254
source/Irrlicht/CGUICheckBox.cpp
Normal file
254
source/Irrlicht/CGUICheckBox.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
// 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"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUICheckBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUICheckBox::serializeAttributes(out,options);
|
||||
|
||||
out->addBool("Checked", Checked);
|
||||
out->addBool("Border", Border);
|
||||
out->addBool("Background", Background);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUICheckBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
Checked = in->getAttributeAsBool ("Checked");
|
||||
Border = in->getAttributeAsBool ("Border", Border);
|
||||
Background = in->getAttributeAsBool ("Background", Background);
|
||||
|
||||
IGUICheckBox::deserializeAttributes(in,options);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
71
source/Irrlicht/CGUICheckBox.h
Normal file
71
source/Irrlicht/CGUICheckBox.h
Normal file
@ -0,0 +1,71 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
#define __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#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
|
||||
virtual void setChecked(bool checked) _IRR_OVERRIDE_;
|
||||
|
||||
//! returns if box is checked
|
||||
virtual bool isChecked() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw) _IRR_OVERRIDE_;
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
/** \return true if background drawing is enabled, false otherwise */
|
||||
virtual bool isDrawBackgroundEnabled() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets whether to draw the border
|
||||
virtual void setDrawBorder(bool draw) _IRR_OVERRIDE_;
|
||||
|
||||
//! Checks if border drawing is enabled
|
||||
/** \return true if border drawing is enabled, false otherwise */
|
||||
virtual bool isDrawBorderEnabled() const _IRR_OVERRIDE_;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event) _IRR_OVERRIDE_;
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw() _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
u32 CheckTime;
|
||||
bool Pressed;
|
||||
bool Checked;
|
||||
bool Border;
|
||||
bool Background;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
479
source/Irrlicht/CGUIColorSelectDialog.cpp
Normal file
479
source/Irrlicht/CGUIColorSelectDialog.cpp
Normal file
@ -0,0 +1,479 @@
|
||||
// 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 "CGUIColorSelectDialog.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "IFileList.h"
|
||||
#include "os.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
const s32 CSD_WIDTH = 350;
|
||||
const s32 CSD_HEIGHT = 300;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct subElementPredefines
|
||||
{
|
||||
const wchar_t *pre;
|
||||
const wchar_t *init;
|
||||
const wchar_t *post;
|
||||
int x, y;
|
||||
int range_down ,range_up;
|
||||
};
|
||||
|
||||
static const subElementPredefines Template [] =
|
||||
{
|
||||
{ L"A:", L"0", 0,50,165, 0, 255 },
|
||||
{ L"R:", L"0", 0,20,205, 0, 255 },
|
||||
{ L"G:", L"0", 0,20,230, 0, 255 },
|
||||
{ L"B:", L"0", 0,20,255, 0, 255 },
|
||||
{ L"H:", L"0", L"°",80,205, 0, 360 },
|
||||
{ L"S:", L"0", L"%",80,230, 0, 100 },
|
||||
{ L"L:", L"0", L"%",80,255, 0, 100 },
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//! constructor
|
||||
CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id)
|
||||
: IGUIColorSelectDialog(environment, parent, id,
|
||||
core::rect<s32>((parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2,
|
||||
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2,
|
||||
(parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2+CSD_WIDTH,
|
||||
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2+CSD_HEIGHT)),
|
||||
Dragging(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IGUIElement::setDebugName("CGUIColorSelectDialog");
|
||||
#endif
|
||||
|
||||
Text = title;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
const s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
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");
|
||||
if (skin && skin->getSpriteBank())
|
||||
{
|
||||
CloseButton->setSpriteBank(skin->getSpriteBank());
|
||||
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
}
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
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();
|
||||
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
ColorRing.Texture = driver->getTexture ( "#colorring" );
|
||||
if ( 0 == ColorRing.Texture )
|
||||
{
|
||||
buildColorRing(core::dimension2d<u32>(128, 128), 1,
|
||||
Environment->getSkin()->getColor(EGDC_3D_SHADOW));
|
||||
}
|
||||
|
||||
core::rect<s32> r(20,20, 0,0);
|
||||
|
||||
ColorRing.Control = Environment->addImage(ColorRing.Texture, r.UpperLeftCorner, true, this);
|
||||
ColorRing.Control->setSubElement(true);
|
||||
ColorRing.Control->grab();
|
||||
|
||||
for ( u32 i = 0; i != sizeof (Template) / sizeof ( subElementPredefines ); ++i )
|
||||
{
|
||||
if ( Template[i].pre )
|
||||
{
|
||||
r.UpperLeftCorner.X = Template[i].x;
|
||||
r.UpperLeftCorner.Y = Template[i].y;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
IGUIElement *t = Environment->addStaticText(Template[i].pre, r, false, false, this);
|
||||
t->setSubElement(true);
|
||||
}
|
||||
|
||||
if ( Template[i].post )
|
||||
{
|
||||
r.UpperLeftCorner.X = Template[i].x + 56;
|
||||
r.UpperLeftCorner.Y = Template[i].y;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
IGUIElement *t = Environment->addStaticText( Template[i].post, r, false, false, this);
|
||||
t->setSubElement(true);
|
||||
}
|
||||
|
||||
r.UpperLeftCorner.X = Template[i].x + 15;
|
||||
r.UpperLeftCorner.Y = Template[i].y-2;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 40;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
|
||||
gui::IGUISpinBox* spin = Environment->addSpinBox( Template[i].init, r, true, this);
|
||||
spin->setSubElement(true);
|
||||
spin->setDecimalPlaces(0);
|
||||
spin->setRange((f32)Template[i].range_down, (f32)Template[i].range_up);
|
||||
spin->grab();
|
||||
|
||||
Battery.push_back(spin);
|
||||
}
|
||||
|
||||
bringToFront(CancelButton);
|
||||
bringToFront(OKButton);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIColorSelectDialog::~CGUIColorSelectDialog()
|
||||
{
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
|
||||
if (OKButton)
|
||||
OKButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
for (u32 i = 0; i != Battery.size(); ++i)
|
||||
Battery[i]->drop();
|
||||
|
||||
if (ColorRing.Control)
|
||||
ColorRing.Control->drop();
|
||||
}
|
||||
|
||||
|
||||
//! renders a antialiased, colored ring
|
||||
void CGUIColorSelectDialog::buildColorRing( const core::dimension2d<u32> & dim, s32 supersample, const video::SColor& borderColor )
|
||||
{
|
||||
const core::dimension2d<u32> d(dim.Width * supersample, dim.Height * supersample);
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
video::IImage *RawTexture = driver->createImage(video::ECF_A8R8G8B8, d);
|
||||
|
||||
RawTexture->fill ( 0x00808080 );
|
||||
|
||||
const s32 radiusOut = ( d.Width / 2 ) - 4;
|
||||
const s32 fullR2 = radiusOut * radiusOut;
|
||||
|
||||
video::SColorf rgb(0,0,0);
|
||||
video::SColorHSL hsl;
|
||||
hsl.Luminance = 50;
|
||||
hsl.Saturation = 100;
|
||||
|
||||
core::position2d<s32> p;
|
||||
for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 )
|
||||
{
|
||||
s32 y2 = p.Y * p.Y;
|
||||
|
||||
for (p.X = -radiusOut; p.X <= radiusOut; p.X += 1)
|
||||
{
|
||||
s32 r2 = y2 + ( p.X * p.X );
|
||||
|
||||
// test point in circle
|
||||
s32 testa = r2 - fullR2;
|
||||
|
||||
if ( testa < 0 )
|
||||
{
|
||||
// dotproduct u ( x,y ) * v ( 1, 0 ) = cosinus(a)
|
||||
|
||||
const f32 r = sqrtf((f32) r2);
|
||||
|
||||
// normalize, dotproduct = xnorm
|
||||
const f32 xn = r == 0.f ? 0.f : -p.X * core::reciprocal(r);
|
||||
|
||||
hsl.Hue = acosf(xn)*core::RADTODEG;
|
||||
if ( p.Y > 0 )
|
||||
hsl.Hue = 360 - hsl.Hue;
|
||||
hsl.Hue -= 90;
|
||||
|
||||
const f32 rTest = r / radiusOut;
|
||||
#if 0
|
||||
if (rTest < 0.33f)
|
||||
{
|
||||
// luminance from 0 to 50
|
||||
hsl.Luminance = 50*(rTest/0.33);
|
||||
hsl.Saturation = 0.f;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
else
|
||||
if ( rTest < 0.66f )
|
||||
{
|
||||
// saturation from 0 to 100
|
||||
hsl.Saturation = 100*(( rTest - 0.33f ) / 0.33f);
|
||||
hsl.Luminance = 50;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// luminance from 50 to 100
|
||||
hsl.Luminance = 100*(0.5f + ( ( rTest - 0.66f ) / .66f ));
|
||||
hsl.Saturation = 100;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
// borders should be slightly transparent
|
||||
if ( rTest >= 0.95f )
|
||||
rgb.a = (1.f-rTest)*20;
|
||||
else
|
||||
rgb.a=1.f;
|
||||
#else
|
||||
if ( rTest > 0.5f )
|
||||
{
|
||||
hsl.Saturation = 100;
|
||||
hsl.Luminance = 50;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
// borders should be slightly transparent
|
||||
if ( rTest < 0.5f )
|
||||
rgb.a = 0;
|
||||
else if ( rTest >= 0.95f )
|
||||
rgb.a = (1.f-rTest)*20;
|
||||
else if ( rTest <= 0.55f )
|
||||
rgb.a = (rTest-0.5f)*20;
|
||||
else
|
||||
rgb.a=1.f;
|
||||
#endif
|
||||
RawTexture->setPixel(4+p.X+radiusOut, 4+p.Y+radiusOut, rgb.toSColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( supersample > 1 )
|
||||
{
|
||||
video::IImage * filter = driver->createImage(video::ECF_A8R8G8B8, dim );
|
||||
RawTexture->copyToScalingBoxFilter(filter);
|
||||
RawTexture->drop();
|
||||
RawTexture = filter;
|
||||
}
|
||||
|
||||
bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false);
|
||||
|
||||
ColorRing.Texture = driver->addTexture ( "#colorring", RawTexture);
|
||||
RawTexture->drop();
|
||||
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIColorSelectDialog::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_SPINBOX_CHANGED:
|
||||
{
|
||||
for ( u32 i = 0; i!= Battery.size (); ++i )
|
||||
{
|
||||
if ( event.GUIEvent.Caller == Battery[i] )
|
||||
{
|
||||
if (i<4)
|
||||
{
|
||||
video::SColor rgb((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
|
||||
(u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
|
||||
video::SColorHSL hsl;
|
||||
video::SColorf rgb2(rgb);
|
||||
hsl.fromRGB(rgb2);
|
||||
Battery[4]->setValue(hsl.Hue);
|
||||
Battery[5]->setValue(hsl.Saturation);
|
||||
Battery[6]->setValue(hsl.Luminance);
|
||||
}
|
||||
else
|
||||
{
|
||||
video::SColorHSL hsl(Battery[4]->getValue(), Battery[5]->getValue(),
|
||||
Battery[6]->getValue());
|
||||
video::SColorf rgb2;
|
||||
hsl.toRGB(rgb2);
|
||||
video::SColor rgb = rgb2.toSColor();
|
||||
Battery[1]->setValue((f32)rgb.getRed());
|
||||
Battery[2]->setValue((f32)rgb.getGreen());
|
||||
Battery[3]->setValue((f32)rgb.getBlue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
sendSelectedEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.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 (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;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIColorSelectDialog::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
core::rect<s32> rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
|
||||
AbsoluteRect, &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();
|
||||
|
||||
// draw color selector after the window elements
|
||||
core::vector2di pos(ColorRing.Control->getAbsolutePosition().UpperLeftCorner);
|
||||
pos.X += ColorRing.Texture->getOriginalSize().Width/2;
|
||||
pos.Y += ColorRing.Texture->getOriginalSize().Height/2;
|
||||
#if 0
|
||||
const f32 h = Battery[4]->getValue();
|
||||
const f32 s = Battery[5]->getValue();
|
||||
const f32 l = Battery[6]->getValue();
|
||||
const f32 factor = 58.f*(((s==0)&&(l<50))?(l*0.33f/50):(
|
||||
(s<100)?((.33f+(s*0.33f/100))):((0.66f+(l-50)*0.33f/50))));
|
||||
|
||||
#else
|
||||
const f32 factor = 44;
|
||||
#endif
|
||||
pos.X += core::round32(sinf(Battery[4]->getValue()*core::DEGTORAD)*factor);
|
||||
pos.Y -= core::round32(cosf(Battery[4]->getValue()*core::DEGTORAD)*factor);
|
||||
Environment->getVideoDriver()->draw2DPolygon(pos, 4, 0xffffffff, 4);
|
||||
}
|
||||
|
||||
|
||||
video::SColor CGUIColorSelectDialog::getColor()
|
||||
{
|
||||
return video::SColor((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
|
||||
(u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
|
||||
}
|
||||
|
||||
video::SColorHSL CGUIColorSelectDialog::getColorHSL()
|
||||
{
|
||||
return video::SColorHSL(Battery[4]->getValue(), Battery[5]->getValue(),
|
||||
Battery[6]->getValue());
|
||||
}
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void CGUIColorSelectDialog::sendSelectedEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_SELECTED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void CGUIColorSelectDialog::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
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
74
source/Irrlicht/CGUIColorSelectDialog.h
Normal file
74
source/Irrlicht/CGUIColorSelectDialog.h
Normal file
@ -0,0 +1,74 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
||||
#define __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIColorSelectDialog.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUISpinBox.h"
|
||||
#include "IGUIImage.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIColorSelectDialog : public IGUIColorSelectDialog
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIColorSelectDialog();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event) _IRR_OVERRIDE_;
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw() _IRR_OVERRIDE_;
|
||||
|
||||
virtual video::SColor getColor() _IRR_OVERRIDE_;
|
||||
virtual video::SColorHSL getColorHSL() _IRR_OVERRIDE_;
|
||||
|
||||
private:
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void sendSelectedEvent();
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void sendCancelEvent();
|
||||
|
||||
core::position2d<s32> DragStart;
|
||||
bool Dragging;
|
||||
IGUIButton* CloseButton;
|
||||
IGUIButton* OKButton;
|
||||
IGUIButton* CancelButton;
|
||||
|
||||
core::array<IGUISpinBox*> Battery;
|
||||
|
||||
struct SColorCircle
|
||||
{
|
||||
IGUIImage * Control;
|
||||
video::ITexture * Texture;
|
||||
};
|
||||
SColorCircle ColorRing;
|
||||
|
||||
void buildColorRing( const core::dimension2d<u32> & dim, s32 supersample, const video::SColor& borderColor );
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
540
source/Irrlicht/CGUIComboBox.cpp
Normal file
540
source/Irrlicht/CGUIComboBox.cpp
Normal file
@ -0,0 +1,540 @@
|
||||
// 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 "CGUIComboBox.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "CGUIListBox.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle)
|
||||
: IGUIComboBox(environment, parent, id, rectangle),
|
||||
ListButton(0), SelectedText(0), ListBox(0), LastFocus(0),
|
||||
Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false),
|
||||
ActiveFont(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIComboBox");
|
||||
#endif
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
ListButton = Environment->addButton(core::recti(0,0,1,1), this, -1, L"");
|
||||
if (skin && skin->getSpriteBank())
|
||||
{
|
||||
ListButton->setSpriteBank(skin->getSpriteBank());
|
||||
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
}
|
||||
ListButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
ListButton->setSubElement(true);
|
||||
ListButton->setTabStop(false);
|
||||
|
||||
SelectedText = Environment->addStaticText(L"", core::recti(0,0,1,1), false, false, this, -1, false);
|
||||
SelectedText->setSubElement(true);
|
||||
SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
|
||||
if (skin)
|
||||
SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT));
|
||||
SelectedText->enableOverrideColor(true);
|
||||
|
||||
updateListButtonWidth(skin ? skin->getSize(EGDS_SCROLLBAR_SIZE) : 15);
|
||||
|
||||
// this element can be tabbed to
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
|
||||
{
|
||||
HAlign = horizontal;
|
||||
VAlign = vertical;
|
||||
SelectedText->setTextAlignment(horizontal, vertical);
|
||||
}
|
||||
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
void CGUIComboBox::setMaxSelectionRows(u32 max)
|
||||
{
|
||||
MaxSelectionRows = max;
|
||||
|
||||
// force recalculation of open listbox
|
||||
if (ListBox)
|
||||
{
|
||||
openCloseMenu();
|
||||
openCloseMenu();
|
||||
}
|
||||
}
|
||||
|
||||
//! Get the maximal number of rows for the selection listbox
|
||||
u32 CGUIComboBox::getMaxSelectionRows() const
|
||||
{
|
||||
return MaxSelectionRows;
|
||||
}
|
||||
|
||||
|
||||
//! Returns amount of items in box
|
||||
u32 CGUIComboBox::getItemCount() const
|
||||
{
|
||||
return Items.size();
|
||||
}
|
||||
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
const wchar_t* CGUIComboBox::getItem(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Name.c_str();
|
||||
}
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
u32 CGUIComboBox::getItemData(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Data;
|
||||
}
|
||||
|
||||
//! Returns index based on item data
|
||||
s32 CGUIComboBox::getIndexForItemData(u32 data ) const
|
||||
{
|
||||
for ( u32 i = 0; i < Items.size (); ++i )
|
||||
{
|
||||
if ( Items[i].Data == data )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
void CGUIComboBox::removeItem(u32 idx)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
if (Selected == (s32)idx)
|
||||
setSelected(-1);
|
||||
|
||||
Items.erase(idx);
|
||||
}
|
||||
|
||||
|
||||
//! Returns caption of this element.
|
||||
const wchar_t* CGUIComboBox::getText() const
|
||||
{
|
||||
return getItem(Selected);
|
||||
}
|
||||
|
||||
|
||||
//! adds an item and returns the index of it
|
||||
u32 CGUIComboBox::addItem(const wchar_t* text, u32 data)
|
||||
{
|
||||
Items.push_back( SComboData ( text, data ) );
|
||||
|
||||
if (Selected == -1)
|
||||
setSelected(0);
|
||||
|
||||
return Items.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
//! deletes all items in the combo box
|
||||
void CGUIComboBox::clear()
|
||||
{
|
||||
Items.clear();
|
||||
setSelected(-1);
|
||||
}
|
||||
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
s32 CGUIComboBox::getSelected() const
|
||||
{
|
||||
return Selected;
|
||||
}
|
||||
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
void CGUIComboBox::setSelected(s32 idx)
|
||||
{
|
||||
if (idx < -1 || idx >= (s32)Items.size())
|
||||
return;
|
||||
|
||||
Selected = idx;
|
||||
if (Selected == -1)
|
||||
SelectedText->setText(L"");
|
||||
else
|
||||
SelectedText->setText(Items[Selected].Name.c_str());
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIComboBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (ListBox && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
|
||||
{
|
||||
// hide list box
|
||||
openCloseMenu();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)
|
||||
{
|
||||
if (!event.KeyInput.PressedDown)
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
|
||||
ListButton->setPressed(ListBox == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.KeyInput.PressedDown)
|
||||
{
|
||||
s32 oldSelected = Selected;
|
||||
bool absorb = true;
|
||||
switch (event.KeyInput.Key)
|
||||
{
|
||||
case KEY_DOWN:
|
||||
setSelected(Selected+1);
|
||||
break;
|
||||
case KEY_UP:
|
||||
setSelected(Selected-1);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
case KEY_PRIOR:
|
||||
setSelected(0);
|
||||
break;
|
||||
case KEY_END:
|
||||
case KEY_NEXT:
|
||||
setSelected((s32)Items.size()-1);
|
||||
break;
|
||||
default:
|
||||
absorb = false;
|
||||
}
|
||||
|
||||
if (Selected <0)
|
||||
setSelected(0);
|
||||
|
||||
if (Selected >= (s32)Items.size())
|
||||
setSelected((s32)Items.size() -1);
|
||||
|
||||
if (Selected != oldSelected)
|
||||
{
|
||||
sendSelectionChangedEvent();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (absorb)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EET_GUI_EVENT:
|
||||
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if (ListBox &&
|
||||
(Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) &&
|
||||
event.GUIEvent.Element != this &&
|
||||
!isMyChild(event.GUIEvent.Element) &&
|
||||
!ListBox->isMyChild(event.GUIEvent.Element))
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
break;
|
||||
case EGET_BUTTON_CLICKED:
|
||||
if (event.GUIEvent.Caller == ListButton)
|
||||
{
|
||||
openCloseMenu();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
if (event.GUIEvent.Caller == ListBox)
|
||||
{
|
||||
setSelected(ListBox->getSelected());
|
||||
if (Selected <0 || Selected >= (s32)Items.size())
|
||||
setSelected(-1);
|
||||
openCloseMenu();
|
||||
|
||||
sendSelectionChangedEvent();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
|
||||
// send to list box
|
||||
if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event))
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
|
||||
// send to list box
|
||||
if (!(ListBox &&
|
||||
ListBox->getAbsolutePosition().isPointInside(p) &&
|
||||
ListBox->OnEvent(event)))
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
{
|
||||
s32 oldSelected = Selected;
|
||||
setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1));
|
||||
|
||||
if (Selected <0)
|
||||
setSelected(0);
|
||||
|
||||
if (Selected >= (s32)Items.size())
|
||||
setSelected((s32)Items.size() -1);
|
||||
|
||||
if (Selected != oldSelected)
|
||||
{
|
||||
sendSelectionChangedEvent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::sendSelectionChangedEvent()
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
SEvent event;
|
||||
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_COMBO_BOX_CHANGED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void CGUIComboBox::updateListButtonWidth(s32 width)
|
||||
{
|
||||
if (ListButton->getRelativePosition().getWidth() != width)
|
||||
{
|
||||
core::rect<s32> r;
|
||||
r.UpperLeftCorner.X = RelativeRect.getWidth() - width - 2;
|
||||
r.LowerRightCorner.X = RelativeRect.getWidth() - 2;
|
||||
r.UpperLeftCorner.Y = 2;
|
||||
r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
|
||||
ListButton->setRelativePosition(r);
|
||||
|
||||
r.UpperLeftCorner.X = 2;
|
||||
r.UpperLeftCorner.Y = 2;
|
||||
r.LowerRightCorner.X = RelativeRect.getWidth() - (width + 2);
|
||||
r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
|
||||
SelectedText->setRelativePosition(r);
|
||||
}
|
||||
}
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIComboBox::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
updateListButtonWidth(skin->getSize(EGDS_SCROLLBAR_SIZE));
|
||||
|
||||
// font changed while the listbox is open?
|
||||
if ( ActiveFont != skin->getFont() && ListBox )
|
||||
{
|
||||
// close and re-open to use new font-size
|
||||
openCloseMenu();
|
||||
openCloseMenu();
|
||||
}
|
||||
|
||||
|
||||
IGUIElement *currentFocus = Environment->getFocus();
|
||||
if (currentFocus != LastFocus)
|
||||
{
|
||||
HasFocus = currentFocus == this || isMyChild(currentFocus);
|
||||
LastFocus = currentFocus;
|
||||
}
|
||||
|
||||
// set colors each time as skin-colors can be changed
|
||||
SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT));
|
||||
if(isEnabled())
|
||||
{
|
||||
SelectedText->setDrawBackground(HasFocus);
|
||||
SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT));
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedText->setDrawBackground(false);
|
||||
SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT));
|
||||
}
|
||||
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
|
||||
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
|
||||
|
||||
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
|
||||
// draw the border
|
||||
|
||||
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT),
|
||||
true, true, frameRect, &AbsoluteClippingRect);
|
||||
|
||||
// draw children
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::openCloseMenu()
|
||||
{
|
||||
if (ListBox)
|
||||
{
|
||||
// close list box
|
||||
Environment->setFocus(this);
|
||||
ListBox->remove();
|
||||
ListBox = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Parent)
|
||||
Parent->bringToFront(this);
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
u32 h = Items.size();
|
||||
|
||||
if (h > getMaxSelectionRows())
|
||||
h = getMaxSelectionRows();
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
|
||||
ActiveFont = skin->getFont();
|
||||
if (ActiveFont)
|
||||
h *= (ActiveFont->getDimension(L"A").Height + 4);
|
||||
|
||||
// open list box
|
||||
core::rect<s32> r(0, AbsoluteRect.getHeight(),
|
||||
AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);
|
||||
|
||||
ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true);
|
||||
ListBox->setSubElement(true);
|
||||
ListBox->setNotClipped(true);
|
||||
ListBox->drop();
|
||||
|
||||
// ensure that list box is always completely visible
|
||||
if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight())
|
||||
ListBox->setRelativePosition( core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) );
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
ListBox->addItem(Items[i].Name.c_str());
|
||||
|
||||
ListBox->setSelected(Selected);
|
||||
|
||||
// set focus
|
||||
Environment->setFocus(ListBox);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIComboBox::serializeAttributes(out,options);
|
||||
|
||||
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
|
||||
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
|
||||
out->addInt("MaxSelectionRows", (s32)MaxSelectionRows );
|
||||
|
||||
out->addInt ("Selected", Selected );
|
||||
out->addInt ("ItemCount", Items.size());
|
||||
for (u32 i=0; i < Items.size(); ++i)
|
||||
{
|
||||
core::stringc s = "Item";
|
||||
s += i;
|
||||
s += "Text";
|
||||
out->addString(s.c_str(), Items[i].Name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIComboBox::deserializeAttributes(in,options);
|
||||
|
||||
setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
|
||||
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
|
||||
setMaxSelectionRows( (u32)(in->getAttributeAsInt("MaxSelectionRows")) );
|
||||
|
||||
// clear the list
|
||||
clear();
|
||||
// get item count
|
||||
u32 c = in->getAttributeAsInt("ItemCount");
|
||||
// add items
|
||||
for (u32 i=0; i < c; ++i)
|
||||
{
|
||||
core::stringc s = "Item";
|
||||
s += i;
|
||||
s += "Text";
|
||||
addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0);
|
||||
}
|
||||
|
||||
setSelected(in->getAttributeAsInt("Selected"));
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
119
source/Irrlicht/CGUIComboBox.h
Normal file
119
source/Irrlicht/CGUIComboBox.h
Normal file
@ -0,0 +1,119 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
#define __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#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
|
||||
virtual u32 getItemCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
virtual const wchar_t* getItem(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns item data of an item. the idx may be a value from 0 to itemCount-1
|
||||
virtual u32 getItemData(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns index based on item data
|
||||
virtual s32 getIndexForItemData( u32 data ) const _IRR_OVERRIDE_;
|
||||
|
||||
//! adds an item and returns the index of it
|
||||
virtual u32 addItem(const wchar_t* text, u32 data) _IRR_OVERRIDE_;
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
virtual void removeItem(u32 id) _IRR_OVERRIDE_;
|
||||
|
||||
//! deletes all items in the combo box
|
||||
virtual void clear() _IRR_OVERRIDE_;
|
||||
|
||||
//! returns the text of the currently selected item
|
||||
virtual const wchar_t* getText() const _IRR_OVERRIDE_;
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
virtual s32 getSelected() const _IRR_OVERRIDE_;
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
virtual void setSelected(s32 idx) _IRR_OVERRIDE_;
|
||||
|
||||
//! sets the text alignment of the text part
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) _IRR_OVERRIDE_;
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
virtual void setMaxSelectionRows(u32 max) _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the maximal number of rows for the selection listbox
|
||||
virtual u32 getMaxSelectionRows() const _IRR_OVERRIDE_;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event) _IRR_OVERRIDE_;
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw() _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) _IRR_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
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
|
879
source/Irrlicht/CGUIContextMenu.cpp
Normal file
879
source/Irrlicht/CGUIContextMenu.cpp
Normal file
@ -0,0 +1,879 @@
|
||||
// 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 "CGUIContextMenu.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id,
|
||||
core::rect<s32> rectangle, bool getFocus, bool allowFocus)
|
||||
: IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0),
|
||||
CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIContextMenu");
|
||||
#endif
|
||||
|
||||
Pos = rectangle.UpperLeftCorner;
|
||||
recalculateSize();
|
||||
|
||||
if (getFocus)
|
||||
Environment->setFocus(this);
|
||||
|
||||
setNotClipped(true);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIContextMenu::~CGUIContextMenu()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->drop();
|
||||
|
||||
if (LastFont)
|
||||
LastFont->drop();
|
||||
}
|
||||
|
||||
//! set behavior when menus are closed
|
||||
void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose)
|
||||
{
|
||||
CloseHandling = onClose;
|
||||
}
|
||||
|
||||
//! get current behavior when the menue will be closed
|
||||
ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const
|
||||
{
|
||||
return CloseHandling;
|
||||
}
|
||||
|
||||
//! Returns amount of menu items
|
||||
u32 CGUIContextMenu::getItemCount() const
|
||||
{
|
||||
return Items.size();
|
||||
}
|
||||
|
||||
|
||||
//! Adds a menu item.
|
||||
u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking)
|
||||
{
|
||||
return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking);
|
||||
}
|
||||
|
||||
//! Insert a menu item at specified position.
|
||||
u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled,
|
||||
bool hasSubMenu, bool checked, bool autoChecking)
|
||||
{
|
||||
SItem s;
|
||||
s.Enabled = enabled;
|
||||
s.Checked = checked;
|
||||
s.AutoChecking = autoChecking;
|
||||
s.Text = text;
|
||||
s.IsSeparator = (text == 0);
|
||||
s.SubMenu = 0;
|
||||
s.CommandId = commandId;
|
||||
|
||||
if (hasSubMenu)
|
||||
{
|
||||
s.SubMenu = new CGUIContextMenu(Environment, this, commandId,
|
||||
core::rect<s32>(0,0,100,100), false, false);
|
||||
s.SubMenu->setVisible(false);
|
||||
}
|
||||
|
||||
u32 result = idx;
|
||||
if ( idx < Items.size() )
|
||||
{
|
||||
Items.insert(s, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Items.push_back(s);
|
||||
result = Items.size() - 1;
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const
|
||||
{
|
||||
for ( u32 i=idxStartSearch; i<Items.size(); ++i )
|
||||
{
|
||||
if ( Items[i].CommandId == commandId )
|
||||
{
|
||||
return (s32)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! Adds a sub menu from an element that already exists.
|
||||
void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu)
|
||||
{
|
||||
if (index >= Items.size())
|
||||
return;
|
||||
|
||||
if (menu)
|
||||
menu->grab();
|
||||
if (Items[index].SubMenu)
|
||||
Items[index].SubMenu->drop();
|
||||
|
||||
Items[index].SubMenu = menu;
|
||||
menu->setVisible(false);
|
||||
|
||||
if (Items[index].SubMenu)
|
||||
{
|
||||
menu->AllowFocus = false;
|
||||
if ( Environment->getFocus() == menu )
|
||||
{
|
||||
Environment->setFocus( this );
|
||||
}
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! Adds a separator item to the menu
|
||||
void CGUIContextMenu::addSeparator()
|
||||
{
|
||||
addItem(0, -1, true, false, false, false);
|
||||
}
|
||||
|
||||
|
||||
//! Returns text of the menu item.
|
||||
const wchar_t* CGUIContextMenu::getItemText(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Text.c_str();
|
||||
}
|
||||
|
||||
|
||||
//! Sets text of the menu item.
|
||||
void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Text = text;
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
//! should the element change the checked status on clicking
|
||||
void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking)
|
||||
{
|
||||
if ( idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].AutoChecking = autoChecking;
|
||||
}
|
||||
|
||||
//! does the element change the checked status on clicking
|
||||
bool CGUIContextMenu::getItemAutoChecking(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return false;
|
||||
|
||||
return Items[idx].AutoChecking;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if a menu item is enabled
|
||||
bool CGUIContextMenu::isItemEnabled(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Items[idx].Enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if a menu item is checked
|
||||
bool CGUIContextMenu::isItemChecked(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Items[idx].Checked;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the menu item should be enabled.
|
||||
void CGUIContextMenu::setItemEnabled(u32 idx, bool enabled)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Enabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the menu item should be checked.
|
||||
void CGUIContextMenu::setItemChecked(u32 idx, bool checked )
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Checked = checked;
|
||||
}
|
||||
|
||||
|
||||
//! Removes a menu item
|
||||
void CGUIContextMenu::removeItem(u32 idx)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
if (Items[idx].SubMenu)
|
||||
{
|
||||
Items[idx].SubMenu->drop();
|
||||
Items[idx].SubMenu = 0;
|
||||
}
|
||||
|
||||
Items.erase(idx);
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! Removes all menu items
|
||||
void CGUIContextMenu::removeAllItems()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->drop();
|
||||
|
||||
Items.clear();
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIContextMenu::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus)
|
||||
{
|
||||
// set event parent of submenus
|
||||
IGUIElement * p = EventParent ? EventParent : Parent;
|
||||
if ( p ) // can be 0 when element got removed already
|
||||
{
|
||||
setEventParent(p);
|
||||
|
||||
SEvent eventClose;
|
||||
eventClose.EventType = EET_GUI_EVENT;
|
||||
eventClose.GUIEvent.Caller = this;
|
||||
eventClose.GUIEvent.Element = 0;
|
||||
eventClose.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
|
||||
if ( !p->OnEvent(eventClose) )
|
||||
{
|
||||
if ( CloseHandling & ECMC_HIDE )
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
if ( CloseHandling & ECMC_REMOVE )
|
||||
{
|
||||
remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
if (event.GUIEvent.Caller == this && !AllowFocus)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
// menu might be removed if it loses focus in sendClick, so grab a reference
|
||||
grab();
|
||||
const u32 t = sendClick(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
|
||||
if ((t==0 || t==1) && Environment->hasFocus(this))
|
||||
Environment->removeFocus(this);
|
||||
drop();
|
||||
}
|
||||
return true;
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (Environment->hasFocus(this))
|
||||
highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! Sets the visible state of this element.
|
||||
void CGUIContextMenu::setVisible(bool visible)
|
||||
{
|
||||
HighLighted = -1;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
for (u32 j=0; j<Items.size(); ++j)
|
||||
if (Items[j].SubMenu)
|
||||
Items[j].SubMenu->setVisible(false);
|
||||
|
||||
IGUIElement::setVisible(visible);
|
||||
}
|
||||
|
||||
|
||||
//! sends a click Returns:
|
||||
//! 0 if click went outside of the element,
|
||||
//! 1 if a valid button was clicked,
|
||||
//! 2 if a nonclickable element was clicked
|
||||
u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p)
|
||||
{
|
||||
u32 t = 0;
|
||||
|
||||
// get number of open submenu
|
||||
s32 openmenu = -1;
|
||||
s32 j;
|
||||
for (j=0; j<(s32)Items.size(); ++j)
|
||||
if (Items[j].SubMenu && Items[j].SubMenu->isVisible())
|
||||
{
|
||||
openmenu = j;
|
||||
break;
|
||||
}
|
||||
|
||||
// delegate click operation to submenu
|
||||
if (openmenu != -1)
|
||||
{
|
||||
t = Items[j].SubMenu->sendClick(p);
|
||||
if (t != 0)
|
||||
return t; // clicked something
|
||||
}
|
||||
|
||||
// check click on myself
|
||||
if (isPointInside(p) &&
|
||||
(u32)HighLighted < Items.size())
|
||||
{
|
||||
if (!Items[HighLighted].Enabled ||
|
||||
Items[HighLighted].IsSeparator ||
|
||||
Items[HighLighted].SubMenu)
|
||||
return 2;
|
||||
|
||||
if ( Items[HighLighted].AutoChecking )
|
||||
{
|
||||
Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true;
|
||||
}
|
||||
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED;
|
||||
if (EventParent)
|
||||
EventParent->OnEvent(event);
|
||||
else if (Parent)
|
||||
Parent->OnEvent(event);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! returns true, if an element was highligted
|
||||
bool CGUIContextMenu::highlight(const core::position2d<s32>& p, bool canOpenSubMenu)
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get number of open submenu
|
||||
s32 openmenu = -1;
|
||||
s32 i;
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
if (Items[i].Enabled && Items[i].SubMenu && Items[i].SubMenu->isVisible())
|
||||
{
|
||||
openmenu = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// delegate highlight operation to submenu
|
||||
if (openmenu != -1)
|
||||
{
|
||||
if (Items[openmenu].Enabled && Items[openmenu].SubMenu->highlight(p, canOpenSubMenu))
|
||||
{
|
||||
HighLighted = openmenu;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// highlight myself
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].Enabled && getHRect(Items[i], AbsoluteRect).isPointInside(p))
|
||||
{
|
||||
HighLighted = i;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
|
||||
// make submenus visible/invisible
|
||||
for (s32 j=0; j<(s32)Items.size(); ++j)
|
||||
if (Items[j].SubMenu)
|
||||
{
|
||||
if ( j == i && canOpenSubMenu && Items[j].Enabled )
|
||||
Items[j].SubMenu->setVisible(true);
|
||||
else if ( j != i )
|
||||
Items[j].SubMenu->setVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
HighLighted = openmenu;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! returns the item highlight-area
|
||||
core::rect<s32> CGUIContextMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
core::rect<s32> r = absolute;
|
||||
r.UpperLeftCorner.Y += i.PosY;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
core::rect<s32> CGUIContextMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
core::rect<s32> r = absolute;
|
||||
r.UpperLeftCorner.Y += i.PosY;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height;
|
||||
r.UpperLeftCorner.X += 20;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIContextMenu::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_MENU);
|
||||
if (font != LastFont)
|
||||
{
|
||||
if (LastFont)
|
||||
LastFont->drop();
|
||||
LastFont = font;
|
||||
if (LastFont)
|
||||
LastFont->grab();
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
IGUISpriteBank* sprites = skin->getSpriteBank();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
core::rect<s32>* clip = 0;
|
||||
|
||||
// draw frame
|
||||
skin->draw3DMenuPane(this, AbsoluteRect, clip);
|
||||
|
||||
// loop through all menu items
|
||||
|
||||
rect = AbsoluteRect;
|
||||
s32 y = AbsoluteRect.UpperLeftCorner.Y;
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].IsSeparator)
|
||||
{
|
||||
// draw separator
|
||||
rect = AbsoluteRect;
|
||||
rect.UpperLeftCorner.Y += Items[i].PosY + 3;
|
||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
|
||||
rect.UpperLeftCorner.X += 5;
|
||||
rect.LowerRightCorner.X -= 5;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), rect, clip);
|
||||
|
||||
rect.LowerRightCorner.Y += 1;
|
||||
rect.UpperLeftCorner.Y += 1;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
|
||||
|
||||
y += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = getRect(Items[i], AbsoluteRect);
|
||||
|
||||
// draw highlighted
|
||||
|
||||
if (i == HighLighted && Items[i].Enabled)
|
||||
{
|
||||
core::rect<s32> r = AbsoluteRect;
|
||||
r.LowerRightCorner.Y = rect.LowerRightCorner.Y;
|
||||
r.UpperLeftCorner.Y = rect.UpperLeftCorner.Y;
|
||||
r.LowerRightCorner.X -= 5;
|
||||
r.UpperLeftCorner.X += 5;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), r, clip);
|
||||
}
|
||||
|
||||
// draw text
|
||||
|
||||
EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT;
|
||||
|
||||
if (i == HighLighted)
|
||||
c = EGDC_HIGH_LIGHT_TEXT;
|
||||
|
||||
if (!Items[i].Enabled)
|
||||
c = EGDC_GRAY_TEXT;
|
||||
|
||||
if (font)
|
||||
font->draw(Items[i].Text.c_str(), rect,
|
||||
skin->getColor(c), false, true, clip);
|
||||
|
||||
// draw submenu symbol
|
||||
if (Items[i].SubMenu && sprites)
|
||||
{
|
||||
core::rect<s32> r = rect;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X - 15;
|
||||
|
||||
sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT),
|
||||
r.getCenter(), clip, skin->getColor(c),
|
||||
(i == HighLighted) ? ChangeTime : 0,
|
||||
(i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
(i == HighLighted), true);
|
||||
}
|
||||
|
||||
// draw checked symbol
|
||||
if (Items[i].Checked && sprites)
|
||||
{
|
||||
core::rect<s32> r = rect;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X - 15;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X + 15;
|
||||
sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED),
|
||||
r.getCenter(), clip, skin->getColor(c),
|
||||
(i == HighLighted) ? ChangeTime : 0,
|
||||
(i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
(i == HighLighted), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
void CGUIContextMenu::recalculateSize()
|
||||
{
|
||||
IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU);
|
||||
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
core::rect<s32> rect;
|
||||
rect.UpperLeftCorner = RelativeRect.UpperLeftCorner;
|
||||
u32 width = 100;
|
||||
u32 height = 3;
|
||||
|
||||
u32 i;
|
||||
for (i=0; i<Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].IsSeparator)
|
||||
{
|
||||
Items[i].Dim.Width = 100;
|
||||
Items[i].Dim.Height = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
Items[i].Dim = font->getDimension(Items[i].Text.c_str());
|
||||
Items[i].Dim.Width += 40;
|
||||
|
||||
if (Items[i].Dim.Width > width)
|
||||
width = Items[i].Dim.Width;
|
||||
}
|
||||
|
||||
Items[i].PosY = height;
|
||||
height += Items[i].Dim.Height;
|
||||
}
|
||||
|
||||
height += 5;
|
||||
|
||||
if (height < 10)
|
||||
height = 10;
|
||||
|
||||
rect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + width;
|
||||
rect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + height;
|
||||
|
||||
setRelativePosition(rect);
|
||||
|
||||
// recalculate submenus
|
||||
for (i=0; i<Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].SubMenu)
|
||||
{
|
||||
// move submenu
|
||||
const s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth();
|
||||
const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight();
|
||||
|
||||
core::rect<s32> subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h);
|
||||
|
||||
gui::IGUIElement * root = Environment->getRootGUIElement();
|
||||
if ( root )
|
||||
{
|
||||
core::rect<s32> rectRoot( root->getAbsolutePosition() );
|
||||
|
||||
// if it would be drawn beyond the right border, then add it to the left side
|
||||
if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X )
|
||||
{
|
||||
subRect.UpperLeftCorner.X = -w;
|
||||
subRect.LowerRightCorner.X = 0;
|
||||
}
|
||||
|
||||
// if it would be drawn below bottom border, move it up, but not further than to top.
|
||||
irr::s32 belowBottom = getAbsolutePosition().UpperLeftCorner.Y+subRect.LowerRightCorner.Y - rectRoot.LowerRightCorner.Y;
|
||||
if ( belowBottom > 0 )
|
||||
{
|
||||
irr::s32 belowTop = getAbsolutePosition().UpperLeftCorner.Y+subRect.UpperLeftCorner.Y;
|
||||
irr::s32 moveUp = belowBottom < belowTop ? belowBottom : belowTop;
|
||||
subRect.UpperLeftCorner.Y -= moveUp;
|
||||
subRect.LowerRightCorner.Y -= moveUp;
|
||||
}
|
||||
}
|
||||
|
||||
Items[i].SubMenu->setRelativePosition(subRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Returns the selected item in the menu
|
||||
s32 CGUIContextMenu::getSelectedItem() const
|
||||
{
|
||||
return HighLighted;
|
||||
}
|
||||
|
||||
|
||||
//! \return Returns a pointer to the submenu of an item.
|
||||
IGUIContextMenu* CGUIContextMenu::getSubMenu(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].SubMenu;
|
||||
}
|
||||
|
||||
|
||||
//! Returns command id of a menu item
|
||||
s32 CGUIContextMenu::getItemCommandId(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return -1;
|
||||
|
||||
return Items[idx].CommandId;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the command id of a menu item
|
||||
void CGUIContextMenu::setItemCommandId(u32 idx, s32 id)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].CommandId = id;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIElement::serializeAttributes(out,options);
|
||||
out->addPosition2d("Position", Pos);
|
||||
|
||||
if (Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU )
|
||||
{
|
||||
const IGUIContextMenu* const ptr = (const IGUIContextMenu*)Parent;
|
||||
// find the position of this item in its parent's list
|
||||
u32 i;
|
||||
// VC6 needs the cast for this
|
||||
for (i=0; (i<ptr->getItemCount()) && (ptr->getSubMenu(i) != (const IGUIContextMenu*)this); ++i)
|
||||
; // do nothing
|
||||
|
||||
out->addInt("ParentItem", i);
|
||||
}
|
||||
|
||||
out->addInt("CloseHandling", (s32)CloseHandling);
|
||||
|
||||
// write out the item list
|
||||
out->addInt("ItemCount", Items.size());
|
||||
|
||||
core::stringc tmp;
|
||||
|
||||
for (u32 i=0; i < Items.size(); ++i)
|
||||
{
|
||||
tmp = "IsSeparator"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].IsSeparator);
|
||||
|
||||
if (!Items[i].IsSeparator)
|
||||
{
|
||||
tmp = "Text"; tmp += i;
|
||||
out->addString(tmp.c_str(), Items[i].Text.c_str());
|
||||
tmp = "CommandID"; tmp += i;
|
||||
out->addInt(tmp.c_str(), Items[i].CommandId);
|
||||
tmp = "Enabled"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].Enabled);
|
||||
tmp = "Checked"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].Checked);
|
||||
tmp = "AutoChecking"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].AutoChecking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIElement::deserializeAttributes(in,options);
|
||||
|
||||
Pos = in->getAttributeAsPosition2d("Position");
|
||||
|
||||
// link to this item's parent
|
||||
if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) )
|
||||
((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this);
|
||||
|
||||
CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling");
|
||||
|
||||
removeAllItems();
|
||||
|
||||
// read the item list
|
||||
const s32 count = in->getAttributeAsInt("ItemCount");
|
||||
|
||||
for (s32 i=0; i<count; ++i)
|
||||
{
|
||||
core::stringc tmp;
|
||||
core::stringw txt;
|
||||
s32 commandid=-1;
|
||||
bool enabled=true;
|
||||
bool checked=false;
|
||||
bool autochecking=false;
|
||||
|
||||
tmp = "IsSeparator"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) )
|
||||
addSeparator();
|
||||
else
|
||||
{
|
||||
tmp = "Text"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
txt = in->getAttributeAsStringW(tmp.c_str());
|
||||
|
||||
tmp = "CommandID"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
commandid = in->getAttributeAsInt(tmp.c_str());
|
||||
|
||||
tmp = "Enabled"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
enabled = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
tmp = "Checked"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
checked = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
tmp = "AutoChecking"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
autochecking = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking);
|
||||
}
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
// because sometimes the element has no parent at click time
|
||||
void CGUIContextMenu::setEventParent(IGUIElement *parent)
|
||||
{
|
||||
EventParent = parent;
|
||||
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->setEventParent(parent);
|
||||
}
|
||||
|
||||
|
||||
bool CGUIContextMenu::hasOpenSubMenu() const
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu && Items[i].SubMenu->isVisible())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CGUIContextMenu::closeAllSubMenus()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->setVisible(false);
|
||||
|
||||
//HighLighted = -1;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
174
source/Irrlicht/CGUIContextMenu.h
Normal file
174
source/Irrlicht/CGUIContextMenu.h
Normal file
@ -0,0 +1,174 @@
|
||||
// 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
|
||||
|
||||
#ifndef __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
#define __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIContextMenu.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
#include "IGUIFont.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! GUI Context menu interface.
|
||||
class CGUIContextMenu : public IGUIContextMenu
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIContextMenu(IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle,
|
||||
bool getFocus = true, bool allowFocus = true);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIContextMenu();
|
||||
|
||||
//! set behavior when menus are closed
|
||||
virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose) _IRR_OVERRIDE_;
|
||||
|
||||
//! get current behavior when the menue will be closed
|
||||
virtual ECONTEXT_MENU_CLOSE getCloseHandling() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns amount of menu items
|
||||
virtual u32 getItemCount() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds a menu item.
|
||||
virtual u32 addItem(const wchar_t* text, s32 commandid,
|
||||
bool enabled, bool hasSubMenu, bool checked, bool autoChecking) _IRR_OVERRIDE_;
|
||||
|
||||
//! Insert a menu item at specified position.
|
||||
virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled,
|
||||
bool hasSubMenu, bool checked, bool autoChecking) _IRR_OVERRIDE_;
|
||||
|
||||
//! Find a item which has the given CommandId starting from given index
|
||||
virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds a separator item to the menu
|
||||
virtual void addSeparator() _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns text of the menu item.
|
||||
virtual const wchar_t* getItemText(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets text of the menu item.
|
||||
virtual void setItemText(u32 idx, const wchar_t* text) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if a menu item is enabled
|
||||
virtual bool isItemEnabled(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets if the menu item should be enabled.
|
||||
virtual void setItemEnabled(u32 idx, bool enabled) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns if a menu item is checked
|
||||
virtual bool isItemChecked(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets if the menu item should be checked.
|
||||
virtual void setItemChecked(u32 idx, bool enabled) _IRR_OVERRIDE_;
|
||||
|
||||
//! Removes a menu item
|
||||
virtual void removeItem(u32 idx) _IRR_OVERRIDE_;
|
||||
|
||||
//! Removes all menu items
|
||||
virtual void removeAllItems() _IRR_OVERRIDE_;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event) _IRR_OVERRIDE_;
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw() _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns the selected item in the menu
|
||||
virtual s32 getSelectedItem() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns a pointer to the submenu of an item.
|
||||
//! \return Pointer to the submenu of an item.
|
||||
virtual IGUIContextMenu* getSubMenu(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the visible state of this element.
|
||||
virtual void setVisible(bool visible) _IRR_OVERRIDE_;
|
||||
|
||||
//! should the element change the checked status on clicking
|
||||
virtual void setItemAutoChecking(u32 idx, bool autoChecking) _IRR_OVERRIDE_;
|
||||
|
||||
//! does the element change the checked status on clicking
|
||||
virtual bool getItemAutoChecking(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns command id of a menu item
|
||||
virtual s32 getItemCommandId(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Sets the command id of a menu item
|
||||
virtual void setItemCommandId(u32 idx, s32 id) _IRR_OVERRIDE_;
|
||||
|
||||
//! Adds a sub menu from an element that already exists.
|
||||
virtual void setSubMenu(u32 index, CGUIContextMenu* menu);
|
||||
|
||||
//! When an eventparent is set it receives events instead of the usual parent element
|
||||
virtual void setEventParent(IGUIElement *parent) _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) _IRR_OVERRIDE_;
|
||||
|
||||
protected:
|
||||
|
||||
void closeAllSubMenus();
|
||||
bool hasOpenSubMenu() const;
|
||||
|
||||
struct SItem
|
||||
{
|
||||
core::stringw Text;
|
||||
bool IsSeparator;
|
||||
bool Enabled;
|
||||
bool Checked;
|
||||
bool AutoChecking;
|
||||
core::dimension2d<u32> Dim;
|
||||
s32 PosY;
|
||||
CGUIContextMenu* SubMenu;
|
||||
s32 CommandId;
|
||||
};
|
||||
|
||||
virtual void recalculateSize();
|
||||
|
||||
//! returns true, if an element was highlighted
|
||||
virtual bool highlight(const core::position2d<s32>& p, bool canOpenSubMenu);
|
||||
|
||||
//! sends a click Returns:
|
||||
//! 0 if click went outside of the element,
|
||||
//! 1 if a valid button was clicked,
|
||||
//! 2 if a nonclickable element was clicked
|
||||
virtual u32 sendClick(const core::position2d<s32>& p);
|
||||
|
||||
//! returns the item highlight-area
|
||||
virtual core::rect<s32> getHRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
virtual core::rect<s32> getRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
|
||||
|
||||
core::array<SItem> Items;
|
||||
core::position2d<s32> Pos;
|
||||
IGUIElement* EventParent;
|
||||
IGUIFont *LastFont;
|
||||
ECONTEXT_MENU_CLOSE CloseHandling;
|
||||
s32 HighLighted;
|
||||
u32 ChangeTime;
|
||||
bool AllowFocus;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
|
1686
source/Irrlicht/CGUIEditBox.cpp
Normal file
1686
source/Irrlicht/CGUIEditBox.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user