//
// Irrlicht Wrapper for Imperative Languages
// Frank Dodd (2006)
//
// Additional Work
// Michael Taupitz (2006)
//
// This wrapper DLL encapsulates a sub-set of the features of the powerful
// Irrlicht 3D Graphics Engine exposing the Object Oriented architecture and
// providing a functional 3D SDK for languages that are not object oriented.
//
// This source was created with the help of the great examples in the Irrlicht
// SDK and the excellent Irrlicht documentation. This software was developed
// using the GCC compiler and Code::Blocks IDE
//

/****h* /Irrlicht
* NAME
*    IrrStart - Start the Irrlicht-Engine
* DESCRIPTION
*   This Covers all Basic-Functions of Irrlicht. Such things like
*   Starting and Stopping the Engine. Getting Framerate and some more
*   Important functions for .... no words at the moment..
****
*/


/* ////////////////////////////////////////////////////////////////////////////
includes
*/
#include "irrlichtwrapper.h"
#include "CCallbackEventReceiver.h"
#include "CEffects.h"

/* ////////////////////////////////////////////////////////////////////////////
global variables
*/

/* ////////////////////////////////////////////////////////////////////////////
external variables
*/
extern IrrlichtDevice *device;
extern IVideoDriver* driver;
extern ISceneManager* smgr;
extern IGUIEnvironment* guienv;
extern ILogger* logger;
extern StackedEventReceiver receiver;

// Needed for CreateDeviceEx;
SIrrlichtCreationParameters irrParameters;

/* ////////////////////////////////////////////////////////////////////////////
Global Function Declarations

all of the below functions are declared as C functions and are exposed without
any mangled names so that they can be easily imported into imperative
languages like FreeBasic
*/
extern "C"
{

/* ////////////////////////////////////////////////////////////////////////////
SYSTEM FUNCTIONS
*/

/****f* Irrlicht/IrrStart
* NAME
*    IrrStart - Start the Irrlicht-Engine
* SYNOPSIS
*    IrrStart(Irr_Device_Type.l, Width.l, Height.l, Fullscreen.l, Shadows.l, CaptureEvents.l)
* FUNCTION
*    Starts the Irrlicht Interface And opens a window For rendering.
*    Only one irrlicht device object is supported by this wrapper. this call creates
*    the device object, a video driver object, scene manager object and a GUI
*   environment object that are exposed to PureBasic
*
* INPUTS
*    Irr_Device_Type.l - Type of the Device . See below the possible Values.
*    Width.l           - specifies the width of the viewport in pixels
*    Height            - specifies the height of the viewport in pixels
*    Fullscreen        - specifies whether the display is to opened in full screen mode (#True) Or in a window (#False)
*    Shadows           - Use shadows (#True) starts the engine in a mode that supports the rendering of stencil shadows.
*    CaptureEvents     - specifies whether you want To capture keyboard,mouse and gui events, If you choose To ignore them they will be handled by Irrlicht For FPS camera control. This parameter should be either of: #True or #False
* RESULT
*    Returns #True if the start was Successfull.
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           ....
*           IrrStop()
*         EndIf
* NOTES
*    Possible Device-Types :
*   [TAB]
*       * #IRR_EDT_NULL	      - =A NULL device With no display
*       * #IRR_EDT_SOFTWARE	  - =Irrlichts Default software renderer
*       * #IRR_EDT_SOFTWARE2  - =An improved quality software renderer
*       * #IRR_EDT_OPENGL	  - =Hardware accelerated OpenGL renderer
*       * #IRR_EDT_DIRECT3D   - =Hardware accelerated DirectX 8 renderer (Binding not included in IrrlichtWrappers irrlicht.dll)
*       * #IRR_EDT_DIRECT3D9  - =Hardware accelerated DirectX 9 renderer
*   [/TAB]
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrStart(Irr_Device_Type.l, Width.l, Height.l, Fullscreen.l, Shadows.l, CaptureEvents.l)
*/

STATIC_EXPORT bool DLL_EXPORT IrrStart(
                              E_DRIVER_TYPE iDevice,
                              int iWidth,
                              int iHeight,
                              bool boFullscreen,
                              bool boShadows,
                              bool boCaptureEvents )
{
    bool boInitStatus = false;
/*
    E_DRIVER_TYPE iDeviceTypes[] = {
            EDT_NULL, EDT_SOFTWARE, EDT_SOFTWARE2, EDT_OPENGL, EDT_DIRECT3D8, EDT_DIRECT3D9 };
*/
    // create an irrlicht device object the root of all irrlicht functionality
    // if it is successfully created
	if ( device = createDevice(
            iDevice, //iDeviceTypes[iDevice],
            dimension2d<s32>( iWidth, iHeight),
            16,
			boFullscreen,
			boShadows,
			false,
			boCaptureEvents ? &receiver : 0 ))
    {

        /* Get a pointer to the video driver, the SceneManager and the
        graphical user interface environment */
        // if we can successfully create these objects
        if (( driver = device->getVideoDriver()) &&
                ( smgr = device->getSceneManager()) &&
                ( guienv = device->getGUIEnvironment()) &&
                ( logger = device->getLogger() )
                )
            boInitStatus = true;
    }
    return boInitStatus;
}


/*
STATIC_EXPORT bool DLL_EXPORT IrrStart2(
                              E_DRIVER_TYPE iDevice,
                              int iWidth,
                              int iHeight,
                              bool boFullscreen,
                              bool boShadows,
                              IEventReceiver* er )
{
    bool boInitStatus = false;
    E_DRIVER_TYPE iDeviceTypes[] = {
            EDT_NULL, EDT_SOFTWARE, EDT_SOFTWARE2, EDT_OPENGL, EDT_DIRECT3D8, EDT_DIRECT3D9 };

    // create an irrlicht device object the root of all irrlicht functionality
    // if it is successfully created
	if ( device = createDevice(
            iDeviceTypes[iDevice],
            dimension2d<s32>( iWidth, iHeight),
            16,
			boFullscreen,
			boShadows,
			false,
			er))
    {

        // Get a pointer to the video driver, the SceneManager and the
        //graphical user interface environment
        // if we can successfully create these objects
        if (( driver = device->getVideoDriver()) &&
                ( smgr = device->getSceneManager()) &&
                ( guienv = device->getGUIEnvironment()))
            boInitStatus = true;
    }
    return boInitStatus;
}
*/

/****f* Irrlicht/IrrStartEx
* NAME
*    IrrStartEx - Start the Irrlicht-Engine
* SYNOPSIS
*    IrrStartEx(Irr_Device_Type.l, Width.l, Height.l, Fullscreen.l, Shadows.l, CaptureEvents.l, Bits.l, AntiAlias.l, useFPU.l, VSync.l, WindowID.l);
* FUNCTION
*    Starts the Irrlicht Interface And opens a window For rendering.
*    This is an extended Version of the IrrStart(). You have here mor control about
*    using depth, antialias (only DX9) and so on.
*    Also yo will be able to use a exsiting created Window as Output for the Engine.
*    (Gadgets are also possible outputs. See example 24_EmmebedIrrlicht.
*
* INPUTS
*    Irr_Device_Type.l - Type of the Device . See below the possible Values.
*    Width.l           - specifies the width of the viewport in pixels
*    Height.l          - specifies the height of the viewport in pixels
*    Fullscreen.l      - specifies whether the display is to opened in full screen mode (#True) Or in a window (#False)
*    Shadows.l         - Use shadows (#True) starts the engine in a mode that supports the rendering of stencil shadows.
*    CaptureEvents.l   - specifies whether you want To capture keyboard,mouse and gui events, If you choose To ignore them they will be handled by Irrlicht For FPS camera control. This parameter should be either of: #True or #False
*    Bits.l            - Bits per pixel in fullscreen mode. Ignored if windowed mode. Default: 16.
*    AntiAlias.l       - Specifies if the device should use fullscreen anti aliasing
*    HighPrecisionFPU.l- Specifies if the device should use high precision FPU setting.
*    Vsync.l           - Specifies vertical syncronisation.
*    WindowId.l        - WindowID
*
* RESULT
*    Returns #True if the start was Successfull.
* EXAMPLE
*         If IrrStartEx( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           ....
*           IrrStop()
*         EndIf
* NOTES
*    Possible Device-Types :
*       * #IRR_EDT_NULL	        A NULL device With no display
*       * #IRR_EDT_SOFTWARE	    Irrlichts Default software renderer
*       * #IRR_EDT_SOFTWARE2	An improved quality software renderer
*       * #IRR_EDT_OPENGL	    Hardware accelerated OpenGL renderer
*       * #IRR_EDT_DIRECT3D8	Hardware accelerated DirectX 8 renderer (Binding not included in IrrlichtWrappers irrlicht.dll)
*       * #IRR_EDT_DIRECT3D9	Hardware accelerated DirectX 9 renderer
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrStartEx(Irr_Device_Type.l, Width.l, Height.l, Fullscreen.l, Shadows.l, CaptureEvents.l, Bits.l, AntiAlias.l, useFPU.l, VSync.l, WindowID.l)
*/

STATIC_EXPORT bool DLL_EXPORT IrrStartEx(   E_DRIVER_TYPE iDevice,
                              int iWidth,
                              int iHeight,
                              bool boFullscreen,
                              bool boShadows,
                              bool boCaptureEvents,
                              int  iBits,
                              bool boAntiAlias,
                              bool boHighPrecisionFPU,
                              bool boVsync,
                              int  iWindowId
                               )
{
    bool boInitStatus = false;
//    E_DRIVER_TYPE iDeviceTypes[] = {
//            EDT_NULL, EDT_SOFTWARE, EDT_SOFTWARE2, EDT_OPENGL, EDT_DIRECT3D8, EDT_DIRECT3D9 };
    // fill the Parameters-Structure
    irrParameters.AntiAlias = boAntiAlias;
    irrParameters.Bits = iBits;
    irrParameters.DriverType = iDevice; //iDeviceTypes[iDevice];
    irrParameters.Fullscreen = boFullscreen;
    irrParameters.HighPrecisionFPU = boHighPrecisionFPU;
    irrParameters.Stencilbuffer = boShadows;
    irrParameters.Vsync = boVsync;
    irrParameters.WindowId = (void*)iWindowId;
    irrParameters.WindowSize = dimension2d<s32>( iWidth, iHeight);
    irrParameters.EventReceiver = boCaptureEvents ? new StackedEventReceiver() : 0 ;

    // create an irrlicht device object the root of all irrlicht functionality
    // if it is successfully created
	if ( device = createDeviceEx(irrParameters))
    {
        /* Get a pointer to the video driver, the SceneManager and the
        graphical user interface environment */
        // if we can successfully create these objects
        if (( driver = device->getVideoDriver()) &&
                ( smgr = device->getSceneManager()) &&
                ( guienv = device->getGUIEnvironment()) &&
                ( logger = device->getLogger() ) )
            boInitStatus = true;
    }
    return boInitStatus;
}

/****f* Irrlicht/IrrRunning
* NAME
*    IrrRunning - Is Irrlicht alive
* SYNOPSIS
*    IrrRunning();
* FUNCTION
*    determine if the irrlicht environment is still running or has been quit
* RESULT
*    Returns #True if irrlicht is still running.
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*               .... Do something
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrRunning()
*/

STATIC_EXPORT int DLL_EXPORT IrrRunning ( void )
{
    if (device)
        return device->run();
    return false;
}

/****f* Irrlicht/IrrBeginScene
* NAME
*    IrrBeginScene - Start Rendering
* SYNOPSIS
*    IrrBeginScene(backBuffer.l, zBuffer.l, red.l, green.l, blue.l);
* INPUTS
*    backbuffer.l - Specifies if the back buffer should be cleared, which means that the
*                   screen is filled with a color specified with the parameter color. If
*                   this parameter is false, the back buffer will not be cleared and the
*                   color parameter is ignored.
*    zBuffer.l    - Specifies if the depth or z buffer should be cleared. It is not nesesarry
*                   to do so, if only 2d drawing is used.
*    Red.l        - RedValue for clearing Background
*    Green.l      - GreenValue for clearing Background
*    Blue.l       - BlueValue for clearing Background
* FUNCTION
*    Applications must call this method before performing any rendering.
* RESULT
*    nothing
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               .... Do something
*             IrrEndScene()
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrBeginScene( red.l, green.l, blue.l,backBuffer.l=#True, zBuffer.l=#True)
*/

STATIC_EXPORT bool DLL_EXPORT IrrBeginScene (  int R, int G, int B, bool backBuffer, bool zBuffer )
{
    // begin the scene
    return driver->beginScene(backBuffer, zBuffer, SColor(0,R,G,B));
}


/****f* Irrlicht/IrrDrawScene
* NAME
*    IrrDrawScene - Draw the Scene
* SYNOPSIS
*    IrrDrawScene();
* FUNCTION
* This can only be invoked between IrrBeginScene() and IrrEndScene().
* Please note that the scene is not only drawn when calling this, but also animated by existing
* scene node animators, culling of scene nodes is done, etc. Applications must call this method
* before performing any rendering.
* RESULT
*    nothing
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               IrrDrawScene()
*             IrrEndScene()
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrDrawScene()
*/

STATIC_EXPORT void DLL_EXPORT IrrDrawScene ( void )
{
    // draw the scene
    smgr->drawAll();
}

/****f* Irrlicht/IrrDrawGUI
* NAME
*    IrrDrawGUI - Draw the GUI
* SYNOPSIS
*    IrrDrawGUI();
* FUNCTION
* This can only be invoked between IrrBeginScene() and IrrEndScene().
* Draws all gui elements.
* RESULT
*    nothing
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               IrrDrawScene()
*               IrrDrawGUI()
*             IrrEndScene()
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrDrawGUI()
*/
STATIC_EXPORT void DLL_EXPORT IrrDrawGUI ( void )
{
    // draw the gui interface
    guienv->drawAll();
}

/****f* Irrlicht/IrrEndScene
* NAME
*    IrrEndScene - Ends the Rendering
* SYNOPSIS
*    IrrEndScene();
* FUNCTION
*   finish the scene and display it
* RESULT
*    nothing
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               IrrDrawScene()
*               IrrDrawGUI()
*             IrrEndScene()
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrEndScene();
*/




/* ----------------------------------------------------------------------------
finish the scene and display it
*/
STATIC_EXPORT void DLL_EXPORT IrrEndScene ( void )
{
    // end the scene and display it
    driver->endScene();
}


/****f* Irrlicht/IrrStop
* NAME
*    IrrStop - Stops Irrlicht
* SYNOPSIS
*    IrrStop();
* FUNCTION
*    release the irrlicht environment and all of its resources
* RESULT
*    nothing
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*               .... Do something
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrStop();
*/
STATIC_EXPORT void DLL_EXPORT IrrStop( void )
{
    DeleteEffects();
    device->closeDevice();
	device->drop();
	device = 0;
}


/****f* Irrlicht/IrrGetFPS
* NAME
*    IrrGetFPS - Frames per Second
* SYNOPSIS
*    IrrGetFPS()
* FUNCTION
*   Returns amount of frames per second drawn.
* RESULT
*    amount of frames per second drawn.
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               .... Do something
*             IrrEndScene()
*             fps.l = IrrGetFPS()
*             IrrSetWindowCaption(Str(fps))
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetFPS()
*/
STATIC_EXPORT int DLL_EXPORT IrrGetFPS( void )
{
    return driver->getFPS();
}

/****f* Irrlicht/IrrGetPrimitivesDrawn
* NAME
*    IrrGetPrimitivesDrawn - Drawn primitives
* SYNOPSIS
*    IrrGetPrimitivesDrawn()
* FUNCTION
*   Returns amount of primitives (mostly triangles) which were drawn in the last frame.
*   Together with IrrGetFPS() very useful method for statistics.
* RESULT
*    amount of primitives which were drawn in the last frame.
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               .... Do something
*             IrrEndScene()
*             fps.l = IrrGetFPS()
*             primitives.l = IrrGetPrimitivesDrawn()
*             IrrSetWindowCaption("FPS:"+Str(fps)+" Primitives:"+Str(primitives))
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetPrimitivesDrawn()
*/
STATIC_EXPORT unsigned int DLL_EXPORT IrrGetPrimitivesDrawn( void )
{
    return driver->getPrimitiveCountDrawn();
}

/****f* Irrlicht/IrrGetPrimitivesDrawn
* NAME
*    IrrIrrSetWindowCaption - Setw Window Caption
* SYNOPSIS
*    IrrSetWindowCaption(title.s)
* INPUTS
*   title.s - Text to diplay in the Windowcaption
* FUNCTION
*   Sets the caption of the window.
* RESULT
*    nothing
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               .... Do something
*             IrrEndScene()
*             fps.l = IrrGetFPS()
*             primitives.l = IrrGetPrimitivesDrawn()
*             IrrSetWindowCaption("FPS:"+Str(fps)+" Primitives:"+Str(primitives))
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetWindowCaption(title.p-unicode)
*/

STATIC_EXPORT void DLL_EXPORT IrrSetWindowCaption( const wchar_t * wcptrText )
{
    device->setWindowCaption( wcptrText );
}

/****f* Irrlicht/IrrSaveScreenshot
* NAME
*    IrrSaveScreenshot - Saves the Scene as Image
* SYNOPSIS
*    IrrSaveScreenshot(filename.s)
* INPUTS
*   filename.s - Filename for the Picture to save
* FUNCTION
*   Save an image created from the last rendered frame.
* RESULT
*    nothing
* EXAMPLE
*         If IrrStart( #IRR_EDT_OPENGL, screen_width, screen_height, #True, #True, #False ) = #True
*           While( IrrRunning())
*             IrrBeginScene(#True,#True,0,0,0)
*               .... Do something
*             IrrEndScene()
*             fps.l = IrrGetFPS()
*             primitives.l = IrrGetPrimitivesDrawn()
*             IrrSetWindowCaption("FPS:"+Str(fps)+" Primitives:"+Str(primitives))
*             If (...)
*               IrrSaveScreenshot("test.bmp")
*             Endif
*           Wend
*           IrrStop()
*         EndIf
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSaveScreenshot(filename.p-ascii)
*/
STATIC_EXPORT void DLL_EXPORT IrrSaveScreenshot( const char * filename )
{
    IImage* image = device->getVideoDriver()->createScreenShot();
    if (image)
        device->getVideoDriver()->writeImageToFile(image, filename);
	image->drop();
}



/****f* Irrlicht/IrrCreateRenderTargetTexture
* NAME
*    IrrCreateRenderTargetTexture - Creates a render target texture.
* SYNOPSIS
*    IrrCreateRenderTargetTexture(width.l, height.l)
* INPUTS
*   width.l, height.l - Size of the texture, in pixels. Width and height should be
*                       a power of two (for example 64, 128, 256, 512, ...) and it
*                       should not be bigger than the backbuffer, because it shares
*                       the zbuffer with the screen buffer.
* FUNCTION
*   Creates a render target texture.
* RESULT
*    Returns a pointer to the created texture or 0 if the texture could not be created.
*    If you no longer need the image, you should call IrrDropPointer().
* EXAMPLE
*    There is a complete Example of using the RenderTarget. Please study it.
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrCreateRenderTargetTexture(width.l, height.l)
*/
STATIC_EXPORT void DLL_EXPORT * IrrCreateRenderTargetTexture( int width, int height)
{

    return (void*) driver->createRenderTargetTexture(dimension2d< s32 >(width,height));
}

/****f* Irrlicht/IrrSetRenderTarget
* NAME
*    IrrSetRenderTarget - Creates a render target texture.
* SYNOPSIS
*    IrrSetRenderTarget(*targetTexture.l, clearBackbuffer.l, clearZBuffer.l, red.l, green.l, blue.l)
* INPUTS
*  *targetTexture.l    - a Pointer (as Result of IrrCreateRenderTargetTexture() )
*    clearBackbuffer.l - Specifies if the back buffer should be cleared, which means that the
*                        screen is filled with a color specified with the parameter color. If
*                        this parameter is false, the back buffer will not be cleared and the
*                        color parameter is ignored.
*    clearZBuffer.l    - Specifies if the depth or z buffer should be cleared. It is not nesesarry
*                        to do so, if only 2d drawing is used.
*    red.l             - RedValue for clearing Background
*    green.l           - GreenValue for clearing Background
*    blue.l            - BlueValue for clearing Background
* FUNCTION
*   Creates a render target texture.
* RESULT
*    Returns a pointer to the created texture or 0 if the texture could not be created.
*    If you no longer need the image, you should call IrrDropPointer().
* EXAMPLE
*    There is a complete Example of using the RenderTarget. Please study it.
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetRenderTarget(*targetTexture.l,red.l, green.l, blue.l, clearBackbuffer.l=#True, clearZBuffer.l = #True)
*/

STATIC_EXPORT bool DLL_EXPORT IrrSetRenderTarget(video::ITexture *  texture , int red, int green, int blue, bool clearBackBuffer, bool  clearZBuffer)
{
    return driver->setRenderTarget(texture,clearBackBuffer,clearZBuffer ,SColor(255,red,green,blue));
}

/****f* Irrlicht/IrrGetCursorPosition
* NAME
*    IrrGetCursorPosition - Get position of the Cursor
* SYNOPSIS
*    IrrGetCursorPosition(*pos.IRR_POS2D)
* INPUTS
*  *pos.IRR_POS2D - Pointer to a IRR_POS2D Structure
* FUNCTION
*   Returns the current position of the mouse cursor.
* RESULT
*    Filled the Structure *pos.IRR_POS2D with the current
*    position of the Cursor
* EXAMPLE
*    Define mypos.IRR_POS2D
*    IrrGetCursorPosition(@mypos)
*    Debug("Current Cursor-Position="+Str(mypos\x)+","+Str(mypos\y))
* NOTES
*
* SEE ALSO
*   IRR_POS2D
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetCursorPosition(*pos.IRR_POS2D)
*/

STATIC_EXPORT void DLL_EXPORT IrrGetCursorPosition(IRR_POS2D* ipos)
{
    position2d<s32> pos;
    pos  = device->getCursorControl()->getPosition();
    ipos->x = pos.X;
    ipos->y = pos.Y;
}

/****f* Irrlicht/IrrGetCursorRelativePosition
* NAME
*    IrrGetCursorRelativePosition - Get position of the Cursor
* SYNOPSIS
*    IrrGetCursorRelativePosition(*pos.IRR_POS2DF)
* INPUTS
*  *pos.IRR_POS2D - Pointer to a IRR_POS2D Structure
* FUNCTION
*   Returns the current position of the mouse cursor.
* RESULT
*    Returns the current position of the cursor. The returned position is a value
*    between (0.0f, 0.0f) and (1.0f, 1.0f), where (0.0f, 0.0f) is the top left
*    corner and (1.0f, 1.0f) is the bottom right corner of the render window.
* EXAMPLE
*    Define mypos.IRR_POS2DF
*    IrrGetCursorRelativePosition(@mypos)
*    Debug("Current Cursor-Position="+StrF(mypos\x)+","+StrF(mypos\y))
* NOTES
*
* SEE ALSO
*   IRR_POS2DF
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetCursorRelativePosition(*pos.IRR_POS2DF)
*/
STATIC_EXPORT void DLL_EXPORT IrrGetCursorRelativePosition(IRR_POS2DF* ipos)
{
    position2d<f32> pos;
    pos  = device->getCursorControl()->getRelativePosition();
    ipos->x = pos.X;
    ipos->y = pos.Y;
}

/****f* Irrlicht/IrrQueryFeature
* NAME
*   IrrQueryFeature - Queries the features of the driver.
* SYNOPSIS
*    IrrQueryFeature(feature.l)
* INPUTS
*  feature.l - A Enum-Value. This can be one of the following :
*       #IRR_EVDF_RENDER_TO_TARGET    - Is driver able To render To a surface?
*       #IRR_EVDF_HARDWARE_TL         - Is hardeware transform And lighting supported?
*       #IRR_EVDF_MULTITEXTURE        -
*       #IRR_EVDF_BILINEAR_FILTER     - Is driver able To render With a bilinear filter applied?
*       #IRR_EVDF_MIP_MAP             - Can the driver handle mip maps?
*       #IRR_EVDF_MIP_MAP_AUTO_UPDATE -
*       #IRR_EVDF_STENCIL_BUFFER      - Are stencilbuffers switched on And does the device support stencil buffers?
*       #IRR_EVDF_VERTEX_SHADER_1_1   - Is Vertex Shader 1.1 supported?
*       #IRR_EVDF_VERTEX_SHADER_2_0   - Is Vertex Shader 2.0 supported?
*       #IRR_EVDF_VERTEX_SHADER_3_0   - Is Vertex Shader 3.0 supported?
*       #IRR_EVDF_PIXEL_SHADER_1_1    - Is Pixel Shader 1.1 supported?
*       #IRR_EVDF_PIXEL_SHADER_1_2    - Is Pixel Shader 1.2 supported?
*       #IRR_EVDF_PIXEL_SHADER_1_3    - Is Pixel Shader 1.3 supported?
*       #IRR_EVDF_PIXEL_SHADER_1_4    - Is Pixel Shader 1.4 supported?
*       #IRR_EVDF_PIXEL_SHADER_2_0    - Is Pixel Shader 2.0 supported?
*       #IRR_EVDF_PIXEL_SHADER_3_0          - Is Pixel Shader 3.0 supported?
*       #IRR_EVDF_ARB_VERTEX_PROGRAM_1      - Are ARB vertex programs v1.0 supported?
*       #IRR_EVDF_ARB_FRAGMENT_PROGRAM_1    - Are ARB fragment programs v1.0 supported?
*       #IRR_EVDF_ARB_GLSL                  - Is GLSL supported?
*       #IRR_EVDF_HLSL                      - Is HLSL supported?
*       #IRR_EVDF_TEXTURE_NPOT
*       #IRR_EVDF_FRAMEBUFFER_OBJECT
* FUNCTION
*   Queries the features of the driver.
*   Returns #True if a feature is available
* RESULT
*    #True if the feature is available.
* EXAMPLE
*    If IrrQueryFeature(#IRR_EVDF_MIP_MAP) = #True
*       Debug("The driver is able to handle mip-maps")
*    Endif
* NOTES
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrQueryFeature(feature.l)
*/
STATIC_EXPORT bool DLL_EXPORT IrrQueryFeature(irr::video::E_VIDEO_DRIVER_FEATURE feature)
{
    return driver->queryFeature(feature);
}

/****f* Irrlicht/IrrWinGetHWnd
* NAME
*    IrrWinGetHWnd - Get the Window-Handle
* SYNOPSIS
*    handle.l = IrrWinGetHWnd()
* FUNCTION
*   Returns the Window-Hadle of the Irrlicht-Window.
* RESULT
*   Returns the Handle (hWnd) of the Window, that Irrlicht created.
*   It will return 0, if ther is now Window-Handle.
* EXAMPLE
*    handle.l = IrrWinGetHWnd()
* NOTES
*   It is Important to know, that this will only work under Windows.
*   Linux is not Supported for this.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrWinGetHWnd()
*/
STATIC_EXPORT int DLL_EXPORT IrrWinGetHWnd()
{
    E_DRIVER_TYPE dtype = driver->getDriverType();
    switch (dtype) {
        case EDT_OPENGL:
            return driver->getExposedVideoData().OpenGLWin32.HWnd;
            break;
        case EDT_DIRECT3D8:
            return driver->getExposedVideoData().D3D8.HWnd;
            break;
        case EDT_DIRECT3D9:
            return driver->getExposedVideoData().D3D9.HWnd;
            break;
    }
    return 0;
}


/****f* Irrlicht/IrrGetExposedVideoData
* NAME
*    IrrGetExposedVideoData - Get the video datas
* SYNOPSIS
*    IrrGetExposedVideoData(*videodatas.SExposedVideoData)
* FUNCTION
*   Fills the SExposedVideoData-Structure with the information
*   from Irrlicht. If you are an experienced Use, you can
*   grab the DirectX-Interfaces to use it for some own drawings.
* RESULT
*   Information about the underlying devices/Contexts
* EXAMPLE
*    IrrGetExposedVideoData(@videodatas.SExposedVideoData)
* NOTES
*   I have still hope, anyone can use this to pass the Data, so we
*   can use 'normal' PB-Drawing/Sprite/Screen-Commands together with
*   Irrlicht.
*   if you have some results, let me know ! (pm in the PB-Forum, nicknam 'neotoma'!)
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetExposedVideoData(*videodatas.SExposedVideoData)
*/
STATIC_EXPORT void DLL_EXPORT IrrGetExposedVideoData(SExposedVideoData* sData)
{
    SExposedVideoData vdata = driver->getExposedVideoData();
    memcpy(sData,&vdata , sizeof(SExposedVideoData));
}




/****f* Irrlicht/IrrSetTextureCreationFlag
* NAME
*    IrrSetTextureCreationFlag - Enables or disables a texture creation flag.
* SYNOPSIS
*    IrrSetTextureCreationFlag(flag.l, bool.l)
* INPUTS
*   flag.l  - One of the TextureCreation Flags :
*      #IRR_ETCF_ALWAYS_16_BIT
*           Forces the driver to create 16 bit textures always,
*           indepenent of which format the file on disk has. When choosing this you
*           may loose some color detail, but gain much speed and memory. 16 bit textures
*           can be transferred twice as fast as 32 bit textures and only use half of the
*           space in memory. When using this flag, it does not make sence to use the
*           flags #IRR_ETCF_ALWAYS_32_BIT, #IRR_ETCF_OPTIMIZED_FOR_QUALITY, or #IRR_ETCF_OPTIMIZED_FOR_SPEED
*           at the same time.
*       #IRR_ETCF_ALWAYS_32_BIT
*           Forces the driver to create 32 bit textures always, indepenent of which format
*           the file on disk has. Please note that some drivers (like the software device)
*           will ignore this, because they only are able to create and use 16 bit textures.
*           When using this flag, it does not make sence to use the flags
*           #IRR_ETCF_ALWAYS_16_BIT, #IRR_ETCF_OPTIMIZED_FOR_QUALITY, or #IRR_ETCF_OPTIMIZED_FOR_SPEED at
*           the same time.
*       #IRR_ETCF_OPTIMIZED_FOR_QUALITY
*           Lets the driver decide in which format the texutures are created and
*           tries to make the textures look as good as possible. Usually it simply
*           chooses the format in which the texture was stored on disk. When using
*           this flag, it does not make sence to use the flags
*           #IRR_ETCF_ALWAYS_16_BIT, #IRR_ETCF_ALWAYS_32_BIT, or #IRR_ETCF_OPTIMIZED_FOR_SPEED
*           at the same time.
*       #IRR_ETCF_OPTIMIZED_FOR_SPEED
*           Lets the driver decide in which format the textures are created and tries
*           to create them maximizing render speed. When using this flag, it does not
*           make sence to use the flags #IRR_ETCF_ALWAYS_16_BIT, #IRR_ETCF_ALWAYS_32_BIT,
*           or #IRR_ETCF_OPTIMIZED_FOR_QUALITY, at the same time.
*       #IRR_ETCF_CREATE_MIP_MAPS
*           Automaticly creates mip map levels for the textures.
*   bool.l - #True or #Flase to enable or disable the flag.
* FUNCTION
*   This flag defines how textures should be created. By changing this value,
*   you can influence for example the speed of rendering a lot. But please
*   note that the video drivers take this value only as recommendation. It could
*   happen that you enable the ETCM_ALWAYS_16_BIT mode, but the driver creates
*   32 bit textures.
* RESULT
*   nothing
* EXAMPLE
*    IrrSetTextureCreationFlag(#IRR_ETCF_OPTIMIZED_FOR_SPEED, #True)
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetTextureCreationFlag(flag.l, bool.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetTextureCreationFlag(E_TEXTURE_CREATION_FLAG  flag, bool value)
{
        driver->setTextureCreationFlag(flag,value);
}

/****f* Irrlicht/IrrCreateEventReceiver
* NAME
*    IrrCreateEventReceiver - Create a Callback-EventReceiver
* SYNOPSIS
*    *eventreceiver.l = IrrCreateEventReceiver(*callbackfunction.l)
* INPUTS
*   *callbackfunction.l - a Pointer to the CallBack Function (@CallBack())
* FUNCTION
*   To enable the full functionality of irrlichts event-mechanism in PureBsic
*   you can create a CallBack-EventReciver.
*   To use this, you need to have a own Callback-Function (Procedure) and
*   this function will be called for each event.
*
*   Under the hood, the IrrlichtWrapper creates a EventReceiver-Class, that
*   calls for each evant the Callback-Function. So you should be carefull
*   and make no big calculations in that Callback-Function.
*
*   You also need to set this EventReceiver as the current EventReceiver in
*   Irrlicht with IrrSetEventReceiver().
* RESULT
*   Returns a Pointer to a EventReceiver.
* EXAMPLE
*   ProcedureCDLL.l eventCallback(*event.SEvent)
*       If *event\EventType = #IRR_EET_GUI_EVENT
*           Debug("GUI-Event")
*       ElseIf *event\EventType = #IRR_EET_MOUSE_INPUT_EVENT
*           Debug("Mouse-Event")
*       ElseIf *event\EventType = #EET_KEY_INPUT_EVENT
*           Debug("Key-Event")
*       ElseIf *event\EventType = #IRR_EET_LOG_TEXT_EVENT
*           Debug("Log-Event")
*       ElseIf *event\EventType = #IRR_EET_USER_EVENT
*           Debug("User-Event")
*       EndIf
*   EndProcedure
*
*   *eventRec.l = IrrCreateEventReceiver(@eventCallback())
*   IrrSetEventReceiver(*eventRec)
*
* NOTES
*   The Example 30 (ImageGui) uses the Callback-EventReceiver.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrCreateEventReceiver(*callbackfunction.l)
*/
STATIC_EXPORT void* DLL_EXPORT IrrCreateEventReceiver(EventReceiverCallbackPtr cb)
{
    return new CCallbackEventReceiver(cb);
}

/****f* Irrlicht/IrrDestroyEventReceiver
* NAME
*    IrrDestroyEventReceiver - Destroy a EventReceiver
* SYNOPSIS
*    IrrDestroyEventReceiver(*eventreceiver.l)
* INPUTS
*   *eventreceiver.l     - a Pointer to a Event-Recevier.
* FUNCTION
*   Destroy a Event-Receiver by deleting them. Do not use the
*   Ponter adter deleting !
* RESULT
*   nothing
* EXAMPLE
*   IrrDestroyEventReceiver(*eventRec)
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrDestroyEventReceiver(*eventreceiver.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrDestroyEventReceiver(CCallbackEventReceiver* er)
{
    delete er;
    er=0;
}

/****f* Irrlicht/IrrGetEventReceiver
* NAME
*    IrrGetEventReceiver - Get current EventReceiver
* SYNOPSIS
*    *eventreceiver.l = IrrGetEventReceiver()
* FUNCTION
*   Returns the current (active) EventReceiver.
* RESULT
*   pointer to the current EventReceiver
* EXAMPLE
*   *eventRec = IrrGetEventReceiver();
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetEventReceiver()
*/
STATIC_EXPORT void* DLL_EXPORT IrrGetEventReceiver()
{
    return (void*)device->getEventReceiver();
}

/****f* Irrlicht/IrrSetEventReceiver
* NAME
*    IrrSetEventReceiver - Set the current EventReceiver
* SYNOPSIS
*    IrrSetEventReceiver(*eventreceiver.l)
* INPUTS
*   *eventreceiver.l - Pointer to a valid Event-Receiver
* FUNCTION
*   Set the given Event-Receiver as the actual and active EventReceiver.
* RESULT
*   nothing
* EXAMPLE
*   IrrSetEventReceiver(*eventRec)
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetEventReceiver(*eventreceiver.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetEventReceiver(IEventReceiver* er)
{
   device->setEventReceiver(er);
}

/****f* Irrlicht/IrrIsWindowActive
* NAME
*    IrrIsWindowActive - Returns if the window is active.
* SYNOPSIS
*    bool.l = IrrIsWindowActive()
* FUNCTION
*   Returns if the window is active.
* RESULT
*   #True if the Window is active, otherwise #False.
* EXAMPLE
*   While IrrRunning()
*       If IrrIsWindowActive()
*           ;Draw everything
*       EndIf
*   Wend
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrIsWindowActive()
*/
STATIC_EXPORT bool DLL_EXPORT IrrIsWindowActive()
{
    return device->isWindowActive();
}

/****f* Irrlicht/IrrSetResizeAble
* NAME
*    IrrSetResizeAble - Enable or Disable Resizing the Window
* SYNOPSIS
*    IrrSetResizeAble(bool.l)
* INPUTS
*   bool.l  -   #True or #Flase to enable or disable this function.
* FUNCTION
*   Enable or Disables the resizing of the Window
* RESULT
*   noting
* EXAMPLE
*   IrrSetResizeAble(#True)
* NOTES
*   This resizing will only work in windowed-mode !
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetResizeAble(bool.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetResizeAble(bool resize)
{
    device->setResizeAble(resize);
}

/****f* Irrlicht/IrrGetVersion
* NAME
*    IrrGetVersion - Returns the version of the engine.
* SYNOPSIS
*    version.s = IrrGetVersion()
* FUNCTION
*   Returns the version of the engine.
* RESULT
*   version of the engine as String
* EXAMPLE
*   version.s = IrrGetVersion()
*   Debug("Irrlicht-Version " + version)
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetVersion()
*/
STATIC_EXPORT const char* DLL_EXPORT IrrGetVersion()
{
    return device->getVersion();
}


/****f* Irrlicht/IrrSetViewPort
* NAME
*    IrrSetViewport - Sets a new viewport.
* SYNOPSIS
*    IrrSetViewport(x1.l, y1.l, x2.l, y2.l)
* FUNCTION
*   Sets a new viewport.
*   Every rendering operation is done into this new area.
* INPUTS
*   x1,y1,x2,y2 - Rectangle defining the new area of rendering operations
* RESULT
*   nothing
* EXAMPLE
*   IrrSetViewport(10,10,200,200)
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetViewPort(x1.l, y1.l, x2.l, y2.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetViewPort(s32 x1,s32 y1, s32 x2,s32 y2)
{
    driver->setViewPort(core::rect<s32>(x1,y1,x2,y2));
}

/****f* Irrlicht/IrrGetViewPort
* NAME
*    IrrSetViewPort - Gets the viewport.
* SYNOPSIS
*    IrrGetViewPort(*x1.l, *y1.l, *x2.l, *y2.l)
* FUNCTION
*   Gets the new viewport.
*   Every rendering operation is done into this new area.
* INPUTS
*   *x1,*y1,*x2,*y2 - Rectangle defining the area of rendering operations
* RESULT
*   nothing
* EXAMPLE
*   IrrSetViewPort(@x1.l,@y1.l,@x2.l,@y2.l)
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetViewPort(*x1.l, *y1.l, *x2.l, *y2.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrGetViewPort(s32 &x1,s32 &y1, s32 &x2,s32 &y2)
{
    core::rect<s32> rc = driver->getViewPort();
    x1 = rc.UpperLeftCorner.X ;
    y1 = rc.UpperLeftCorner.Y ;
    x2 = rc.LowerRightCorner.X ;
    y2 = rc.LowerRightCorner.Y ;
}


/****f* Irrlicht/IrrPostEventFromUser
* NAME
*    IrrPostEventFromUser - Post a User-Event
* SYNOPSIS
*    IrrPostEventFromUser(UserData1.l,UserData2.l,UserData3.f)
* FUNCTION
*   Send a User-Defined Event through the Irrlicht-Event-Mechanism.
*   You can catch such events with a Callback-Event-Receiver created
*   with IrrCreateEventReceiver().
* RESULT
*   nothing
* EXAMPLE
*   IrrPostEventFromUser(UserId, AlienID, crashPoint)
* NOTES
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPostEventFromUser(UserData1.l,UserData2.l,UserData3.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrPostEventFromUser(s32 UserData1, s32 UserData2, f32 UserData3)
{
    SEvent event;
    event.EventType = EET_USER_EVENT;
    event.UserEvent.UserData1 = UserData1;
    event.UserEvent.UserData2 = UserData2;
    event.UserEvent.UserData3 = UserData3;
    device->postEventFromUser(event);
}


//* Experimental *//

//A Quad consists out of 4 Vertices,
/*
STATIC_EXPORT void * DLL_EXPORT IrrCreateQuad()
{

}
*/


/****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:makeNormalMapTexture(*texture, amplutude.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrMakeNormalMapTexture(video::ITexture *texture, f32 amplitude=1.0f)
{
    if (texture)
        driver->makeNormalMapTexture(texture,amplitude);
}

/****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrMakeColorKeyTextureByPos(*texture, pixelpos_x.l, pixelpos_y.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrMakeColorKeyTextureByPos(video::ITexture *texture, s32 pixelpos_x, s32 pixelpos_y)
{
    if (texture)
        driver->makeColorKeyTexture(texture,core::position2d<s32>(pixelpos_x, pixelpos_y));
}


/****
Creates an 1bit alpha channel of the texture based of an color key.
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrMakeColorKeyTexture(*texture, color.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrMakeColorKeyTexture(video::ITexture *texture, u32 color)
{
    if (texture)
        driver->makeColorKeyTexture(texture,video::SColor(color));
}




/* ////////////////////////////////////////////////////////////////////////////
all of the above functions are declared as C functions and are exposed without
any mangled names
*/
}
